基于LDA的人脸识别算法研究

本文介绍了一种基于线性判别分析(LDA)的人脸识别技术,该技术在ORL人脸库上的识别率达到99.5%,并通过10折交叉验证算法验证了算法的准确性。

一.实验背景:

一个完整的人脸识别系统包括人脸检测与定位、人脸特征提取、分类识别等,如图1所示。

在这里插入图片描述

图1 人脸识别系统

研究者们从各种不同的途径提出了多种方法,其中主要有:基于模板匹配的方法,基于知识的人脸验证的方法,以及目前比较流行的基于统计的学习方法和基于神经网络的方法等。在基于统计方法的识别方法中,PCA、LDA方法是利用测试图像在特定子空间上投影向量作为特征向量,本文重点介绍了基于线性判别分析(LDA)原理的人脸识别技术。线性判别分析是一种传统的用于特征提取的线性分类的方法。本文重点研究了基于 LDA 人脸识别的算法,并对该算法进行了实验验证与分析,实验结果表明该算法能有效提鉴别别信息,具有较高的识别率。

二.实验要求:

采用自己编写的LDA算法,对ORL人脸库进行识别,用10折交叉验证的方法计算准确率,并对结果进行分析。

三.算法/素材介绍:

①LDA算法介绍:

  线性判别分析(LDA)技术,它是以对样本进行很好的分类为目的,充分利用了训练样本已知的类别信息,寻找最有助于分类的投影方向子空间,属于监督学习方法。

经典的LDA采用Fisher判别准则函数,因此也成为FLD,最早由Fisher在1936年提出,基本思想是寻找是Fisher准则达到极大值的向量作为最佳投影方向,使投影后的样本能达到最大的类间离散度和最小的类内离散度,使投影后样本具有最佳的可分离性,是一种有效用于分类的特征提取方法。利用Fisher准则,当Sw非奇异,可以通过对Sw-1Sb进行特征值分解,从而求出最佳投影方向W(Sw:本的类内离散度矩阵,Sb:样本类间离散度矩阵)。但是当LDA用于人脸特征提取时,因图像转换为列向量维数太大,往往远大于样本数,造成Sw奇异,很难解出最佳投影方向,即小样本问题,所以先利用PCA技术对人脸图像进行降维,使Sw满秩,再利用LDA技术对其进行特征提取,进而进行人脸识别,是一种较经典的解决LDA用于人脸识别时遇到的小样本问题的方法,称为Fisherfaces方法或PCA+LDA方法。

②10折交叉验证算法:

我们把每个数据集分成两个子集

- 一个用于构建分类器,该数据集称为训练集(training set)
  • 另一个数据集用于评估分类器,该数据集称为测试集(test set)

在这里插入图片描述

图2数据分类图

我们可以将数据划分成10部分,每次利用9/10的数据训练而在其余1/10的数据上进行测试。因此,整个过程看起来如下:

第一次迭代 使用Part 1~Part 9训练,使用Part
10测试

第二次迭代 使用Part 1~Part 8,Part10训练,使用Part 9测试

第三次迭代 使用Part 1和Part 7,Part9~Part10训练,使用Part 8测试

对上述结果求平均。

在数据挖掘中,最常用的划分数目是10,这种方法称为10折交叉验证(10-fold
Cross Validation)使用这种方法,我们将数据集随机分成10份,使用其中9份进行训练而将另外1份用作测试。该过程可以重复10次,每次使用的测试数据不同。在程序中,通过一个for循环对数据进行分类,分类程序见图3。

在这里插入图片描述

图3数据集分类

③实验素材介绍:

ORL人脸数据库由剑桥大学AT&T实验室创建,其中包含40个人的不同图像。有些人的图像是在不同的时间、不同的光线、不同的表情(睁眼/闭眼,笑/不笑)下拍摄的。其中人脸姿态也有很大的变化,其深度旋转和平面旋转可达20度。人脸的尺寸也有不超过10%的变化。ORL人脸库见图4。

在这里插入图片描述

图4 ORL人脸库

四.实验步骤:

先利用PCA降维,再利用LDA寻找最优投影向量,在ORL上测试,采用10折交叉算法验证不同训练集对识别率的影响,并寻找最佳投影维数,最后输出识别率。程序流程图见图5,步骤图见图6。
在这里插入图片描述
图5程序流程图

在这里插入图片描述

图6实验步骤图

进行 matlab 的仿真得出实验的结果,主要是研究了用 PCA 方法对人脸进行特征的提取,用经过改进后的 LDA方法算出真确的人脸识别率,先用 PCA 方法降维,在用标准的 LDA 方法进行识别,这是本实验的目的。同时用10折交叉验证的方法验证LDA算法的准确率。

五.实验结果:
在这里插入图片描述在这里插入图片描述

图7实验结果图

六.结论:

在PCA算法的基础上,运用LDA算法对ORL人脸库进行识别,最后通过十折交叉验证算法对LDA算法的准确率进行验证,得到的识别率在97.5%~100%之间,取十次的准确率的均值99.5%作为LDA算法识别ORL人脸库准确率的估计,所以LDA算法对ORL人脸库的识别是较准确的。

