pca算法介绍及java实现_PCA算法原理及实现
眾所周知,PCA(principal component analysis)是一種數(shù)據(jù)降維的方式,能夠有效的將高維數(shù)據(jù)轉(zhuǎn)換為低維數(shù)據(jù),進(jìn)而降低模型訓(xùn)練所需要的計(jì)算資源。
以上是比較官方的說法,下面是人話(正常人講的話)版。
pca就是一種能夠有效壓縮數(shù)據(jù)的方法!打個(gè)不太準(zhǔn)確的例子:我們現(xiàn)在有一個(gè)描述人的健康狀況的數(shù)據(jù):(年齡,身高,體重,地區(qū),血壓,心率,肺活量,體溫,體脂),也就是說(年齡,身高,體重,地區(qū),血壓,心率,肺活量,體溫,體脂)這些東西是特征,而這些特征對(duì)應(yīng)的標(biāo)簽是健康狀況:健康/亞健康/不健康。那么pca就是通過一些方法,將這9個(gè)特征壓縮到只有4個(gè),3個(gè)甚至更少的特征(暫且稱之為x1, x2, x3, x4),但是我們?nèi)阅苡眠@些特征來準(zhǔn)確預(yù)測(cè)它們對(duì)應(yīng)的健康狀況。
在這里補(bǔ)充一下,在數(shù)學(xué)/機(jī)器學(xué)習(xí)中,我們會(huì)把特征抽象為向量,比如上面提到的健康狀況的數(shù)據(jù):(年齡,身高,體重,地區(qū),血壓,心率,肺活量,體溫,體脂),我們會(huì)抽象為(18, 180, 70,廣東,100,80, 5000, 37, 0.1),其中地區(qū)這一項(xiàng)顯得與眾特別,畢竟其他的維度都是數(shù)值,就它是文字。我們把這樣的維度稱為類別,因?yàn)樗窃谟邢薜倪x項(xiàng)中選出來的(從世界上所有的地區(qū)中取一個(gè)),在計(jì)算機(jī)中表示這樣的信息,我們可以有很多方式,但是為了簡(jiǎn)化難度,這邊我就暫且不搞,直接把這一列刪掉。于是乎我們的數(shù)據(jù)(其實(shí)就是向量!)就是(18, 180, 70, 100, 80, 5000, 37, 0.1),值得一提的是,這樣的一個(gè)數(shù)據(jù)是屬于一個(gè)實(shí)體的(也就是說這是描述一個(gè)人的健康狀況的),在機(jī)器學(xué)習(xí)中,我們傾向于將一個(gè)實(shí)體的數(shù)據(jù)排成一列,也就是(18, 180, 70, 100, 80, 5000, 37, 0.1)^T(轉(zhuǎn)置)。
本文要介紹的目錄為:使用PCA的必要性
PCA的本質(zhì)
前置知識(shí)的介紹
PCA的數(shù)學(xué)原理
PCA的思想
PCA的實(shí)現(xiàn)
使用PCA的必要性
前面說了,pca就是將高維(很多列屬性)數(shù)據(jù)轉(zhuǎn)換為低維(較少列)數(shù)據(jù)的方法,同時(shí)保留大部分信息(可以用保留的信息準(zhǔn)確預(yù)測(cè))。但是我們可能會(huì)想:如果我不壓縮的話,那我不就可以有100%的數(shù)據(jù)嗎?我閑著沒事干壓縮干哈?其實(shí)我一開始使用的時(shí)候也有這樣的疑惑,因?yàn)槲乙婚_始是用在圖像上的,而一個(gè)圖像只有500多個(gè)維度(列)的數(shù)據(jù),使用pca壓縮到100列可以保存原始數(shù)據(jù)95%的信息,但是我發(fā)現(xiàn)我用壓縮的數(shù)據(jù)和不壓縮的數(shù)據(jù)對(duì)模型的訓(xùn)練速度并沒有什么影響。。。但是后來我做其他一些有500000維度的數(shù)據(jù)的時(shí)候,發(fā)現(xiàn)使用pca將維度降到5000就能保存接近98%的數(shù)據(jù),而且訓(xùn)練速度可以提升數(shù)十倍!于是我就成了pca的腦殘粉了。。。所以pca在應(yīng)對(duì)高維度數(shù)據(jù)的時(shí)候是有奇效的!它不僅可以有效減少訓(xùn)練時(shí)間而且還可以防止過擬合,前面一點(diǎn)上文已給出原因,防止過擬合在下文給出。
PCA的本質(zhì)
其實(shí)pca的本質(zhì)很簡(jiǎn)單,上面也有說,就是將高維度數(shù)據(jù)轉(zhuǎn)換到低維度,不過在這里為了讓大家能夠有所體會(huì),我使用2維數(shù)據(jù)降到1維在解釋這點(diǎn)。
如上圖所示,假設(shè)我們的原始數(shù)據(jù)A, B, C是在直角坐標(biāo)系中的三個(gè)點(diǎn),它們的坐標(biāo)分別為A(x_a, y_a), B(x_b, y_b), C(x_c, y_c),那么我們現(xiàn)在想要使用pca,將這三個(gè)在平面上的點(diǎn)降維到直線上(也就是上圖中黃色的線上)。那么現(xiàn)在的問題就是:平面中的A, B, C點(diǎn)(高維數(shù)據(jù))可以通過怎樣的映射關(guān)系降維到黃線上(也就是高維的數(shù)據(jù)如何在低維中表示)。
這條黃線(就是低維)怎么求/確定?
前置知識(shí)的介紹
對(duì)于上面提到的題一個(gè)問題(如何將高維度數(shù)據(jù)映射到低維度中),我們需要先知道數(shù)據(jù)點(diǎn)如何被表示。
這看起來似乎是一個(gè)很蠢的問題,因?yàn)榇鸢该菜坪芎?jiǎn)單,比如圖xx中的點(diǎn)ABC不就是A(x1, y1), B(x2, y2), C(x3, y3)嗎?對(duì)滴!這個(gè)答案是沒有問題的,但是這樣的答案并不具有普遍性,也就是說如果我們的坐標(biāo)系發(fā)生了變化(類比直角坐標(biāo)系變化到極坐標(biāo)系),那就不能再用(x, y)這樣的形式進(jìn)行表示了,那么我們這里需要更加普遍的方法。
我先說答案,再說為什么是這個(gè)答案~。答案就是通過坐標(biāo)系的基向量來表示數(shù)據(jù)(向量)。如圖所示,我們?nèi)和j作為基向量(在這里i的坐標(biāo)為(1,0), j的坐標(biāo)為(0, 1)),那么數(shù)據(jù)A(1, 2),就可以表示為(1*i, 2*j)。于是我們把這個(gè)問題拓展開來,二維上的數(shù)據(jù)點(diǎn)可以通過(基向量i*數(shù)據(jù)點(diǎn)在基向量i上的投影長(zhǎng)度,基向量j*數(shù)據(jù)點(diǎn)在基向量j上的投影長(zhǎng)度)表示,那么三維上的數(shù)據(jù)點(diǎn)也可以用這樣的方式,于是乎n(n>=2)維上的點(diǎn)可以表示為:(基向量i*數(shù)據(jù)點(diǎn)在基向量i上的投影長(zhǎng)度,基向量j*數(shù)據(jù)點(diǎn)在基向量j上的投影長(zhǎng)度,…,基向量n * 數(shù)據(jù)點(diǎn)在基向量n上的投影長(zhǎng)度),于是乎我們這個(gè)子問題就解決了,即找到了一種在不同維度坐標(biāo)系下表示數(shù)據(jù)的方法。
PCA的數(shù)學(xué)原理
那么接下來的問題就是,我們?nèi)绾伟岩粋€(gè)數(shù)據(jù)點(diǎn)從一個(gè)維度轉(zhuǎn)變到另一個(gè)維度。
在解決這個(gè)問題之前,我們先用矩陣描述一下上一個(gè)問題,比如我們現(xiàn)在基向量為(0,1)和(1,0)的坐標(biāo)中表示(3,2),則可以寫作為:
假設(shè)我們現(xiàn)在有一個(gè)新的坐標(biāo)系,這個(gè)坐標(biāo)系的基向量i和j在普通平面直角坐標(biāo)系中的表示是(0, -1)和(1, 0),(其實(shí)就是普通直角坐標(biāo)系順時(shí)針旋轉(zhuǎn)90度),如下圖所示(黑色為新的坐標(biāo)系):
A點(diǎn)在普通直角坐標(biāo)系中為(3, 2),在新的直角坐標(biāo)系中為(-2, 3)。新的坐標(biāo)(-2, 3)可以通過以下方式計(jì)算:
于是乎我們找到了二維空間下數(shù)據(jù)變換的方式:
新的基向量矩陣*原基向量矩陣的轉(zhuǎn)置*原數(shù)據(jù)向量=新的數(shù)據(jù)向量
也就是說我們想要將高維數(shù)據(jù)轉(zhuǎn)換為低維數(shù)據(jù)可以通過:
低維空間的基向量矩陣 * 高維空間的基向量矩陣的轉(zhuǎn)置 * 高維數(shù)據(jù)向量 = 低維數(shù)據(jù)向量
而參考上圖,我們可以知道‘高維空間的基向量矩陣的轉(zhuǎn)置 * 高維數(shù)據(jù)向量’是等于高維數(shù)據(jù)向量本身的,于是乎可以得到:
低維空間的基向量矩陣 * 高維數(shù)據(jù)向量 = 低維數(shù)據(jù)向量(此處應(yīng)有數(shù)學(xué)公式)
接下來我們解決第二個(gè)大問題,也就是如下這條黃線(就是低維)怎么求/確定?
PCA的思想
這樣要確定低維,要么就要給出標(biāo)準(zhǔn),也就是什么樣的低維是好的?
在這里先確定兩個(gè)標(biāo)準(zhǔn),稍后解釋為什么確定這兩標(biāo)準(zhǔn):不同特征之間的方差盡可能大。
不同特征之間的協(xié)方差等于0。
設(shè)立這兩個(gè)標(biāo)準(zhǔn)的原因是這樣的:
先做一個(gè)前提假設(shè)哈!
假設(shè)我們現(xiàn)在有兩個(gè)樣本(在這個(gè)例子中就是兩個(gè)人),他們的健康狀況如下:
好了,我要來解釋了。
第一個(gè)標(biāo)準(zhǔn)的解釋其實(shí)不算太難,假設(shè)我們現(xiàn)在要處理上面的數(shù)據(jù),也就是要將小王和老丁的數(shù)據(jù)的進(jìn)行降維,而他們的健康數(shù)據(jù)包含9個(gè)特征(健康水平是算作label而不是特征X,相當(dāng)于y=f(X)中的y),理想狀態(tài)是每個(gè)特征描述的東西都是完全不同的(因?yàn)樘卣髅枋龅氖菍?duì)象的特性,如果兩個(gè)特征描述的東西很類似甚至可以被代替,那就浪費(fèi)了大把的計(jì)算資源了。比如說現(xiàn)在有這樣兩個(gè)特征,第一個(gè)特征是:是否為男性,第二個(gè)特征是:是否為女性。如果第一個(gè)特征為真,則第二個(gè)特征必定為假,也就是這兩個(gè)東西描述的都是同一個(gè)特性,就是性別),也就是說在原始數(shù)據(jù)中,不同的特征它們之間的方差應(yīng)該是很大的(可以理解為方差越大,這兩個(gè)東西越不同)。而每個(gè)特征之間我們希望降維之后它們也和原來的數(shù)據(jù)一樣,不同的特征之間保持有大的方差,于是乎就有了第一個(gè)標(biāo)準(zhǔn):不同特征之間的方差盡可能大。
第二個(gè)標(biāo)準(zhǔn)的解釋其實(shí)和第一個(gè)標(biāo)準(zhǔn)是類似的,只不過形式不同。上面說過了,我們是希望原數(shù)據(jù)中不同的特征降維后還是不同,而希望它們不同就等價(jià)于說它們之間不相關(guān),而協(xié)方差就是用來衡量?jī)蓚€(gè)特征之間的相關(guān)程度的,當(dāng)協(xié)方差等于0的時(shí)候,就說明這兩個(gè)特征之間是無關(guān)的。所以就有了這個(gè)標(biāo)準(zhǔn):不同特征之間的協(xié)方差等于0。
好了!現(xiàn)在我們已經(jīng)有了處理標(biāo)準(zhǔn)了,接下來我們就要把這個(gè)標(biāo)準(zhǔn)給抽象化(就是寫成數(shù)學(xué)公式)方便我們計(jì)算!
我重新上面的數(shù)據(jù)貼出來:
寫成向量的形式
讓我們先寫出標(biāo)準(zhǔn)1的公式吧:
其中X就是一個(gè)特征的數(shù)據(jù),用我們上面的例子來說,假設(shè)X是身高,則X為(180, 175),則/mu就是177.5,m等于2,于是就求得Var(X)= xxx,同樣的道理可以用來算年齡呀,血壓呀,心率呀啥的。
這里有個(gè)技巧,就是我們先對(duì)X進(jìn)行處理,就是將其減去它的均值:X = X - /mu,于是乎我們的公式就變成了:
標(biāo)準(zhǔn)2的公式如下:
我們用上面的技巧,于是乎我們的公式就變成了:
現(xiàn)在我們把這兩個(gè)標(biāo)準(zhǔn)給寫成數(shù)學(xué)的公式了,這樣我們就可以用計(jì)算機(jī)來算了。但是這兩個(gè)公式是分開的。。(就是說他們是兩個(gè)公式),這樣并不太方便于我們計(jì)算,我們要像個(gè)辦法把他們組合起來,這樣優(yōu)化起來才能”聯(lián)動(dòng)”。在這里我介紹一個(gè)矩陣,叫做協(xié)方差矩陣:
可以發(fā)現(xiàn),這個(gè)矩陣的正對(duì)角線就是我們的標(biāo)準(zhǔn)1,也就是方差,而其他的位置則為協(xié)方差。所以我們的目的就是使得協(xié)方差的位置為0,然后選取方差最大的值(選取方差最大的值可能有點(diǎn)疑惑,是這樣的:我們的特征矩陣X是可以有很多特征的,比如年齡,血壓,心率,肺活量等等,而方程右邊的a和b就是這些特征中的一個(gè),那么勢(shì)必有些特征的方差比較大,有些特征的方差比較小。而那些方差比較小的特征我們就覺得它們沒有那么好的區(qū)分效果,而那些方差大的就覺得它們有很好的區(qū)分效果,于是乎就把它們選中)。
于是乎我們的目標(biāo)就變成了,通過優(yōu)化方法,使得協(xié)方差矩陣對(duì)角化(就是非對(duì)角線的位置值為0)。接下來是很簡(jiǎn)單的數(shù)學(xué)推導(dǎo)了。
假設(shè)我們最終的協(xié)方差矩陣(就是上面說的對(duì)角化后的矩陣)為D,X為我們的特征矩陣,C為我們特征矩陣X的協(xié)方差矩陣,我們要找到一個(gè)矩陣P,使得我們的X特征矩陣可以變成D矩陣。
也就是說,我們現(xiàn)在的目標(biāo)就變成了找到一個(gè)矩陣P,使得矩陣以上等式成立。這里需要一丟丟線性代數(shù)的知識(shí),主要是關(guān)于實(shí)對(duì)稱矩陣的知識(shí),但是這里就不說啦!
最后我們就可以得到矩陣P,這個(gè)矩陣P是由我們的特征X矩陣找到的,你也可以理解為它蘊(yùn)含著我們X矩陣的信息,而這些信息的重要性是越往上的越重要,比如:
則第一行中的(0.2 0.3)的重要性要高于第二行的(0.4 0.2),然后我們想將我們的數(shù)據(jù)降到一維度,則:
其中X是原始特征,newX是降維后的特征,而(0.2 0.3)就是我們P矩陣的第一列。從之前的知識(shí)可以知道,我們是將X矩陣降維到一維。
PCA的實(shí)現(xiàn)import numpy as npimport pandas as pdimport matplotlib.pyplot as plt
定義一個(gè)均值函數(shù)。#計(jì)算均值,要求輸入數(shù)據(jù)為numpy的矩陣格式,行表示樣本數(shù),列表示特征def?meanX(dataX):return?np.mean(dataX,axis=0)#axis=0表示依照列來求均值。假設(shè)輸入list,則axis=1
開始實(shí)現(xiàn)pca的函數(shù):def pca(XMat, k):'''XMat:傳入的是一個(gè)numpy的矩陣格式,行表示樣本數(shù),列表示特征k:表示取前k個(gè)特征值相應(yīng)的特征向量finalData:指的是返回的低維矩陣reconData:相應(yīng)的是移動(dòng)坐標(biāo)軸后的矩陣'''average = meanX(XMat)m, n = np.shape(XMat)data_adjust = []avgs = np.tile(average, (m, 1))data_adjust = XMat - avgscovX = np.cov(data_adjust.T) #計(jì)算協(xié)方差矩陣featValue, featVec= np.linalg.eig(covX) #求解協(xié)方差矩陣的特征值和特征向量index = np.argsort(-featValue) #依照featValue進(jìn)行從大到小排序finalData = []if k > n:print('k must lower than feature number')returnelse:#注意特征向量時(shí)列向量。而numpy的二維矩陣(數(shù)組)a[m][n]中,a[1]表示第1行值selectVec = np.matrix(featVec.T[index[:k]]) #所以這里須要進(jìn)行轉(zhuǎn)置finalData = data_adjust * selectVec.TreconData = (finalData * selectVec) + averagereturn finalData, reconData
到這里整個(gè)流程基本就結(jié)束了~
總結(jié)
以上是生活随笔為你收集整理的pca算法介绍及java实现_PCA算法原理及实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java8 时间加一秒_Java8中对时
- 下一篇: select 移动端 第一个无法选中_总