機器學(xué)習(xí)經(jīng)典算法 - PCA

對于機器學(xué)習(xí)來說运悲,數(shù)據(jù)的質(zhì)量很大程度上決定了模型的質(zhì)量,因此對于幾乎所有的情況下都需要對于數(shù)據(jù)進行預(yù)處理项钮。其中較為常用的數(shù)據(jù)處理方式是數(shù)據(jù)的標(biāo)準(zhǔn)化班眯,進一步還可以通過主成分分析 Principal components analysis, PCA,隨機投影 Random Projection 和獨立成分分析 Independent Conponent Analysis 來對數(shù)據(jù)進行降維 dimensionality reduction烁巫。

數(shù)據(jù)的標(biāo)準(zhǔn)化

數(shù)據(jù)標(biāo)準(zhǔn)化最基本目的是對于將要進行運算的數(shù)據(jù)的取值進行縮放署隘,使得數(shù)據(jù)在取值范圍上處于同一個數(shù)量級,避免在運算過程中取值較小的特征被取值較大的特征“吃掉”亚隙。但將不同特征縮放到同一數(shù)量級的前提是各自特征對于最終分類和判斷的重要性是等同的磁餐,否則就不應(yīng)該做這一處理。

常用的標(biāo)準(zhǔn)化方式:

  • 采用最大值最小值縮放 Min-Max Scaler 的方式:x' = [ x - min(x) ] / [ max(x) - min(x) ]

  • 采用正態(tài)分布的標(biāo)準(zhǔn)值 standard value 的方式:z = (x - x?) / σ

-采用整體縮放的方式:在圖像處理中常常將圖片數(shù)組整體除以 255 以將取值縮放在 [0, 1] 之間

這里 xx'阿弃, z 代表向量诊霹,采用最大值最小縮放標(biāo)準(zhǔn)化后的取值范圍是 [0, 1]羞延,而標(biāo)準(zhǔn)值方法標(biāo)準(zhǔn)化的結(jié)果是將原本服從正態(tài)分布的元素進一步標(biāo)準(zhǔn)化成服從均值為 0, 方差為 1 的標(biāo)準(zhǔn)正態(tài)分布畅哑,且這兩種方法在使用過程中必須要注意 排除異常值 Outlier 的影響肴楷。

數(shù)據(jù)的標(biāo)準(zhǔn)化可以通過借助 skitlearn 的預(yù)處理模塊很容易的完成:

In[3]:
import numpy as np
from sklearn.preprocessing import MinMaxScaler

# sklearn prefers your inputs as float
# otherwise will pop out a warning BUT still do the calculation
weights = np.array([[115], [140], [175]]) 
scaler = MinMaxScaler()
rescaled_weight = scaler.fit_transform(weights)
# rescaled_weight = MinMaxScaler().fit_transform(weights)
rescaled_weight

Out[3]:
array([[ 0.        ],
       [ 0.41666667],
       [ 1.        ]])

In [4]:
from sklearn.preprocessing import StandardScaler

weights = np.array([[115], [140], [175]]) 
scaler = StandardScaler()
rescaled_weight = scaler.fit_transform(weights) 
# rescaled_weight = StandardScaler().fit_transform(weights)
rescaled_weight

Out[4]:
array([[-1.15138528],
       [-0.13545709],
       [ 1.28684238]])

矩陣的數(shù)據(jù)處理

在實際的工作中,尤其是計算機視覺方面的應(yīng)用荠呐, 更多的數(shù)據(jù)是以矩陣的形式存儲的。對于一個形如 [N, D] 的矩陣 X砂客,其中 N 為樣本的數(shù)量泥张,D 為特征的數(shù)量。

特征的去均值化 Mean subtraction

對于矩陣中的每一列特征都減去相應(yīng)特征的均值鞠值,這種處理使得數(shù)據(jù)在各個特征維度上都更加趨近于中心位置媚创,使得數(shù)據(jù)更加密集。

相應(yīng)的在 Numpy 中的處理方式為:X = X - np.mean(X, axis=0)

而對于圖像矩陣來說最常做的一個數(shù)據(jù)處理是在圖像矩陣的各個通道上減去相應(yīng)通道上全部訓(xùn)練樣本的像素值的均值彤恶,例如在 VGG16 中的 Imagenet 數(shù)據(jù)前處理部分就是將輸入圖像的三個 RGB 通道上分別減去 103.939钞钙,116.779,123.68声离,后面這三個數(shù)是所有 Imagenet 中的圖片在三個通道上分別計算得到的均值芒炼。

相應(yīng)的在 Numpy 中的處理方式為:X = X - np.mean(X)

