一步步教你輕鬆學主成分分析PCA降維算法

一步步教你輕鬆學主成分分析PCA降維算法

白寧超 2018年10月22日10:14:18)html

摘要:主成分分析(英語:Principal components analysis,PCA)是一種分析、簡化數據集的技術。主成分分析常常用於減小數據集的維數,同時保持數據集中的對方差貢獻最大的特徵。經常應用在文本處理、人臉識別、圖片識別、天然語言處理等領域。能夠作在數據預處理階段很是重要的一環,本文首先對基本概念進行介紹,而後給出PCA算法思想、流程、優缺點等等。最後經過一個綜合案例去實現應用。(本文原創,轉載必須註明出處.)python

目錄

機器學習:一步步教你輕鬆學KNN模型算法

機器學習:一步步教你輕鬆學決策樹算法

機器學習:一步步教你輕鬆學樸素貝葉斯模型算法理論篇1 

機器學習:一步步教你輕鬆學樸素貝葉斯模型實現篇2 

機器學習:一步步教你輕鬆學樸素貝葉斯模型算法Sklearn深度篇3

機器學習:一步步教你輕鬆學邏輯迴歸模型算法

機器學習:一步步教你輕鬆學K-means聚類算法

機器學習:一步步教你輕鬆學關聯規則Apriori算法

機器學習: 一步步教你輕鬆學支持向量機SVM算法之理論篇1

10 機器學習: 一步步教你輕鬆學支持向量機SVM算法之案例篇2

11 機器學習: 一步步教你輕鬆學主成分分析PCA降維算法

12 機器學習: 一步步教你輕鬆學支持向量機SVM降維算法

更多文章請點擊這裏>>

數據降維

預備知識

  • 均值
  • 方差
  • 標準差
  • 協方差
  • 正交矩陣

什麼是降維

降維是對數據高維度特徵的一種預處理方法。降維是將高維度的數據保留下最重要的一些特徵,去除噪聲和不重要的特徵,從而實現提高數據處理速度的目的。在實際的生產和應用中,降維在必定的信息損失範圍內,能夠爲咱們節省大量的時間和成本。降維也成爲了應用很是普遍的數據預處理方法。git

咱們正經過電視觀看體育比賽,在電視的顯示器上有一個足球。顯示器大概包含了100萬像素點,而球則多是由較少的像素點組成,例如說一千個像素點。人們實時的將顯示器上的百萬像素轉換成爲一個三維圖像,該圖像就給出運動場上球的位置。在這個過程當中,人們已經將百萬像素點的數據,降至爲三維。這個過程就稱爲降維(dimensionality reduction)github

數據降維的目的:算法

  • 使得數據集更容易使用
  • 確保這些變量是相互獨立的
  • 下降不少算法的計算開銷
  • 去除噪音
  • 使得結果易懂

適用範圍:api

  • 在已標註與未標註的數據上都有降維技術。
  • 本文主要關注未標註數據上的降維技術,將技術一樣也能夠應用於已標註的數據。

常見降維技術(PCA的應用目前最爲普遍)數組

  • 主成分分析就是找出一個最主要的特徵,而後進行分析。例如: 考察一我的的智力狀況,就直接看數學成績就行(數學、語文、英語成績)
  • 因子分析(Factor Analysis),將多個實測變量轉換爲少數幾個綜合指標。它反映一種降維的思想,經過降維將相關性高的變量聚在一塊兒,從而減小須要分析的變量的數量,而減小問題分析的複雜性.例如: 考察一我的的總體狀況,就直接組合3樣成績(隱變量),看平均成績就行(存在:數學、語文、英語成績),應用的領域包括社會科學、金融等。在因子分析中,
    • 假設觀察數據的成分中有一些觀察不到的隱變量(latent variable)。
    • 假設觀察數據是這些隱變量和某些噪音的線性組合。
    • 那麼隱變量的數據可能比觀察數據的數目少,也就說經過找到隱變量就能夠實現數據的降維。
  • 獨立成分分析(Independ Component Analysis, ICA),ICA 認爲觀測信號是若干個獨立信號的線性組合,ICA 要作的是一個解混過程。
    • 例如:咱們去ktv唱歌,想辨別唱的是什麼歌曲?ICA 是觀察發現是原唱唱的一首歌【2個獨立的聲音(原唱/主唱)】。
    • ICA 是假設數據是從 N 個數據源混合組成的,這一點和因子分析有些相似,這些數據源之間在統計上是相互獨立的,而在 PCA 中只假設數據是不 相關(線性關係)的。同因子分析同樣,若是數據源的數目少於觀察數據的數目,則能夠實現降維過程。

