1 引子
我看到了我的愛戀
我飛到她的身邊
我捧出給她的禮物
那是一小塊凝固的時(shí)間
時(shí)間上有美麗的條紋
摸出來像淺海的泥一樣柔軟
她把時(shí)間涂滿全身
然后拉起我飛向存在的邊緣
這是靈態(tài)的飛行
我們眼中的星星像幽靈
星星眼中的我們也像幽靈
——《三體-死神永生》
讀過《三體》的人應(yīng)該都對(duì)這首歌謠印象深刻,在地球文明還在大力建造各種掩體各種戰(zhàn)艦以期抵抗外星文明時(shí),宇宙中的一個(gè)名為歌者文明的小清理員哼唱者這首歌謠,向太陽系隨手丟出了一張二向箔,便對(duì)整個(gè)太陽系實(shí)施了降唯打擊,于是,整個(gè)太陽系跌落成了一幅二維巨畫。
今天,我們不是來講《三體》的,我們要講的是數(shù)據(jù)科學(xué)領(lǐng)域中的主成分分析法,什么是主成分分析法呢,它又是用來做什么的呢?其實(shí),主成分分析法就是數(shù)據(jù)科學(xué)界的二向箔,它的主要作用就是數(shù)據(jù)降維。
2 主成分分析法的用途和原理
主成分分析法的全稱是principal component analysis,簡稱PCA,是一種數(shù)學(xué)變換的方法, 它把給定的一組相關(guān)變量通過線性變換轉(zhuǎn)成另一組不相關(guān)的變量,這些新的變量按照方差依次遞減的順序排列。在數(shù)學(xué)變換中保持變量的總方差不變,使第一變量具有最大的方差,稱為第一主成分,第二變量的方差次大,并且和第一變量不相關(guān),稱為第二主成分。依次類推,I個(gè)變量就有I個(gè)主成分。
進(jìn)行主成分分析后,還可以根據(jù)需要進(jìn)一步利用K-L變換(霍特林變換)對(duì)原數(shù)據(jù)進(jìn)行投影變換,達(dá)到降維的目的。
——《百度百科》
以上是百度百科對(duì)PCA的簡介說明,PCA是Pearson在1901年提出的,再后來由hotelling在1933年加以發(fā)展提出的一種多變量的統(tǒng)計(jì)方法,目前已經(jīng)被廣泛應(yīng)用于機(jī)器學(xué)習(xí)領(lǐng)域。PCA最主要的用途在于“數(shù)據(jù)降維”,它既可以通過析取主成分顯出的最大的個(gè)別差異,也可以用來削減回歸分析和聚類分析中變量的數(shù)目.
舉個(gè)例子,假如你要對(duì)某銀行的貸款用戶進(jìn)行分析,通過建立邏輯回歸模型預(yù)測用戶是否會(huì)按時(shí)還款,銀行給我們提供了包括用戶性別、年齡、婚姻狀況、工齡、銀行流水記錄、信用卡賬單記錄、申貸金額、申請時(shí)間、放款時(shí)間等近20項(xiàng)指標(biāo),你可能覺著每項(xiàng)指標(biāo)都很重要,可是如果同時(shí)對(duì)這近20個(gè)指標(biāo)進(jìn)行分析,又會(huì)過于繁瑣,僅數(shù)據(jù)建模前的數(shù)據(jù)清理和數(shù)據(jù)轉(zhuǎn)換就要花費(fèi)很長時(shí)間,這個(gè)時(shí)間可能已經(jīng)遠(yuǎn)超過了工作預(yù)期,這個(gè)時(shí)候你就可以采用主成分分析的方法對(duì)這20多個(gè)數(shù)據(jù)指標(biāo)進(jìn)行降維了。
通過主成分分析,我們可以根據(jù)這些指標(biāo)間的相互關(guān)系將近20個(gè)分析指標(biāo)降唯為5~6個(gè)主成分指標(biāo),甚至更少,這些主成分指標(biāo)既涵蓋了所有指標(biāo)中的絕大部分信息,又讓你的分析得到了簡化。通過主成分分析,我們簡化了數(shù)據(jù)分析過程上的數(shù)據(jù)轉(zhuǎn)換過程、增加了結(jié)果精度,又保證了數(shù)據(jù)分析報(bào)告的按時(shí)完成。
關(guān)于PCA的數(shù)學(xué)原理及推導(dǎo)過程,我們不在這里贅述,感興趣的可以自行去查閱相關(guān)的文獻(xiàn)資料,PCA原理簡單而言,即線性變換,在數(shù)據(jù)分析的應(yīng)用層面上,就是將具有一定相關(guān)性的多個(gè)指標(biāo)簡化為一組線性不相關(guān)的綜合主成分指標(biāo),轉(zhuǎn)換后的這些主成分指標(biāo)方差最大的為第一主成分。
上圖是主成分分析法的簡單圖解,圖中的點(diǎn)集是由一些二維變量構(gòu)成,假如我們想把這些二維變量降為一維,理想情況下這個(gè)一維變量應(yīng)該最大限度的包含原始二維變量的信息。一般而言,變量方差越大,變量的差異越大,所含的信息就越多,從這個(gè)角度出發(fā),我們應(yīng)該選擇Y1方向,因?yàn)閅1方向的方差最大,離散程度最大,包含的信息量越大。
3 主成分分析法的實(shí)現(xiàn)
以下是主成分分析法的計(jì)算流程:
-
1 數(shù)據(jù)標(biāo)準(zhǔn)化/歸一化
以下是數(shù)據(jù)標(biāo)準(zhǔn)化/歸一化的常用的兩種方法,具體使用方法和使用場景這里不做贅述。- min-max標(biāo)準(zhǔn)化
- Z-score標(biāo)準(zhǔn)化方法
-
2 計(jì)算協(xié)方差矩陣
協(xié)方差矩陣計(jì)算公式 3 計(jì)算協(xié)方差矩陣的特征值和特征向量
4 將特征值排序
5 保留前N個(gè)最大的特征值對(duì)應(yīng)的特征向量
6 將數(shù)據(jù)轉(zhuǎn)換到上面得到的N個(gè)特征向量構(gòu)建的新空間中(實(shí)現(xiàn)特征壓縮)
了解了算法之后我們可以結(jié)合自己掌握的編程語言如python , R, Java等一步步實(shí)現(xiàn)PCA算法,下面是通過python實(shí)現(xiàn)的PCA代碼示例:
def pca(dataMat, topNfeat=9999999):
"""pca
Args:
dataMat 原數(shù)據(jù)集矩陣
topNfeat 應(yīng)用的N個(gè)特征
Returns:
lowDDataMat 降維后數(shù)據(jù)集
reconMat 新的數(shù)據(jù)集空間
"""
# 數(shù)據(jù)標(biāo)準(zhǔn)化/歸一化,這里未對(duì)數(shù)據(jù)歸一化,只是取了平均值,實(shí)際應(yīng)用時(shí)根據(jù)業(yè)務(wù)數(shù)據(jù)進(jìn)行數(shù)據(jù)歸一化
meanVals = mean(dataMat, axis=0)
meanRemoved = dataMat - meanVals
# cov協(xié)方差=[(x1-x均值)*(y1-y均值)+(x2-x均值)*(y2-y均值)+...+(xn-x均值)*(yn-y均值)+]/(n-1)
'''
方差:(一維)度量兩個(gè)隨機(jī)變量關(guān)系的統(tǒng)計(jì)量
協(xié)方差: (二維)度量各個(gè)維度偏離其均值的程度
協(xié)方差矩陣:(多維)度量各個(gè)維度偏離其均值的程度
當(dāng) cov(X, Y)>0時(shí),表明X與Y正相關(guān);(X越大,Y也越大;X越小Y,也越小。這種情況,我們稱為“正相關(guān)”。)
當(dāng) cov(X, Y)<0時(shí),表明X與Y負(fù)相關(guān);
當(dāng) cov(X, Y)=0時(shí),表明X與Y不相關(guān)。
'''
covMat = cov(meanRemoved, rowvar=0)
# eigVals為特征值, eigVects為特征向量
eigVals, eigVects = linalg.eig(mat(covMat))
# print 'eigVals=', eigVals
# print 'eigVects=', eigVects
# 對(duì)特征值,進(jìn)行從小到大的排序,返回從小到大的index序號(hào)
# 特征值的逆序就可以得到topNfeat個(gè)最大的特征向量
'''
>>> x = np.array([3, 1, 2])
>>> np.argsort(x)
array([1, 2, 0]) # index,1 = 1; index,2 = 2; index,0 = 3
>>> y = np.argsort(x)
>>> y[::-1]
array([0, 2, 1])
>>> y[:-3:-1]
array([0, 2]) # 取出 -1, -2
>>> y[:-6:-1]
array([0, 2, 1])
'''
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
# 將數(shù)據(jù)轉(zhuǎn)換到新空間
# print "---", shape(meanRemoved), shape(redEigVects)
lowDDataMat = meanRemoved * redEigVects
reconMat = (lowDDataMat * redEigVects.T) + meanVals
# print 'lowDDataMat=', lowDDataMat
# print 'reconMat=', reconMat
return lowDDataMat, reconMat
在機(jī)器學(xué)習(xí)領(lǐng)域目前已經(jīng)有一部分相當(dāng)成熟和完善的機(jī)器學(xué)習(xí)算法庫,如sklearn、tensorflow等,這些算法庫里也幾乎都集成了PCA算法,實(shí)際在應(yīng)用時(shí),直接從這些算法庫里調(diào)用就可以了。下面是使用sklearn中PCA算法的例子,可以發(fā)現(xiàn),相比手動(dòng)寫代碼實(shí)現(xiàn)要方便快捷很多。
import numpy as np
from sklearn.decomposition import PCA
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
'''創(chuàng)建一個(gè)PCA對(duì)象,其中參數(shù)n_components表示保留的特征數(shù),
這里默認(rèn)保存2個(gè),如果設(shè)置成‘mle’,那么會(huì)自動(dòng)確定保留的特征數(shù)'''
pca = PCA(n_components=2)
pca.fit(X)
print(pca.explained_variance_ratio_)
關(guān)于PCA算法,今天就講解到這里,請繼續(xù)關(guān)注數(shù)喆數(shù)據(jù),后續(xù)我們會(huì)繼續(xù)以具體的數(shù)據(jù)為例,和大家一起學(xué)習(xí)探索PCA算法的深入使用。