zoukankan      html  css  js  c++  java
  • 降维算法-PCA主成分分析

    1、PCA算法介绍
    主成分分析(Principal Components Analysis),简称PCA,是一种数据降维技术,用于数据预处理。一般我们获取的原始数据维度都很高,比如1000个特征,在这1000个特征中可能包含了很多无用的信息或者噪声,真正有用的特征才100个,那么我们可以运用PCA算法将1000个特征降到100个特征。这样不仅可以去除无用的噪声,还能减少很大的计算量。

    PCA算法是如何实现的?

    简单来说,就是将数据从原始的空间中转换到新的特征空间中,例如原始的空间是三维的(x,y,z),x、y、z分别是原始空间的三个基,我们可以通过某种方法,用新的坐标系(a,b,c)来表示原始的数据,那么a、b、c就是新的基,它们组成新的特征空间。在新的特征空间中,可能所有的数据在c上的投影都接近于0,即可以忽略,那么我们就可以直接用(a,b)来表示数据,这样数据就从三维的(x,y,z)降到了二维的(a,b)。

    问题是如何求新的基(a,b,c)?

    一般步骤是这样的:先对原始数据零均值化,然后求协方差矩阵,接着对协方差矩阵求特征向量和特征值,这些特征向量组成了新的特征空间。具体的细节,推荐Andrew Ng的网页教程:Ufldl 主成分分析 ,写得很详细。

    (1)零均值化

    假如原始数据集为矩阵dataMat,dataMat中每一行代表一个样本,每一列代表同一个特征。零均值化就是求每一列的平均值,然后该列上的所有数都减去这个均值。也就是说,这里零均值化是对每一个特征而言的,零均值化都,每个特征的均值变成0。实现代码如下:
    1 def zeroMean(dataMat):      
    2     meanVal=np.mean(dataMat,axis=0)     #按列求均值,即求各个特征的均值
    3     newData=dataMat-meanVal
    4     return newData,meanVal
    函数中用numpy中的mean方法来求均值,axis=0表示按列求均值。

    该函数返回两个变量,newData是零均值化后的数据,meanVal是每个特征的均值,是给后面重构数据用的。

    (2)求协方差矩阵

    1    newData,meanVal=zeroMean(dataMat)
    2    covMat=np.cov(newData,rowvar=0)

    numpy中的cov函数用于求协方差矩阵,参数rowvar很重要!若rowvar=0,说明传入的数据一行代表一个样本,若非0,说明传入的数据一列代表一个样本。因为newData每一行代表一个样本,所以将rowvar设置为0。
    covMat即所求的协方差矩阵。

    (3)求特征值、特征矩阵
    调用numpy中的线性代数模块linalg中的eig函数,可以直接由covMat求得特征值和特征向量:

    1 eigVals,eigVects=np.linalg.eig(np.mat(covMat))

    eigVals存放特征值,行向量。
    eigVects存放特征向量,每一列带别一个特征向量。
    特征值和特征向量是一一对应的

    (4)保留主要的成分[即保留值比较大的前n个特征]
    第三步得到了特征值向量eigVals,假设里面有m个特征值,我们可以对其排序,排在前面的n个特征值所对应的特征向量就是我们要保留的,它们组成了新的特征空间的一组基n_eigVect。将零均值化后的数据乘以n_eigVect就可以得到降维后的数据。代码如下:

    1     eigValIndice=np.argsort(eigVals)            #对特征值从小到大排序
    2     n_eigValIndice=eigValIndice[-1:-(n+1):-1]   #最大的n个特征值的下标
    3     n_eigVect=eigVects[:,n_eigValIndice]        #最大的n个特征值对应的特征向量
    4     lowDDataMat=newData*n_eigVect               #低维特征空间的数据
    5     reconMat=(lowDDataMat*n_eigVect.T)+meanVal  #重构数据
    6     return lowDDataMat,reconMat

    代码中有几点要说明一下,首先argsort对特征值是从小到大排序的,那么最大的n个特征值就排在后面,所以eigValIndice[-1:-(n+1):-1]就取出这个n个特征值对应的下标。【python里面,list[a:b:c]代表从下标a开始到b,步长为c。】

    reconMat是重构的数据,乘以n_eigVect的转置矩阵,再加上均值meanVal。

    OK,这四步下来就可以从高维的数据dataMat得到低维的数据lowDDataMat,另外,程序也返回了重构数据reconMat,有些时候reconMat课便于数据分析。

    贴一下总的代码:

     1 #零均值化
     2 def zeroMean(dataMat):      
     3     meanVal=np.mean(dataMat,axis=0)     #按列求均值,即求各个特征的均值
     4     newData=dataMat-meanVal
     5     return newData,meanVal
     6  
     7 def pca(dataMat,n):
     8     newData,meanVal=zeroMean(dataMat)
     9     covMat=np.cov(newData,rowvar=0)    #求协方差矩阵,return ndarray;若rowvar非0,一列代表一个样本,为0,一行代表一个样本
    10     
    11     eigVals,eigVects=np.linalg.eig(np.mat(covMat))#求特征值和特征向量,特征向量是按列放的,即一列代表一个特征向量
    12     eigValIndice=np.argsort(eigVals)            #对特征值从小到大排序
    13     n_eigValIndice=eigValIndice[-1:-(n+1):-1]   #最大的n个特征值的下标
    14     n_eigVect=eigVects[:,n_eigValIndice]        #最大的n个特征值对应的特征向量
    15     lowDDataMat=newData*n_eigVect               #低维特征空间的数据
    16     reconMat=(lowDDataMat*n_eigVect.T)+meanVal  #重构数据
    17     return lowDDataMat,reconMat

    3、选择主成分个数
    文章写到这里还没有完,应用PCA的时候,对于一个1000维的数据,我们怎么知道要降到几维的数据才是合理的?即n要取多少,才能保留最多信息同时去除最多的噪声?一般,我们是通过方差百分比来确定n的,这一点在Ufldl教程中说得很清楚,并且有一条简单的公式,下面是该公式的截图:

     

    根据这条公式,可以写个函数,函数传入的参数是百分比percentage和特征值向量,然后根据percentage确定n,代码如下:

     1 def percentage2n(eigVals,percentage):
     2     sortArray=np.sort(eigVals)   #升序
     3     sortArray=sortArray[-1::-1]  #逆转,即降序
     4     arraySum=sum(sortArray)
     5     tmpSum=0
     6     num=0
     7     for i in sortArray:
     8         tmpSum+=i
     9         num+=1
    10         if tmpSum>=arraySum*percentage:
    11             return num

    那么pca函数也可以重写成百分比版本,默认百分比99%。

     1 def pca(dataMat,percentage=0.99):
     2     newData,meanVal=zeroMean(dataMat)
     3     covMat=np.cov(newData,rowvar=0)    #求协方差矩阵,return ndarray;若rowvar非0,一列代表一个样本,为0,一行代表一个样本
     4     eigVals,eigVects=np.linalg.eig(np.mat(covMat))#求特征值和特征向量,特征向量是按列放的,即一列代表一个特征向量
     5     n=percentage2n(eigVals,percentage)                 #要达到percent的方差百分比,需要前n个特征向量
     6     eigValIndice=np.argsort(eigVals)            #对特征值从小到大排序
     7     n_eigValIndice=eigValIndice[-1:-(n+1):-1]   #最大的n个特征值的下标
     8     n_eigVect=eigVects[:,n_eigValIndice]        #最大的n个特征值对应的特征向量
     9     lowDDataMat=newData*n_eigVect               #低维特征空间的数据
    10     reconMat=(lowDDataMat*n_eigVect.T)+meanVal  #重构数据
    11     return lowDDataMat,reconMat

     

    作者:wepon_
    来源:CSDN
    原文:https://blog.csdn.net/u012162613/article/details/42177327
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    NetSuite Batch Process Status
    NetSuite generated bank files and the Bank Reconciliation process
    Global Search file content in Gitlab repositories, search across repositories, search across all files
    FedEx Package Rate Integration with NetSuite direct integrate by WebServices
    git Merge branches
    git tag and NetSuite deployment tracking
    API 读写cookie的方法
    C# 生成缩略图
    解决jquery操作checkbox全选全不选无法勾选问题
    JS读取写入删除Cookie方法
  • 原文地址:https://www.cnblogs.com/dlfeng/p/10009588.html
Copyright © 2011-2022 走看看