程序:
①读取样本函数

function sample=readsample(address,classnum,num)
%这个函数用来读取样本。
%输入:address就是要读取的样本的地址,classnum代表要读入样本的类别,num是每类的样本;
%输出为样本矩阵
allsamples=[];
image=imread([pwd '\ORL\s1_1.bmp']);%读入第一幅图像
[rows cols]=size(image);%获得图像的行数和列数
for i=classnum
    for j=num
        a=imread(strcat(address,num2str(i),'_',num2str(j),'.bmp'));
        b=a(1:rows*cols);
        b=double(b);
        allsamples=[allsamples;b];
    end
end
sample=allsamples;

②计算Sw,Sb



function [sw
sb]=computswb(samples,classnum,num)

%计算sw,sb

%samples为输入的样本,classnum为类别数,num为每一类的样本数

%输出sw为类内协方差矩阵,sb为类间协方差矩阵。

samplemean=mean(samples);

for i=1:classnum%类别数

   
newsamplemean(i,:)=mean(samples((i-1)*num+1:i*num,:));

end

sw=0;

for i=1:classnum

   
for j=1:num

       
sw=sw+(samples((i-1)*num+j,:)-newsamplemean(i,:))'*(samples((i-1)*num+j,:)-newsamplemean(i,:));

   
end

end

sb=0;

for i=1:classnum

   
sb=sb+(newsamplemean(i,:)-samplemean)'*(newsamplemean(i,:)-samplemean);

end

③计算计算sw/sb投影的最优向量



function vsort=projectto(sw,sb,num)

%计算sw/sb投影的最优向量

%sw为类内协方差矩阵,sb是类间协方差矩阵

%vsort为最优投影向量

invSw=inv(sw);

newspace=invSw*sb;

[x y]=eig(newspace);

d=diag(y);

[d1 index1]=dsort(d);

for i=1:num

   
vsort(:,i)=x(:,index1(i));

end

④主分量分析程序



function [newsample basevector]=pca(patterns,num)

%主分量分析程序,patterns表示输入模式向量,num为控制变量,当num大于1的时候表示

%要求的特征数为num,当num大于0小于等于1的时候表示求取的特征数的能量为num

%输出:basevector表示求取的最大特征值对应的特征向量,newsample表示在basevector

%映射下获得的样本表示。

[u v]=size(patterns);

totalsamplemean=mean(patterns);

for i=1:u

   
gensample(i,:)=patterns(i,:)-totalsamplemean;

end

sigma=gensample*gensample';

[U V]=eig(sigma);

d=diag(V);

[d1 index]=dsort(d);

if num>1

   
for i=1:num

       
vector(:,i)=U(:,index(i));

       
base(:,i)=d(index(i))^(-1/2)* gensample' * vector(:,i);

   
end

else

   
sumv=sum(d1);

   
for i=1:u

       
if sum(d1(1:i))/sumv>=num

           
l=i;

           
break;

       
end

   
end

   
for i=1:l

       
vector(:,i)=U(:,index(i));

       
base(:,i)=d(index(i))^(-1/2)* gensample' * vector(:,i);

   
end

end

newsample=patterns*base;

basevector=base;

⑤计算准确率的函数



function accuracy=computaccu(testsample,num1,trainsample,num2)

%计算准确率的函数

%输入testsample表示经过投影后的测试样本,num1表示每一类测试样本的个数,

%trainsample代表经过投影后的训练样本,num2代表每一类训练样本的个数

%输出为正确率

accu=0;

testsampnum=size(testsample,1);

trainsampnum=size(trainsample,1);

for i=1:testsampnum

    for j=1:trainsampnum

       
juli(j)=norm(testsample(i,:)-trainsample(j,:));

    end

    [temp index]=sort(juli);

    if
ceil(i/num1)==ceil(index(1)/num2)

        accu=accu+1;

    end

end

accuracy=accu/testsampnum;

⑥主函数



clear all

clc

close all

start=clock;

sample_class=1:40;%样本类别

sample_classnum=size(sample_class,2);%样本类别数

fprintf('程序运行开始....................\n\n');

 pic_num = 10;

for pic_index = 1:pic_num;

   
test=pic_index;%每类测试样本

    if test > 1

   
train1=1:pic_index-1;%每类训练样本

   
train2=pic_index+1:10;

   
train=[train1,train2];

    else

    train=2:10;

    end

   
train_num=size(train,2);%每类训练样本数

   
test_num=size(test,2);%每类测试样本数

    address=[pwd
'\ORL\s'];

    %读取训练样本

   
allsamples=readsample(address,sample_class,train);

        %先使用PCA进行降维

    [newsample
base]=pca(allsamples,0.9);

    %计算Sw,Sb

    [sw
sb]=computswb(newsample,sample_classnum,train_num);

    

    %读取测试样本

   
testsample=readsample(address,sample_class,test);

    best_acc=0;%最优识别率

    %寻找最佳投影维数

    for
temp_dimension=1:1:length(sw)

       
vsort1=projectto(sw,sb,temp_dimension);

        

        %训练样本和测试样本分别投影

       
