基于表示的分类方法(representation based classification method, RBCM)研究较多的就是John Wright等在2009年提出的稀疏表示分类(sparse representation based classification, SRC)方法了,Google已经有3778次引用了。
Wright J, Yang A Y, Ganesh A, et al. Robust face recognition via sparse representation. PAMI, 2009, 31(2): 210-227.
标准的SRC目标函数为:
当然还有其它形式,比如考虑小的噪声影响:
或者大的噪声或遮挡:
其中
SRC相比于传统方法取得了较好的识别效果,尤其当样本受到随机像素污损(random pixel corruption)或者有遮挡(random block occlusion, wearing sunglasses or scarves)时,SRC也能准确识别。
然而SRC一个缺点就是求解1范数比较耗时,尤其当训练样本数目比较多或者求解扩展的SRC时,即处理样本受到随机像素污损或者遮挡时,计算时间明显增加。一个改进的方法就是把1范数换成2范数求解,即
上述目标函数对求导并令其为零,可以得到
令,这个矩阵对所有的测试样本保持不变(独立于具体的测试样本),可以事先计算好。这个就是香港理工张磊组提出的协同表示分类(collaborative representation based classification, CRC)了。
Zhang D, Yang M, Feng X. Sparse representation or collaborative representation: Which helps face recognition?[C]//ICCV, 2011: 471-478.
之前主要复现了CRC的代码,这几天看了下面这篇文章:
Shi Q, Eriksson A, Van Den Hengel A, et al. Is face recognition really a compressive sensing problem?[C]//CVPR, 2011: 553-560.
这篇文章是比较早提出用2范数替换1范数的,CRC应该是在这个基础上提出的。这篇文章的方法简单称为L2方法。
L2方法的目标函数为:
通过最小二乘估计,可以得到表示系数
如果对A进行QR分解,Q为正交矩阵,R为上三角矩阵,即
则
那么
这儿的对所有的测试样本也保持不变。
实现起来应该也比较简单,当和作者提供的代码比较时,发现自己复现的计算时间有点长,计算时间是作者提供的2.5倍左右。
仔细检查了一下,作者在重构每类样本时,使用了稀疏矩阵,即MATLAB的sparse命令,这样一方面存储空间少了,同时计算速度也加快了。
实验在Extended Yale B数据库上进行,图片是192*168的,38个人,每人取58幅,随机选择29幅训练,其余29幅测试。样本没有进行降维。
自己复现的和作者提供的代码识别率一样,不过作者的代码耗时96.322秒,我的有256.30秒。实现算法是一方面,算法的优化也比较重要。
主函数(EYaleB.mat下载http://pan.baidu.com/s/1i3CEVad)
clear all
clc
close all
load EYaleB
tic
[Q,R]=qr(train_data,0);%训练样本QR分解
R=pinv(R);
P = R*Q';%得到矩阵P,对所有的测试样本都一样
Coeff=P*test_data;%所有测试样本的表示系数
%作者提供,构造sparse矩阵加快计算速度
accuracy=computaccuracy(train_data,train_label,test_data,test_label,Coeff);
%自己复现,每类循环计算残差,速度相对慢一些
% [accuracy,xp,r]=computaccuracy1(train_data,train_label,test_data,test_label,Coeff);
fprintf(2,'识别率为:%g\n\n',accuracy);
toc
computaccuracy.m
function accuracy=computaccuracy(train_data,train_label,test_data,test_label,Coeff)
ClassNum=length(unique(train_label));%样本类别数
test_tol=size(test_data,2);%测试样本总数
train_tol=size(train_data,2);%训练样本总数
h = waitbar(0,'Please wait...');
pre_label=zeros(1,test_tol);%预定义的测试样本标签向量
for i=1:test_tol
%取出第i个测试样本数据及其表示系数
x=Coeff(:,i);
y=test_data(:,i);
%构造sparse矩阵,大小为train_tol*ClassNum,最多有length(x)个非零值
W=sparse([],[],[],train_tol,ClassNum,length(x));
%得到每类对应的系数
for j=1:ClassNum
ind=(j==train_label);
W(ind,j)=x(ind);
end
%计算测试样本和每类重构样本之间的残差
temp=train_data*W-repmat(y,1,ClassNum);
residual=sqrt(sum(temp.^2));
%把测试样本分在最小残差对应的类别中
[~,index]=min(residual);
pre_label(i)=index;
% computations take place here
per = i / test_tol;
waitbar(per, h ,sprintf('%2.0f%%',per*100))
end
close(h)
%计算正确识别率
accuracy=sum(pre_label==test_label)/test_tol;
computaccuracy1.m
function [accuracy,xp,r]=computaccuracy1(train_norm,train_label,test_norm,test_label,Coeff)
test_tol=size(test_norm,2);
ClassNum=length(unique(train_label));
h = waitbar(0,'Please wait...');
pre_label=zeros(1,test_tol);
for i=1:test_tol
y=test_norm(:,i);
xp=Coeff(:,i);
r=zeros(1,ClassNum);
for j=1:ClassNum
ind=(j==train_label);
r(j)=norm(y-train_norm(:,ind)*xp(ind,:));
end
[~,index]=min(r);
pre_label(i)=index;
% computations take place here
per = i / test_tol;
waitbar(per, h ,sprintf('%2.0f%%',per*100))
end
close(h)
accuracy=sum(pre_label==test_label)/test_tol;