Machine Learning in Action 读书笔记---第13章 利用PCA来简化数据

Machine Learning in Action 读书笔记

第13章 利用PCA来简化数据



一、降维技术

降维(dimensionality reduction),可以将数据从高维度将低维度,在低维下,数据更容易进行处理。
对数据进行简化有如一系列原因:

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

本章主要关注为标注数据上的降维技术,该技术同时也可以应用于已标注的数据。

降维方法:

  1. 主成分分析(Principal Component Analysis,PCA):在PCA中,数据从原来的坐标系转换到了新的坐标系,新坐标系的选择是由数据本身决定的。第一个新坐标轴选择的是原始数据中方差最大的方向,第二个新坐标轴的选择和第一个坐标轴正交(垂直)且具有最大方差的方向。该过程一直重复,重复次数为原始数据中特征的数目。
  2. 因子分析(Factor Analysis):假设在观察数据的生成中有一些观察不到的隐变量(latent variable),通过找到隐变量就可以实现数据的降维。
  3. 独立成分分析(Independent Component Analysis,ICA):和因子分析一样,如果数据源的数目少于观察数据的数目,则可以实现降维过程。

二、主成分分析

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

通过python中的Numpy来实现PCA。

1.移动坐标轴

        在PCA中,我们对数据的坐标进行了旋转,该旋转的过程取决于数据的本身。第一条坐标轴旋转到覆盖数据的最大方差位置(最长直线,也是数据集中差异化最大的方向),数据的最大方差给出了数据的最重要的信息。在选择了覆盖数据最大差异性的坐标轴之后,选择第二条坐标轴,该坐标轴与第一条坐标轴垂直(正交,orthogonal),他就是覆盖数据次大差异性的坐标轴。,利用PCA,可以将数据坐标轴旋转至数据角度上的那些最重要的方向。

通过PCA进行降维处理,就可以同时获得SVM和决策树的优点:一方面,得到了和决策树一样简单的分类器,同时分类间隔和SVM(支持向量机)一样好。

前面提到,第一个主成分就是从数据差异性最大(即方差最大)的方向提取出来的。第二个主成分则来自于数据差异性次大的方向,并且该方向与第一个主成分方向正交。通过数据集的协方差矩阵及其特征值分析,就可以求得这些主成分的值。
一旦得到协方差矩阵的特征向量,就可以保留最大的N个值,这些特征向量也给出了N个最重要特征的真实结构。可以通过将数据乘上这N个特征向量而将它转换到新的空间

在Numpy中实现PCA的伪代码:

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

PCA算法:

from numpy import *
import matplotlib
import matplotlib.pyplot as plt
# PCA(主成分分析)算法
def loadDataSet(fileName, delim='\t'):
    fr = open(fileName)
    stringArr = [line.strip().split(delim) for line in fr.readlines()] # 使用两个列表推导式来构建矩阵
    datArr = [list(map(float,line)) for line in stringArr]
    return mat(datArr)

def pca(dataMat, topNfeat=9999999): # 参数:用于进行pca操作的数据集,应用的N个特征(可以选择,如果不指定,函数就会返回前9999999个特征,或者原始数据中给的全部特征)
    meanVals = mean(dataMat, axis=0) # 计算原始数据集的平均值
    meanRemoved = dataMat - meanVals # 减去原始数据集的平均值
    covMat = cov(meanRemoved, rowvar=0) # 计算协方差矩阵
    eigVals,eigVects = linalg.eig(mat(covMat)) # 计算协方差矩阵的特征值和特征向量
    # print(eigVals) #[0.36651371 2.89713496]
    # print('==============================================')
    # print(eigVects) #[[-0.85389096 -0.52045195] [ 0.52045195 -0.85389096]]
    eigValInd = argsort(eigVals)            #利用argsort()函数对特征值进行从小到大的排序
    eigValInd = eigValInd[:-(topNfeat+1):-1]  #根据特征值排序结果的逆序得到topNfeat个最大的特征向量
    redEigVects = eigVects[:,eigValInd]       #重组从最大到最小的特征向量
    lowDDataMat = meanRemoved * redEigVects  #将数据乘上N个特征向量,利用N个特征将原始数据转换到新空间中
    reconMat = (lowDDataMat * redEigVects.T) + meanVals
    return lowDDataMat, reconMat # 返回降维之后的数据集和重构后的原始数据,返回重构后的原始数据用于调试

通过以下代码将二维原始数据和降维后的数据绘制出来:

if __name__ == '__main__':
    dataMat = loadDataSet('testSet.txt')
    # print(dataMat)
    # print(shape(dataMat)) # (1000, 2)
    lowDMat, reconMat = pca(dataMat, 1)
    # print(shape(lowDMat)) # (1000, 1)

    # 将降维后的数据和原始数据一起绘制出来
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(dataMat[:, 0].flatten().A[0], dataMat[:, 1].flatten().A[0], marker='^', s=90)
    ax.scatter(reconMat[:, 0].flatten().A[0], reconMat[:, 1].flatten().A[0], marker='o', s=50, c='red')
    plt.show()

二维原始数据和降维后的数据(红)
在这里插入图片描述

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

'''示例:利用PCA对半导体制造数据降维'''
# 将NaN(not a number)替换成平均值的函数
def replaceNanWithMean():
    datMat = loadDataSet('secom.data', ' ')
    numFeat = shape(datMat)[1] # 获得特征数量(列数)
    for i in range(numFeat):
        # 为每一列(每个特征)计算非NAN值的平均值
        meanVal = mean(datMat[nonzero(~isnan(datMat[:,i].A))[0],i]) #nonzero返回非零元素的索引值;mat.A可以将矩阵转化为数组;isnan逐个元素测试是否为NaN并以布尔数组形式返回结果。
        datMat[nonzero(isnan(datMat[:,i].A))[0],i] = meanVal  #将NaN用上面计算的平均值替换
    return datMat

if __name__ == '__main__':
    '''示例:利用PCA对半导体制造数据降维'''
    dataMat = replaceNanWithMean()
    meanVals = mean(dataMat, axis=0)
    meanRemoved = dataMat - meanVals
    covMat = cov(meanRemoved, rowvar=0)
    eigVals, eigVects = linalg.eig(mat(covMat))
    # print(eigVals)
    '''
    从求得的特征值可以知道,其中有超多百分之二十的特征值都是0,这就意味着这些特征都是其他特征的副本,可以通过其他特征来表示,本身并没有提供额外的信息
    从求得的特征的大小可以知道,从开始到后面特征值在慢慢减小,后面的值变得非常小,这说明只有部分重要特征,重要特征的数目也很快就会下降
    [ 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  8.15850591e+04  7.76560524e+04
      ...
      5.01137874e-09  3.48686481e-09  2.91267158e-09  2.77880632e-09
      1.73093443e-09  1.42391218e-09  1.16455138e-09  1.11816007e-09
      9.24977357e-10  1.80003603e-10  1.97062639e-10  2.61907926e-10
      6.95076631e-10  6.13339126e-10  5.27540889e-10 -1.85894956e-15
      2.27343919e-15  2.69163026e-16  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
      ...   
    '''

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值