基于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函数的训练,预测(注意人脸识别是多分类问题)等就不一一说了,我会把整个代码打包发上来。
PS:如果有同学对PCA函数不是很理解的话,可以直接用MATLAB自带的princomp函数,我一开始为了偷懒,也是用的这个函数,把相应的主函数也一并贴上来,供需要的同学参考。
% 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),'%']); %显示结果;
PS:本人还只是机器学习的一名菜鸟,在很多问题的理解上肯定还存在很多缺陷,还望各位大神指正。另外,写这篇文章之前我参考学习了相关资料,如有侵权,请和我联系。这是我的第一篇博客,很高兴能与大家一起学习交流。
代码下载:基于PCA+SVM的人脸识别