三種方法實現(xiàn)PCA算法(Python)

??主成分分析斥难,即Principal Component Analysis(PCA)枝嘶,是多元統(tǒng)計中的重要內(nèi)容,也廣泛應用于機器學習和其它領域哑诊。它的主要作用是對高維數(shù)據(jù)進行降維群扶。PCA把原先的n個特征用數(shù)目更少的k個特征取代,新特征是舊特征的線性組合镀裤,這些線性組合最大化樣本方差竞阐,盡量使新的k個特征互不相關(guān)。關(guān)于PCA的更多介紹暑劝,請參考:https://en.wikipedia.org/wiki/Principal_component_analysis.
??PCA的主要算法如下:

  • 組織數(shù)據(jù)形式骆莹,以便于模型使用;
  • 計算樣本每個特征的平均值担猛;
  • 每個樣本數(shù)據(jù)減去該特征的平均值(歸一化處理)幕垦;
  • 求協(xié)方差矩陣;
  • 找到協(xié)方差矩陣的特征值和特征向量毁习;
  • 對特征值和特征向量重新排列(特征值從大到小排列)智嚷;
  • 對特征值求取累計貢獻率;
  • 對累計貢獻率按照某個特定比例纺且,選取特征向量集的字跡合盏道;
  • 對原始數(shù)據(jù)(第三步后)告抄。

??其中協(xié)方差矩陣的分解可以通過按對稱矩陣的特征向量來仅淑,也可以通過分解矩陣的SVD來實現(xiàn)包斑,而在Scikit-learn中逼侦,也是采用SVD來實現(xiàn)PCA算法的靖避。關(guān)于SVD的介紹及其原理绽左,可以參考:矩陣的奇異值分解(SVD)(理論)屯断。
??本文將用三種方法來實現(xiàn)PCA算法昨稼,一種是原始算法步咪,即上面所描述的算法過程论皆,具體的計算方法和過程,可以參考:A tutorial on Principal Components Analysis, Lindsay I Smith. 一種是帶SVD的原始算法,在Python的Numpy模塊中已經(jīng)實現(xiàn)了SVD算法点晴,并且將特征值從大從小排列感凤,省去了對特征值和特征向量重新排列這一步。最后一種方法是用Python的Scikit-learn模塊實現(xiàn)的PCA類直接進行計算粒督,來驗證前面兩種方法的正確性陪竿。
??用以上三種方法來實現(xiàn)PCA的完整的Python如下:

import numpy as np
from sklearn.decomposition import PCA
import sys
#returns choosing how many main factors
def index_lst(lst, component=0, rate=0):
    #component: numbers of main factors
    #rate: rate of sum(main factors)/sum(all factors)
    #rate range suggest: (0.8,1)
    #if you choose rate parameter, return index = 0 or less than len(lst)
    if component and rate:
        print('Component and rate must choose only one!')
        sys.exit(0)
    if not component and not rate:
        print('Invalid parameter for numbers of components!')
        sys.exit(0)
    elif component:
        print('Choosing by component, components are %s......'%component)
        return component
    else:
        print('Choosing by rate, rate is %s ......'%rate)
        for i in range(1, len(lst)):
            if sum(lst[:i])/sum(lst) >= rate:
                return i
        return 0