PCA 概述

主成分分析(Principal Component Analysis, PCA):通俗理解:就是找出一個最主要的特徵,而後進行分析。機器學習

主成分分析(英語:Principal components analysis,PCA)是一種分析、簡化數據集的技術。主成分分析常常用於減小數據集的維數,同時保持數據集中的對方差貢獻最大的特徵。這是經過保留低階主成分,忽略高階主成分作到的。這樣低階成分每每可以保留住數據的最重要方面。可是,這也不是必定的,要視具體應用而定。因爲主成分分析依賴所給數據,因此數據的準確性對分析結果影響很大。函數

主成分分析由卡爾·皮爾遜於1901年發明,用於分析數據及創建數理模型。其方法主要是經過對協方差矩陣進行特徵分解,以得出數據的主成分(即特徵向量)與它們的權值(即特徵值)。PCA是最簡單的以特徵量分析多元統計分佈的方法。其結果能夠理解爲對原數據中的方差作出解釋:哪個方向上的數據值對方差的影響最大?換而言之,PCA提供了一種下降數據維度的有效辦法;若是分析者在原數據中除掉最小的特徵值所對應的成分,那麼所得的低維度數據一定是最優化的(也即,這樣下降維度一定是失去訊息最少的方法)。主成分分析在分析複雜數據時尤其有用,好比人臉識別。oop

PCA是最簡單的以特徵量分析多元統計分佈的方法。一般狀況下,這種運算能夠被看做是揭露數據的內部結構,從而更好的解釋數據的變量的方法。若是一個多元數據集可以在一個高維數據空間座標系中被顯現出來,那麼PCA就可以提供一幅比較低維度的圖像,這幅圖像即爲在訊息最多的點上原對象的一個‘投影’。這樣就能夠利用少許的主成分使得數據的維度下降了。PCA跟因子分析密切相關,而且已經有不少混合這兩種分析的統計包。而真實要素分析則是假定底層結構,求得微小差別矩陣的特徵向量。

PCA 場景

例如: 考察一我的的智力狀況,就直接看數學成績就行(存在:數學、語文、英語成績)

PCA 思想

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

PCA 原理

  1. 找出第一個主成分的方向,也就是數據方差最大的方向。
  2. 找出第二個主成分的方向,也就是數據方差次大的方向,而且該方向與第一個主成分方向正交(orthogonal 若是是二維空間就叫垂直)。
  3. 經過這種方式計算出全部的主成分方向。
  4. 經過數據集的協方差矩陣及其特徵值分析,咱們就能夠獲得這些主成分的值。
  5. 一旦獲得了協方差矩陣的特徵值和特徵向量,咱們就能夠保留最大的 N 個特徵。這些特徵向量也給出了 N 個最重要特徵的真實結構,咱們就能夠經過將數據乘上這 N 個特徵向量 從而將它轉換到新的空間上。

PCA 算法流程

下面咱們看看具體的算法流程。

輸入:n維樣本集\( D=(x^{(1)},x^{(2)},...,x^{(m)}) \),要降維到的維數n.
輸出:降維後的樣本集\( D^′\)
1) 對全部的樣本進行中心化:\( x^{(i)}=x^{(i)}−\frac{1}{m}\sum_{j=1}^{m}x^{(j)} \)
2) 計算樣本的協方差矩陣\( XX^T\)
3) 對矩陣\( XX^T\)進行特徵值分解
4)取出最大的n'個特徵值對應的特徵向量\( (w_1,w_2,...,w_n^′) \), 將全部的特徵向量標準化後,組成特徵向量矩陣W。
5)對樣本集中的每個樣本\( x^{(i)}\),轉化爲新的樣本\( z^{(i)}=W^Tx^{(i)} \)
6) 獲得輸出樣本集\( D^′=(z^{(1)},z^{(2)},...,z^{(m)}) \)

PCA 優缺點

優勢:下降數據的複雜性,識別最重要的多個特徵。
缺點:不必定須要,且可能損失有用信息。
適用數據類型:數值型數據。

實例理解

