標籤:python pca 資料
主成分分析法原理及其python實現前言:
這片文章主要參考了Andrew Ng的Machine Learning課程講義,我進行了翻譯,並配上了一個python示範demo加深理解。
本文主要介紹一種降維演算法,主成分分析法,Principal Components Analysis,簡稱PCA,這種方法的目標是找到一個資料近似集中的子空間,至於如何找到這個子空間,下文會給出詳細的介紹,PCA比其他降維演算法更加直接,只需要進行一次特徵向量的計算即可。(在Matlab,python,R中這個可以輕易的用eig()函數來實現)。
假設我們給出這樣一個資料集代表m輛不同種類的汽車,每個資料點各個屬性代表該類汽車的最大速度,轉彎半徑等等,假設對每個i都有(n << m)但是有一點我們不知道,對於某些Xi和Xj來說,最大時速是用不同的單位給出的,一個是用mile/hour,一個是用kilometers/hour,這兩個屬性顯然是線性相關的,至於有一些不同是因為在mph和kph之間的轉換造成的,因此,資料其實是近似集中在一個n-1維的子空間裡的,我們如何自動偵測並且移除這些冗餘呢?
再舉一個更加具體的例子,我們現在擁有一個由對遙控直升機飛行員的問卷調查得出的資料集,第i個資料點的第一個分量代表該飛行員的飛行技巧,第二個分量表示TA對飛行過程的享受程度,因為遙控直升機非常難以操控,所以只有那些真正享受這個過程的人才能成為一個好的飛行員,所以,這兩個屬性具有很強的關聯性,,實際上,我們可以假設資料實際集中在看起來像是一個斜的座標軸附近,我們可以把這個座標軸直觀理解為一個人與飛行的”緣分”,(這樣的直觀理解可以協助理解PCA),如所示,我們如何自動計算出u1這個方向呢?
沒錯,計算u1這個方向的方法就是PCA演算法,但是在資料集上運行PCA演算法之前,通常我們要首先對資料進行預先處理來標準化資料的均值和方差。下面是預先處理過程:
步驟1-2是為了讓整個資料集的均值為0,如果這個資料集的均值已經是0,則這兩步可以忽略,步驟3-4更新了每個屬性的資料使得在同一個屬性上的資料具有單位方差(歸一化),從而保證不同的屬性都有相同的資料範圍而受到“平等對待”,打個比方,如果屬性x1表示汽車的最快時速,用mph來表示,資料範圍通常在大幾十到一百多,x2表示汽車的座位元,資料範圍通常在2-4,此時就需要重新標準化這兩個不同的屬性使他們更有可比性,當然,如果我們已經得知不同的屬性具有相同的資料規模時,步驟3-4就可以忽略不做,例如當每個資料點代表一個灰階映像時,此時每個都是從{0,1……,255}中取值的。
現在,我們已經執行了資料的標準化,接下來該計算“資料差異主要所在”的軸u,即資料主要集中的方向,解決這個問題的方法是找到一個單位向量u使得當資料投影到這個方向時,投影資料的方差最大化,直觀上理解,資料集中包含了資料的方差和資料資訊,我們應該選擇一個方向u使得我們能近似的讓這些資料集中在u代表的方向或者子空間上,並且儘可能的保留這些資料的方差。
考慮下面的資料集合,對於這個資料集合我們已經執行了標準化步驟:
現在,假設我們選出了一個u代表中的方向,黑點代表了未經處理資料在這條線上的投影,
在中,我們看到投影資料仍然具有相當大的方差,並且這些點都遠離原點,我們來看看另外一種情況,假設選出的u是這種方向的:
在這張圖中,可以明顯的觀察到投影的方差明顯比小很多,並且投影資料更加接近原點。
所以,我們想要通過某種演算法來挑選出方向u對應於上面兩張圖中的前者的方向,為了用標準數學語言描述,假設有一個單位向量u和一個點x,則x投影在u上的長度為等價的說法就是,如果xi是現有資料集中的一個點(用圖中的一個叉來表示),則它在u上的投影(圖上的黑點)到原點的距離為,因此,為了使投影的方差最大化,我們需要挑選出一個單位向量使得下面的式子取得最大值:
我們可以比較容易的通過拉格朗日乘數法發現當上面的式子取最大值時u取這個矩陣的主特徵向量即可,通過觀察,我們發現這個矩陣恰好是未經處理資料集的共變數矩陣。
總結一下,我們發現如果我們希望找到一個一維子空間來近似簡化資料集,我們只需要計算出的主特徵向量u即可,推廣到高維空間來說,如果我們把我們的資料集投影到k-維子空間(k< n),我們就應該用矩陣前k大的特徵向量來作為u1,u2,…..uk,也就是說ui現在組成了資料集上一組新的基。之後,為了表示xi在這組新的基下的座標,我們只需要計算對應的資料向量即可這樣,未經處理資料向量yi現在位於一個比n維更低的,k-dim的子空間,用來近似代替或者完全代替xi,因此PCA也被稱之為一種降維演算法,向量u1,u2,…..uk被稱作資料集的前k個主成分。
PCA有很多的應用情境,首先,壓縮是一個明顯的用途—用yi來代替xi,如果我們用高維資料集縮減為k=2或者3維,我們就可以畫出yi從而使資料視覺效果,打個比方,如果我們將資料集縮減到二維,然後我們就可以把資料畫到座標平面裡(圖中一個點代表一類車型),然後觀察哪些車型是類似的,哪一類車型可以被聚類。
其他的標準用途包括在運行監督學習演算法之前對資料集進行預先處理使維度減少,除了可以減少計算開銷之外,減少資料的維度同樣可以減少考慮假設分類的複雜程度同時避免過度學習。
下面提供一個python的pca實現,為了直觀的描述pca演算法,使用一個1000*2的矩陣作為測試資料集,降到1維,並畫出映像來進行觀察,首先查看一下我們的測試資料檔案前十個資料點,(如果你需要這個測試資料集,可以發送給你。)
之後我們運行利用python實現的pca演算法並且畫圖,代碼如下:
from numpy import *def loadDataSet(fileName,delim=‘\t‘): fr=open(fileName) stringArr=[line.strip().split(delim) for line in fr.readlines()] datArr=[map(float,line) for line in stringArr] return mat(datArr)def pca(dataMat,topNfeat=9999999): meanVals=mean(dataMat,axis=0) meanRemoved=dataMat-meanVals covMat=cov(meanRemoved,rowvar=0) eigVals,eigVets=linalg.eig(mat(covMat)) eigValInd=argsort(eigVals) eigValInd=eigValInd[:-(topNfeat+1):-1] redEigVects=eigVets[:,eigValInd] print meanRemoved print redEigVects lowDDatMat=meanRemoved*redEigVects reconMat=(lowDDatMat*redEigVects.T)+meanVals return lowDDatMat,reconMatdataMat=loadDataSet(‘testSet.txt‘)lowDMat,reconMat=pca(dataMat,1)def plotPCA(dataMat,reconMat): import matplotlib import matplotlib.pyplot as plt datArr=array(dataMat) reconArr=array(reconMat) n1=shape(datArr)[0] n2=shape(reconArr)[0] xcord1=[];ycord1=[] xcord2=[];ycord2=[] for i in range(n1): xcord1.append(datArr[i,0]);ycord1.append(datArr[i,1]) for i in range(n2): xcord2.append(reconArr[i,0]);ycord2.append(reconArr[i,1]) fig=plt.figure() ax=fig.add_subplot(111) ax.scatter(xcord1,ycord1,s=90,c=‘red‘,marker=‘^‘) ax.scatter(xcord2,ycord2,s=50,c=‘yellow‘,marker=‘o‘) plt.title(‘PCA‘) plt.show()plotPCA(dataMat,reconMat)
最後的降維結果
主成分分析法原理及其python實現