本文代码推荐使用Jupyter notebook跑,这样得到的结果更为直观。


主成分分析(PCA)

特征抽取通常用于提高计算效率,降低维度灾难。

主成分分析(Principe component analysis,PCA):

       是一种广泛应用于不同领域的无监督线性数据转换技术,作用是降维。

 

常用领域:

股票交易市场数据的探索性分析和信号去噪、生物信息学领域的基因组和基因表达水平数据分析

 

PCA可以基于特征之间的关系识别出数据内在模式

PCA的目标:在高维数据中找到最大方差的方向,并将数据映射到一个维度不大于原始数据的新的子空间上。

 

PCA图:






新特征的坐标是相互正交为约束条件,子空间上的正交的坐标轴(PC)为方差最大方向。

x1和x2为原始特征坐标轴,pc1和pc2为主成分。





构建一个d x k维的转换矩阵W,将一个样本向量x映射到一个新的k维特征子空间上,此空间维度小于原始的d维特征空间。

完成从原始的d维数据到新的k维子空间转换后,第一主成分的方差应该最大,由于各主成分是正交的,后续主成分也可能具备更大方差。

 

主成分方向对数据值的范围高度敏感,如果特征值不同维度应该先对特征标准化处理,让各特征具有相同的重要性。





PCA算法流程:

 1、       对原始d维数据集做标准化

 2、       构造样本的协方差矩阵

 3、       计算协方差矩阵的特征值和相应的特征向量

 4、       选择与前k个最大特征值对应的特征向量,其中k为新特征空间维度(k<=d)

 5、       通过前k个特征向量构建映射矩阵W

 6、       通过映射矩阵W将d维的输入数据集X转换到新的k维特征子空间





第一步,加载数据集,标准化数据集。

# 加载葡萄酒数据集 import pandas as pd df_wine =
pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data',
header=None) # 将数据分成70%的培训和30%的测试子集。 from sklearn.cross_validation import
train_test_split X, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].values
X_train, X_test, y_train, y_test = \ train_test_split(X, y, test_size=0.3,
random_state=0) # 使用单位方差标准化 from sklearn.preprocessing import StandardScaler sc
= StandardScaler() X_train_std = sc.fit_transform(X_train) X_test_std =
sc.fit_transform(X_test)

第二步,构造协方差矩阵,dxd维协方差矩阵是沿对角线对称,d为数据集的维度,矩阵存储了不同特征之间的协方差。

协方差公式:


μj和μk分别为特征j和k的均值。

标准化后均值为0。

两个特征之间的协方差为正,则两个特征同时递减。

协方差为负,则两个特征反向移动


协方差矩阵的特征向量代表主成分,对应的特征值大小决定特征向量的重要性。




# 协方差矩阵的特征分解,计算数据集协方差矩阵的特征对。 import numpy as np cov_mat =
np.cov(X_train_std.T) eigen_vals, eigen_vecs = np.linalg.eig(cov_mat)
print('\nEigenvalues \n%s' % eigen_vals)


cov函数得到标准化处理的训练集协方差矩阵

eig函数进行特征分解,得到特征向量及其对应的特征值。


只选择包含最多信息的特征向量组成子集。

特征值决定了特征向量的重要性,需要将特征值按降序排列,取排序在前k的特征值对应的特征向量。

 

绘制特征值的方差贡献率图像,某个特征值与所有特征值和的比较


# 使用NumPy的cumsum函数,计算累计方差。 tot = sum(eigen_vals) var_exp = [(i / tot) for i in
sorted(eigen_vals, reverse=True)] cum_var_exp = np.cumsum(var_exp) #
通过Plo的step绘制 import matplotlib.pyplot as plt %matplotlib inline
plt.bar(range(1, 14), var_exp, alpha=0.5, align='center', label='individual
explained variance') plt.step(range(1, 14), cum_var_exp, where='mid',
label='cumulative explained variance') plt.ylabel('Explained variance ratio')
plt.xlabel('Principal components') plt.legend(loc='best') plt.tight_layout() #
plt.savefig('./figures/pca1.png', dpi=300) plt.show()




第一主成分占方差总和40%,前两个主成分占比近60%