tstsample=testsample*base*vsort1;

       
trainsample=newsample*vsort1;

        %计算识别率

       
accuracy=computaccu(tstsample,test_num,trainsample,train_num);

        if
accuracy>best_acc

           
best_dimension=temp_dimension;%保存最佳投影维数

            best_acc=accuracy;

        end

    end

   
%---------------------------------输出显示----------------------------------

    fprintf('10折交叉验证第 %d 次 \n',pic_index);

    fprintf('每类训练样本数为:%d\n',train_num);

    fprintf('最佳投影维数为:%d\n',best_dimension);

    fprintf('LDA的识别率为:%.2f%%\n',best_acc*100);

    fprintf('程序运行时间为:%3.2fs\n\n',etime(clock,start)); end

fprintf('程序运行结束....................\n\n');

现在我们回到LDA的原理上,我们在第一节说讲到了LDA希望投影后希望同一种类别数据的投影点尽可能的接近,而不同类别的数据的类别中心之间的距离尽可能的大,但是这只是一个感官的度量。现在我们首先从比较简单的二类LDA入手,严谨的分析LDA的原理。     假设我们的数据集D={(x1,y1),(x2,y2),...,((xm,ym))}D={(x1,y1),(x2,y2),...,((xm,ym))},其中任意样本xixi为n维向量,yi∈{0,1}yi∈{0,1}。我们定义Nj(j=0,1)Nj(j=0,1)为第j类样本的个数,Xj(j=0,1)Xj(j=0,1)为第j类样本的集合,而μj(j=0,1)μj(j=0,1)为第j类样本的均值向量,定义Σj(j=0,1)Σj(j=0,1)为第j类样本的协方差矩阵(严格说是缺少分母部分的协方差矩阵)。     μjμj的表达式为: μj=1Nj∑x∈Xjx(j=0,1) μj=1Nj∑x∈Xjx(j=0,1)     ΣjΣj的表达式为: Σj=∑x∈Xj(x−μj)(x−μj)T(j=0,1) Σj=∑x∈Xj(x−μj)(x−μj)T(j=0,1)     由于是两类数据,因此我们只需要将数据投影到一条直线上即可。假设我们的投影直线是向量ww,则对任意一个样本本xixi,它在直线ww的投影为wTxiwTxi,对于我们的两个类别的中心点μ0,μ1μ0,μ1,在在直线ww的投影为wTμ0wTμ0和wTμ1wTμ1。由于LDA需要让不同类别的数据的类别中心之间的距离尽可能的大,也就是我们要最大化||wTμ0−wTμ1||22||wTμ0−wTμ1||22,同时我们希望同一种类别数据的投影点尽可能的接近,也就是要同类样本投影点的协方差wTΣ0wwTΣ0w和wTΣ1wwTΣ1w尽可能的小,即最小化wTΣ0w+wTΣ1wwTΣ0w+wTΣ1w。综上所述,我们的优化目标为: argmaxwJ(w)=||wTμ0−wTμ1||22wTΣ0w+wTΣ1w=wT(μ0−μ1)(μ0−μ1)TwwT(Σ0+Σ1)w argmax⏟wJ(w)=||wTμ0−wTμ1||22wTΣ0w+wTΣ1w=wT(μ0−μ1)(μ0−μ1)TwwT(Σ0+Σ1)w     我们一般定义类内散度矩阵SwSw为: Sw=Σ0+Σ1=∑x∈X0(x−μ0)(x−μ0)T+∑x∈X1(x−μ1)(x−μ1)T Sw=Σ0+Σ1=∑x∈X0(x−μ0)(x−μ0)T+∑x∈X1(x−μ1)(x−μ1)T     同时定义类间散度矩阵SbSb为: Sb=(μ0−μ1)(μ0−μ1)T Sb=(μ0−μ1)(μ0−μ1)T     这样我们的优化目标重写为: argmaxwJ(w)=wTSbwwTSww argmax⏟wJ(w)=wTSbwwTSww     仔细一看上式,这不就是我们的广义瑞利商嘛!这就简单了,利用我们第二节讲到的广义瑞利商的性质,我们知道我们的J(w)J(w)最大值为矩阵S−12wSbS−12wSw−12SbSw−12的最大特征值,而对应的ww为S−12wSbS−12wSw−12SbSw−12的最大特征值对应的特征向量! 而S−1wSbSw−1Sb的特征值和S−12wSbS−12wSw−12SbSw−12的特征值相同,S−1wSbSw−1Sb的特征向量w′w′和S−12wSbS−12wSw−12SbSw−12的特征向量ww满足w′=S−12www′=Sw−12w的关系!     注意到对于二类的时候,SbwSbw的方向恒为μ0−μ1μ0−μ1,不妨令Sbw=λ(μ0−μ1)Sbw=λ(μ0−μ1),将其带入:(S−1wSb)w=λw(Sw−1Sb)w=λw,可以得到w=S−1w(μ0−μ1)w=Sw−1(μ0−μ1), 也就是说我们只要求出原始二类样本的均值和方差就可以确定最佳的投影方向ww了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一叶孤舟渡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值