基于PCA和SVM的人脸识别
svm推廣到多類情況
一對多的最大響應策略(one against all)
假設有A 、B、C.. D四類樣本需要劃分。在抽取訓練集的時候,分別按照如下4種方式劃分。
- A. 所對應的樣本特征向量作為正集(類標簽為+1), B、C、D所對應的樣本特征向量作為負集(類標簽為-1).
- B所對應的樣本特征向量作為正集,A. C. D所對應的樣本特征向量作為負集
- C所對應的樣本特征向量作為正集, A. B, D所對應的樣本特征向量作為負集.
- D所對應的樣本特征向量作為正集, A. B、 C所對應的樣本特征向量作為負集.
對上述4個訓練集分別進行訓練, 得到4個SVM分類器。在測試的時候, 把未知類別的測試樣本又分別送入這4個分類器進行判決,取最大值
一對一的投票策略(one against one 葉th voting)
將A. B、C, D四類樣本兩類兩類地組成訓練集, 即(A,B)、(A.C)、(A,D)、(B,C)、(B,D)、{C,D), 得到6個(對于n類問題, 為n(n-1)/2個) SVM二分器。在測試的時候,把測試樣本又依次送入這6個二分類器, 采取投票形式, 最后得到一組結果。投票是以如下方式進行的。
初始化: vote(A)= vote(B)= vote(C)= vote{D)=O。
投票過程:如果使用訓練集(A,B)得到的分類器將f判定為A類,則vote(:A)=vote(A)+ 1 , 否則vote(B)=vote(B)+ 1; 如果使用(A,C)訓練的分類器將又判定為A類,則vote(.4.)=vote(A)+ 1, 否則vote(C)=vote(C)+l; . ….. ; 如果使用(C,D)訓練的分類器將又判定為C類,則
vote(C)=vote(C)+ 1 , 否則vote(D)=vote(D)+ 1。
最終判決: Max(vote(A), vote(B), vote{C), vote(D))。如有兩個以上的最大值, 則一般可簡單地取第一個最大值所對應的類別。
3. 一對一的淘汰策略(one against one with. eUmlnating)
這是在文獻中專門針對SVM提出的一種多類推廣策略,實際上它也適用于所有可以提供分類器置信度信息的二分器。該方法同樣基于一對一判別策略解決多類問題, 對于這4類問題, 需訓練6個分類器(A,.B)、(A,C)、(A,D)、(B,C)、(B,D)、(C,D)。顯然, 對于這4類中的任意一類, 如第A類中的某一樣本, 就可由(A,B)、(A,C)、(A,D)這3個二分器中的任意一個來識別,即判別函數間存在冗余。于是我們將這些二分器根據其置信度從大到小排序,置信度越大表示此二分器分類的結果越可靠, 反之則越有可能出現誤判。對這6個分類器按其置信度由大到小排序并分別編號, 假設為1 # (A,C), 2# (A,B), 3#(A,D)., 4# (B,D), 5# (C,D), 6# (B,C) 。
此時, 判別過程如下。
(1) 設被識別對象為X, 首先由1#判別函數進行識別。若判別函數h(x) = +1, 則結果為類型A, 所有關于類型C的判別函數均被淘汰;若判別函數h(x) =-1, 則結果為類型C,所有關于類型A的判別函數均被淘汰;若判別函數h(x) = 0, 為“ 拒絕決策” 的情形, 則直接選用2#判別函數進行識別。
(2)被識別對象x再由4#判別函數進行識別。若結果為類型+1, 淘汰所有關于D類的判別函數, 則所剩判別函數為6# (B,C)。
(3) 被識別對象x再由6#判別函數進行識別。若得到結果為類型+1 則可判定最終的分類結果為B。
那么, 如何來表示置信度呢?對于SVM而言,分割超平面的分類間隔越大,就說明兩類樣本越容易分開,表明了問題本身較好的可分性。因此可以用各個SVM二分器的分類間隔大小作為其置信度。
SVM的Matlab實現
訓練一svmtrain
函數svmtrain用來訓練一個SVM分類器, 常用的調用語法為:
SVMStruct = svmtrain(Tranining,Group);
? Training是一個包含訓練數據的m行n列的2維矩陣。每行表示1個訓練樣本(特征 向量),m表示訓練樣本數目; n表示樣本的維數.
? Group是一個代表訓練樣本類標簽的1維向量.其元素值只能為0或1.通常1表示正例,0表示反例.Group的維數必須和Traningg的行數相等,以保證訓練樣本同其 類別標號的一一對應.
SVMStruct是訓練所得的代表SVM分類器的結構體,包含有關最佳分割超平面的種種信息,也可以計算出分類間隔值。
除上述的常用調用形式外,還可通過<屬性名, 屬性值>形式的可選參數設置一些訓練相關的高級選項, 從而實現某些自定義功能, 具體說明如下
訓練結果的可視化
當訓練數據是2維時可利用ShowPlot選項來獲得訓練結果的可視化解釋, 調用形式如下:
svmtrain(…,”ShowPlot”,true);
設定錯誤代價C
在13.2.2小節討論非線性可分情況下的C-SVM時, 介紹了錯誤代價系數C對于訓練和分類結果的影響, 下面將給出設定C值的方法。由式(13-21)可知, 引入C對于二次規劃問題求解的影響僅僅體現在約束條件當中, 因此通過在調用svmtrain時設置一個優化選項’boxconstraint’即可, 調用形式為:
svmStruct = svmtarin(…,”boxconstraint”,C);
其中, C 為錯誤代價系數,默認取值為Inf, 表示錯分的代價無限大, 分割超平面將傾向于盡可能最小化訓練錯誤。通過適當地設置一個有限的C值, 將得到一個圖13.7 Cc)中所示的軟超平面。
分類-svmclassify
函數svmclassify的作用是利用訓練得到的SVMStruct結構對一組樣本進行分類,常用調用形式為:
Group = svmclassify(SVMStruct,sample);
SVMStruct是訓練得到的代表SVM分類器的結構體, 由函數svmtrain返回.
Sample是要進行分類的樣本矩陣, 每行為1個樣本特征向量,總行數等于樣本數目,總列數是樣本特征的維數,它必須和訓練該SVM時使用的樣本特征維數相同.Group是一個包含Sample中所有樣本分類結果的列向量, 其維數與Sample矩陣的行數相同.
應用實例
svm訓練分類鳶尾植物
人臉識別
人臉識別簡介
人臉識別技術就是以計算機為輔助手段, 從靜態圖像或動態圖像中識別人臉。問題一般可以描述為:給定一個場景的靜態或視頻圖像, 利用已經存儲的人臉數據庫確認場景中的一個或多個人。一般來說, 人臉識別研究一般分為3個部分: 從具有復雜背景的場景中檢測并
分離出人臉所在的區域;抽取人臉識別特征;然后進行匹配和識別
前期處理
實驗數據集仍然采用ORI人臉庫。由千每幅人臉圖像均包括112X92個像素(參見10.4.1小節),巨大的維數打消了我們將每幅圖像直接以其像素作為特征(ANN數字字符識別中的做法)的念頭。而實際上, 由于原始圖像各維像素之間存在著大量的相關性這種做法也是沒有必要的。因此需要首先通過主成分分析(PCA)的方法去除相關性, 我們將在1.0.4節那個基于主成份分析(PCA)的人臉特征提取工作的基礎上進行本實驗,將PCA降維后得到的20維特征向量作為SVM分類的特征。
前期預處理工作的具體步驟如下。
(1) 數據集的分割。
將整個數據集分為兩個部分1個訓練集和1個測試集。具體地說,我們將每個人的10張面部圖像分成兩組,前5張放入訓練集,另外5張用作測試。這樣訓練集與測試集各有40x5 = 200個人臉樣本。
(2) 讀入訓練圖像。
將每張圖像按列存儲為1個10304維的行向量。這樣400個人共組成一個400x10304的2維矩陣faceContainer, 每行1個人臉樣本.. readFeacsO 函數封裝了上述功能
(3)利用PCA降維去除像素之間的相關性。
數據規格化 (Scaling)
數據規格化又稱數據尺度歸一化,是指將特征的某個屬性(特征向量的某一維)的取值范圍投射到一個特定范圍之內,以消除數值型屬性因大小范圍不一而影響基于距離的分類方法結果的公正性。
數據規格化的必要性
可以毫不夸張地說,Scaling在一個模式識別問題中占據著舉足輕重的地位,甚至關系到整個識別系統的成敗。然而如此重要的一個環節卻往往易被初學者忽視。當您在同一個數據集上應用了相同的分類器卻得到遠不如他人的結果時,首先請確定是否進行了正確的Scaling。通常進行Scaling 一般有以下兩點必要性:
(1)防止那些處在相對較大的數字范圍(numeric ranges)的特征壓倒那些處在相對較小的數字范圍的特征。
(2)避免計算過程中可能會出現的數字問題。
數據規格化方法
(1)最大最小規格化方法。
(2)零均值規格化方法
實現人臉數據的規格化
function [SVFM, lowVec, upVec] = scaling(VecFeaMat, bTest, lRealBVec, uRealBVec) % Input: VecFeaMat --- 需要scaling的 m*n 維數據矩陣,每行一個樣本特征向量,列數為維數 % bTest --- =1:說明是對于測試樣本進行scaling,此時必須提供 lRealBVec 和 uRealBVec % 的值,此二值應該是在對訓練樣本 scaling 時得到的 % =0:默認值,對訓練樣本進行 scaling % lRealBVec --- n維向量,對訓練樣本 scaling 時得到的各維的實際下限信息 % uRealBVec --- n維向量,對訓練樣本 scaling 時得到的各維的實際上限信息 % % output: SVFM --- VecFeaMat的 scaling 版本 % upVec --- 各維特征的上限(只在對訓練樣本scaling時有意義,bTest = 0) % lowVec --- 各維特征的下限(只在對訓練樣本scaling時有意義,bTest = 0) if nargin < 2bTest = 0; end% 縮放目標范圍[-1, 1] lTargB = -1; uTargB = 1;[m n] = size(VecFeaMat);SVFM = zeros(m, n);if bTestif nargin < 4error('To do scaling on testset, param lRealB and uRealB are needed.');endif nargout > 1error('When do scaling on testset, only one output is supported.');endfor iCol = 1:nif uRealBVec(iCol) == lRealBVec(iCol)SVFM(:, iCol) = uRealBVec(iCol);SVFM(:, iCol) = 0;elseSVFM(:, iCol) = lTargB + ( VecFeaMat(:, iCol) - lRealBVec(iCol) ) / ( uRealBVec(iCol)-lRealBVec(iCol) ) * (uTargB-lTargB); % 測試數據的scalingendend elseupVec = zeros(1, n);lowVec = zeros(1, n);for iCol = 1:nlowVec(iCol) = min( VecFeaMat(:, iCol) );upVec(iCol) = max( VecFeaMat(:, iCol) );if upVec(iCol) == lowVec(iCol)SVFM(:, iCol) = upVec(iCol);SVFM(:, iCol) = 0;elseSVFM(:, iCol) = lTargB + ( VecFeaMat(:, iCol) - lowVec(iCol) ) / ( upVec(iCol)-lowVec(iCol) ) * (uTargB-lTargB); % 訓練數據的scalingendend end核函數的選擇
到目前為止, 要送入SVM的數據已經準備就緒, 但在 “ 啟動”SVM之前仍有兩個問題擺在面前:
(1)選擇哪一種核函數 (Kerne]);
(2)確定核函數的參數以及錯誤代價系數C的 最佳取值。
下面先來解決第1個問題, 第2個問題留到13.4.5中討論。由于只有4種常用的核函數(參見13.2.3小節),將它們依次嘗試并選擇對測試數據效果最好的一個似乎可行, 但后續的參數選擇問題將使這成為一個復雜的排列組合問題, 而遠 遠不是4種可能那么簡單。盡管最佳核函數的選擇一般與問題自身有關, 但仍有規律可循。 建議初學者在通常情況 下優先考慮徑向基核函數RBF
構建多類svm分類器
首先進行訓練
在多類SVM訓練階段, 我們要做的就是用n=40類樣本構建n(n - 1)/2個SVM二分器,把每個SVM二分器的訓練結果(SVMStruct結構體)都保存到一個結構體的細胞數組CASVMStruct中, 具體地說CASVMStruct{ii} {jj}中保存著第ii類與第jj類兩類訓練得到的
SVMStruct 。最終將多類SVM分類時需要的全部信息保存至結構體multiSVMStruct中返回,可以說multiSVMStruct中包含了我們的訓練成果。
分類實現
在多類 SVM 分類階段, 讓測試樣本依次經過訓練得到的 n(n-1)/2 個 (n = 40) 個 SVM 二分器, 通過投票決定其最終類別歸屬。
開始訓練
function train(C, gamma) % 整個訓練過程,包括讀入圖像,PCA降維以及多類 SVM 訓練,各個階段的處理結果分別保存至文件: % 將 PCA 變換矩陣 W 保存至 Mat/PCA.mat % 將 scaling 的各維上、下界信息保存至 Mat/scaling.mat % 將 PCA 降維并且 scaling 后的數據保存至 Mat/trainData.mat % 將多類 SVM 的訓練信息保存至 Mat/multiSVMTrain.matglobal imgRow; global imgCol;display(' '); display(' '); display('訓練開始...');nPerson=40; nFacesPerPerson = 5; display('讀入人臉數據...'); [imgRow,imgCol,FaceContainer,faceLabel]=ReadFaces(nFacesPerPerson,nPerson); display('..............................');nFaces=size(FaceContainer,1);%樣本(人臉)數目display('PCA降維...'); [pcaFaces, W] = fastPCA(FaceContainer, 20);% 主成分分析PCA% pcaFaces是200*20的矩陣, 每一行代表一張主成分臉(共40人,每人5張),每個臉20個維特征 % W是分離變換矩陣, 10304*20 的矩陣 visualize_pc(W);%顯示主成分臉 display('..............................');X = pcaFaces;display('Scaling...'); [X,A0,B0] = scaling(X); save('Mat/scaling.mat', 'A0', 'B0');% 保存 scaling 后的訓練數據至 trainData.mat TrainData = X; trainLabel = faceLabel; W = W; save('Mat/trainData.mat', 'TrainData', 'trainLabel','W');display('..............................');for iPerson = 1:nPersonnSplPerClass(iPerson) = sum( (trainLabel == iPerson) ); endmultiSVMStruct = multiSVMTrain(TrainData, nSplPerClass, nPerson, C, gamma); display('正在保存訓練結果...'); save('Mat/multiSVMTrain.mat', 'multiSVMStruct'); display('..............................'); display('訓練結束。');識別
function nClass = classify(newFacePath) % 整個分類(識別)過程display(' '); display(' '); display('識別開始...');% 讀入相關訓練結果 display('載入訓練參數...'); load('Mat/PCA.mat'); load('Mat/scaling.mat'); load('Mat/trainData.mat'); load('Mat/multiSVMTrain.mat'); display('..............................');xNewFace = ReadAFace(newFacePath); % 讀入一個測試樣本 xNewFace = double(xNewFace); % TestFace = (TestFace-repmat(meanVec, m, 1))*V; %其中V是主成分分量,這種才是降維的方法,原代碼錯了 xNewFace = (xNewFace-repmat(meanVec, 1, 1))*V; % 經過pca變換降維 xNewFace = scaling(xNewFace,1,A0,B0);display('身份識別中...'); nClass = multiSVMClassify(xNewFace); display('..............................'); display(['身份識別結束,類別為:' num2str(nClass), '。']);測試
function test() % 測試對于整個測試集的識別率 % % 輸出:accuracy --- 對于測試集合的識別率display(' '); display(' '); display('測試開始...');nFacesPerPerson = 5; nPerson = 40; bTest = 1; % 讀入測試集合 display('讀入測試集合...'); [imgRow,imgCol,TestFace,testLabel] = ReadFaces(nFacesPerPerson, nPerson, bTest); display('..............................');% 讀入相關訓練結果 display('載入訓練參數...'); load('Mat/PCA.mat'); load('Mat/scaling.mat'); load('Mat/trainData.mat'); load('Mat/multiSVMTrain.mat'); display('..............................');% PCA降維 display('PCA降維處理...'); [m n] = size(TestFace); TestFace = (TestFace-repmat(meanVec, m, 1))*V; % 經過pca變換降維 TestFace = scaling(TestFace,1,A0,B0); display('..............................');% 多類 SVM 分類 display('測試集識別中...'); classes = multiSVMClassify(TestFace); display('..............................');% 計算識別率 nError = sum(classes ~= testLabel); accuracy = 1 - nError/length(testLabel); display(['對于測試集200個人臉樣本的識別率為', num2str(accuracy*100), '%']);在C=128,gamma= 0.0785的情況下,準確率大概在81.5%
源碼:SourceCode
總結
以上是生活随笔為你收集整理的基于PCA和SVM的人脸识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 李航《统计学习方法》---感知机
- 下一篇: XGBoost的安装与介绍