在去均值化的基礎(chǔ)上,如果有必要還可以進一步除以相應(yīng)特征的標(biāo)準(zhǔn)差使得數(shù)據(jù)進一步標(biāo)準(zhǔn)化:X /= np.std(X, axis=0)

Data normalization, from Stanford CS231n notes

在這里需要注意的是术徊,這里的均值和方差都是針對訓(xùn)練數(shù)據(jù)集而言的本刽,也即應(yīng)該在劃分訓(xùn)練數(shù)據(jù)集、驗證數(shù)據(jù)集和測試數(shù)據(jù)集后在訓(xùn)練數(shù)據(jù)集上進行計算赠涮,再用訓(xùn)練數(shù)據(jù)集中的均值和方差來處理驗證數(shù)據(jù)集和測試數(shù)據(jù)集子寓。

主成分分析 Principal Components Analysis

對于本部分需要的數(shù)學(xué)知識,如 基的變換笋除、本征值分解和奇異值分解斜友,協(xié)方差 請見鏈接中的筆記內(nèi)容,這里直接進入主題垃它。

之所以要做主成分分析鲜屏,是因為大多數(shù)實踐中的數(shù)據(jù)都是默認(rèn)基于自然基 naive basis 進行記錄和表示的,并且這些數(shù)據(jù)當(dāng)中通常有大量的干擾噪聲 noise 和冗余特征 redundancy嗤瞎,而尋找主成分的過程就是希望通過對于基的線性變換來找到對于被觀察的數(shù)據(jù)更簡潔的表示形式墙歪,從中提取最為重要的特征,即主成分贝奇,而忽略次要特征虹菲,這對簡化模型復(fù)雜度和提高模型的穩(wěn)健性具有重要的意義。

如果我們通過對自然基下的特征數(shù)據(jù)做線性變換后發(fā)現(xiàn)其在某一個方向上變動的離散程度很大掉瞳,也即方差最大毕源,則這個方向就可以認(rèn)為是特征取值變動的方向浪漠,通常也就是我們感興趣的方向,或者稱信號的方向霎褐,而與之垂直的方向則可以理解為噪聲的方向址愿。評估數(shù)據(jù)質(zhì)量的一個重要指標(biāo)是信噪比 Signal-to-noise-ratio, SNR,其數(shù)學(xué)定義為:

  • SNR = σ2signal / σ2noise 冻璃,這個公式也隱含(一般情況下)高信號方差對應(yīng)高信噪比
Signals with variances not coincide with data collection coordinate system / basis

除噪聲外响谓,多個特征之間很可能存在直接的相關(guān)性,也即我們只需要包含其中的部分特征就可以推導(dǎo)出其他的全部特征省艳,因此可以在數(shù)據(jù)處理的過程中去除冗余特征娘纷,借此降低特征矩陣的維數(shù),以減小模型需要處理的數(shù)據(jù)量跋炕。

在機器學(xué)習(xí)中對于被研究對象的多個特征的多次觀測的結(jié)果通常會以一個矩陣的形式表示赖晶,稱為特征矩陣,因此為了便于區(qū)分辐烂,后續(xù)涉及到利用本征值對矩陣進行的分解我都稱之為本征值分解遏插,而不是國內(nèi)很多教材上的特征分解。借由統(tǒng)計相關(guān)知識纠修,兩個特征的相關(guān)性可以通過協(xié)方差 Covariance 來衡量胳嘲,對于多個特征來說,則可以基于原有的特征矩陣構(gòu)建協(xié)方差矩陣 Covariance matrix分瘾。在協(xié)方差矩陣中胎围,對角線元素為同一個特征的方差,較大的方差值則意味著其可能是我們需要主要關(guān)注的重要變動元素德召。而非對角線元素則對應(yīng)不同的兩個特征之間的協(xié)方差白魂,較大的協(xié)方差數(shù)值意味著兩個特征之間具有較大的線性相關(guān)性,也即存在較大可能的冗余上岗。

如果期望可以最大程度的降低冗余福荸,則希望這個協(xié)方差矩陣可以通過線性變換變成一個對角矩陣。從協(xié)方差矩陣的構(gòu)建過程可以看到它是一個實對稱矩陣肴掷,而對于任意實對稱矩陣來說都可以進行本征值分解敬锐,其結(jié)果為 C = QΛQT = QΛQ-1,其中 Q 為本征向量構(gòu)成的正交矩陣 Quadrature matrix呆瞻,Λ 為本征值構(gòu)成的對角矩陣台夺。對于本征向量來說,如果一個向量是矩陣的本征向量痴脾,則其任意非零 k 倍也是本征向量颤介,這也可以理解為在本征向量的方向上可以有最多的信號聚集,在機器學(xué)習(xí)和深度學(xué)習(xí)的語境中,協(xié)方差矩陣的本征向量構(gòu)成的正交矩陣就是特征數(shù)據(jù)集的主成分 Principal components滚朵。

