主成分分析PCA实现
- 一、数据降维
- 二、应用“手写体数字图像”数据进行PCA操作
- 参考文献:
一、数据降维
降维/压缩问题是选取具有代表性的特征,在保持数据多样性( Variance )的基础上,规避掉大量的特征冗余和噪声,不过这个过程也很有可能会损失一些有用的模式信息。经过大量的实践证明,相较于损失的少部分模型性能,维度压缩能够节省大量用于模型训练的时间,使得 PAC 所带来的模型综合效率变得更为划算。
在数据挖掘过程中,高维数据是非常棘手的研究对象。特别是在文本挖掘、图像处理和基因数据分析中,维度过高使很多学习器无法工作或效率降低,所以降维也是数据预处理过程的一项必要任务。
数据降维、选择特征的好处有:
① 避免过度拟合,改进预测性能;
② 使学习器运行更快,效能更高;
③ 剔除不相关的特征使模型更为简单,容易解释。
应用 PAC 降维时需要注意:
① PCA 可以降维,应用 PCA 提取主成分可能会解决一些过拟合( overfitting )的问题,但是不建议用这种方法解决 overfitting 问题,建议用加入 regularization 项(例如 ridge regression 和 LASSO
② PCA 中主成分分析只应用到训练集( Training Data )数据,选择主分量的时候只应用 training data 。
③ 不要盲目使用 PCA 进行降维,它适用于在原数据上跑到了一个比较好的结果,但运行速度又太慢的时候,否则降维取得的效果往往不好。
二、应用“手写体数字图像”数据进行PCA操作
# 导入数据和工具包
import pandas as pd
# 从互联网读入手写体图片识别任务的训练数据,存储在变量 digits_train 中。
digits_train = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/optdigits/optdigits.tra', header=None)
# 从互联网读入手写体图片识别任务的测试数据,存储在变量 digits_test 中。
digits_test = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/optdigits/optdigits.tes', header=None)
# 分割数据及数据处理
# 分割训练数据的特征向量和标记。
X_digits = digits_train[np.arange(64)]
y_digits = digits_train[64]
# 从 sklearn.decomposition 导入 PCA。
from sklearn.decomposition import PCA
# 显示手写体数字图片经 PAC 压缩后的二维空间分布
# 初始化一个可以将高维度特征向量(64 维)压缩至 2 个维度的 PCA。
estimator = PCA(n_components=2)
X_pca = estimator.fit_transform(X_digits)
# 显示 10 类手写体数字图片经 PCA 压缩后的 2 维空间分布。
#定义散点图点的颜色,i 取 0 时就画黑色的点,以此类推。
from matplotlib import pyplot as plt
def plot_pca_scatter():
colors = ['black', 'blue', 'purple', 'yellow', 'white', 'red', 'lime', 'cyan', 'orange', 'gray']
for i in range(len(colors)):
px = X_pca[:, 0][np.array(y_digits) == i]
py = X_pca[:, 1][np.array(y_digits)== i]
plt.scatter(px, py, c=colors[i])
plt.legend(np.arange(0,10).astype(str))
plt.xlabel('First Principal Component')
plt.ylabel('Second Principal Component')
plt.show()
plot_pca_scatter()
我们可以看到,即使在2维的主成分空间中,0~9这10个手写数字分布依然有不同的分布情况。
使用原始像素特征和经 PAC 压缩重建的低维特征,在相同配置的支持向量机分类模型上分别进行图像识别
# 对训练数据、测试数据进行特征向量(图片像素)与分类目标的分隔。
X_train = digits_train[np.arange(64)]
y_train = digits_train[64]
X_test = digits_test[np.arange(64)]
y_test = digits_test[64]
# 导入基于线性核的支持向量机分类器。
from sklearn.svm import LinearSVC
# 使用默认配置初始化 LinearSVC,对原始 64 维像素特征的训练数据进行建模,并在测试数据上做出预测,存储在 y_predict 中。
svc = LinearSVC()
svc.fit(X_train, y_train)
y_predict = svc.predict(X_test)
# 使用 PCA 将原 64 维的图像数据压缩到 20 个维度。
estimator = PCA(n_components=20)
# 利用训练特征决定(fit)20个正交维度的方向,并转化(transform)原训练特征。
pca_X_train = estimator.fit_transform(X_train)
# 测试特征也按照上述的 20 个正交维度方向进行转化(transform)。
pca_X_test = estimator.transform(X_test)
# 使用默认配置初始化 LinearSVC,对压缩过后的 20 维特征的训练数据进行建模,并在测试数据上做出预测,存储在 pca_y_predict 中。
pca_svc = LinearSVC()
pca_svc.fit(pca_X_train, y_train)
pca_y_predict = pca_svc.predict(pca_X_test)
# 从 sklearn.metrics 导入 classification_report 用于更加细致的分类性能分析。
from sklearn.metrics import classification_report
# 对使用原始图像高维像素特征训练的支持向量机分类器的性能作出评估。
print (svc.score(X_test, y_test))
print (classification_report(y_test, y_predict, target_names=np.arange(10).astype(str)))
# 对使用 PCA 压缩重建的低维图像特征训练的支持向量机分类器的性能作出评估。
print (pca_svc.score(pca_X_test, y_test))
print (classification_report(y_test, pca_y_predict, target_names=np.arange(10).astype(str)))
原始像素特征,SVM性能评估
PAC 压缩重建的低维特征,SVM性能评估
由上面的输出结果可以发现,尽管经过 PAC 特征压缩和重建之后的特征数据会损失 2% 左右的预测精确性,但是相比于原始数据 64 维度的特征而言,我们却使用 PAC 压缩并且降低了 68.75% 的维度,显然 PAC 所带来的模型综合效率变得更为划算。
参考文献:
[1] 范淼,李超.Python 机器学习及实践[M].清华大学出版社, 北京, 2016.