經(jīng)典算法回顧 - 快速 get 核-PCA 的要點(diǎn)
引言
在機(jī)器學(xué)習(xí)中,將數(shù)據(jù)點(diǎn)按行擺放,所有數(shù)據(jù)點(diǎn)就構(gòu)成一個(gè)矩陣(也可以看成表格、二維數(shù)組)。矩陣的一行對應(yīng)一個(gè)數(shù)據(jù),矩陣的一列對應(yīng)一個(gè)特征,因此也稱為特征矩陣。如下圖所示,用矩陣
對于已經(jīng)零中心化(即
上面矩陣的元素對應(yīng)特征之間的協(xié)方差,這種定義形式簡單也好理解。
以上是在原始特征空間中作主成分分析,但本篇的主題是核主成分分析。所謂核,則是為在更高維的特征空間作分析服務(wù)的。首先,假設(shè)我們通過以下方式將數(shù)據(jù)非線性映射到特征空間
為什么要將數(shù)據(jù)映射到更高維空間中呢,不是增加了計(jì)算量嗎?主要目的是想讓數(shù)據(jù)在更高維空間中線性可分。因?yàn)槟靡粋€(gè)超平面將數(shù)據(jù)一分為二是行走江湖的基本招術(shù)。記住,機(jī)器學(xué)習(xí)的一個(gè)基本招術(shù) - 劈柴功。

然而,在原始空間中往往不讓你施展這一招。比如下面的例子,原始數(shù)據(jù)在二維空間中,兩個(gè)類別分布在不同的同心圓上,此時(shí)如果想使用線性分類器來區(qū)分兩類是做不到的。
那怎么辦呢?可以這么來辦吧,改變斧子或者數(shù)據(jù)。一個(gè)辦法就是改變斧子,為某個(gè)問題專門設(shè)計(jì)某種斧子,似乎也是可行的,只是斧子一般不再是平的了。還有個(gè)辦法就是改變數(shù)據(jù),讓它變得線性可分。第二個(gè)辦法更通用,所以我們來看它。

這個(gè)簡單例子中,僅僅對數(shù)據(jù)增加一個(gè)維度即可,在三維空間中就可以施展劈柴大功將兩類輕松分開。
我們回到核 PCA,可以證明,即使
但這里我們需要解決一個(gè)問題,那就是我們并不知道映射函數(shù)
一個(gè)是如何計(jì)算新特征的協(xié)方差矩陣;
另一個(gè)在高維空間中往新坐標(biāo)軸投影得到新的坐標(biāo)。
答案是,并不需要直接計(jì)算這些值,而是通過使用所謂的核技巧來實(shí)現(xiàn)的。下面就來看這是如何推導(dǎo)出來的。
核 PCA
假設(shè)將數(shù)據(jù)映射到新的特征空間中,并且
換句話說,我們只知道目標(biāo)是將數(shù)據(jù)映射到更高維的空間中去,但并不給出怎么映射過去。那么問題來了,如何在高維空間中計(jì)算相應(yīng)的協(xié)方差矩陣呢?類似于矩陣奇異值分解的秩-1 展開式,協(xié)方差矩陣也可以寫為另一種形式,即展開為
對照式 (1) 和式 (2),會(huì)發(fā)現(xiàn)它們其實(shí)是同一個(gè)協(xié)方差矩陣的兩種表示形式。回到核問題,此時(shí)將高維空間中的點(diǎn)代入,得
同樣的,我們不知道映射函數(shù)
回顧一下 PCA(可以看這篇),我們需要找到滿足
仔細(xì)一看,發(fā)現(xiàn)所有解
張成的空間內(nèi)。即存在系數(shù)
從 PCA 方法那里可知,我們只需要知道上式中的系數(shù)就知道了所謂的主方向 PC。因此,問題轉(zhuǎn)化為如何求解這些系數(shù)
我們可以考慮一個(gè)等價(jià)系統(tǒng),即對于所有
將式 (3) 和式 (4) 代入式 (5),將出現(xiàn)我們真正需要計(jì)算的新特征間的內(nèi)積,即
接下來,我們?nèi)缦露x一個(gè)
由上面兩式可得,
其中
顯然,式 (8) 的所有解都滿足式 (7)。
如果對解
而對于投影到主成分,我們可以根據(jù)以下公式計(jì)算測試點(diǎn)
到此,第二個(gè)問題,即在高維空間中的投影問題也被搞定了。
注意,式 (6) 和式 (10) 都不需要提供映射函數(shù)
,僅需內(nèi)積即可。
因此,我們能夠使用核函數(shù)來模擬這些內(nèi)積,而無需給出實(shí)際的映射函數(shù)。常用的核函數(shù)有多項(xiàng)式核,
徑向基核
以及 sigmoid 核
等等??梢宰C明,次數(shù)為
小結(jié)
不知道映射函數(shù)
仔細(xì)一想,在高維特征空間中計(jì)算協(xié)方差矩陣也好,投影到主成分也好,其實(shí)都是以內(nèi)積的形式出現(xiàn)的。
因此,完全可以繞過對映射函數(shù)的依賴,直接用某些核函數(shù)來模擬高維空間中向量的內(nèi)積來間接執(zhí)行 PCA。當(dāng)然,這個(gè)內(nèi)積的效果好不好,也只有試了才知道。
附錄
最后,來一個(gè)小例子快速實(shí)驗(yàn)一下,我們使用 sklearn.decomposition 實(shí)現(xiàn)好的版本分別采用 rbf 核和多項(xiàng)式核來對三個(gè)同心圓數(shù)據(jù)執(zhí)行 KPCA,發(fā)現(xiàn)這個(gè)例子中 rbf 的效果優(yōu)于多項(xiàng)式核。
X1, y1 = make_circles(n_samples=500, random_state=123, noise=0.1, factor=0.1)X1 = X1*0.5
X2, y2 = make_circles(n_samples=500, random_state=123, noise=0.1, factor=0.5)X = np.r_[X1, X2]y = np.r_[1-y1, 2-y2]plt.figure(figsize=(7.5,7.5))plt.scatter(X[y==0, 0], X[y==0, 1], color='red', marker='+', alpha=0.5)plt.scatter(X[y==1, 0], X[y==1, 1], color='green', marker='s', alpha=0.5)plt.scatter(X[y==2, 0], X[y==2, 1], color='blue', marker='o', alpha=0.5)plt.show()

from sklearn.decomposition import KernelPCAkpca_0 = KernelPCA(kernel='rbf',fit_inverse_transform=True,gamma=3.5)X_kpca_0 = kpca_0.fit_transform(X)kpca_1 = KernelPCA(kernel='poly',degree=1,fit_inverse_transform=True,gamma=1.0)X_kpca_1 = kpca_1.fit_transform(X)
fig, ax = plt.subplots(nrows=1,ncols=2, figsize=(12,6))ax[0].scatter(X_kpca_0[y==0, 0], X_kpca_0[y==0, 1],color='red', marker='+', alpha=0.5)ax[0].scatter(X_kpca_0[y==1, 0], X_kpca_0[y==1, 1],color='green', marker='s', alpha=0.5)ax[0].scatter(X_kpca_0[y==2, 0], X_kpca_0[y==2, 1],color='blue', marker='o', alpha=0.5)ax[1].scatter(X_kpca_1[y==0, 0], X_kpca_1[y==0, 1],color='red', marker='+', alpha=0.5)ax[1].scatter(X_kpca_1[y==1, 0], X_kpca_1[y==1, 1],color='green', marker='s', alpha=0.5)ax[1].scatter(X_kpca_1[y==2, 0], X_kpca_1[y==2, 1],color='blue', marker='o', alpha=0.5)ax[0].set_xlabel('PC1')ax[0].set_ylabel('PC2')ax[1].set_ylim([-1, 1])ax[1].set_yticks([])ax[1].set_xlabel('PC1')plt.show()

參考資料
kpca: https://people.eecs.berkeley.edu/~wainwrig/stat241b/scholkopf_kernel.pdf