真實的訓練數據老是存在各類各樣的問題:

  1. 好比拿到一個汽車的樣本,裏面既有以「公里/每小時」度量的最大速度特徵,也有「英里/小時」的最大速度特徵,顯然這兩個特徵有一個多餘。
  2. 拿到一個數學系的本科生期末考試成績單,裏面有三列,一列是對數學的興趣程度,一列是複習時間,還有一列是考試成績。咱們知道要學好數學,須要有濃厚的興趣,因此第二項與第一項強相關,第三項和第二項也是強相關。那是否是能夠合併第一項和第二項呢?
  3. 拿到一個樣本,特徵很是多,而樣例特別少,這樣用迴歸去直接擬合很是困難,容易過分擬合。好比北京的房價:假設房子的特徵是(大小、位置、朝向、是否學區房、建造年代、是否二手、層數、所在層數),搞了這麼多特徵,結果只有不到十個房子的樣例。要擬合房子特徵->房價的這麼多特徵,就會形成過分擬合。
  4. 這個與第二個有點相似,假設在IR中咱們創建的文檔-詞項矩陣中,有兩個詞項爲「learn」和「study」,在傳統的向量空間模型中,認爲二者獨立。然而從語義的角度來說,二者是類似的,並且二者出現頻率也相似,是否是能夠合成爲一個特徵呢?
  5. 在信號傳輸過程當中,因爲信道不是理想的,信道另外一端收到的信號會有噪音擾動,那麼怎麼濾去這些噪音呢?

這時能夠採用主成分分析(PCA)的方法來解決部分上述問題。PCA的思想是將n維特徵映射到k維上(k<n),這k維是全新的正交特徵。這k維特徵稱爲主元,是從新構造出來的k維特徵,而不是簡單地從n維特徵中去除其他n-k維特徵。

PCA 算法實現

準備數據

收集數據:提供文本文件,文件名:testSet.txt.文本文件部分數據格式以下:

10.235186    11.321997
10.122339    11.810993
9.190236    8.904943
9.306371    9.847394
8.330131    8.340352
10.152785    10.123532
10.408540    10.821986
9.003615    10.039206
9.534872    10.096991
9.498181    10.825446
9.875271    9.233426
10.362276    9.376892
10.191204    11.250851

數據集處理代碼實現以下

'''加載數據集'''
def loadDataSet(fileName, delim='\t'):
    fr = open(fileName)
    stringArr = [line.strip().split(delim) for line in fr.readlines()]
    datArr = [list(map(float, line)) for line in stringArr]
    #注意這裏和python2的區別,須要在map函數外加一個list(),不然顯示結果爲 map at 0x3fed1d0
    return mat(datArr)

PCA 數據降維

在等式 Av=λv 中,v 是特徵向量, λ 是特徵值。表示 若是特徵向量 v 被某個矩陣 A 左乘,那麼它就等於某個標量 λ 乘以 v.
幸運的是: Numpy 中有尋找特徵向量和特徵值的模塊 linalg,它有 eig() 方法,該方法用於求解特徵向量和特徵值。具體代碼實現以下:

  • 方差:(一維)度量兩個隨機變量關係的統計量,數據離散程度,方差越小越穩定
  • 協方差: (二維)度量各個維度偏離其均值的程度
  • 協方差矩陣:(多維)度量各個維度偏離其均值的程度
    • 當 cov(X, Y)>0時,代表X與Y正相關(X越大,Y也越大;X越小Y,也越小。)
    • 當 cov(X, Y)<0時,代表X與Y負相關;
    • 當 cov(X, Y)=0時,代表X與Y不相關。
'''pca算法
    cov協方差=[(x1-x均值)*(y1-y均值)+(x2-x均值)*(y2-y均值)+...+(xn-x均值)*(yn-y均值)]/(n-1)
    Args:
        dataMat   原數據集矩陣
        topNfeat  應用的N個特徵
    Returns:
        lowDDataMat  降維後數據集
        reconMat     新的數據集空間
'''
def pca(dataMat, topNfeat=9999999):
    # 計算每一列的均值
    meanVals = mean(dataMat, axis=0)
    # print('meanVals', meanVals)
    # 每一個向量同時都減去均值
    meanRemoved = dataMat - meanVals
    # print('meanRemoved=', meanRemoved)
    # rowvar=0,傳入的數據一行表明一個樣本,若非0,傳入的數據一列表明一個樣本
    covMat = cov(meanRemoved, rowvar=0)
    # eigVals爲特徵值, eigVects爲特徵向量
    eigVals, eigVects = linalg.eig(mat(covMat))
    # print('eigVals=', eigVals)
    # print('eigVects=', eigVects)

    # 對特徵值,進行從小到大的排序,返回從小到大的index序號
    # 特徵值的逆序就能夠獲得topNfeat個最大的特徵向量
    eigValInd = argsort(eigVals)
    # print('eigValInd1=', eigValInd)
    # -1表示倒序,返回topN的特徵值[-1到-(topNfeat+1)不包括-(topNfeat+1)]
    eigValInd = eigValInd[:-(topNfeat+1):-1]
    # print('eigValInd2=', eigValInd)
    # 重組 eigVects 最大到最小
    redEigVects = eigVects[:, eigValInd]
    # print('redEigVects=', redEigVects.T)

    # 將數據轉換到新空間
    # print( "---", shape(meanRemoved), shape(redEigVects))
    lowDDataMat = meanRemoved * redEigVects
    reconMat = (lowDDataMat * redEigVects.T) + meanVals
    # print('lowDDataMat=', lowDDataMat)
    # print('reconMat=', reconMat)
    return lowDDataMat, reconMat