def main():
    # test data
    mat = [[-1,-1,0,2,1],[2,0,0,-1,-1],[2,0,1,1,0]]
    
    # simple transform of test data
    Mat = np.array(mat, dtype='float64')
    print('Before PCA transforMation, data is:\n', Mat)
    print('\nMethod 1: PCA by original algorithm:')
    p,n = np.shape(Mat) # shape of Mat 
    t = np.mean(Mat, 0) # mean of each column
    
    # substract the mean of each column
    for i in range(p):
        for j in range(n):
            Mat[i,j] = float(Mat[i,j]-t[j])
            
    # covariance Matrix
    cov_Mat = np.dot(Mat.T, Mat)/(p-1)
    
    # PCA by original algorithm
    # eigvalues and eigenvectors of covariance Matrix with eigvalues descending
    U,V = np.linalg.eigh(cov_Mat) 
    # Rearrange the eigenvectors and eigenvalues
    U = U[::-1]
    for i in range(n):
        V[i,:] = V[i,:][::-1]
    # choose eigenvalue by component or rate, not both of them euqal to 0
    Index = index_lst(U, component=2)  # choose how many main factors
    if Index:
        v = V[:,:Index]  # subset of Unitary matrix
    else:  # improper rate choice may return Index=0
        print('Invalid rate choice.\nPlease adjust the rate.')
        print('Rate distribute follows:')
        print([sum(U[:i])/sum(U) for i in range(1, len(U)+1)])
        sys.exit(0)
    # data transformation
    T1 = np.dot(Mat, v)
    # print the transformed data
    print('We choose %d main factors.'%Index)
    print('After PCA transformation, data becomes:\n',T1)
    
    # PCA by original algorithm using SVD
    print('\nMethod 2: PCA by original algorithm using SVD:')
    # u: Unitary matrix,  eigenvectors in columns 
    # d: list of the singular values, sorted in descending order
    u,d,v = np.linalg.svd(cov_Mat)
    Index = index_lst(d, rate=0.95)  # choose how many main factors
    T2 = np.dot(Mat, u[:,:Index])  # transformed data
    print('We choose %d main factors.'%Index)
    print('After PCA transformation, data becomes:\n',T2)
    
    # PCA by Scikit-learn
    pca = PCA(n_components=2) # n_components can be integer or float in (0,1)
    pca.fit(mat)  # fit the model
    print('\nMethod 3: PCA by Scikit-learn:')
    print('After PCA transformation, data becomes:')
    print(pca.fit_transform(mat))  # transformed data
            
main()

運行以上代碼,輸出結(jié)果為:

Eclipse運行結(jié)果

??這說明用以上三種方法來實現(xiàn)PCA都是可行的屠橄。這樣我們就能理解PCA的具體實現(xiàn)過程啦~~
??有興趣的讀者可以用其它語言實現(xiàn)一下哈族跛。


參考文獻:

  1. PCA 維基百科: https://en.wikipedia.org/wiki/Principal_component_analysis.
  2. 講解詳細又全面的PCA教程: A tutorial on Principal Components Analysis, Lindsay I Smith.
  3. 博客:矩陣的奇異值分解(SVD)(理論):http://www.cnblogs.com/jclian91/p/8022426.html.
  4. 博客:主成分分析PCA: https://www.cnblogs.com/zhangchaoyang/articles/2222048.html.
  5. Scikit-learn的PCA介紹:http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html.
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市锐墙,隨后出現(xiàn)的幾起案子礁哄,更是在濱河造成了極大的恐慌,老刑警劉巖贮匕,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姐仅,死亡現(xiàn)場離奇詭異,居然都是意外死亡刻盐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門劳翰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敦锌,“玉大人,你說我怎么就攤上這事佳簸∫仪剑” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵生均,是天一觀的道長听想。 經(jīng)常有香客問我,道長马胧,這世上最難降的妖魔是什么汉买? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮佩脊,結(jié)果婚禮上蛙粘,老公的妹妹穿的比我還像新娘。我一直安慰自己威彰,他們只是感情好出牧,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著歇盼,像睡著了一般舔痕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天伯复,我揣著相機與錄音盈咳,去河邊找鬼。 笑死边翼,一個胖子當著我的面吹牛鱼响,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播组底,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼丈积,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了债鸡?” 一聲冷哼從身側(cè)響起江滨,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎厌均,沒想到半個月后唬滑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡棺弊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年晶密,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片模她。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡稻艰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出侈净,到底是詐尸還是另有隱情尊勿,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布畜侦,位于F島的核電站元扔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏旋膳。R本人自食惡果不足惜澎语,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望溺忧。 院中可真熱鬧咏连,春花似錦、人聲如沸鲁森。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽歌溉。三九已至垄懂,卻和暖如春骑晶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背草慧。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工桶蛔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人漫谷。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓仔雷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舔示。 傳聞我的和親對象是個殘疾皇子碟婆,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容