zoukankan      html  css  js  c++  java
  • 转:PCA的Python实现

    http://blog.csdn.net/jerr__y/article/details/53188573

    本文主要参考下面的文章,文中的代码基本是把第二篇文章的代码手写实现了一下。 
    - pca讲解:http://www.cnblogs.com/jerrylead/archive/2011/04/18/2020209.html 
    - python实现:http://blog.csdn.net/u012162613/article/details/42177327

    总体代码

    """
    总的代码.
    Func: 对原始的特征矩阵进行降维, lowDataMat为降维之后返回新的特征矩阵。
    Usage: lowDDataMat = pca(dataMat, k)
    """
    # 零均值化
    def zeroMean(dataMat):
        # 求各列特征的平均值
        meanVal = np.mean(dataMat, axis=0)
        newData = dataMat - meanVal
        return newData, meanVal
    def pca(dataMat,k):  
        newData,meanVal=zeroMean(dataMat)  
        covMat=np.cov(newData,rowvar=0)    #求协方差矩阵,return ndarray;若rowvar非0,一列代表一个样本,为0,一行代表一个样本  
    
        eigVals,eigVects=np.linalg.eig(np.mat(covMat))#求特征值和特征向量,特征向量是按列放的,即一列代表一个特征向量  
        eigValIndice=np.argsort(eigVals)            #对特征值从小到大排序  
        k_eigValIndice=eigValIndice[-1:-(k+1):-1]   #最大的k个特征值的下标  
        k_eigVect=eigVects[:,k_eigValIndice]        #最大的k个特征值对应的特征向量  
        lowDDataMat=newData*k_eigVect               #低维特征空间的数据
        return lowDDataMat
    #     reconMat=(lowDDataMat*k_eigVect.T)+meanVal  #重构数据  
    #     return lowDDataMat,reconMat  
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    下面逐步来实现PCA

    (0)先准备好数据

    import numpy as np
    • 1
    # n维的原始数据,本例中n=2。
    data = np.array([[2.5,2.4], [0.5, 0.7], [2.2, 2.9], [1.9, 2.2], [3.1, 3.0], [2.3, 2.7],
                     [2, 1.6], [1, 1.1], [1.5, 1.6], [1.1, 0.9]])
    print data
    • 1
    • 2
    • 3
    • 4
    [[ 2.5  2.4]
     [ 0.5  0.7]
     [ 2.2  2.9]
     [ 1.9  2.2]
     [ 3.1  3. ]
     [ 2.3  2.7]
     [ 2.   1.6]
     [ 1.   1.1]
     [ 1.5  1.6]
     [ 1.1  0.9]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (1)零均值化

    # (1)零均值化
    def zeroMean(dataMat):
        # 求各列特征的平均值
        meanVal = np.mean(dataMat, axis=0)
        newData = dataMat - meanVal
        return newData, meanVal
    newData, meanVal = zeroMean(data)
    print 'the newData is 
    ', newData
    print 'the meanVal is 
    ', meanVal
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    the newData is 
    [[ 0.69  0.49]
     [-1.31 -1.21]
     [ 0.39  0.99]
     [ 0.09  0.29]
     [ 1.29  1.09]
     [ 0.49  0.79]
     [ 0.19 -0.31]
     [-0.81 -0.81]
     [-0.31 -0.31]
     [-0.71 -1.01]]
    the meanVal is 
    [ 1.81  1.91]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    (2)对各维特征的协方差矩阵

    # (2)求协方差矩阵,rowvar=036表示每列对应一维特征
    covMat = np.cov(newData, rowvar=0)
    print covMat
    # 若rowvar=1表示没行是一维特征,每列表示一个样本,显然咱们的数据不是这样的
    # covMat2 = np.cov(newData, rowvar=1)
    # print covMat2
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    [[ 0.61655556  0.61544444]
     [ 0.61544444  0.71655556]]
    
    • 1
    • 2
    • 3

    (3)求(2)中的协方差矩阵的特征值和特征向量

    # (3)求协方差矩阵的特征值和特征向量,利用numpy中的线性代数模块linalg中的eig函数
    eigVals, eigVects = np.linalg.eig(np.mat(covMat))
    print '特征值为:
    ', eigVals
    print '特征向量为
    ', eigVects
    • 1
    • 2
    • 3
    • 4
    特征值为:
    [ 0.0490834   1.28402771]
    特征向量为
    [[-0.73517866 -0.6778734 ]
     [ 0.6778734  -0.73517866]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上面的结果中: 
    特征值为:

    0.0490834 1.28402771]

    特征向量为

    [[-0.73517866 -0.6778734 ]

    [0.6778734 -0.73517866]]

    特征值0.0490834对应的特征向量是第一列(-0.73517866 0.6778734)T

    (4)降维到k维(k < n)

    # (4)保留主要的成分,将特征值按照从大到小的顺序排序,选择其中最大的k个,然后将对应的k个特征向量分别作为列向量组成的特征向量矩阵。
    # 比如本例子中保留1.28402771对应的特征向量(-0.6778734 -0.73517866)^T
    k = 1 # 此例中取k = 1
    eigValIndice = np.argsort(eigVals) # 从小到大排序
    n_eigValIndice = eigValIndice[-1:-(k+1):-1] # 取值最大的k个下标
    n_eigVect = eigVects[:, n_eigValIndice] # 取对应的k个特征向量
    print n_eigVect
    print n_eigVect.shape
    lowDataMat = newData*n_eigVect # 低维特征空间的数据
    reconMat = (lowDataMat * n_eigVect.T) + meanVal # 重构数据,得到降维之后的数据
    print '将样本点投影到选取的低维特征向量上,实际使用的是这个结果作为新的特征:
    ', lowDataMat
    print '降维之后的样本:
    ', reconMat
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    [[-0.6778734 ]
     [-0.73517866]]
    (2L, 1L)
    
    • 1
    • 2
    • 3
    • 4

    将样本点投影到选取的低维特征向量上,实际使用的是这个结果作为新的特征

    [[-0.82797019]
     [ 1.77758033]
     [-0.99219749]
     [-0.27421042]
     [-1.67580142]
     [-0.9129491 ]
     [ 0.09910944]
     [ 1.14457216]
     [ 0.43804614]
     [ 1.22382056]]
    降维之后的样本:
    [[ 2.37125896  2.51870601]
     [ 0.60502558  0.60316089]
     [ 2.48258429  2.63944242]
     [ 1.99587995  2.11159364]
     [ 2.9459812   3.14201343]
     [ 2.42886391  2.58118069]
     [ 1.74281635  1.83713686]
     [ 1.03412498  1.06853498]
     [ 1.51306018  1.58795783]
     [ 0.9804046   1.01027325]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    降维之后的样本:

    [[ 2.37125896 2.51870601] 
    [ 0.60502558 0.60316089] 
    [ 2.48258429 2.63944242] 
    [ 1.99587995 2.11159364] 
    [ 2.9459812 3.14201343] 
    [ 2.42886391 2.58118069] 
    [ 1.74281635 1.83713686] 
    [ 1.03412498 1.06853498] 
    [ 1.51306018 1.58795783] 
    [ 0.9804046 1.01027325]] 
    原始样本: 
    [[ 2.5 2.4] 
    [ 0.5 0.7] 
    [ 2.2 2.9] 
    [ 1.9 2.2] 
    [ 3.1 3. ] 
    [ 2.3 2.7] 
    [ 2. 1.6] 
    [ 1. 1.1] 
    [ 1.5 1.6] 
    [ 1.1 0.9]] 
    通过比较可以看出,通过降维之后我们成功地实现了特征从二维降到了一维,降维之后会和原始数据有一定的变化, 
    我们可以认为通过这种方式消除了一部分的噪声(当然实际上很可能损失了部分真实信息)。 
    ——————————————-分割线———————————————————

    利用sklearn实现PCA

    # 原始数据
    data = np.array([[2.5,2.4], [0.5, 0.7], [2.2, 2.9], [1.9, 2.2], [3.1, 3.0], [2.3, 2.7],
                     [2, 1.6], [1, 1.1], [1.5, 1.6], [1.1, 0.9]])
    # print data
    • 1
    • 2
    • 3
    • 4
    # 好吧,就是这么简单
    from sklearn.decomposition import PCA
    pca = PCA(n_components=1)
    new_feature = pca.fit_transform(data)
    print new_feature
    • 1
    • 2
    • 3
    • 4
    • 5

    [[-0.82797019] 
    [ 1.77758033] 
    [-0.99219749] 
    [-0.27421042] 
    [-1.67580142] 
    [-0.9129491 ] 
    [ 0.09910944] 
    [ 1.14457216] 
    [ 0.43804614] 
    [ 1.22382056]]

  • 相关阅读:
    线程练习-网络买票
    永久储存信息(已完善)
    Linux命令
    oracle(3)
    小结
    java开发中中文编码问题
    double保留两位小数
    oracle(2)
    javadate相关
    分布式
  • 原文地址:https://www.cnblogs.com/DjangoBlog/p/8280428.html
Copyright © 2011-2022 走看看