可視化結果分析

接下來咱們查看降維後的數據與原始數據可視化效果,咱們將原始數據採用綠色△表示,降維後的數據採用紅色○表示。可視化代碼以下:

'''降維後的數據和原始數據可視化'''
def show_picture(dataMat, reconMat):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(dataMat[:, 0].flatten().A[0], dataMat[:, 1].flatten().A[0], marker='^', s=90,c='green')
    ax.scatter(reconMat[:, 0].flatten().A[0], reconMat[:, 1].flatten().A[0], marker='o', s=50, c='red')
    plt.show()

調用代碼:

# 2 主成分分析降維特徵向量設置
    lowDmat, reconMat = pca(dataMat, 1)
    print(shape(lowDmat))
    # 3 將降維後的數據和原始數據一塊兒可視化
    show_picture(dataMat, reconMat)

運行結果顯示:

PCA對半導體制造數據降維

項目概述

半導體是在一些極爲先進的工廠中製造出來的。設備的生命早期有限,而且花費極其巨大。雖然經過早期測試和頻繁測試來發現有瑕疵的產品,但仍有一些存在瑕疵的產品經過測試。若是咱們經過機器學習技術用於發現瑕疵產品,那麼它就會爲製造商節省大量的資金。具體來說,它擁有590個特徵。咱們看看可否對這些特徵進行降維處理。對於數據的缺失值的問題,將缺失值NaN(Not a Number縮寫),所有用平均值來替代(若是用0來處理的策略就太差了)。收集數據:提供文本文件,文件名:secom.data.文本文件部分數據格式以下:

3030.93 2564 2187.7333 1411.1265 1.3602 100 97.6133 0.1242 1.5005 0.0162
-0.0034 0.9455 202.4396 0 7.9558 414.871 10.0433 0.968 192.3963 12.519 1.4026 
-5419 2916.5 -4043.75 751 0.8955 1.773 3.049 64.2333 2.0222 0.1632 3.5191 
83.3971 9.5126 50.617 64.2588 49.383 66.3141 86.9555 117.5132 61.29 4.515 70 
352.7173 10.1841 130.3691 723.3092 1.3072 141.2282 1 624.3145 218.3174 0 4.592

數據預處理

將數據集中NaN替換成平均值,代碼實現以下:

'''將NaN替換成平均值函數'''
def replaceNanWithMean():
    datMat = loadDataSet('./secom.data', ' ')
    numFeat = shape(datMat)[1]
    for i in range(numFeat):
        # 對value不爲NaN的求均值
        # .A 返回矩陣基於的數組
        meanVal = mean(datMat[nonzero(~isnan(datMat[:, i].A))[0], i])
        # 將value爲NaN的值賦值爲均值
        datMat[nonzero(isnan(datMat[:, i].A))[0],i] = meanVal
    return datMat

分析數據

咱們拿到數據進行數據預處理以後,再跑下程序,看看中間結果若是,分析數據代碼以下:

'''分析數據'''
def analyse_data(dataMat):
    meanVals = mean(dataMat, axis=0)
    meanRemoved = dataMat-meanVals
    covMat = cov(meanRemoved, rowvar=0)
    eigvals, eigVects = linalg.eig(mat(covMat))
    eigValInd = argsort(eigvals)

    topNfeat = 20
    eigValInd = eigValInd[:-(topNfeat+1):-1]
    cov_all_score = float(sum(eigvals))
    sum_cov_score = 0
    for i in range(0, len(eigValInd)):
        line_cov_score = float(eigvals[eigValInd[i]])
        sum_cov_score += line_cov_score
        '''
        咱們發現其中有超過20%的特徵值都是0。
        這就意味着這些特徵都是其餘特徵的副本,也就是說,它們能夠經過其餘特徵來表示,而自己並無提供額外的信息。

        最前面15個值的數量級大於10^5,實際上那之後的值都變得很是小。
        這就至關於告訴咱們只有部分重要特徵,重要特徵的數目也很快就會降低。

        最後,咱們可能會注意到有一些小的負值,他們主要源自數值偏差應該四捨五入成0.
        '''
        print('主成分:%s, 方差佔比:%s%%, 累積方差佔比:%s%%' % (format(i+1, '2.0f'), format(line_cov_score/cov_all_score*100, '4.2f'), format(sum_cov_score/cov_all_score*100, '4.1f')))

