本文将从数据降维方法开始介绍,分解应用于一个简单的人脸识别的demo,对数据降维与特征判别进行一些定性的讨论。
降维方法
主元分析法(PCA)
对于一幅的普通图像来说,最后抽象为一个维的高维向量,如此庞大的维数对于后续图像计算式来说相当困难,因此有必要在尽可能不丢失重要信息的前提下降低图像维数,PCA即降低图像维数的一种有效方法。
通过正交变换,可将一组存在相关性的变量转换为一组线性不相关的变量,转换后的这组变量即称为主成分。
Fisher线性判别式(FLD)
PCA方法可将训练样本集投影到特征脸空间,但除了减少了维数之外,实际上并没有提供分类信息。(当然,可以在此时即计算欧氏距离,则也能找到"最相同的"类别)
故而,我们需要在PCA变换的基础上,进一步运用FLD方法,为分类找到一个最佳的子空间,使得类间距离和类内距离之比最大化。
应用与讨论
将数据降维手段简单应用到一个人类识别/分类任务,从而可对数据降维的效果进行简单的定性辨析。
数据集
ORL数据库(ORL Database of Faces)是英国剑桥大学提供的一个常用的人脸数据库。
这些图像拍摄于不同时间(1992.04-1994.04),在光照强度、角度,面部表情,姿态,面部细节等方面都具有显著变化。同时,这些图像都是在黑色背景下拍摄的,且要求被拍摄者保持头部直立,而头部允许上下左右有最大20°的倾斜和旋转。人像的比例控制在10%左右。所有的图像是以PGM格式存储,灰度图图像大小宽度为92,高度为112.
程序实现
对于单维向量形式的图像A,减去其均值,并选择原图中最主要、最有代表性的信息(通过过滤掉矩阵A'A较小的特征值对应的特征向量实现),近似表征人脸图像,保留人脸最主要的特征,由此也获取了特征脸。
matlab
A = T - repmat(m_database,1,Pic);
L = A'*A;
[V,D] = eig(L);
% 过滤掉小的特征值对应的特征向量
L_eig_vec = [];
for i = 1 : Pic-Class_number
L_eig_vec = [L_eig_vec V(:,i)];
end
% V_PCA:PCA空间传递矩阵
V_PCA = A * L_eig_vec;
% 投影到PCA特征空间
ProjectedImages_PCA = [];
for i = 1 : Pic
temp = V_PCA'*A(:,i);
ProjectedImages_PCA = [ProjectedImages_PCA temp];
end
当人脸图像都投影到PCA特征空间,对于特征空间中的每一类,引入最大化类间离散度矩阵和最小化类内离散度矩阵,通过最大化类间和类内变化的比率来估计Fisher判别的基向量(也是特征向量).
matlab
for i = 1 : Class_number
m_Intra(:,i) = mean( ( ProjectedImages_PCA(:,((i-1)*Class_population+1):i*Class_population) ), 2 )';
S = zeros(Pic-Class_number,Pic-Class_number);
for j = ( (i-1)*Class_population+1 ) : ( i*Class_population )
S = S + (ProjectedImages_PCA(:,j)-m_Intra(:,i))*(ProjectedImages_PCA(:,j)-m_Intra(:,i))';
end
S_Within = S_Within + S;
S_Between = S_Between + (m_PCA-m_Intra(:,i)) * (m_PCA-m_Intra(:,i))';
end
其中S_Within即类内离散度矩阵,S_Between即类间离散度矩阵。
将训练图像投影到Fisher线性空间(严格来说,是从PCA创建的特征空间投影到Fisher空间)即实现了人脸特征的提取。
matlab
% 计算fisher线性基
[J_eig_vec, J_eig_val] = eig(S_Between,S_Within);
% J_eig_val:广义特征值矩阵,J_eig_vec:广义特征向量矩阵
% J = inv(S_Within) * S_Between
J_eig_vec = fliplr(J_eig_vec);
%消除零特征向量
for i = 1 : Class_number-1
V_Fisher(:,i) = J_eig_vec(:,i); %V_Fisher矩阵
end
%投影到Fisher线性空间中
for i = 1 : Class_number*Class_population
ProjectedImages_Fisher(:,i) = V_Fisher' * ProjectedImages_PCA(:,i);
end
对于测试集中图像的处理与上述步骤的原理是类似的,有:
- 测试图像减去均值m_database
- 将测试图像投影到Fisher空间
- 计算测试图像与训练图像在Fisher空间的欧氏距离
- 指定欧氏距离最小的图像具有相同的类别,返回其文件索引
matlab
InImage = reshape(temp',irow*icol,1);
Difference = double(InImage)-m_database; % 背离程度
ProjectedTestImage = V_Fisher' * V_PCA' * Difference; % 测试图片的特征向量
%计算欧式距离,取欧式距离最小的图片输出
Euc_dist = [];
for i = 1 : Train_Number
q = ProjectedImages_Fisher(:,i);
temp = ( norm( ProjectedTestImage - q ) )^2;
Euc_dist = [Euc_dist temp];
End
[Euc_dist_min, Recognized_index] = min(Euc_dist);
在演算过程中,我们可以获取PCA特征空间上的特征脸。
由此也可以直观看到所谓"主元分析",或曰"数据降维"是如何发生的:当选用的特征脸基图像占据原图像矩阵中大部分的能量,这些数据即保留了原图中最主要、最有代表性的信息。
方法性能讨论
作为经典方法,当然是有一定效果的。我们重点来看错误匹配的结果,例如上图。未能被正确匹配的图像与测试图像之间存在头部的倾斜和旋转,为识别带来了干扰。而误匹配的图像头部皆保持直立正视。
将上述的表述在数学原理上进行表述,以对误分类的缘由进行探究,则有必要指出的是:FLD是一种线性变换,对于线性可分的数据,可以达到很好的全局优化效果,但是人脸并不符合线性子空间的假设------因为不同的人脸数据之间具有较大的重叠性,同样的人也可能因姿态、光线等原因呈现不同的面部特征。
相关问题可以在经典论文G Donato. Classifying facial actions. 1999.中看到详细讨论。
总的来说:
- 在PCA中,原始图像被投影到特征空间,以协方差矩阵的主要特征向量重建特征脸,从而提取人脸部特征。在FLD中,利用了类成员的信息,计算类间散度矩阵与类内散度矩阵,抽取特征向量集,其核心思想即:最大化类间距离,最小化类内距离。
- 若将特征值分解看作处于时域的图像矩阵的频域分解,重构的图像与原图的差距正在于未被使用的频率分量的能量。这也暗示着降维是如何可行的 :只要选用的特征向量能占据原图像矩阵中大部分的能量,这些数据即保留了原图中最主要、最有代表性的信息,一如在信号处理中,获取信号频谱的主瓣即能提取大部分信息。(当然,此处只是简短而笼统地谈论线性变换的一种物理意义,具体到PCA的分析还有很多值得深入的空间。在PCA中,构造协方差矩阵其实是为了实对称矩阵的对角化,使得不同的正交方向之间没有相关性。 )