山东大学机器学习实验5

这次实验主要是通过sklearn库来熟悉PCA流程,掌握PCA的必要步骤。通过两个代码示例来做实验,并实现PCA(实现代码在最后部分),部分理解如下:

第一个示例只是用来降维,部分如下:

这是提前导入PCA库:

from sklearn.decomposition import PCA

这是用PCA保留1个特征个数:

pca = PCA(n_components=1)

这是用X来训练,即对X进行PCA降维:

pca.fit(X)

返回具有最大方差的成分

pca.components_

扫描二维码关注公众号,回复: 14658383 查看本文章

这是用X来训练PCA模型,同时返回降维后的数据:

X_reduction = pca.transform(X)

这是将降维后的数据转换成原始数据,方便绘图:

X_restore = pca.inverse_transform(X_reduction)

第二个示例则使用了数据集来实现了较为完整的PCA和K近邻算法的使用,部分如下:

这是将数据分成训练集和测试集:

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)

这是导入k近邻算法转换器:

knn_clf = KNeighborsClassifier()

这是用X_train, y_train来训练模型:

knn_clf.fit(X_train, y_train)

这是用测试集来检验模型的正确率:

knn_clf.score(X_test, y_test)

这是第一个示例,图中紫色散点图是原来数据的二维特征,图中红色散点是用PCA将2维数据降至1维后,又返回到二维绘制的图像,这就相当于将紫色的点投影到红色所在的线上。而且发现投影后各点分布比较离散,方差很大,说明降维的效果很好。

这是第二个示例中,随着特征个数保留的变化,方差的变化情况,从图中可以看出,当保留特征数为2时,方差仅仅只有0.2左右,所以这就是为什么正确率只有60%。当特征数在30左右时,方差增加的很缓慢,区域稳定,所以当保留95%的方差时,数据降维到28维,且正确率为0.98。所以降维所保留特征数不能太少,那样正确率比较低,保留太大特征时,方差变化不大,正确率增加也不大,应该灵活调整。

这是第二个示例中,用PCA将数据降到二维后画出的10个类型的散点图,从图中可以发现有些数据存在重合现象。将本来的64维降到2维后,方差保留较少,降维的效果不太好,所以应该适当选择保留特征数。

PCA算法的主要优点有:

  • 1.仅仅需要以方差衡量信息量,不受数据集以外的因素影响。 

  • 2.各主成分之间正交,可消除原始数据成分间的相互影响的因素。

  • 3.计算方法简单,主要运算是特征值分解,易于实现。

PCA算法的主要缺点有:

  • 1.主成分各个特征维度的含义具有一定的模糊性,不如原始样本特征的解释性强。

  • 2.方差小的非主成分也可能含有对样本差异的重要信息,因降维丢弃可能对后续数据处理有影响。

PCA类:

class PCA(object):

"""定义PCA类"""

def __init__(self, x, n_components=None):

self.x = x

self.dimension = x.shape[1]

if n_components and n_components >= self.dimension:

raise DimensionValueError("n_components error")

self.n_components = n_components

def reduce_dimension(self):

"""指定维度降维和根据方差贡献率自动降维"""

c_df_sort = self.get_feature()

varience = self.explained_varience_()

if self.n_components: #指定降维维度

p = c_df_sort.values[0:self.n_components, 1:]

y = np.dot(p, np.transpose(self.x))

return np.transpose(y)

varience_sum = sum(varience)

varience_radio = varience / varience_sum

varience_contribution = 0

for R in xrange(self.dimension):

varience_contribution += varience_radio[R]

if varience_contribution >= 0.99:

break

p = c_df_sort.values[0:R+1, 1:] #取前R个特征向量

y = np.dot(p, np.transpose(self.x))

return np.transpose(y)

def cov(self):

"""求x的协方差矩阵"""

x_T = np.transpose(self.x) #矩阵转置

x_cov = np.cov(x_T) #协方差矩阵

return x_cov

def get_feature(self):

"""求协方差矩阵C的特征值和特征向量"""

x_cov = self.cov()

a, b = np.linalg.eig(x_cov)

m = a.shape[0]

c = np.hstack((a.reshape((m,1)), b))

c_df = pd.DataFrame(c)

c_df_sort = c_df.sort(columns=0, ascending=False)

return c_df_sort

  • 第一个示例:

  • import numpy as np

  • import matplotlib.pyplot as plt

  • X = np.empty((100, 2))

  • X[:,0] = np.random.uniform(0., 100., size=100)

  • X[:,1] = 0.75 * X[:,0] + 3. + np.random.normal(0, 10., size=100)

  • from playML import PCA

  • pca = PCA(n_components=2)#保留2个特征个数

  • pca.fit(X)#用X来训练

  • pca.components_#返回具有最大方差的成分

  • pca = PCA(n_components=1)

  • pca.fit(X)

  • X_reduction = pca.transform(X)#用X来训练PCA模型,同时返回降维后的数据

  • X_reduction.shape

  • X_restore = pca.inverse_transform(X_reduction)#将降维后的数据转换成原始数据

  • X_restore.shape

  • plt.scatter(X[:,0], X[:,1], color='b', alpha=0.5)#散点图

  • plt.scatter(X_restore[:,0], X_restore[:,1], color='r', alpha=0.5)

  • plt.show()

第二个示例:

import numpy as np

import matplotlib.pyplot as plt

from sklearn import datasets

digit = datasets.load_digits()

X = digit.data

y = digit.target

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)

X_train.shape

%%time

from sklearn.neighbors import KNeighborsClassifier

knn_clf = KNeighborsClassifier()

knn_clf.fit(X_train, y_train)

knn_clf.score(X_test, y_test)

%%time

knn_clf = KNeighborsClassifier()

knn_clf.fit(X_train_reduction, y_train)

knn_clf.score(X_test_reduction, y_test)

pca.explained_variance_ratio_ ##拟合原数据的多少

pca = PCA(n_components=X_train.shape[1])

pca.fit(X_train)

pca.explained_variance_ratio_#返回所保留的n个成分各自的方差百分比

plt.plot([i for i in range(X_train.shape[1])],

[np.sum(pca.explained_variance_ratio_[:i+1]) for i in range(X_train.shape[1])])

plt.show()

pca = PCA(0.95) #解释原来数据95%的方差

pca.fit(X_train)

pca.n_components_

X_train_reduction = pca.transform(X_train)

X_test_reduction = pca.transform(X_test)

%%time

knn_clf = KNeighborsClassifier()

knn_clf.fit(X_train_reduction, y_train)

knn_clf.score(X_test_reduction, y_test)

pca = PCA(n_components=2)

pca.fit(X)

X_reduction = pca.transform(X)

X_reduction.shape

for i in range(10):

plt.scatter(X_reduction[y==i,0], X_reduction[y==i,1], alpha=0.8)

plt.show()

猜你喜欢

转载自blog.csdn.net/qq_50213874/article/details/129554636