去均值化的特徵值結果顯示以下:

[ 5.34151979e+07  2.17466719e+07  8.24837662e+06  2.07388086e+06
  1.31540439e+06  4.67693557e+05  2.90863555e+05  2.83668601e+05
  2.37155830e+05  2.08513836e+05  1.96098849e+05  1.86856549e+05
  1.52422354e+05  1.13215032e+05  1.08493848e+05  1.02849533e+05
  1.00166164e+05  8.33473762e+04  8.15850591e+04  7.76560524e+04
...
  0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
  0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
  0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
  0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
  0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
  0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
  0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
  0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
  0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
]

數據分析結果以下:

主成分: 1, 方差佔比:59.25%, 累積方差佔比:59.3%
主成分: 2, 方差佔比:24.12%, 累積方差佔比:83.4%
主成分: 3, 方差佔比:9.15%, 累積方差佔比:92.5%
主成分: 4, 方差佔比:2.30%, 累積方差佔比:94.8%
主成分: 5, 方差佔比:1.46%, 累積方差佔比:96.3%
主成分: 6, 方差佔比:0.52%, 累積方差佔比:96.8%
主成分: 7, 方差佔比:0.32%, 累積方差佔比:97.1%
主成分: 8, 方差佔比:0.31%, 累積方差佔比:97.4%
主成分: 9, 方差佔比:0.26%, 累積方差佔比:97.7%
主成分:10, 方差佔比:0.23%, 累積方差佔比:97.9%
主成分:11, 方差佔比:0.22%, 累積方差佔比:98.2%
主成分:12, 方差佔比:0.21%, 累積方差佔比:98.4%
主成分:13, 方差佔比:0.17%, 累積方差佔比:98.5%
主成分:14, 方差佔比:0.13%, 累積方差佔比:98.7%
主成分:15, 方差佔比:0.12%, 累積方差佔比:98.8%
主成分:16, 方差佔比:0.11%, 累積方差佔比:98.9%
主成分:17, 方差佔比:0.11%, 累積方差佔比:99.0%
主成分:18, 方差佔比:0.09%, 累積方差佔比:99.1%
主成分:19, 方差佔比:0.09%, 累積方差佔比:99.2%
主成分:20, 方差佔比:0.09%, 累積方差佔比:99.3%

咱們發現其中有超過20%的特徵值都是0。這就意味着這些特徵都是其餘特徵的副本,也就是說,它們能夠經過其餘特徵來表示,而自己並無提供額外的信息。最前面值的數量級大於10^5,實際上那之後的值都變得很是小。這就至關於告訴咱們只有部分重要特徵,重要特徵的數目也很快就會降低。最後,咱們可能會注意到有一些小的負值,他們主要源自數值偏差應該四捨五入成0.

根據實驗結果咱們繪製半導體數據中前七個主要成分所佔的方差百分好比下

主成分 方差百分比(%) 累積方差百分比(%)
1 59.25 59.3
2 24.12 83.4
3 9.15 92.5
4 2.30 94.8
5 1.46 96.3
6 0.52 96.8
7 0.32 97.1
20 0.09 99.3

PCA降維結果可視化

調用咱們上文寫的代碼以下:

lowDmat, reconMat = pca(dataMat, 20)
print(shape(lowDmat))
show_picture(dataMat, reconMat)

運行結果以下:

參考文獻

  1. 主成分分析
  2. 中文維基百科
  3. GitHub
  4. 圖書:《機器學習實戰》
  5. 圖書:《天然語言處理理論與實戰》
  6. 一篇深刻剖析PCA的好文
  7. 主成分分析原理總結

完整代碼下載

源碼請進【機器學習和天然語言QQ羣:436303759】文件下載:天然語言處理和機器學習技術QQ交流

做者聲明

本文版權歸做者全部,旨在技術交流使用。未經做者贊成禁止轉載,轉載後需在文章頁面明顯位置給出原文鏈接,不然相關責任自行承擔。

相關文章
相關標籤/搜索