[完]机器学习实战 第十三章 利用PCA来简化数据

本章内容

  • 降维技术
  • 主成分分析(PCA,Principal Component Analysis)
  • 对半导体数据进行降维处理

体育比赛中,人们面对的原本是百万像素的数据,但只有球的三维位置才是最重要的,这就被称为降维(dimensionality reduction)。在低维下,数据更容易进行处理。通常,在应用其他机器学习之前,须先识别出其相关特征。

一、降维技术

对数据进行简化的原因:

  • 多维数据难以显示
  • 使得数据集更易使用
  • 降低很多算法的计算开销
  • 去除噪声
  • 使得结果易懂

在已标注和未标注的数据上都有降维技术,这里主要关注未标注数据上的降维技术。

  • 主成分分析(Principal Component Analysis,PCA),在PCA中,数据从原来的坐标系转换到新的坐标系,新坐标系的选择是由数据本身决定的。第一个新坐标轴选择的是原始数据中方差最大的方向,第二个新坐标轴的选择和第一个坐标轴正交且具有最大方差的方向。该过程一直重复,重复次数是原始数据中特征的数目。我们发现,大部分方差都包含在最前面的几个新坐标轴中。因此,可以忽略余下的坐标轴,即对数据进行降维处理。
  • 因子分析(Factor Analysis),在因子分析中,假设在观察数据的生成中有一些观察不到的隐变量(latent variable)。假设观察数据是这些隐变量和某些噪声的线性组合。那么隐变量的数据可能比观察的数据数目少,也就是说通过找到隐变量就可以实现数据的降维。因子分析已经应用于社会科学、金融和其他领域中了。
  • 独立成分分析(Independent Component Analysis,ICA),ICA假设数据是从N个数据源生成的,这和因子分析有些类似。假设数据为多个数据源的混合观察结果,这些数据源之间在统计上是相互独立的,而PCA只假设数据是不相关的。同因子分析一样,如果数据源的数目少于观察数据的数目,则可以实现降维过程,则可以实现降维过程。

在上述降维技术中,PCA应用最为广泛,文中只关注PCA。

二、PCA

优点:降低数据的复杂性,识别最重要的多个特征。
缺点:不一定需要,且可能损失有用信息。
使用数据类型:数值型数据。

2-1 移动坐标轴

考虑一下图1中的大量数据点。若要求画出一条直线,这条线要尽可能覆盖这些点,三条直线中B最长。在PCA中,对数据的坐标进行旋转,该旋转的过程取决于数据的本身。第一条坐标轴旋转到覆盖数据的最大方差为止,即直线B。数据的最大方差给出了数据的最重要的信息。


覆盖整个数据集的三条直线,其中直线B最长,并给出了数据集中差异化最大的方向
图1 覆盖整个数据集的三条直线,其中直线B最长,并给出了数据集中差异化最大的方向

在选择了覆盖数据最大差异性的坐标轴后,继续选择第二条坐标轴。假如该坐标轴与第一条坐标轴垂直,它就是覆盖数据次大差异性的坐标轴。更严谨的说法是正交(orthogonal)。在二维平面下,垂直和正交是一回事。在图1中,直线C就是第二条坐标轴。利用PCA,可将数据坐标轴旋转至数据角度上的那些最重要的方向。


二维空间的三个类别。当在该数据集上应用PCA时,就可以去掉一维,从而使得该分类问题变得更容易处理
图2 二维空间的三个类别。当在该数据集上应用PCA时,就可以去掉一维,从而使得该分类问题变得更容易处理

实现坐标轴旋转后,可讨论降维。坐标轴的旋转并没有减少数据的维度。图2中包含三个不同的类别。要区分这三个类别,可使用决策树。决策树每次都是基于一个特征来做决策。我们会发现,在x轴上可找到一些值,这些值能够很好地将这3个类别分开。这样可得到一些规则,比如当(X<4)时,数据属于类别0。若使用SVM这样稍复杂的分类器,可得到更好的分类面和分类规则,比如当(w0*x + w1*y + b) > 0时,数据也属于类别0。SVM可能比决策树得到更好的分类间隔,但分类超平面却很难解释。

通过PCA进行降维处理,可同时获得SVM和决策树的优点:一方面,得到了和决策树一样的简单分类器,同时分类间隔和SVM一样好。考虑图2中下面的图,其中的数据来自于上面的图并经PCA转换后绘制而成。如果仅使用原始数据,那么这里的间隔会比决策树的间隔大。另外,由于只需要考虑一维信息,因此数据可通过比SVM简单得多的、且容易采用的规则进行区分。

