1. 程式人生 > >機器學習實戰之PCA

機器學習實戰之PCA

數據預處理 每一個 numpy 矩陣 分享 topn 文本 bsp 偽代碼

一,引言

  降維是對數據高維度特征的一種預處理方法。降維是將高維度的數據保留下最重要的一些特征,去除噪聲和不重要的特征,從而實現提升數據處理速度的目的。在實際的生產和應用中,降維在一定的信息損失範圍內,可以為我們節省大量的時間和成本。降維也成為了應用非常廣泛的數據預處理方法。

  降維具有如下一些優點:

(1)使得數據集更易使用

(2)降低算法的計算開銷

(3)去除噪聲

(4)使得結果容易理解

  PCA(principal Component Analysis),即主成分分析方法,是一種使用最廣泛的數據壓縮算法。在PCA中,數據從原來的坐標系轉換到新的坐標系,由數據本身決定。轉換坐標系時,以方差最大的方向作為坐標軸方向,因為數據的最大方差給出了數據的最重要的信息。第一個新坐標軸選擇的是原始數據中方差最大的方法,第二個新坐標軸選擇的是與第一個新坐標軸正交且方差次大的方向。重復該過程,重復次數為原始數據的特征維數。

  通過這種方式獲得的新的坐標系,我們發現,大部分方差都包含在前面幾個坐標軸中,後面的坐標軸所含的方差幾乎為0,。於是,我們可以忽略余下的坐標軸,只保留前面的幾個含有絕不部分方差的坐標軸。事實上,這樣也就相當於只保留包含絕大部分方差的維度特征,而忽略包含方差幾乎為0的特征維度,也就實現了對數據特征的降維處理。

  那麽,我們如何得到這些包含最大差異性的主成分方向呢?事實上,通過計算數據矩陣的協方差矩陣,然後得到協方差矩陣的特征值及特征向量,選擇特征值最大(也即包含方差最大)的N個特征所對應的特征向量組成的矩陣,我們就可以將數據矩陣轉換到新的空間當中,實現數據特征的降維(N維)。

  既然,說到了協方差矩陣,那麽這裏就簡單說一下方差和協方差之間的關系,首先看一下均值,方差和協方差的計算公式:

技術分享

 由上面的公式,我們可以得到一下兩點區別:

(1)方差的計算公式,我們知道方差的計算是針對一維特征,即針對同一特征不同樣本的取值來進行計算得到;而協方差則必須要求至少滿足二維特征。可以說方差就是協方差的特殊情況。 

(2)方差和協方差的除數是n-1,這樣是為了得到方差和協方差的無偏估計。具體推導過程可以參見博文:http://blog.csdn.net/maoersong/article/details/21823397

二,PCA算法實現

  將數據轉換為只保留前N個主成分的特征空間的偽代碼如下所示:

去除平均值
計算協方差矩陣
計算協方差矩陣的特征值和特征向量
將特征值排序
保留前N個最大的特征值對應的特征向量
將數據轉換到上面得到的N個特征向量構建的新空間中(實現了特征壓縮)

  具體的代碼為:

#導入numpy庫
from numpy import *

#解析文本數據函數
#@filename 文件名txt
#@delim 每一行不同特征數據之間的分隔方式,默認是tab鍵‘\t‘
def loadDataSet(filename,delim=\t)
    #打開文本文件
    fr=open(filename)
    #對文本中每一行的特征分隔開來,存入列表中,作為列表的某一行
    #行中的每一列對應各個分隔開的特征
    stringArr=[line.strip().split(delim) for line in fr.readlines()]
    #利用map()函數,將列表中每一行的數據值映射為float型
    datArr=[map(float.line)for line in stringArr]
    #將float型數據值的列表轉化為矩陣返回
    return mat(datArr)

#pca特征維度壓縮函數
#@dataMat 數據集矩陣
#@topNfeat 需要保留的特征維度,即要壓縮成的維度數,默認4096    
def pca(dataMat,topNfeat=4096):
    #求數據矩陣每一列的均值
    meanVals=mean(dataMat,axis=0)
    #數據矩陣每一列特征減去該列的特征均值
    meanRemoved=dataMat-meanVals
    #計算協方差矩陣,除數n-1是為了得到協方差的無偏估計
    #cov(X,0) = cov(X) 除數是n-1(n為樣本個數)
    #cov(X,1) 除數是n
    covMat=cov(meanRemoved,rowvar=0)
    #計算協方差矩陣的特征值及對應的特征向量
    #均保存在相應的矩陣中
    eigVals,eigVects=linalg.eig(mat(conMat))
    #sort():對特征值矩陣排序(由小到大)
    #argsort():對特征值矩陣進行由小到大排序,返回對應排序後的索引
    eigValInd=argsort(eigVals)
    #從排序後的矩陣最後一個開始自下而上選取最大的N個特征值,返回其對應的索引
    eigValInd=eigValInd[:-(topNfeat+1):-1]
    #將特征值最大的N個特征值對應索引的特征向量提取出來,組成壓縮矩陣
    redEigVects=eigVects[:,eigValInd]
    #將去除均值後的數據矩陣*壓縮矩陣,轉換到新的空間,使維度降低為N
    lowDDataMat=meanRemoved*redEigVects
    #利用降維後的矩陣反構出原數據矩陣(用作測試,可跟未壓縮的原矩陣比對)
    reconMat=(lowDDataMat*redEigVects.T)+meanVals
    #返回壓縮後的數據矩陣即該矩陣反構出原始數據矩陣
    return lowDDataMat,reconMat

  上述降維過程,首先根據數據矩陣的協方差的特征值和特征向量,得到最大的N個特征值對應的特征向量組成的矩陣,可以稱之為壓縮矩陣;得到了壓縮矩陣之後,將去均值的數據矩陣乘以壓縮矩陣,就實現了將原始數據特征轉化為新的空間特征,進而使數據特征得到了壓縮處理。

  當然,我們也可以根據壓縮矩陣和特征均值,反構得到原始數據矩陣,通過這樣的方式可以用於調試和驗證。

  下圖是通過matplotlib將原始數據點(三角形點)和第一主成分點(圓形點)繪制出來的結果。顯然,第一主成分點占據著數據最重要的信息。

