PCA matlab實現

PCA 流程如下:

1、去均值  2、計算協方差矩陣 3、計算協方差特徵值和特徵向量 4、降序排列特徵值選取較大的特徵值,選擇相應的特徵值和特徵向量

以下按照步驟編寫matlab代碼。

 

1.去均值

Matlab函數mean可得:如下

Mean_Image=mean(Train_SET,2); 
Train_SET=Train_SET-Mean_Image*ones(1,Train_NUM);

2.計算協方差矩陣


協方差定義:

具體求解:


*注意分母爲(n-1)而不是n,因爲這樣定義的協方差方差是總體方差的無偏估計(具體可見:

http://en.wikipedia.org/wiki/Unbiased_estimator#Sample_variancehttp://www.zhihu.com/question/20099757

 

協方差矩陣如下:

其元素aij表示變量i,j之間的協方差cov(i,j);

(關於協方差矩陣的含義,可見blog:http://blog.csdn.net/ice110956/article/details/14250745

 

計算方法:

A.

其中Xj爲去中心化之後的特徵向量。

去中心化後,可表示爲如下:


求和之後,可以得到協方差矩陣。

 

B.

同理,上面的向量相加我們可以直接用矩陣相乘的形式得到。

設X爲去中心後的特徵矩陣,那麼


 

C.

直接用matlab自帶的協方差的函數cov()計算,不過注意cov按行計算,實際運用時要轉置。

 

我們使用矩陣形式,得到如下代碼:

R=Train_SET*Train_SET'/(Train_NUM-1);

3.計算特徵值與特徵向量

 

根據PCA的原理,我們需要尋找使協方差矩陣對角化的變換矩陣

(可見blog:http://blog.csdn.net/ice110956/article/details/14250745)。


一個方陣可以寫成如下形式:

 

其中Q爲其特徵向量組成的矩陣,爲其特徵值組成的對角矩陣,轉化一下式子,得到:

於是,我們現在只要得到協方差矩陣的歸一化特徵向量,組成轉化矩陣Q即可。

 

使用matlab自帶的函數eig(),

代碼:

[V,S]=eig(R);

**小樣本問題:

上面的代碼存在一個問題,就是常見的小樣本問題。樣本維數>>樣本個數,這樣得到的協方差矩陣很大,直接求解時間複雜度過高。於是我們通過另一種方式來求解。

 

SVD(奇異值分解):

 

A.奇異值

設A爲m*n階實矩陣,則存在m階正交陣U和n階正交陣V,使得

 

  A = U*S*V’

 

其中S=diag(σi,σ2,……,σr),σi>0 (i=1,…,r),r=rank(A)。

 

其中:

 

對任意矩陣A,它的奇異值就是AA'或A'A的非零特徵值的開方(它們有相同的非零特徵值),這些特徵值都是正數。

U 爲AA'單位特徵向量矩陣。

V爲A’A單位特徵向量矩陣。

 

B.奇異值與特徵值的聯繫

奇異值有類似於特徵值的性質,當矩陣爲共軛對稱矩陣時,特徵值=奇異值。不過一般情況是不相同的。

如果把矩陣看做一個線性變換,那麼特徵值表徵了其特徵向量方向的能量大小。根據定義我們可以看出,奇異值也有類似的性質

 

C.奇異值分解與PCA的關係

通過變換,我們可以得到:


也就是,已知A,V,我們可以求得U。

 

如上,如果AA’維數過大,計算機不好求解其特徵向量U,那麼我們可以轉而求A’*A的特徵向量V。

求解PCA的過程中,對於小樣本問題,樣本維數M>>樣本個數N,那麼X*X’得到的協方差矩陣爲M*M,不好特徵分解。如果我們根據SVD的原理,解X’*X(N*N)的特徵向量,最後再變化,也能達到同樣的目的。

 

(SVD具體可見:

http://www.cnblogs.com/LeftNotEasy/archive/2011/01/19/svd-and-applications.html

http://szshdy.blog.163.com/blog/static/1322012512010511156587/

 

通過奇異值分解,得到協方差矩陣特徵向量,代碼如下:

R=Train_SET'*Train_SET/(Train_NUM-1);
 
  [V,S]=Find_K_Max_Eigen(R,Eigen_NUM);
  disc_value=S;
  disc_set=zeros(NN,Eigen_NUM);
 
  Train_SET=Train_SET/sqrt(Train_NUM-1);
  for k=1:Eigen_NUM
   disc_set(:,k)=(1/sqrt(disc_value(k)))*Train_SET*V(:,k);
  end

4.完整代碼

最終,整合上述的代碼,得到如下完整的PCA代碼:

function [disc_set,disc_value,Mean_Image]=Eigenface_f(Train_SET,Eigen_NUM)


[NN,Train_NUM]=size(Train_SET);

if NN<=Train_NUM 
    
   Mean_Image=mean(Train_SET,2);  
   Train_SET=Train_SET-Mean_Image*ones(1,Train_NUM);
   R=Train_SET*Train_SET'/(Train_NUM-1);
   
   [V,S]=Find_K_Max_Eigen(R,Eigen_NUM);
   disc_value=S;
   disc_set=V;

else % 小樣本問題,svd
    
   Mean_Image=mean(Train_SET,2);  
   Train_SET=Train_SET-Mean_Image*ones(1,Train_NUM);

  R=Train_SET'*Train_SET/(Train_NUM-1);
  
  [V,S]=Find_K_Max_Eigen(R,Eigen_NUM);
  disc_value=S;
  disc_set=zeros(NN,Eigen_NUM);
  
  Train_SET=Train_SET/sqrt(Train_NUM-1);
  for k=1:Eigen_NUM
    disc_set(:,k)=(1/sqrt(disc_value(k)))*Train_SET*V(:,k);
  end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [Eigen_Vector,Eigen_Value]=Find_K_Max_Eigen(Matrix,Eigen_NUM)

[NN,NN]=size(Matrix);
[V,S]=eig(Matrix); %Note this is equivalent to; [V,S]=eig(St,SL); also equivalent to [V,S]=eig(Sn,St); %

S=diag(S);
[S,index]=sort(S);

Eigen_Vector=zeros(NN,Eigen_NUM);
Eigen_Value=zeros(1,Eigen_NUM);

p=NN;
for t=1:Eigen_NUM
    Eigen_Vector(:,t)=V(:,index(p));
    Eigen_Value(t)=S(p);
    p=p-1;
end


發佈了89 篇原創文章 · 獲贊 51 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章