【人臉識別】基於matlab PCA+LDA人臉識別【含Matlab原始碼 680期】
一、簡介
1 PCA
1.1 資料降維
降維的方法包括:主成分分析(PCA)、因子分析(FA)、和獨立成分分析(ICA)
主成分分析:尋找向量,使各個樣本到該向量的投影之和最小。
因子分析:
獨立成分分析:
1.2 PCA:目的是降維,降維的實際原理是最大化目標函式(資料投影后的方差最大)
強推原理博文:https://blog.csdn.net/fendegao/article/details/80208723
(1)假設有m個n維樣本: {Z1,Z2,…,Zm}
(2)樣本中心 u 為: 所有樣本觀測值之和/(mxn)
(3)去中心化後,得到矩陣 {X1,X2,…,Xm}={Z1-U,Z2-U,…,Zm-U}
(4)記含有n個元素的向量W,則樣本X1在w方向上的投影為二者內積 X1 . W
(5)PCA的目標函式為最大化投影
目標方程可以化為矩陣形式求解,求解方法:
(1)構建拉格朗日運算元,求導為0,解得投影最大的向量為特徵值最大對應的特徵向量。
根據特徵值的累計貢獻率可以指定選取多少個W向量作為K-L變換矩陣。若選擇了4個主成分,則對於每一個n維度樣本,經過矩陣變換後,都變為了(1xn)x(nx4)=1x4維向量,即達到了降維的目的。
(2)SVD奇異值分解:降維只需求出右奇異矩陣,即AA(T)的特徵向量,不需要求A的協方差矩陣。對記憶體友好。
1.3 基於PCA的人臉識別
(1)基於人臉樣本庫,例如現實中人臉拍照(銀行、車站)等資料採集方法,建立人臉庫。
(2)求取訓練人臉庫的協方差陣的特徵值和特徵向量。
(3)對於需要判別的人臉,判斷其在特徵向量上的投影與哪個訓練樣本的投影最接近。
!!!注::需要注意,協方差矩陣是維度之間的協方差,故是nxn維,但是在實際應用時,例如影象降維(假設一幅影象有200*10個畫素,有100幅影象),一個畫素就是一個維度,則原本協方差陣XX’為 (2000x100)x (100x2000)維,計算機儲存計算消耗過大,此時可以考慮使用替代矩陣P=X’X(100x2000)x(2000x100)替代:
P的特徵值即原始協方差陣的特徵值,P的特徵向量左乘資料矩陣即為原始協方差陣的特徵向量。
2 LDA
LDA:線性判別分析,也稱為Fisher線性判別,是常用的降維技術。
基本思想:將高維的模式樣本投影到最佳鑑別向量空間,以達到抽取分類資訊和壓縮特徵空間維數的效果,投影后保證模式樣本在新的子空間有最大的類間距離和最小的類內距離,即模式在該空間中有最佳的可分離性。
LDA降維後的維度是直接和類別的個數相關的,與資料本身的維度沒關係,比如原始資料是n維的,一共有C個類別,那麼LDA降維之後,維數取值範圍為(1,C-1),舉個例子,假設影象分類,兩個類別正例反例,每個影象用10000維特徵表示,那麼LDA之後,就只有1維特徵,並且這維特徵的分類能力最好。
對於很多兩類分類的情況,LDA之後就剩下1維,找到分類效果最好的一個閾值貌似就可以了。
假設,x是一個N維的列向量,要使x通過LDA降到C維,只需要找到一個投影矩陣w,也即,一個N*C的矩陣,讓w的轉置矩陣和x相乘,便成為C維的了。(投影在數學上的表示就是用一個矩陣去相乘)
此時,問題的關鍵就在於:尋找一個投影矩陣!並且,該投影矩陣要保證模式樣本在新的子空間有最大的類間距離和最小的類內距離。
2.2 LDA數學表示:
二、原始碼
clear all
clc
close all
start=clock;
sample_class=1:40;%樣本類別
sample_classnum=size(sample_class,2);%樣本類別數
fprintf('程式執行開始....................\n\n');
for train_samplesize=3:8;
train=1:train_samplesize;%每類訓練樣本
test=train_samplesize+1:10;%每類測試樣本
train_num=size(train,2);%每類訓練樣本數
test_num=size(test,2);%每類測試樣本數
address=[pwd '\ORL\s'];
%讀取訓練樣本
allsamples=readsample(address,sample_class,train);
%先使用PCA進行降維
[newsample base]=pca(allsamples,0.9);
%計算Sw,Sb
[sw sb]=computswb(newsample,sample_classnum,train_num);
%讀取測試樣本
testsample=readsample(address,sample_class,test);
best_acc=0;%最優識別率
%尋找最佳投影維數
for temp_dimension=1:1:length(sw)
vsort1=projectto(sw,sb,temp_dimension);
%訓練樣本和測試樣本分別投影
tstsample=testsample*base*vsort1;
trainsample=newsample*vsort1;
%計算識別率
accuracy=computaccu(tstsample,test_num,trainsample,train_num);
if accuracy>best_acc
best_dimension=temp_dimension;%儲存最佳投影維數
best_acc=accuracy;
end
end
%---------------------------------輸出顯示----------------------------------
fprintf('每類訓練樣本數為:%d\n',train_samplesize);
fprintf('最佳投影維數為:%d\n',best_dimension);
fprintf('FisherFace的識別率為:%.2f%%\n',best_acc*100);
fprintf('程式執行時間為:%3.2fs\n\n',etime(clock,start));
end
function [newsample basevector]=pca(patterns,num)
%主分量分析程式,patterns表示輸入模式向量,num為控制變數,當num大於1的時候表示
%要求的特徵數為num,當num大於0小於等於1的時候表示求取的特徵數的能量為num
%輸出:basevector表示求取的最大特徵值對應的特徵向量,newsample表示在basevector
%對映下獲得的樣本表示。
[u v]=size(patterns);
totalsamplemean=mean(patterns);
for i=1:u
gensample(i,:)=patterns(i,:)-totalsamplemean;
end
sigma=gensample*gensample';
[U V]=eig(sigma);
d=diag(V);
[d1 index]=dsort(d);
if num>1
for i=1:num
vector(:,i)=U(:,index(i));
base(:,i)=d(index(i))^(-1/2)* gensample' * vector(:,i);
end
else
sumv=sum(d1);
for i=1:u
if sum(d1(1:i))/sumv>=num
l=i;
break;
end
end
for i=1:l
vector(:,i)=U(:,index(i));
base(:,i)=d(index(i))^(-1/2)* gensample' * vector(:,i);
end
end
function sample=readsample(address,classnum,num)
%這個函式用來讀取樣本。
%輸入:address就是要讀取的樣本的地址,classnum代表要讀入樣本的類別,num是每類的樣本;
%輸出為樣本矩陣
allsamples=[];
image=imread([pwd '\ORL\s1_1.bmp']);%讀入第一幅影象
[rows cols]=size(image);%獲得影象的行數和列數
for i=classnum
for j=num
a=imread(strcat(address,num2str(i),'_',num2str(j),'.bmp'));
b=a(1:rows*cols);
b=double(b);
allsamples=[allsamples;b];
end
end
三、執行結果
四、備註
版本:2014a
完整程式碼或代寫加1564658423