PCA是一种无监督方法,可以忽略类标信息

随机森林通过类标信息计算节点的不纯度,方差度量的是特征值在轴线是的分布。

# 按特征值的降序排列特征对 # 列出(特征值,特征向量)元组。 eigen_pairs = [(np.abs(eigen_vals[i]),
eigen_vecs[:,i]) for i in range(len(eigen_vals))] # 从高到低排序(特征值,特征向量)元组。
eigen_pairs.sort(reverse=True) # 本案例只选择前60%的两个特征向量 w =
np.hstack((eigen_pairs[0][1][:, np.newaxis], eigen_pairs[1][1][:, np.newaxis]))
print('Matrix W:\n', w)






# 通过计算矩阵点积,将整个训练集转换到包含两个主成分的子空间上。 X_train_pca = X_train_std.dot(w) # 可视化
colors = ['r', 'b', 'g'] markers = ['s', 'x', 'o'] for l, c, m in
zip(np.unique(y_train), colors, markers): plt.scatter(X_train_pca[y_train==l,
0], X_train_pca[y_train==l, 1], c=c, label=l, marker=m) plt.xlabel('PC 1')
plt.ylabel('PC 2') plt.legend(loc='lower left') plt.tight_layout() #
plt.savefig('./figures/pca2.png', dpi=300) plt.show()










# 使用Scikit-learn进行主成分分析 from sklearn.decomposition import PCA pca = PCA()
X_train_pca = pca.fit_transform(X_train_std) # pca.explained_variance_ratio_
plt.bar(range(1, 14), pca.explained_variance_ratio_, alpha=0.5, align='center')
plt.step(range(1, 14), np.cumsum(pca.explained_variance_ratio_), where='mid')
plt.ylabel('Explained variance ratio') plt.xlabel('Principal components')
plt.show()




pca = PCA(n_components=2) X_train_pca = pca.fit_transform(X_train_std)
X_test_pca = pca.transform(X_test_std) plt.scatter(X_train_pca[:,0],
X_train_pca[:,1]) plt.xlabel('PC 1') plt.ylabel('PC 2') plt.show()






# 使用plot_decision_regions函数进行可视化决策区域 from matplotlib.colors import
ListedColormap def plot_decision_regions(X, y, classifier, resolution=0.02):
#设置标记生成器和颜色映射。 markers = ('s', 'x', 'o', '^', 'v') colors = ('red', 'blue',
'lightgreen', 'gray', 'cyan') cmap = ListedColormap(colors[:len(np.unique(y))])
# plot 决定表面 x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 x2_min,
x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx1, xx2 =
np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max,
resolution)) Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) Z =
Z.reshape(xx1.shape) plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
plt.xlim(xx1.min(), xx1.max()) plt.ylim(xx2.min(), xx2.max()) # plot 类样本 for
idx, cl in enumerate(np.unique(y)): plt.scatter(x=X[y == cl, 0], y=X[y == cl,
1], alpha=0.8, c=cmap(idx), marker=markers[idx], label=cl) # 使用前两个主要组件训练逻辑回归分类器
from sklearn.linear_model import LogisticRegression lr = LogisticRegression()
lr = lr.fit(X_train_pca, y_train) plot_decision_regions(X_train_pca, y_train,
classifier=lr) plt.xlabel('PC 1') plt.ylabel('PC 2') plt.legend(loc='lower
left') plt.tight_layout() # plt.savefig('./figures/pca3.png', dpi=300)
plt.show()






SKlearn实现的PCA和之前实现的PCA是经过y轴旋转后的。

特征分析方法:特征向量可以为正或者为负

有时候需要乘上-1在实现图像的镜像。

# 绘制逻辑回归在转换后的测试数据上得到的决策区域 plot_decision_regions(X_test_pca, y_test,
classifier=lr) plt.xlabel('PC 1') plt.ylabel('PC 2') plt.legend(loc='lower
left') plt.tight_layout() # plt.savefig('./figures/pca4.png', dpi=300)
plt.show()



# 获取相应的方差贡献率 pca = PCA(n_components=None) X_train_pca =
pca.fit_transform(X_train_std) pca.explained_variance_ratio_