http://blog.youkuaiyun.com/haitao111313/article/details/7765023
PCA的原理
PCA的原理就是将原来的样本数据投影到一个新的空间中,相当于我们在矩阵分析里面学习的将一组矩阵映射到另外的坐标系下。通过一个转换坐标,也可以理解成把一组坐标转换到另外一组坐标系下,但是在新的坐标系下,表示原来的原本不需要那么多的变量,只需要原来样本的最大的一个线性无关组的特征值对应的空间的坐标即可。
比如,原来的样本是30*1000000的维数,就是说我们有30个样本,每个样本有1000000个特征点,这个特征点太多了,我们需要对这些样本的特征点进行降维。那么在降维的时候会计算一个原来样本矩阵的协方差矩阵,这里就是1000000*1000000,当然,这个矩阵太大了,计算的时候有其他的方式进行处理,这里只是讲解基本的原理,然后通过这个1000000*1000000的协方差矩阵计算它的特征值和特征向量,最后获得具有最大特征值的特征向量构成转换矩阵。比如我们的前29个特征值已经能够占到所有特征值的99%以上,那么我们只需要提取前29个特征值对应的特征向量即可。这样就构成了一个1000000*29的转换矩阵,然后用原来的样本乘以这个转换矩阵,就可以得到原来的样本数据在新的特征空间的对应的坐标。30*1000000 * 1000000*29 = 30 *29, 这样原来的训练样本每个样本的特征值的个数就降到了29个。
PAC人脸识别的基本思想就是从人脸图像中找出最能代表人脸的特征空间,去除一些不能代表人脸特征的属性。一个单个的人脸图片映射到这个特征空间得到这个特征空间的一组系数,这组系数就表示这张人脸图片的特征脸特征。如果两张人脸图片映射到这个特征空间的系数差不多,就表示这两张人脸是同一个人。
训练阶段:
1:一张人脸图片在计算机表示为一个像素矩阵,即是一个二维数组,现在把这个二维数组变成一维数组,即把第一行后面的数全部添加到第一行。这样一张图片就能表示为一个向量d=(x1,x2......xn)。xn表示像素。
2:现在训练库里有m张人脸图片,把这些图片都表示成上述的向量形式,即d1,d2,。。。dm,把这m个向量取平均值得向量avg=(y1,y2......yn)。
3:用d1,d2...........dm分别减去avg后组成一个矩阵A,即矩阵A的第一行为d1-avg,后面类似。A的大小为m×n。因为找特征空间不能基于一张图片,而要在所有的人脸图片提取出共同特征,所以要取所有脸向量的平均,具体来说是各个人脸向量到平均人脸向量avg的向量差。依据这个每个人脸图片跟平均脸向量的向量差组成矩阵A,然后依据矩阵A来求解最特征空间。
4: 矩阵A乘以A的逆矩阵A‘得A的协方差矩阵B,B的大小m×m,求B的特征向量。取最大的K个特征向量组成新的矩阵T,T的大小m×k。
5;使用A’乘以T得到特征脸C,C的大小n×k。
6:用图片向量d乘以C得到图片向量d在特征脸的投影向量pn,有多少张图片就有多少个pn。pn的大小1×k
识别阶段:
1:一张新的图片也表示为d的向量,记为D,D的大小1×n
2:D乘以上面训练得到的特征脸C得到这个图片向量D在C下的投影向量P,p的大小1×k。
3:计算p与上面所有的pn的向量距离,与p最小的那个向量所对应的人脸图片跟这张新人脸图片最像。
这里说明一下,为什么矩阵A的协方差矩阵的特征向量能最大的表示矩阵A的主要特征。其中有个解释是最大方差理论,意思是最好的n维样本投影到k维后,每一维样本的方差都要今年最大。而最佳的投影直线是协方差矩阵的特征值最大时对应的特征向量,其次是第二大对应的特征向量,依次类推。
当然以上只是最简单的PCA,而且PCA只对符合高斯分布的样本合适。
自实现pca的MATLAB代码
http://blog.youkuaiyun.com/mpbchina/article/details/7384425- %训练
- %Lx=X'*X
- clear;
- clc;
- train_path='..\Data\TrainingSet\';
- phi=zeros(64*64,20);
- for i=1:20
- path=strcat(train_path,num2str(i),'.bmp');
- Image=imread(path);
- Image=imresize(Image,[64,64]);
- phi(:,i)=double(reshape(Image,1,[])');
- end;
- %mean
- mean_phi=mean(phi,2);
- mean_face=reshape(mean_phi,64,64);
- Image_mean=mat2gray(mean_face);
- imwrite(Image_mean,'meanface.bmp','bmp');
- %demean
- for i=1:19
- X(:,i)=phi(:,i)-mean_phi;
- end
- Lx=X'*X;
- tic;
- [eigenvector,eigenvalue]=eigs(Lx,19);
- toc;
- %normalization
- for i=1:19
- %K-L变换
- UL(:,i)=X*eigenvector(:,i)/sqrt(eigenvalue(i,i));
- end
- %display Eigenface
- for i=1:19
- Eigenface=reshape(UL(:,i),[64,64]);
- figure(i);
- imshow(mat2gray(Eigenface));
- end
- %使用测试样本进行测试
- clc;
- test_path='..\Data\TestingSet\';
- error=zeros([1,4]);
- for i=1:4
- path=strcat(test_path,num2str(i),'.bmp');
- Image=imread(path);
- Image=double(imresize(Image,[64,64]));
- phi_test=zeros(64*64,1);
- phi_test(:,1)=double(reshape(Image,1,[])');
- X_test=phi_test-mean_phi;
- Y_test=UL'*X_test;
- X_test_re=UL*Y_test;
- Face_re=X_test_re+mean_phi;
- calculate error rate
- e=Face_re-phi_test;
- %%display figure
- Face_re_2=reshape(Face_re(:,1),[64,64]);
- figure(i);
- imshow(mat2gray(Image));
- title('Original');
- figure(10+i);
- imshow(mat2gray(Face_re_2));
- title('Reconstruct');
- error(1,i)=norm(e);
- %dispaly error rate
- error_rate=error(1,i);
- display(error_rate);
- end