2020.12.16新增:
哈哈,遲來的原始碼,csdn要積分,我把它放到github上了:pca+svm用於人臉檢測原始碼;歡迎取用,歡迎討論,歡迎star;
###################正文分割線######################
基於pca+svm的人臉識別演算法流程:
(1)輸入訓練資料,資料預處理;
(2)進行pca降維;
(3)進行多分類的svm訓練(人臉識別為多分類問題,可分為多個二分類svm分類器);
(4)輸入檢測資料並利用上一步的訓練結果進行分類;
(5)計算準確率並顯示結果。
網上關於pca用於人臉識別的文章有很多,大家可以參考這篇文章matlab pca+svm人臉識別(一),我的**部分是參考這個寫的,只是做了簡化,讓像我一樣的初學者更容易看懂。
這裡主要講自己對pca演算法的理解,並將自己的實驗過程與大家分享。對於pca的理解,大家可以看吳恩達教授在史丹福大學的公開課主成分分析,講的非常好。
pca演算法:
(1)訓練資料預處理(令均值為零);
(2)計算協方差矩陣;
(3)找出協方差矩陣的前k個特徵向量;
(4)用前k個特徵向量與原資料矩陣相乘得到新的資料矩陣;
(5)將新得到的資料矩陣代入svm分類器中訓練。
預備知識:
向量x投影到向量u的投影長度為:
首先必須明確,我們的目的是x投影到u的方差最大化(不明白為什麼的可以看吳恩達教授的公開課)
因此我們的代價函式為:
下面,我將簡單分析pca+svm用於人臉識別的**:
先貼出主程式demo.m,用到的資料集是orl人臉庫,當維度降到30維時,人臉識別的準確率是84.5%。
%2以下部分是用自己寫的pca函式進行降維;
clc;clear;
nperson=40; %輸入的樣本類別數
imgmatrix=inputimg(nperson,0); %輸入的資料轉換為矩陣,行表示樣本數,列表示特徵維數;
ma=mean(imgmatrix); %求資料矩陣每一列的平均值;
[v,img_train_reduced]=fpca(imgmatrix,30,ma); %得到降維後的資料img_train_reduced;
lowvec=min(img_train_reduced,,1); %沿列向求最小值;
upvec=max(img_train_reduced,,1); %沿列向求最大值;
% % img_train_reduced = scaling(img_train_reduced,lowvec,upvec); %資料歸一化
multisvmstruct=multisvmtrain(img_train_reduced,nperson); %進行多分類的svm訓練;
[imgmatrix_test,realclass]=inputimg(nperson,1); %輸入測試資料;
%使得測試資料均值為0;
m=size(imgmatrix_test,1);
mdata_testmatrix=repmat(ma,m,1);
testdata=imgmatrix_test-mdata_testmatrix;
%降維後的測試資料;此處不用重新計算特徵向量v的原因是測試集跟訓練集必須保證投影在同個特徵空間裡;
img_test_reduced=testdata*v;
% % img_test_reduced = scaling(img_test_reduced,lowvec,upvec);
class=multisvm(img_test_reduced,multisvmstruct,nperson); %對每個測試樣本進行分類,分類結果儲存於class;
accuracy=sum(class==realclass')/length(class); %計算準確率;
msgbox(['識別準確率:',num2str(accuracy*100),'%']); %顯示結果;
下面貼出pca函式的**:
function [v,pcadata]=fpca(traindata,k,ma)
m=size(traindata,1);
% mdata=mean(traindata,1);
mdata_matrix=repmat(ma,m,1);
z=traindata-mdata_matrix; %使得原始資料均值為0;
a=z*z';
[u,d]=eigs(a,k); %計算a的前k個特徵值對角陣d與特徵向量u;其中u為z*z'的特徵向量;
d=inv(d); %求矩陣的逆;
v=z'*u*d; %v為z'*z的特徵向量;這一步是按照自己對svd的理解寫的,不一定正確,但對結果影響不大;
% v=z'*u; %如果對上一步有疑問,可以用這一步代替,我看別人是這樣寫的;
for i=1:k %特徵向量歸一化
l=norm(v(:,i));
v(:,i)=v(:,i)/l;
end
pcadata=z*v;
end
還有其他資料預處理,svm函式的訓練,**(注意人臉識別是多分類問題)等就不一一說了,我會把整個**打包發上來。
% 1這部分是自己用matlab自帶的princomp函式進行pca降維;
clc;clear;
nperson=40; %輸入的樣本類別數
imgmatrix=inputimg(nperson,0); %輸入的資料轉換為矩陣,行表示樣本數,列表示特徵維數;
[coeff,~,latent]=princomp(imgmatrix,'econ'); %pca降維;latent為特徵值,coeff為相應特徵值下的特徵向量;
img_train_reduced=imgmatrix*coeff(:,1:30); %降維後的訓練資料;
multisvmstruct=multisvmtrain(img_train_reduced,nperson); %進行多分類的svm訓練;
[imgmatrix_test,realclass]=inputimg(nperson,1); %輸入測試資料;
img_test_reduced=imgmatrix_test*coeff(:,1:30);
% 降維後的測試資料;此處不用重新計算特徵向量的原因是測試集跟訓練集必須保證投影在同個特徵空間裡;
class=multisvm(img_test_reduced,multisvmstruct,nperson); %對每個測試樣本進行分類,分類結果儲存於class;
accuracy=sum(class==realclass')/length(class); %計算準確率;
msgbox(['識別準確率:',num2str(accuracy*100),'%']); %顯示結果;
奇異值分解(SVD)與PCA
奇異值分解在資料降維中有較多的應用,比如pca 影象壓縮。參考文章 x 二維陣列 svd v,np.linalg.svd x,full matrices 1,compute uv 1 svd v就是算出的奇異值。主成分分析 pca scikit learn的pca演算法的背後真正的實現就是用的svd...
奇異值分解
奇異值分解 singular value decomposition 是線性代數中一種重要的 矩陣分解,是矩陣分析中正規矩陣酉對角化的推廣。在訊號處理 統計學等領域有重要應用。1基本介紹 2理論描述 3幾何意義 4範數 5應用 求偽逆 平行奇異值模型 矩陣近似值 奇異值分解在某些方面與 對稱矩陣或 ...
奇異值分解
從幾何 的角度上來看奇異值分解 上圖表明任意的矩陣 a 是可以分解成三個矩陣相乘的形式。v表示了原始域的標準正交基,u表示經過a 變換後的co domain的標準正交基,表示了v 中的向量與u中相對應向量之間的關係。我們仔細觀察上圖發現,線性變換a可以分解為旋轉 縮放 旋轉這三種基本線性變換。接下來...