同時冤灾,為突出具有較大方差的特征的重要性,可以將 Λ 對角線上的元素按照從大到小的順序進行布置辕近。對本征值從大到小的排列后韵吨,為了滿足本征分解的運算條件,本征值對應(yīng)的本征向量也要在正交矩陣中保持相同的順序移宅,這也使得我們可以容易的識別出哪些本征向量的方向最為重要归粉,進而舍棄掉不重要的特征實現(xiàn)維度縮減。

Correlation means redundancy

對于已有的輸入特征矩陣 X吞杭,在通過本征值分解進行主元素分析時盏浇,需要采用以下幾個步驟:

  1. 對特征矩陣的每一列 x 進行去均值化得到標(biāo)準(zhǔn)化后的矩陣 XX -= np.mean(X, axis = 0)

  2. 通過計算每一列特征 x 與其他特征的協(xié)方差來構(gòu)造協(xié)方差矩陣

    • 兩個特征向量的協(xié)方差計算公式為:Cov(x, y) = sx,y = (x - x?) ? (y - y?) / n - 1,其中 n 為每一個特征的樣本數(shù)量芽狗,n - 1 是為了實現(xiàn)誤差校正,即減少因樣本方差少于總體方差帶來的估計誤差痒蓬,并且采用代碼實現(xiàn)時分母采用向量內(nèi)積 np.dot(x - x?, y - y?)

    • covariance_matrix = np.dot(X.T, X) / (X.shape[0] - 1)

  3. 在 Numpy 中實施本征分解的方法為:

    • eigen_values, eigen_vectors = np.linalg.eig(convariance_matrix)
  4. 在本征分解后童擎,將本征值和本征向量配對,并將本征值按照從大到小的方式排列(Numpy 默認(rèn)不是按照本征值大小進行排列的):

    • eigen_pairs = [(np.abs(eigen_values[i]), eigen_vectors[:, i]) for i in range(len(eigen_values))]

    • eigen_paris.sort(reverse=True) # sort the pairs with eigen_values

    • 此時在 Numpy 中本征向量會以行向量的方式進行存儲攻晒,構(gòu)造本征向量構(gòu)成的投影矩陣 P

  5. 用之前的特征矩陣乘以這個投影矩陣得到 Y = XPT 即為基變換后的矩陣顾复,如果只選取前 n' 行,n' ≤ n 即可以實現(xiàn)降維 Y = np.dot(X, P.T)

在 Numpy 中的 PCA 具體實現(xiàn)舉例如下:

import numpy as np
In [42]:
X = np.array([[1, 2, 3], [4, 6, 1], [6, 2, 0], [7, 3, 1]], dtype='float64')
X
Out[42]:
array([[ 1.,  2.,  3.],
       [ 4.,  6.,  1.],
       [ 6.,  2.,  0.],
       [ 7.,  3.,  1.]])
In [44]:
X -= np.mean(X, axis=0)
X
Out[44]:
array([[-3.5 , -1.25,  1.75],
       [-0.5 ,  2.75, -0.25],
       [ 1.5 , -1.25, -1.25],
       [ 2.5 , -0.25, -0.25]])
In [45]:
cov = np.dot(X.T, X)
cov
Out[45]:
array([[ 21.  ,   0.5 ,  -8.5 ],
       [  0.5 ,  10.75,  -1.25],
       [ -8.5 ,  -1.25,   4.75]])
In [46]:
eigen_values, eigen_vectors = np.linalg.eig(cov)
In [47]:
eigen_values
Out[47]:
array([ 24.6986712 ,   1.02265454,  10.77867426])
In [48]:
eigen_vectors
Out[48]:
array([[ 0.91627689,  0.38756163, -0.10115656],
       [ 0.06821481,  0.0978696 ,  0.99285864],
       [-0.39469406,  0.9166338 , -0.06323821]])
In [49]:
eigen_pairs = [(np.abs(eigen_values[i]), eigen_vectors[:, i]) for i in range(len(eigen_values))]
eigen_pairs.sort(reverse=True)
In [50]:
eigen_pairs
Out[50]:
[(24.698671197292434, array([ 0.91627689,  0.06821481, -0.39469406])),
 (10.778674258520375, array([-0.10115656,  0.99285864, -0.06323821])),
 (1.0226545441871755, array([ 0.38756163,  0.0978696 ,  0.9166338 ]))]
In [51]:
projection = np.array([element[1] for element in eigen_pairs[:2]])
projection
Out[51]:
array([[ 0.91627689,  0.06821481, -0.39469406],
       [-0.10115656,  0.99285864, -0.06323821]])
