核主成分分析(Kernel Principal Component Analysis, KPCA)的公式推導過程


KPCA,中文名稱”核主成分分析“,是對PCA算法的非線性擴展,言外之意,PCA是線性的,其對於非線性數據往往顯得無能為力,例如,不同人之間的人臉圖像,肯定存在非線性關系,自己做的基於ORL數據集的實驗,PCA能夠達到的識別率只有88%,而同樣是無監督學習的KPCA算法,能夠輕松的達到93%左右的識別率(雖然這二者的主要目的是降維,而不是分類,但也可以用於分類),這其中很大一部分原因是,KPCA能夠挖掘到數據集中蘊含的非線性信息。

1. 理論部分

KPCA的公式推導和PCA十分相似,只是存在兩點創新:

1. 為了更好地處理非線性數據,引入非線性映射函數,將原空間中的數據映射到高維空間,注意,這個是隱性的,我們不知道,也不需要知道它的具體形式是啥。

2. 引入了一個定理:空間中的任一向量(哪怕是基向量),都可以由該空間中的所有樣本線性表示,這點對KPCA很重要,我想大概當時那個大牛想出KPCA的時候,這點就是它最大的靈感吧。話說這和”稀疏“的思想比較像。

假設中心化后的樣本集合X(d*N,N個樣本,維數d維,樣本”按列排列“),現將X映射到高維空間,得到,假設在這個高維空間中,本來在原空間中線性不可分的樣本現在線性可分了,然后呢?想啥呢!果斷上PCA啊!~

於是乎!假設D(D >> d)維向量為高維空間中的特征向量,為對應的特征值,高維空間中的PCA如下:

     (1)   

和PCA太像了吧?這個時候,在利用剛才的定理,將特征向量利用樣本集合線性表示,如下:

 (2)  

然后,在把代入上上公式,得到如下的形式:

 (3)  

進一步,等式兩邊同時左乘,得到如下公式:

 (4)  

 

你可能會問,這個有啥用?

這樣做的目的是,構造兩個出來,進一步用核矩陣K(為對稱矩陣)替代,其中:

  (5)  

第二個等號,是源於核函數的性質,核函數比較多,有如下幾種:

於是,公式進一步變為如下形式:

  (6)  

兩邊同時去除K,得到了PCA相似度極高的求解公式:

(7)

求解公式的含義就是求K最大的幾個特征值所對應的特征向量,由於K為對稱矩陣,所得的解向量彼此之間肯定是正交的。

但是,請注意,這里的只是K的特征向量,但是其不是高維空間中的特征向量,回看公式(2),高維空間中的特征向量w應該是由進一步求出。

這時有的朋友可能會問,這個時候,如果給定一個測試樣本,應該如何降維,如何測試?

是這樣的,既然我們可以得到高維空間的一組基,這組基可以構成高維空間的一個子空間,我們的目的就是得到測試樣本在這個子空間中的線性表示,也就是降維之后的向量。具體如下:

(8)

於是呼~就可以對降維了,然后就做你想要做的事情。。。。

 

2. 實驗部分

做了一些仿真實驗,分別比較了PCA與KPCA之間的效果,KPCA基於不同核函數的效果,二者對於原始數據的要求,以及效果隨着參數變化的規律。

1)下面展示的是“無重疊的”非線性可分數據下,PCA與KPCA(基於高斯核)的區別,注意,原始數據是二維數據,投影之后也是二維數據

2)下面展示的是“部分重疊的”非線性可分數據下,PCA與KPCA的區別

3)下面展示的是“無高斯擾動的”非線性可分數據下,PCA與KPCA的區別

4)下面展示的是上述三類數據下,基於多項式核函數的KPCA效果

5)下面展示的是在“部分重疊的”非線性可分數據下,基於多項式核函數的KPCA在不同多項式參數下的效果圖

 

3. 實驗結論

1. 從2.1中我們可以看出,PCA與KPCA對於非線性數據各自的處理能力,仔細觀察PCA其實只對原始數據進行了旋轉操作,這是由於其尋找的是數據的“主要分布方向”。KPCA可以將原始數據投影至線性可分情況,其原因就是第一部分所說的內容。
 
2. 至於為何將數據分為“無重疊”,“部分重疊”,“無高斯擾動”,是自己在試驗中發現,對於部分重疊的數據,KPCA不能將數據投影至完全線性可分的程度(2.3第三幅圖中,不同類別數據仍舊存在重疊現象),這說明KPCA只是個無監督的降維算法,它不管樣本的類別屬性,只是降維而已。
 
3. 這里提供了高斯核與多項式核的效果,我們很容易發現,二者的效果有很大不同,這直觀地說明不同核函數具有不同的特質。並且,針對於無高斯擾動數據,始終沒有找到參數p,有可能針對這類數據,多項式核函數無能為力。
 
4. 2.5中展示了多項式核的參數影響,我們可以發現,往往p值是偶數時,數據可以做到近似線性可分,p是奇數時,數據分布的形態也屬於另外一種固定模式,但是不再是線性可分。
 

