Part 1:程序流程简介
这个程序是典型的。在已有资源中使用一部分做训练集,找到一个合适的模型或者结论,然后用剩下的部分来测试自己的结论的正确度,进而一步步提高自己的算法效率或者正确性等。
所以,在这次的程序中,前半部分是训练部分,中间有几段是画图部分,后面部分是测试部分。
Part 2:数据库和PCA算法简介
数据库使用的是Yale的人脸数据库。一共15组图片,每组图片里面有11张图片。在我的程序里面,我使用了每组里面的8张照片为训练集,剩下的3张为测试集。所以,一共是120张训练照片,45张测试照片。
PCA算法步骤:
1.Matrix X (input data) N dimensional input space
即原始矩阵
2.Matrix QX (Covariance of X) QX = cov(X) = E[(x-m)(x-m)T]
求出X的协方差矩阵QX
3.Valuable λk(eigenvalue of QX) λ1≥λ2≥λ3。。。
求出特征值,降序排列
4.Vector Vk
求出对应的特征向量
5.Projection: V*X
最后一步,在求出的向量基上面投影(降维)
Part 3:具体代码
- <strong>%**********************************************
- % Aim : The first AI program homework
- % Title : PCA for face recognition
- % Author : GongWanlu & Hufei
- % Version : 1.0 final
- % Submit Time : 2011-04-07
- %**********************************************
- % %%%%%%%%%%%%%%%%%%%%%%INITIAL
- clear all
- clc
- close all
- % %%%%%%%%%%%%%%%%%%%%%%Some variables according to the Yale Face DB
- Num_subject = 15;
- Num_image = 11;
- Train_num_image = 8; %for every subject we choose 8 to train
- Test_num_image = 9; %choose the left 3 images to test
- % %%%%%%%%%%%%%%%%%%%%%%Load Data
- Data = [];
- for i=1:Num_subject
- for j=1:Train_num_image
- path = sprintf('FaceDB_yaleA/%03d/%02d.jpg',i,j);
- pic = imread (path); %read one picture
- %Make Data ,Add pic into Data
- pic_line = pic(1:147*137); %The pic size is 147*137
- %pic_line is 1*N ,N=147*137. from up to
- %down,left to right.
- %Reshape 2D image to 1D image
- %vectors
- Data = [Data;double(pic_line)]; %add pic_line into Data
- end
- end
- % End of Load Data
- %%%%%%%%%%%%%%%%%%%%%%%Substract mean from Data and make covariance from centering Data
- samplemean = mean(Data); %mean pic 1*N
- for k = 1:(Num_subject * Train_num_image)
- xmean(k,:)=Data(k,:)-samplemean; %Normalize
- end %xmean is M*N ,each line is one pic
- %data(mean data) be normalized
- sigma = xmean *xmean'; %M*M , here is 120*120
- [V D]=eig(sigma); %calculate the eigenvalue&eigenvector
- %eigenvalue in D,and vectors in V
- D1=diag(D); %the eigenvalues
- %%%%%%%%%%%%%%%%%%%%%%%% Sorting and eliminating eigenvalues
- % At first : sort desc
- Dsort=flipud(D1);
- Vsort=fliplr(V);
- %choose part eigenvalues
- Dsum = sum(Dsort); %sum of the eigenvalues,we only choose 80%
- %we have different ways to choose
- %eigenvalues we need,90%,or>1……
- temp_sum = 0;
- p = 0;
- while(temp_sum/Dsum<0.8)
- p = p+1;
- temp_sum = sum(Dsort(1:p));
- end
- %End of sort part
- %%%%%%%%%%%%%%%%%%%%%%%Train Step: get the coordinate system
- i=1;
- while(i<=p && Dsort(i)>0)
- face_base(:,i) = Dsort(i)^(-1/2) * xmean' * Vsort (:,i);
- i=i+1;
- end
- % Dsort(i)^(-1/2) used to normalize, make variance=1
- % face_base is N*p
- % xmean' * Vsort (:,i); is change small matrix to big matrix. CHACHENG(Chinese)
- %next sentence is vary important is our train result
- allcoor = Data * face_base;
- %End of training
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Draw part
- %draw CDF
- x = Dsort (1:p);
- x = flipud (x);
- for i=1:p
- y(i) = 1/p*i;
- end
- figure,plot(x,y,'r*'),hold on,plot(x,y,'b');
- axis([0 inf 0 1]);
- title('CDF of selected values','fontsize',18);
- %draw the face (only use the first value) to show the result
- for k=1
- temp = reshape(face_base(:,k),147,137); %1D to 2D
- end
- figure,imshow(mat2gray(temp)); %draw it
- title('one eigen face','fontsize',18);
- %draw the face (use 100 values) to show the result
- BigMap = [];
- for k=1:4
- map = [];
- for j=1:4
- temp = reshape(face_base(:,(k-1)*4+j),147,137);%1D to 2D
- map = cat(2,map,temp);
- end
- BigMap = cat (1,BigMap,map);
- end
- figure,imshow(mat2gray(BigMap)); %draw it
- Title ('Result of Chosen EigenValues','fontsize',18);
- %End of drwing part
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Test Part
- Bingo = 0;
- for i=1:Num_subject
- for j=Test_num_image:Num_image %read the left 15*3 images
- path = sprintf('FaceDB_yaleA/%03d/%02d.jpg',i,j);
- test_pic = imread(path);
- test_pic_line = test_pic(1:147*137);
- test_pic_line = double(test_pic_line);
- tcoor= test_pic_line * face_base; %get the value
- for k=1:Num_subject* Train_num_image
- mdist(k)=norm(tcoor-allcoor(k,:)); %norm() distence
- end;
- %三阶近邻
- [dist,index2] = sort(mdist);
- class1=floor( (index2(1)-1)/Train_num_image)+1;
- class2=floor((index2(2)-1)/Train_num_image)+1;
- class3=floor((index2(3)-1)/Train_num_image)+1;
- if class1~=class2 && class2~=class3 ID = class1;
- elseif (class1==class2) ID = class2;
- elseif (class2==class3) ID = class3;
- end;
- if ID==i
- Bingo=Bingo+1;
- end;
- end;
- end;
- accuracy = Bingo/45; %output the result
- disp(accuracy);
- % End of Test</strong>