使用PCA进行特征降维

特征降维:
特征降维是无监督学习的另一个应用,目的有二:其一,我们会经常在实际项目中遭遇特征维度非常之高的训练样本,而往往又无法借助自己的领域知识人工构建有效特征; 其二,在数据表现方面,我们无法用肉眼观测超过三个维度的特征。因此,特征降维不仅重构了有效的低维度特征向量,同时也为数据展现提供了可能。
在特征降维的方法中,主成分分析是最为经典和实用的特征降维技术,特别在辅助图像识别方面有突出的表现。


如何用矩阵的秩来判别向量组的线性相关性:
m×n 矩阵 A ,如果 r(A) = m < n,则行向量组无关,列向量组相关,
如果 r(A) = k < min(m,n),则行向量组、列向量组都相关,
如果 r(A) = n < m,则列向量组无关,行向量组相关。
如果 r(A) = m = n ,则行向量组、列向量组都无关。


如下图代码所示,我们有一组2*2的数据[(1,2),(2,4)]。假设这两个数据都反映到一个类别(分类)或者一个类簇(聚类)。如果我们的学习模型模型是线性模型,那么这两个数据其实只能帮助权重参数更新一次,因为他们线性相关,所有的特征数值都只是扩张了相同的倍数;如果使用PCA分析的话,这个矩阵的“秩”是1,也就是说,在多样性程度上,这个矩阵只有一个*度。

#--线性相关矩阵秩计算样例
#导入numpy工具包
import numpy as np
#初始化一个2*2的线性相关矩阵
M=np.array([[1,2],[2,4]])
#计算2*2线性相关矩阵的秩
np.linalg.matrix_rank(M,tol=None)
#out:1

使用PCA进行特征降维

 

其实,我们也可以把PCA当作特征选择,只是和普通理解的不同,这种特征选择是首先把原来的特征空间做了映射,使得新的映射后特征空间数据彼此正交。这样一来,我们通过主成分分析就尽可能保留下具备区分性的低维数据特征。

数据描述:本节我们依然沿用上一节使用的“手写体数字图像”全集数据。因为之前我们已经对这个数据集中训练、测试样本的数量,图像的数码维度做了介绍,这里便不再赘述。而是从主成分分析技术方便展示数据的角度出发,为读者朋友显示经过PCA处理之后,这些数据图像映射在二维空间的分布情况,如下图所示。尽管我们把原始64维度的图像压缩到只有2个维度的特征空间,依然可以发现绝大多数数字之间的区分性。

使用PCA进行特征降维


#--显示手写体数字图片经PCA压缩后的二维空间分布
#导入pandas用于数据读取和处理
import pandas as pd

#从互联网读入手写体图片识别任务的训练数据,存储在变量digits_train中。
digits_train=pd.read_csv(r'https://archive.ics.uci.edu/ml/machine-learning-databases/optdigits/optdigits.tra',header=None)

#从互联网读入手写体图片识别任务的测试数据,存储在变量digits_test中。
digits_test=pd.read_csv(r'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

#初始化一个可以将高维度特征向量(64维)压缩至2个维度的PCA
estimator=PCA(n_components=2)
x_pca=estimator.fit_transform(x_digits)

#显示10类手写体数字图片经PCA压缩后的2维空间分布
from matplotlib import pyplot as plt

def plot_pca_scatter():
    colors=['black','blue','purple','yellow','white','red','lime','cyan','orange','gray']
    for i in xrange(len(colors)):
        px=x_pca[:,0][y_digits.as_matrix()==i]
        py=x_pca[:,1][y_digits.ma_matrix()==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.1.1.2支持向量机(分类)”节使用支持向量机分类模型对手写体数字图像进行识别,并取得了很好的预测性能。当时,我们使用了全部8*8=64维度的图像像素特征对模型进行训练。这一节,我们通过代码53,分别训练两个以支持向量机(分类)为基础的手写体数字图像识别模型,其中一个模型使用原始64维度的像素特征,另一个采用经过PCA压缩重建之后的低维特征。

#--使用原始像素特征和经PCA压缩重建的低维特征,在相同配置的支持向量机(分类)模型上分别进行图像识别
#对训练数据、测试数据进行特征向量(图片像素)与分类目标的分隔
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)

性能测评:下列代码将对比原始维度特征与经过PCA压缩重建之后的图像特征,在相同配置的支持向量机(分类)模型上识别性能的差异

#--原始像素特征与PCA压缩重建的低维特征,在相同配置的支持向量机(分类)模型上识别性能的差异
#从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)))

使用PCA进行特征降维

 

使用PCA进行特征降维

我们从以上代码的输出中发现,尽管经过PCA特征压缩和重建之后的特征数据会损失2%左右的预测准确性,但是相比于原始数据64维度的特征而言,我们却使用PCA压缩并且降低了68.75%的维度。

特点分析:
降维/压缩问题则是选取数据具有代表性的特征,在保持数据多样性的基础上,规避掉大量的特征冗余和噪声,不过这个过程也很有可能会损失一些有用的模式信息。经过大量的实践证明,相较于损失的少部分模型性能,维度压缩能够节省大量用于模型训练的时间。这样一来,使得PCA所带来的模型综合效率变得更为划算。
 

上一篇:如何使用Python通过PCA获得第一个主要组件?


下一篇:机器学习之发明PCA之路