目前,pca 算法已经广泛应用于各方面,就拿图像处理,经常做的一件事就是当提取的图像特征
维度比较高时,为了简化计算量以及储存空间,需要对这些高维数据进行一定程度上的降维,并
尽量保证数据的不失真。
先举个例子,方便理解:
1)对于一个训练集,20 个 sample(i=1,2,3,...,20),特征 Xi 是 100 维
[Xi1,Xi2,Xi3,...Xij,...,Xi100](j=1,2,..,100),那么它可以建立一个 20*100 的样本矩阵 M。
2)紧接着我们开始求这个样本的协方差矩阵,得到一个 20*20 的协方差矩阵,计算过
程如下:
•先求解出 Xi 的平均 Xav=(∑xi)/20;
•对每一个 Xi,计算 Xi-Xav,即 Mi(第 i 行)变为 Mi-Xav,记为 Mn;
•则容易得到协方差矩阵 Z 为 Mn*Mn'( ' 表示转置 ) 。
3)然后求出这个协方差矩阵 Z20x20 的特征值和特征向量,一般情况下应该有 20 个特
征值和特征向量,现在根据特征值的大小,取出较大的特征值以及其所对应的特征向量,(假设
提取的特征值为较大的 5 个特征值),那么这 5 个特征向量就会构成一个 20*5 的矩阵 V,这个
矩阵就是我们要求的特征矩阵。
4)用 Mn'去乘以 V,得到一个 base 矩阵(*),大小为 100x5。
5)任取一个样本 1x100,乘上这个 100*5 的特征矩阵,就得到了一个 1*5 的新的样本,
显然每个 sample 的维数下降了,然后再用这个 1x5 向量去比较相似性。
% calc xmean,sigma and its eigen decomposition
allsamples=[];%所有训练图像
for i=1:40
for j=1:5
a=imread(strcat('D:\rawdata\ORL\s',num2str(i),'\',num2str(j),'.pgm'));
% imshow(a);
b=a(1:112*92); % b 是行矢量 1×N,其中 N=10304,提取顺序是先列后行,即从
上到下,从左到右
b=double(b);
allsamples=[allsamples; b]; % allsamples 是一个 M * N 矩阵,allsamples 中每一
行数据代表一张图片,其中 M=200
end
end
samplemean=mean(allsamples); % 平均图片,1 × N
for i=1:200 xmean(i,:)=allsamples(i,:)-samplemean; % xmean 是一个 M × N 矩阵,xmean
每一行保存的数据是“每个图片数据-平均图片”mean(i,:)表示取出 x 的 i 行
end;
sigma=xmean*xmean'; % M * M 阶矩阵
[v d]=eig(sigma);%求矩阵 sigma 的全部特征值,构成对角阵 d,并求 sigma 的特征向量
构成 V 的列向量。
d1=diag(d);
[d2 index]=sort(d1); %以升序排序,index 为返回的排序后在原数组中的行位置或者列位置
cols=size(v,2);% 特征向量矩阵的列数 size(A,n),当 n=1 时返回行数,当 n=2 时返回列数
for i=1:cols
vsort(:,i) = v(:, index(cols-i+1) ); % vsort 是一个 M*col(注:col 一般等于 M)阶矩阵,保
存的是按降序排列的特征向量,每一列构成一个特征向量
dsort(i)
= d1( index(cols-i+1) ); % dsort 保存的是按降序排列的特征值,是一维行
向量
end %完成降序排列
%以下选择 90%的能量
dsum = sum(dsort);
dsum_extract = 0;
p = 0;
while( dsum_extract/dsum < 0.9)
p = p + 1;
dsum_extract = sum(dsort(1:p));
end
i=1;
% (训练阶段)计算特征脸形成的坐标系
while (i<=p && dsort(i)>0)
base(:,i) = dsort(i)^(-1/2) * xmean' * vsort(:,i); % base 是 N×p 阶矩阵,除以
dsort(i)^(1/2)是对人脸图像的标准化,详见《基于 PCA 的人脸识别算法研究》p31
i = i + 1;
end
% add by wolfsky 就是下面两行代码,将训练样本对坐标系上进行投影,得到一个 M*p 阶
矩阵 allcoor
allcoor = allsamples * base;
accu = 0;
% 测试过程
for i=1:40
for j=6:10 %读入 40 x 5 副测试图像
a=imread(strcat('D:\rawdata\ORL\s',num2str(i),'\',num2str(j),'.pgm'));
b=a(1:10304);
b=double(b);
tcoor= b * base; %计算坐标,是 1×p 阶矩阵
for k=1:200
mdist(k)=norm(tcoor-allcoor(k,:));
end;
%三阶近邻
[dist,index2]=sort(mdist);
class1=floor( index2(1)/5 )+1;
class2=floor(index2(2)/5)+1;
class3=floor(index2(3)/5)+1;
if class1~=class2 && class2~=class3%~=是不等于的意思
class=class1;
elseif class1==class2
class=class1;
elseif class2==class3
class=class2;
end;
if class==i
accu=accu+1;
end;
end;
end;
accuracy=accu/200 %输出识别率
%zuobiao=[1:100];
%plot(zuobiao,accuracy);
函数调用是定义函数,然后用函数名进行调用就可以了