import matplotlib
import matplotlib.pyplot as plt
fig=plt.figure()
ax=fig.add_subplot(lll)
#三角形表示原始數據點
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=90,c=red)                

技術分享

三,示例:PCA對半導體數據進行降維

  我們知道,像集成電路這樣的半導體,成本非常昂貴。如果能在制造過程中盡早和盡快地檢測出是否出現瑕疵,將可能為企業節省大量的成本和時間。那麽,我們在面對大規模和高維度數據集時,顯然計算損耗會很大,無疑會非常耗時。所以,如果利用PCA等降維技術將高維的數據特征進行降維處理,保留那些最重要的數據特征,舍棄那些可以忽略的特征,將大大加快我們的數據處理速度和計算損耗,為企業節省不小的時間和成本。

1 數據缺失值的問題

  顯然,數據集中可能會包含很多缺失值,這些缺失值是以NaN進行標識的。那麽如何對待這些缺失值呢?如果存在大量的樣本存在缺失值,顯然選擇將這些有缺失值得樣本丟棄不可取;此外,由於並不知道這些值的意義,選擇將缺失值替換為0也不是一個很好的決定。所以,這裏我們選擇將數據集中的特征缺失值,用數據集中該維度所有非NaN特征的均值進行替換。相比之下,采用均值替換的方法在這裏是一個相對較好的選擇。

#缺失值處理函數
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])
        #將該維度中所有NaN特征全部用均值替換
        datMat[nonzero(isnan(datMat[:,i].A))[0],i]=meanVal
return datMat

  這樣,我們就去除了所有NaN特征,接下來就可以對數據集利用PCA算法進行降維處理了。

2 PCA降維

  那麽我們如果確定需要保留哪些重要特征呢?PCA函數可以給出數據所包含的信息量,然後通過定量的計算數據中所包含的信息決定出保留特征的比例。下面是具體代碼:

dataMat=pca.replaceNanWithMean()
meanVals=mean(dataMat,axis=0)
meanRemoved=dataMat-meanVals
conMat=cov(meanRemoved,rowvar=0)
eigVals,eigVects=linalg.eig(mat(covMat))

技術分享

  從上面的特征值結果,我們可以看到如下幾個重要信息:

(1)裏面有很多值都是0,這意味著這些特征都是其他特征的副本,都可以通過其他特征來表示,其本身沒有提供額外的信息。

(2)可以看到最前面的15個特征值得數量級都大於105,而後面的特征值都變得非常小。這表明,所有特征中只有部分特征是重要特征。

  下圖示出了數據集前20個主成分占總方差的百分比:

技術分享

  可以看出,數據的絕大部分方差都包含在前面的幾個主成分中,舍棄後面的主成分並不會損失太多的信息。如果只保留前面幾個最重要的主成分,那麽在保留了絕大部分信息的基礎上,可以將數據集特征壓縮到一個非常低的程度,顯然大大提高了計算效率。

  下表是數據集前20個主成分所占的總方差百分比,以及累計方差百分比:

技術分享

  由上表可以看出,前六個主成分覆蓋了數據96.8%的方差,前二十個主成分覆蓋了99.3%的方差。這表明,通過特征值分析,我們可以確定出需要保留的主成分及其個數,在數據集整體信息(總方差)損失很小的情況下,我們可以實現數據的大幅度降維。

  一旦,通過特征值分析知道了需要保留的主成分個數,那麽我們就可以通過pca函數,設定合適的N值,使得函數最終將數據特征降低到最佳的維度。

四,總結

(1)降維是一種數據集預處理技術,往往在數據應用在其他算法之前使用,它可以去除掉數據的一些冗余信息和噪聲,使數據變得更加簡單高效,提高其他機器學習任務的計算效率。

(2)pca可以從數據中識別主要特征,通過將數據坐標軸旋轉到數據角度上那些最重要的方向(方差最大);然後通過特征值分析,確定出需要保留的主成分個數,舍棄其他主成分,從而實現數據的降維。

機器學習實戰之PCA