在图2中,只需一维信息即可,因为另一维信息只是对分类缺乏贡献的噪声数据。在二维平面下,这看上去微不足道,但在高维空间则意义重大。

对PCA的基本过程简单阐述后,接下来可通过代码实现PCA过程。前面提到第一个主成分就是从数据差异性最大(即方差最大)的方向提取出来的,第二个主成分则来自于数据差异次大的方向,并且该方向与第一个主成分方向正交。通过数据集的协方差矩阵及其特征值分析,可以求得这些主成分的值。

一旦得到了协方差矩阵的特征向量,就可以保留最大的N个值。这些特征向量也给出了N个最重要的真实结构。可以通过将数据乘上这N个特征向量而将它转到新的空间。

2-2 在NumPy中实现PCA

将数据转换成前N个主成分的伪代码如下:

去除平均值
计算协方差矩阵
计算协方差矩阵的特征值和特征向量
将特征值从大到小排序
保留最上面的N个特征向量
将数据转换到上述N个特征向量构建的新空间中

建立一个名为pca.py的文件并将下列代码加入用于计算PCA。

# coding=utf-8

from numpy import *

#
def loadDataSet(fileName, delim='\t') :
    fr = open(fileName)
    stringArr = [line.strip().split(delim) for line in fr.readlines()]
    dataArr = [map(float, line) for line in stringArr]
    return mat(dataArr)

# dataMat: 用于进行PCA操作的数据集
# topNfeat: 可选参数,即应用的N个特征。
# 若不指定topNfeat的值,那么函数就会返回前9999999个特征,或者原始数据中的全部特征
def pca(dataMat, topNfeat=9999999) :
    # 计算平均值
    meanVals = mean(dataMat, axis=0)
    # 减去原始数据的平均值
    meanRemoved = dataMat - meanVals
    # 计算协方差矩阵及其特征值
    covMat = cov(meanRemoved, rowvar=0)
    eigVals, eigVects = linalg.eig(mat(covMat))
    # 利用argsort()函数对特征值进行从小到大的排序,根据特征值排序结果的逆序就可以得到
    # topNfeat个最大的特征向量
    eigValInd = argsort(eigVals)
    eigValInd = eigValInd[:-(topNfeat+1):-1]
    # 这些特征向量将构成后面对数据进行转换的矩阵,该矩阵则利用N个特征将原始数据转换到新空间中
    redEigVects = eigVects[:, eigValInd]
    lowDDataMat = meanRemoved * redEigVects
    reconMat = (lowDDataMat * redEigVects.T) + meanVals
    return lowDDataMat, reconMat

代码的运行结果:

>>> import ml.pca as pca
>>> dataMat = pca.loadDataSet('c:\python27\ml\\testSet.txt')
# 进行PCA操作,lowDMat包含了降维之后的矩阵,这里是一个一维矩阵
>>> lowDMat, reconMat = pca.pca(dataMat, 1)
>>> import numpy
>>> numpy.shape(lowDMat)
(1000, 1)
# 绘制图形
>>> import matplotlib
>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> ax.scatter(dataMat[:,0].flatten().A[0], dataMat[:,1].flatten().A[0], marker=
'^', s=90)
<matplotlib.collections.PathCollection object at 0x02CEC9B0>
>>> ax.scatter(reconMat[:,0].flatten().A[0], reconMat[:,1].flatten().A[0], marke
r='o', s=50, c='red')
<matplotlib.collections.PathCollection object at 0x02CE5F30>
>>> plt.show()

执行上述命令,会得到和图3类似的结果。


原始数据集(三角形点表示)及第一主成分(圆形点表示)
图3 原始数据集(三角形点表示)及第一主成分(圆形点表示)

三、示例:利用PCA对半导体制造数据降维

半导体制造数据拥有590个特征,需要对这些特征进行降维处理。该数据集有很多缺失值。缺失值以NaN表示。在590个特征下,几乎所有样本都有NaN,因此,去除不完整的样本不太现实。可将NaN替换成0,但由于不知道这些值得意义,这样做是下策。若它们是开氏温度,则将它们置为0这种策略就太差劲了。接下来使用平均值来代替缺失值,平均值根据那些非NaN得到。