4. 代碼

前面給出了自己對KPCA的理論解釋,以及做的一些基礎實驗,不給出實現代碼,就不厚道了,代碼如下所示,一部分是KPCA算法代碼,另一部分是實驗代碼。
[plain]
 
function [eigenvalue, eigenvectors, project_invectors] = kpca(x, sigma, cls, target_dim)  
    % kpca進行數據提取的函數  
    psize=size(x);  
    m=psize(1);     % 樣本數  
    n=psize(2);     % 樣本維數  
  
  
    % 計算核矩陣k  
    l=ones(m,m);  
    for i=1:m  
        for j=1:m  
           k(i,j)=kernel(x(i,:),x(j,:),cls,sigma);   
        end  
    end  
  
  
    % 計算中心化后的核矩陣  
    kl=k-l*k/m-k*l/m+l*k*l/(m*m);    
  
  
    % 計算特征值與特征向量  
    [v,e] = eig(kl);   
    e = diag(e);  
  
  
    % 篩選特征值與特征向量  
    [dump, index] = sort(e, 'descend');  
    e = e(index);  
    v = v(:, index);  
    rank = 0;  
    for i = 1 : size(v, 2)  
        if e(i) < 1e-6  
            break;  
        else  
            v(:, i) = v(:, i) ./ sqrt(e(i));  
        end  
        rank = rank + 1;  
    end  
    eigenvectors = v(:, 1 : target_dim);  
    eigenvalue = e(1 : target_dim);  
  
  
    % 投影  
    project_invectors = kl*eigenvectors;   %計算在特征空間向量上的投影   
end  

  


[plain] 
 
function compare  
    clear all;  
    close all;  
    clc;  
      
    % 生成非線性可分的三類數據  
    if exist('X1.mat')  
        load 'X1.mat'  
        load 'X2.mat'  
        load 'X3.mat'  
        figure(1)         
        plot(X1(1, :),X1(2, :) ,'ro')  
        hold on;  
        plot(X2(1, :),X2(2, :),'g*')  
        hold on;  
        plot(X3(1, :),X3(2, :),'b.')  
        hold on;  
          
        title('原始數據');  
        xlabel('第一維');  
        ylabel('第二維');  
        saveas(gcf, '原始數據圖.jpg')  
    else  
        [X1, X2, X3] = generate_data();  
        save 'X1.mat'  X1  
        save 'X2.mat'  X2  
        save 'X3.mat'  X3  
    end  
  
    X = [X1 X2 X3];  
    [nFea, nSmps] = size(X);  
    nClsSmps = nSmps / 3;  
      
    % PCA  
    [vec_pca, Y_pca, value_pca] = princomp(X');  
    Y_pca = Y_pca';  
      
    figure(2);  
    plot(Y_pca(1, 1 : nClsSmps),Y_pca(2, 1 : nClsSmps), 'ro');  
    hold on;  
    plot(Y_pca(1, nClsSmps + 1 : 2 * nClsSmps),Y_pca(2, nClsSmps + 1 : 2 * nClsSmps), 'g*');  
    hold on;  
    plot(Y_pca(1, 2 * nClsSmps + 1 : end),Y_pca(2, 2 * nClsSmps + 1 : end), 'b.');  
    hold on;  
    title('PCA');  
    xlabel('第一維');  
    ylabel('第二維');  
    saveas(gcf, 'PCA投影圖.jpg')  
      
    % KPCA  
    percent = 1;  
    var   = 2; % 1 代表高斯核,2代表多項式核,3代表線性核  
    sigma = 6; % 核參數  
    [vec_KPCA, value_KPCA, Y_pca] = kpca(X', sigma, var, 2);  
    Y_pca = Y_pca';  
      
    figure(3);  
    plot(Y_pca(1, 1 : nClsSmps),Y_pca(2, 1 : nClsSmps), 'ro');  
    hold on;  
    plot(Y_pca(1, nClsSmps + 1 : 2 * nClsSmps),Y_pca(2, nClsSmps + 1 : 2 * nClsSmps), 'g*');  
    hold on;  
    plot(Y_pca(1, 2 * nClsSmps + 1 : end),Y_pca(2, 2 * nClsSmps + 1 : end), 'b.');  
    hold on;  
    str = strcat('KPCA', '(p =', num2str(sigma), ')');  
    title(str);  
    xlabel('第一維');  
    ylabel('第二維');  
    str = strcat(str, '.jpg')  
    saveas(gcf, str)  
end  

 

 

5. 總結

KPCA的算法雖然簡單,但是個人認為,它的意義更在於一種思想:將數據隱式映射到高維線性可分空間,利用核函數進行處理,無需知道映射函數的具體形式。這種思想實在是太牛了,它讓降維變得更有意義。為這種思想點贊!!!
 

轉自:http://blog.csdn.NET/wsj998689aa/article/details/40398777   作者:迷霧forest


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM