Kernel PCA 原理和演示
主成份(Principal Component Analysis)分析是降維(Dimension Reduction)的重要手段。每一個主成分都是數據在某一個方向上的投影,在不同的方向上這些數據方差Variance的大小由其特徵值(eigenvalue)決定。一般我們會選取最大的幾個特徵值所在的特徵向量(eigenvector),這些方向上的信息豐富,一般認為包含了更多我們所感興趣的信息。當然,這裡面有較強的假設:
(1)特徵根的大小決定了我們感興趣信息的多少。即小特徵根往往代表了雜訊,但實際上,向小一點的特徵根方向投影也有可能包括我們感興趣的數據;
(2)特徵向量的方向是互相正交(orthogonal)的,這種正交性使得PCA容易受到Outlier的影響,例如在文獻[1]中提到的例子;
(3)難於解釋結果。例如在建立線性回歸模型(Linear Regression Model)分析因變數(response)和第一個主成份的關係時,我們得到的回歸係數(Coefficiency)不是某一個自變數(covariate)的貢獻,而是對所有自變數的某個線性組合(Linear Combination)的貢獻。
在Kernel PCA分析之中,我們同樣需要這些假設,但不同的地方是我們認為原有數據有更高的維數,我們可以在更高維的空間(Hilbert Space)中做PCA分析(即在更高維空間里,把原始數據向不同的方向投影)。這樣做的優點有:對於在通常線性空間難於線性分類的數據點,我們有可能再更高維度上找到合適的高維線性分類平面。我們第二部分的例子就說明了這一點。
本文寫作的動機是因為作者沒有找到一篇好的文章(看了wikipedia和若干google結果後)深層次介紹PCA和Kernel PCA之間的聯繫,以及如何以公式形式來解釋如何利用Kernel PCA來做投影,特別有些圖片的例子只是展示了結果和一些公式,這裡面具體的過程並沒有涉及。希望這篇文章能做出較好的解答。
1. Kernel Principal Component Analysis 的矩陣基礎
我們從解決這幾個問題入手:傳統的PCA如何做?在高維空間里的PCA應該如何做?如何用Kernel Trick在高維空間做PCA?如何在主成分方向上投影?如何Centering 高維空間的數據?
1.1 傳統的PCA如何做?
讓我先定義如下變數: 是一個矩陣,代表輸入的數據有個,每個sample的維數是。我們做降維,就是想用維的數據來表示原始的維數據()。
當我們使用centered的數據(即)時,可定義協方差矩陣為:
做特徵值分解,我們可以得到:
注意這裡的,,的維數都是, 且, 。當我們做降維時,可以利用前個特徵向量。則將一個維的向維的主成分的方向投影后的數據為(這裡的每一個都是維的,代表是一個投影方向,且,表示這是一個旋轉變數)
1.2 在高維空間里的PCA應該如何做?
高維空間中,我們定義一個映射,這裡表示Hilbert泛函空間。
現在我們的輸入數據是,他們的維數可以是無窮維的(泛函空間),為了方便討論,設其空間的維數為()。在這個新的空間(特徵空間)中,將中心化的數據記為,即其中
將中心化的核矩陣記為(具體求法見*****),且定義
中心化的數據()的協方差矩陣為:
這裡有一個陷阱:
在對Kernel trick一知半解的時候,我們常常從形式上認為可以用來代替,因此對做特徵值分解,然後得到,並且對原有數據降維的時候,定義。但這個錯誤的方法有兩個問題:一是我們不知道矩陣的維數,也即不知道的具體形式;二是從形式上看不出是從高維空間的的投影,並且當有新的數據時,我們無法從理論上理解是從高維空間的投影,後面(11111)發現,投影方向不是這裡的。如果應用這種錯誤的方法,我們有可能得到看起來差不多正確的結果,但本質上這是錯誤的。正確的方法是通過Kernel trick將PCA投影的過程通過內積的形式表達出來,詳細見1.31.3 如何用Kernel Trick在高維空間做PCA?
在1.1節中,通過PCA,我們得到了矩陣。這裡將介紹如何僅利用內積的概念來計算傳統的PCA。
首先我們證明U可以由展開(span):由於得進而我們顯示PCA投影可以用內積運算表示,例如我們把向任意一個主成分分量進行投影,得到的是,也就是。作者猜測寫成這種形式是為了能抽出的內積形式。
也就是說,對於,
將其寫成矩陣的形式為:
當我們定義時,上式可以寫為(這裡定義為.)
進一步,我們得到解為:
,其中矩陣包含特徵值和特徵向量,我們可以通過可以計算得到特徵向量。注意特徵值分解(Eigen decomposition)時,只代表一個方向,它的長度(模長)一般為1,但在此處不為1。下面計算出的長度(下面將要用到):因為的長度是1,我們有:
所以在上面的分析過程中,我們使用了內積的思想完成了傳統PCA的過程,即可以通過核矩陣的特徵值和特徵向量計算協方差矩陣的特徵值和特徵向量
(PS:不要問為什麼不直接用協方差矩陣進行特徵值分解(SVD),得到想要的主方向。請記住在特徵空間的協方差矩陣式是不能得到的,所以不能進行大俠想的特徵分解)。1.4 KPCA實現
下面我們重複1.3過程,看看KPCA中的有關推導。
設的特徵值和對應的特徵向量分別為和,即
由1.3知,,即存在,使得:
用同時作用於得
上式左邊可以化為:
其中
,
右邊可以化為:
讓依次取遍的所有數,得到上面推到的「左邊=右邊」的矩陣表示:
化簡得到
即之前假設的為中心化的核矩陣的第個特徵向量(對應的特徵值為)。現在我們可以用所求的和去表示協方差矩陣的特徵值和向量:
,,其中
現在還有個小問題沒有解決,在傳統PCA方法中,協方差矩陣得到的特徵向量是單位正交的。同樣,我們希望也是單位向量,即:
因此,將的特徵向量的長度歸一化到,便能保證的長度為1。
下面證明正交性:
得證!
最後總結下之前的結論,特徵空間中協方差矩陣的特徵值為,對應的特徵向量為,,其中和為的 特徵值和特徵向量。
由於映射未知,直接在特徵空間內進行數據中心化不可行,直接將輸入數據在特徵空間中心化的過程見1.6。
1.5 如何在主成分方向上投影?
傳統PCA投影時,只需要使用矩陣,假設我們得到的新數據為,那麼在方向的投影是:
對於高維空間的數據,,我們可以用Kernel trick,用來帶入上式:
一般不能顯式得到,從而需要計算輸入數據的中心化核矩陣,記為。
1.5 如何Centering 高維空間的數據?
在我們的分析中,協方差矩陣的定義需要centered data。在高維空間中,顯式的將中心化並不簡單, 因為我們並不知道的顯示錶達。但從上面兩節可以看出,所有的計算只和矩陣有關。具體計算如下:
令,居中:不難看出,
其中為的矩陣,其中每一個元素都是。對於新的數據,如果數據:所以:
如果數據,則上式中有,且。
2. 演示 (R code)
首先我們應該注意輸入數據的格式,一般在統計中,我們要求矩陣是的,但在我們的推導中,矩陣是。
這與統計上的概念並不矛盾:在前面的定義下協方差矩陣為,而在後面的定義中是。另外這裡的協方差矩陣是樣本(Sample)的協方差矩陣,我們的認為大寫的代表矩陣,而不是代表一個隨機變數。另外,在下面的結果中,Gaussian 核函數(kernel function)的標準差(sd)為2。在其他取值條件下,所得到的圖像是不同的。KPCA圖片:
R 源代碼(Source Code):鏈接到完整的代碼 KernelPCA
Kernel PCA部分代碼:
# Kernel PCA# Polynomial Kernel# k(x,y) = t(x) %*% y + 1k1 = function (x,y) { (x[1] * y[1] + x[2] * y[2] + 1)^2 }K = matrix(0, ncol = N_total, nrow = N_total)for (i in 1:N_total) { for (j in 1:N_total) { K[i,j] = k1(X[i,], X[j,])}}ones = 1/N_total* matrix(1, N_total, N_total)K_norm = K - ones %*% K - K %*% ones + ones %*% K %*% onesres = eigen(K_norm) V = res$vectorsD = diag(res$values) rank = 0for (i in 1:N_total) { if (D[i,i] < 1e-6) { break } V[,i] = V[,i] / sqrt (D[i,i]) rank = rank + 1}Y = K_norm %*% V[,1:rank]plot(Y[,1], Y[,2], col = rainbow(3)[label], main = "Kernel PCA (Poly)", xlab="x", ylab="y")
實例:
function demo_kpca_ushape%% PARAMETERSN_split = [30, 30, 60]; % number of data points in 2 straight parts and curve of "U"corners = [3 4 2 4]; % corners: x1 x2 y1 y2nvar = 0.05; % noise variancekernel.type = gauss;kernel.par = .5;numeig = 4; % number of eigenvalues to plotNtest = [50,50]; % number of test grid divisions, in each dimensionborder = [0 6 0 6]; % test grid border %% PROGRAMtic%% generate dataN = sum(N_split);N1 = N_split(1); N2 = N_split(2); N3 = N_split(3);X1 = [linspace(corners(1),corners(2),N1) repmat(corners(3),N1,1)]; % lower straight partX2 = [linspace(corners(1),corners(2),N2) repmat(corners(4),N2,1)]; % upper straight partangles = linspace(pi/2,3*pi/2,N3);rad = (corners(4)-corners(3))/2;m3 = [corners(1) corners(3)+rad];X3 = repmat(m3,N3,1) + rad*[cos(angles) sin(angles)];n = nvar*randn(N,2);X = [X1; X2; X3] + n;%% generate test grid dataNt1 = Ntest(1); Nt2 = Ntest(2);Xtest = zeros(Nt1*Nt2,2);absc = linspace(border(1),border(2),Nt1);ordi = linspace(border(3),border(4),Nt2);for i=1:Nt1, for j=1:Nt2, Xtest((i-1)*Nt2+j,:) = [absc(i) ordi(j)]; endend%% calculate kernel principal components and projections of Xtest[E,v] = km_kpca(X,numeig,kernel.type,kernel.par);Kt = km_kernel(X,Xtest,kernel.type,kernel.par); % kernels of test data setXtestp = E*Kt; % projections of test data set on the principal directionsY = cell(numeig,1);for i=1:numeig, Y{i} = reshape(Xtestp(i,:),Nt2,Nt1); % shape into 2D gridendtoc%% OUTPUTsubplot(3,2,1)plot(X(:,1),X(:,2),.)% axis(border)title(original data of shape U)% fireworks!for i=1:numeig, subplot(2,3,i+2); hold on [C,h] = contourf(-interp2(Y{i},2),25); plot(X(:,1)/border(2)*(Nt1*4-1)+1,X(:,2)/border(4)*(Nt2*4-1)+1,o,... MarkerFaceColor,White,MarkerEdgeColor,Black) title([projections to the ,num2str(i), th principal directions]) set(gca, XTick, []) set(gca, YTick, [])end%Additional functionfunction [E,v] = km_kpca(X,m,ktype,kpar)n = size(X,1);K = km_kernel(X,X,ktype,kpar);[E,V] = eig(K);v = diag(V); % eigenvalues[v,ind] = sort(v,descend);v = v(1:m);E = E(:,ind(1:m)); % principal componentsfor i=1:m E(:,i) = E(:,i)/sqrt(n*v(i)); % normalizationendfunction K = km_kernel(X1,X2,ktype,kpar)switch ktype case gauss % Gaussian kernel sgm = kpar; % kernel width dim1 = size(X1,1); dim2 = size(X2,1); norms1 = sum(X1.^2,2); norms2 = sum(X2.^2,2); mat1 = repmat(norms1,1,dim2); mat2 = repmat(norms2,dim1,1); distmat = mat1 + mat2 - 2*X1*X2; % full distance matrix K = exp(-distmat/(2*sgm^2)); case gauss-diag % only diagonal of Gaussian kernel sgm = kpar; % kernel width K = exp(-sum((X1-X2).^2,2)/(2*sgm^2)); case poly % polynomial kernel p = kpar(1); % polynome order c = kpar(2); % additive constant K = (X1*X2 + c).^p; case linear % linear kernel K = X1*X2; otherwise % default case error (unknown kernel type)end
結果
3. 主要參考資料
[1] A Tutorial on Principal Component Analysis ,Jonathon Shlens, Shlens03
[2] Wikipedia: http://en.wikipedia.org/wiki/Kernel_principal_component_analysis
[3] Original KPCA Paper:Kernel principal component analysis,Bernhard Sch?lkopf, Alexander Smola and Klaus-Robert Müller http://www.springerlink.com/content/w0t1756772h41872/fulltext.pdf
[4] Max Wellings』s classes notes for machine learning Kernel Principal Component Analaysis http://www.ics.uci.edu/~welling/classnotes/papers_class/Kernel-PCA.pdf
轉載(糾正部分錯誤)http://zhanxw.com/blog/2011/02/kernel-pca-原理和演示/
推薦閱讀:
※崛起中的機器文明
※EdX-Columbia機器學習課第5講筆記:貝葉斯線性回歸
※[視頻講解]史上最全面的正則化技術總結與分析--part1
※【翻譯】Brian2高級指導_Brian如何工作
TAG:機器學習 |