# 
def replaceNanWithMean() :
    dataMat = loadDataSet('c:\python27\ml\\secom.data', ' ')
    numFeat = shape(dataMat)[1]
    for i in range(numFeat) :
        # 计算非NaN值得平均值
        meanVal = mean(dataMat[nonzero(~isnan(dataMat[:,i].A))[0],i])
        # 将所有NaN替换为平均值
        dataMat[nonzero(isnan(dataMat[:,i].A))[0],i] = meanVal
    return dataMat

移除所有NaN后,考虑在该数据集上应用PCA。首先确认所需特征和可以去除特征的数目。PCA会给出数据中所包含的信息量。需要强调的是,数据(data)和信息(information)之间具有巨大的差别。数据指的是接受的的原始材料,其中可能包含噪声和不相关信息。信息是指数据中的相关部分。这些并非抽象概念,还可以定量地计算数据中所包含的信息并决定保留的比例。

接下来看看实现情况。

>>> reload(pca)
<module 'ml.pca' from 'C:\Python27\ml\pca.py'>
>>> dataMat = pca.replaceNanWithMean()
>>> from numpy import *
>>> meanVals = mean(dataMat, axis=0)
>>> meanRemoved = dataMat - meanVals
>>> covMat = cov(meanRemoved, rowvar=0)
>>> eigVals, eigVects = linalg.eig(mat(covMat))
>>> eigVals
array([  5.34151979e+07,   2.17466719e+07,   8.24837662e+06,
         2.07388086e+06,   1.31540439e+06,   4.67693557e+05,
         2.90863555e+05,   2.83668601e+05,   2.37155830e+05,
         2.08513836e+05,   1.96098849e+05,   1.86856549e+05,
         1.52422354e+05,   1.13215032e+05,   1.08493848e+05,
         1.02849533e+05,   1.00166164e+05,   8.33473762e+04,
    ......
         0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
         0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
         0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
         0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
         0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
         0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
         0.00000000e+00,   0.00000000e+00])

在得到的一堆值中,会发现其中超过20%的值都是0。这意味着这些特征都是其他特征的副本,也就是说,它们可通过其他特征来表示,而本身并没有提供额外的信息。

接下来,我们了解一下部分数值的数量级。最前面的15个值得数量级大于 105 ,实际上那以后的值都变得非常小。这就相当于告诉我们只有部分重要特征,重要特征的数目也很快就会下降。存在一些小的负值,它们主要源自数值误差应该四舍五入成0。

图4给出了总方差的百分比,在开始几个主成分之后,方差就会迅速下降。


前20个主成分占总方差的百分比
图4 前20个主成分占总方差的百分比

表1给出了这些主成分所对应的方差百分比和累计方差百分比。查看“累计方差百分比(%)”这一列就会注意到,前六个主成分就覆盖了数据96.8%的方差,而前20个主成分覆盖了99.3%的方差。这就表明,如果保留前6个而去除后584个主成分,我们就可以实现大概100:1的压缩比。另外,由于舍弃了噪声的主成分,将后面的主成分去除便使得数据更加干净。

表1 半导体数据中前七个主成分所占的方差百分比

主成分 方差百分比(%) 累积方差百分比(%)
1 59.2 59.2
2 24.1 83.4
3 9.2 92.5
4 2.3 94.8
5 1.5 96.3
6 0.5 96.8
7 0.3 97.1
20 0.08 99.3


从上,可知在数据集的前面多个主成分中所包含的信息量。可以尝试不同的截断值来检验它们的性能。有些人使用能包含90%信息量的主成分数量,而其他人使用前20个主成分。我们一般无法精确知道所需要的主成分数目,必须通过在实验中取不同的值来确定。有效的主成分数目取决于数据集和具体应用。

上述分析能够得到所用到的主成分数目,然后可以将该数目输入到PCA算法中,最后得到约简后数据就可以在分类器中使用了。

四、本章小结

降维技术使得数据更易使用,且能够消除数据中的噪声,使得其他机器学习任务更为精确。降维往往作为预处理步骤,在数据应用到其他算法之前清洗数据。有很多技术可以用于数据降维,其中,独立成分分析、因子分析和主成分分析比较流行,其中又以主成分分析应用最为广泛。

PCA可从数据中识别其主要特征,它是通过沿着数据最大方差方向旋转坐标轴来实现的。选择方差最大的方向作为第一条坐标轴,后续坐标轴与前面的坐标轴正交。协方差矩阵的特征值分析可以用一系列的正交坐标轴来获取。

本章的PCA将所有的数据集都调入内存,如果无法做到,就需要其他方法来寻找其特征值。

猜你喜欢

转载自blog.csdn.net/namelessml/article/details/52937462