【火炉炼AI】机器学习053-数据降维绝招-PCA和核PCA
【火爐煉AI】機(jī)器學(xué)習(xí)053-數(shù)據(jù)降維絕招-PCA和核PCA
(本文所使用的Python庫(kù)和版本號(hào): Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )
主成分分析(Principal Component Analysis, PCA)可以說(shuō)是數(shù)據(jù)降維的絕招,不僅在人口統(tǒng)計(jì)學(xué),數(shù)量地理學(xué),分子動(dòng)力學(xué)模擬,數(shù)學(xué)建模等領(lǐng)域有著重要的應(yīng)用,而且在機(jī)器學(xué)習(xí)領(lǐng)域,PCA也是非常常用的一種數(shù)據(jù)降維方法。
首先來(lái)理解什么叫數(shù)據(jù)降維:假設(shè)有一個(gè)項(xiàng)目,要從外觀上來(lái)判斷某個(gè)人是男人還是女人,我們可以提取各種各樣的特征,比如身高,一般而言,男人的身高要比女人高,但也有特例,比如頭發(fā)長(zhǎng)度,有無(wú)胡須,臉型,衣服顏色,身材,體重,膚色,BMI指標(biāo)。。。。等等,如果有需要,你可以為這個(gè)項(xiàng)目提取幾百甚至幾千個(gè)特征,假如你一口氣提取了200個(gè)特征,每一個(gè)特征都反映了一個(gè)人的某一個(gè)方面的信息,那么,用機(jī)器學(xué)習(xí)的方法對(duì)這200個(gè)特征進(jìn)行建模,并用訓(xùn)練集來(lái)訓(xùn)練,則會(huì)非常耗時(shí),而且得到的模型結(jié)構(gòu)龐大,故而我們需要減少特征數(shù)量,但是我們不希望減少特征數(shù)量的同時(shí)把重要的信息給弄丟了。將特征數(shù)量從幾百上千降低到幾十的過(guò)程就是數(shù)據(jù)降維。
在上面這個(gè)項(xiàng)目中,有很多特征之間是由關(guān)聯(lián)的,比如BMI指標(biāo)就是身高/體重的平方,那么很明顯,BMI指標(biāo)一個(gè)特征就包括了身高和體重兩個(gè)特征,BMI和這兩個(gè)指標(biāo)之間具有非常強(qiáng)的相關(guān)性。同理,200個(gè)特征之間也可能有很多變量之間具有相關(guān)性,所以這些相關(guān)特征之間所反映的信息是一樣的,PCA的作用就是對(duì)所有的這200個(gè)特征,去除相關(guān)性非常強(qiáng)的特征,建立盡可能少的新特征,使得這些新特征之間是兩兩不相關(guān),并且這些新特征在反應(yīng)項(xiàng)目的信息方面會(huì)盡可能保持原有的信息。
關(guān)于PCA的理論推導(dǎo)和更深層次的數(shù)學(xué)邏輯,請(qǐng)參考博文PCA算法
1. 用PCA對(duì)數(shù)據(jù)集降維
為了看到降維效果,此處我們用隨機(jī)數(shù)自動(dòng)生成一個(gè)數(shù)據(jù)集,前兩個(gè)特征向量都是隨機(jī)數(shù),后三個(gè)特征向量是前兩個(gè)特征計(jì)算組合而來(lái)。如下為代碼
# 假如某個(gè)項(xiàng)目有5個(gè)特征,這五個(gè)特征分別為: f1=np.random.normal(size=250) f2=np.random.normal(size=250) # 后面的三個(gè)特征是前面兩個(gè)特征演變而來(lái),即與前面兩特征具有很強(qiáng)的相關(guān)性 f3=2*f1+3*f2 f4=4*f1-f2 f5=f3+2*f4很多時(shí)候,我們要查看數(shù)據(jù)集中各特征向量之間的相關(guān)性,如下
# 將這些特征組合成數(shù)據(jù)集 dataset_X=np.c_[f1,f2,f3,f4,f5] # 計(jì)算各特征列之間的相關(guān)系數(shù) df=pd.DataFrame(dataset_X,columns=['f1','f2','f3','f4','f5']) print(df.corr())-------------------------------------輸---------出--------------------------------
f1 f2 f3 f4 f5f1 1.000000 -0.002496 0.528931 0.966354 0.994370
f2 -0.002496 1.000000 0.847342 -0.259627 0.103485
f3 0.528931 0.847342 1.000000 0.292844 0.615884
f4 0.966354 -0.259627 0.292844 1.000000 0.933656
f5 0.994370 0.103485 0.615884 0.933656 1.000000
--------------------------------------------完-------------------------------------
可以明顯看出,數(shù)據(jù)集中有很多特征之間具有比較強(qiáng)的相關(guān)性,比如f1-f5,f1-f4等。
所以我們可以用PCA來(lái)進(jìn)行降維:
# 可以看出f1-f5,f1-f4,f2-f3等之間具有強(qiáng)相關(guān)性,故而可以用PCA降維 from sklearn import decomposition pca=decomposition.PCA() pca.fit(dataset_X) # 用PCA降維 # 打印降維后的新特征 variances=pca.explained_variance_ print(variances) # 可以理解成該特征的重要性,后面三個(gè)數(shù)字非常小,即特征不重要-------------------------------------輸---------出--------------------------------
[1.15552796e+02 1.14453854e+01 3.08872295e-31 8.39043564e-32
1.18268234e-32]
--------------------------------------------完-------------------------------------
# 故而可以為重要性設(shè)置一個(gè)閾值,小于該閾值的認(rèn)為該特征不重要,可刪除 thresh=0.8 useful_features=variances>thresh print(useful_features) # 標(biāo)記為T(mén)rue的表示重要特征,要保留,False則刪除-------------------------------------輸---------出--------------------------------
[ True True False False False]
--------------------------------------------完-------------------------------------
一旦我們通過(guò)PCA進(jìn)行了降維,就需要將原來(lái)的高維數(shù)據(jù)集轉(zhuǎn)換為低維數(shù)據(jù)集,然后用低維數(shù)據(jù)集來(lái)建模
useful_features_num=np.sum(useful_features) # 計(jì)算True的個(gè)數(shù)# 進(jìn)行PCA降維之后的新數(shù)據(jù)集為: pca.n_components=useful_features_num # 即設(shè)置PCA的新特征數(shù)量為n_components new_dataset_X=pca.fit_transform(dataset_X) print('before PCA, dataset shape: ', dataset_X.shape) print('after PCA, dataset shape: ', new_dataset_X.shape)-------------------------------------輸---------出--------------------------------
before PCA, dataset shape: (250, 5)
after PCA, dataset shape: (250, 2)
--------------------------------------------完-------------------------------------
PCA的優(yōu)點(diǎn)和缺點(diǎn):
優(yōu)點(diǎn):1,對(duì)數(shù)據(jù)進(jìn)行降維處理,我們可以對(duì)新求出的“主元”向量的重要性進(jìn)行排序,根據(jù)需要取前面最重要的部分,將后面的維數(shù)省去,可以達(dá)到降維從而簡(jiǎn)化模型或是對(duì)數(shù)據(jù)進(jìn)行壓縮的效果。同時(shí)最大程度的保持了原有數(shù)據(jù)的信息。
2,完全無(wú)參數(shù)限制,處理結(jié)果只與數(shù)據(jù)相關(guān),而與用戶無(wú)關(guān):在PCA的計(jì)算過(guò)程中完全不需要人為的設(shè)定參數(shù)或是根據(jù)任何經(jīng)驗(yàn)?zāi)P蛯?duì)計(jì)算進(jìn)行干預(yù),最后的結(jié)果只與數(shù)據(jù)相關(guān),與用戶是獨(dú)立的。
缺點(diǎn):1,PCA以線性方式工作,如果數(shù)據(jù)集不是以線性方式組織的,那么PCA效果就很差,此時(shí),我們可以根據(jù)先驗(yàn)知識(shí)對(duì)數(shù)據(jù)預(yù)先進(jìn)行非線性轉(zhuǎn)換,將非線性數(shù)據(jù)集轉(zhuǎn)換到相信空間中,這種分析方式叫做Kernel-PCA,也叫核PCA,它解決了PCA只能處理線性數(shù)據(jù)集的缺點(diǎn),又結(jié)合一些先驗(yàn)知識(shí)的約束,是目前比較流行的方法。
2,有的數(shù)據(jù)集的分布并不滿足高斯分布,在非高斯分布的情況下,PCA得到的主要特征可能并不是最優(yōu)的,在尋找主要特征時(shí)不能將方差作為衡量重要性的標(biāo)準(zhǔn),此時(shí)要根據(jù)數(shù)據(jù)的分布情況選擇合適的描述完全分布的變量,根據(jù)一定的概率分布公式來(lái)計(jì)算兩個(gè)特征數(shù)據(jù)分布的相關(guān)性,這種分析方式叫獨(dú)立主元分解(ICA)。
可以參考博文: 主成分分析(Principal components analysis)-最小平方誤差解釋
2. 用核PCA對(duì)數(shù)據(jù)集降維
前面提到,PCA雖好,但也不是放之四海而皆準(zhǔn),對(duì)于非線性方式組織的數(shù)據(jù)集,PCA方法可能效果較差,此時(shí)需要用核PCA方法來(lái)解決。
我們來(lái)看一個(gè)典型的非線性方式組織的數(shù)據(jù)集:
# 準(zhǔn)備數(shù)據(jù)集 from sklearn.datasets import make_circles dataset_X,dataset_y=make_circles(n_samples=500,factor=0.2,noise=0.04)該數(shù)據(jù)集的二維分布圖為:
那么如果我們用普通PCA對(duì)這個(gè)數(shù)據(jù)集進(jìn)行降維,會(huì)得到什么樣的結(jié)果了?
# 如果用普通的PCA來(lái)降維 from sklearn.decomposition import PCA pca = PCA() dataset_X_pca = pca.fit_transform(dataset_X) print(dataset_X_pca.shape) visual_2D_dataset(dataset_X_pca,dataset_y,'PCA transformed dataset') # 從圖中幾乎看不出PCA降維前后有啥區(qū)別如果用核PCA來(lái)降維,能夠?qū)?shù)據(jù)集變成線性可分,如下:
# 用核PCA方法來(lái)降維 from sklearn.decomposition import KernelPCA kernel_pca = KernelPCA(kernel="rbf", fit_inverse_transform=True, gamma=10) X_kernel_pca = kernel_pca.fit_transform(dataset_X) print(X_kernel_pca.shape) # 2維特征變成了465維,降維?增維? visual_2D_dataset(X_kernel_pca[:,:2],dataset_y,'Kernel PCA transformed dataset')很明顯,得到的新數(shù)據(jù)集便是線性可分。
話說(shuō),怎么經(jīng)過(guò)核PCA降維之后,原先的2個(gè)特征怎么增加到465個(gè)特征?降維還是增維?呵呵。
那么從這個(gè)核PCA得到的新數(shù)據(jù)集能夠返回到原來(lái)的數(shù)據(jù)集了?
# 如何從Kernel PCA得到的數(shù)據(jù)集反向計(jì)算出原始的數(shù)據(jù)集 dataset_X_inverse = kernel_pca.inverse_transform(X_kernel_pca) print(dataset_X_inverse.shape) visual_2D_dataset(dataset_X_inverse,dataset_y,'inversed dataset_X from KernelPCA')可以看出,恢復(fù)之后的數(shù)據(jù)集的分布情況和原始數(shù)據(jù)集的分布情況相同。
########################小**********結(jié)###############################
1,對(duì)數(shù)據(jù)集進(jìn)行降維可以很好地解決特征數(shù)太多導(dǎo)致的訓(xùn)練太耗時(shí),模型結(jié)構(gòu)臃腫的問(wèn)題,降維方法有很多種,其中的PCA降維方式可以解決具有線性方式的數(shù)據(jù)集,而核PCA方法可以對(duì)具有非線性方式組織的數(shù)據(jù)集進(jìn)行降維。
#################################################################
注:本部分代碼已經(jīng)全部上傳到(我的github)上,歡迎下載。
參考資料:
1, Python機(jī)器學(xué)習(xí)經(jīng)典實(shí)例,Prateek Joshi著,陶俊杰,陳小莉譯
總結(jié)
以上是生活随笔為你收集整理的【火炉炼AI】机器学习053-数据降维绝招-PCA和核PCA的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 计算机启动时滴滴两声,电脑开机时出现滴滴
- 下一篇: 声明式导航编程式导航