In [52]:
Y = np.dot(X, projection.T)
Y
Out[52]:
array([[-3.98295224, -0.99769222],
       [-0.17187419,  2.79674909],
       [ 1.78251439, -1.31376037],
       [ 2.37231203, -0.4852965 ]])

由于 Numpy 中 SVD 分解后會默認(rèn)的將奇異值按照從大到小的方式進行排列鲁捏,因此上述 PCA 過程還可以利用 Numpy 的 SVD 分解來進行:


In [53]:
cov
Out[53]:
array([[ 21.  ,   0.5 ,  -8.5 ],
       [  0.5 ,  10.75,  -1.25],
       [ -8.5 ,  -1.25,   4.75]])
In [54]:
U, S, V = np.linalg.svd(cov)
U
Out[54]:
array([[-0.91627689,  0.10115656,  0.38756163],
       [-0.06821481, -0.99285864,  0.0978696 ],
       [ 0.39469406,  0.06323821,  0.9166338 ]])
In [55]:
S
Out[55]:
array([ 24.6986712 ,  10.77867426,   1.02265454])
In [56]:
V
Out[56]:
array([[-0.91627689, -0.06821481,  0.39469406],
       [ 0.10115656, -0.99285864,  0.06323821],
       [ 0.38756163,  0.0978696 ,  0.9166338 ]])
In [57]:
Z = np.dot(X, U[:, :2])
Z
Out[57]:
array([[ 3.98295224,  0.99769222],
       [ 0.17187419, -2.79674909],
       [-1.78251439,  1.31376037],
       [-2.37231203,  0.4852965 ]])

上述兩種方法計算得到的特征向量有一個互為相反數(shù)芯砸,是因為特征向量不唯一導(dǎo)致的。

進一步地给梅,如果輸入特征本身不可以通過自然基線性表示假丧、不服從正態(tài)分布,或者特征之間不能正交分離动羽,那么則無法有效的通過上述方法進行降維包帚。

Situations where PCA fails

隨機投影 Random Projection

當(dāng)發(fā)現(xiàn)數(shù)據(jù)集中的特征維數(shù)過高時,此時如果通過 PCA 來實現(xiàn)降維可能所需的計算量非常大运吓,此時可以考慮通過矩陣乘積的形式對原始數(shù)據(jù)進行隨機投影渴邦,這一投影降維的過程可以理解為一種 Embedding 實現(xiàn)。

在 Scikit-Learn 中實現(xiàn)隨機投影的代碼如下:

from sklearn import random_projection

rp = random_projection.SparseRandomProjection()

projected = rp.fit_transform(X)

獨立成分分析 ICA

PCA 通過分離出輸入數(shù)據(jù)中方差變化較大的項而實現(xiàn)降維拘哨,ICA 則從另一個角度谋梭,其認(rèn)為輸入的高維數(shù)據(jù)是由多個不同的獨立成分混合而成的,因此這一算法試圖分離出這些獨立的成分以實現(xiàn)降維倦青。

在 Scikit-Learn 中實現(xiàn) ICA 的代碼如下:

from sklearn.decomposition import FastICA

ica = FastICA(n_components=3)
components = ica.fit(X)

參考閱讀

  1. A tutorial on Principal Components Analysis by Google

  2. 斯坦福大學(xué)計算機視覺CS231n 課程筆記

  3. 主成分分析 PCA 學(xué)習(xí)總結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瓮床,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纤垂,老刑警劉巖矾策,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異峭沦,居然都是意外死亡贾虽,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門吼鱼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蓬豁,“玉大人,你說我怎么就攤上這事菇肃〉胤啵” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵琐谤,是天一觀的道長蟆技。 經(jīng)常有香客問我,道長斗忌,這世上最難降的妖魔是什么质礼? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮织阳,結(jié)果婚禮上眶蕉,老公的妹妹穿的比我還像新娘。我一直安慰自己唧躲,他們只是感情好造挽,可當(dāng)我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著弄痹,像睡著了一般饭入。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上界酒,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天圣拄,我揣著相機與錄音,去河邊找鬼毁欣。 笑死庇谆,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的凭疮。 我是一名探鬼主播饭耳,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼执解!你這毒婦竟也來了寞肖?” 一聲冷哼從身側(cè)響起纲酗,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔗坯,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年吮螺,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帕翻。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡鸠补,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嘀掸,到底是詐尸還是另有隱情紫岩,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布睬塌,位于F島的核電站泉蝌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏揩晴。R本人自食惡果不足惜梨与,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望文狱。 院中可真熱鬧,春花似錦缘挽、人聲如沸瞄崇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽苏研。三九已至,卻和暖如春腮郊,著一層夾襖步出監(jiān)牢的瞬間摹蘑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工轧飞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衅鹿,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓过咬,卻偏偏與公主長得像大渤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子掸绞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,494評論 2 348

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