PCA ( principal component analysis)概念
主成分分析方法(PCA)指的是在各个变量之间相关关系研究的基础上,用较少的新变量代替原来较多的变量,而且使这些较少的新变量尽可能多地保留原来较多的变量所反映信息的一种方法。它在面部识别和图像压缩等方面都有广泛的应用,是一种非常有效的降维处理的方法。
计算步骤
(1)获取初始数据 一般应用时需要先采集数据信息,这些信息可以是2 维、3 维甚至更多维数的,如用三维扫描仪获取的人脸数据,有 N个3D维扫描点构成3*N维空间。
(2)对原始数据进行修正 为了能使 PCA 算法有效进行,需要对原始数据进行预处理,这里采取的办法就是将每一维的数据都减掉各自的均值。
(3)计算协方差矩阵 协方差用于衡量两个不同参数之间的关系,假设有三维的数据 (x, y, z),可以计算任意两个维度之间的协方差,计算 x 自身的协方差会得到 x 的方差。
这里有必要重温下矩阵和概率论中的相关知识点
(4)计算协方差矩阵的特征值和特征向量 对于协方差矩阵来说,其特征向量有如下特征:一个 n×n 的对称方阵有 n 个特征向量,并且将特征向量成比例扩大或缩小后仍是特征向量,这是因为将特征向量成比例扩大或缩小只会影响它的长度而不会改变它的方向;不管矩阵有多少维,它的不同特征值的特征向量都是正交的。这个特征很重要,因为正交意味着可以用特征向量来代替原始的数据轴表示数据。矩阵代数中,在计算特征向量时,都需要把它归一化,这是因为一个特征向量的决定因素不是它的长度,而是它的方向。因此,为了使特征向量有一个统一的标准,规定所有的特征向量的长度都需要归一化为 1,这样所有的特征向量就具有统一的长度。特征向量和特征值总是成对出现的,计算得到一个特征向量的同时会得到一个与此相关的一个特征值。
(5)选取主要成分构成特征基 求出特征向量之后可以把特征向量按照特征值从大到小进行排序,由于特征值的大小决定了特征向量在最后的特征基中所占的比重,因此可以去掉特征值较小的特征向量,这样虽然会丢失一些信息,但是由于特征值很小,因此失去的信息量很小,这样一来,最后的数据将会比原始数据维数减小,就可以达到对数据降维的目的。对于高维向量可通过 SVD 求解。
PCA数学推导过程可以参考这篇博文,博主讲解的很详细
http://blog.csdn.net/watkinsong/article/details/38536463
在matlab中运用PCA做人脸重构
%% Initialization
clear ; close all; clc
fprintf('this code will load 40 images and do PCA for each face.\n');
fprintf('35 images are used to train PCA and the other 5 images are used to test PCA.\n');
m = 35; % number of samples
trainset = zeros(m, 28 * 23); % image size is : 28 * 23
for i = 1 : m
img = imread(strcat('E:\Picture\ORL人脸库\ORL人脸库\ORL92112\ORL92112\bmp\trainset\', int2str(i), '.bmp')); %从文件中读取
img = double(img);
trainset(i, :) = img(:);
end
%% before training PCA, do feature normalization
mu = mean(trainset);
trainset_norm = bsxfun(@minus, trainset, mu); % 执行trainset-mu操作
sigma = std(trainset_norm); %returnsa row vector containing the standard deviation of the elements ofeach column of X
trainset_norm = bsxfun(@rdivide, trainset_norm, sigma);
%% we could save the mean face mu to take a look the mean face
imwrite(uint8(reshape(mu, 28, 23)), 'meanface.bmp'); %写到文件
fprintf('mean face saved. paused\n');
pause;
%% compute reduce matrix
X = trainset_norm; % just for convience
[m, n] = size(X);
U = zeros(n);
S = zeros(n);
Cov = 1 / m * X' * X;
[U, S, V] = svd(Cov);
fprintf('compute cov done.\n');
%% save eigen face
for i = 1:20
ef = U(:, i)';
img = ef;
minVal = min(img);
img = img - minVal; %将图像灰度整体调整,使得最低灰度值为0
max_val = max(abs(img));
img = img / max_val; %归一化操作,使得图像灰度在[0,1]之间
img = reshape(img,28, 23);
imwrite(img, strcat('E:\MATLAB实例\PCA\eigenface\eigenface', int2str(i), '.bmp'));%写到文件
end
fprintf('eigen face saved, paused.\n');
pause(10);
%% dimension reduction
k = 100; % reduce to 100 dimension
test = zeros(5, 28* 23);
for i = 36:40
img = imread(strcat('E:\Picture\ORL人脸库\ORL人脸库\ORL92112\ORL92112\bmp\trainset\', int2str(i), '.bmp'));
img = double(img);
test(i - 35, :) = img(:);
end
% test set need to do normalization
test = bsxfun(@minus, test, mu); %执行test-mu操作
% reduction
Uk = U(:, 1:k);
Z = test * Uk;
fprintf('reduce done.\n');
%% reconstruction
%% for the test set images, we only minus the mean face,
% so in the reconstruct process, we need add the mean face back
Xp = Z * Uk'; %重构测试集
% show reconstructed face
for i = 1:5
face = Xp(i, :) + mu;
face = reshape((face), 28, 23);
imwrite(uint8(face), strcat('E:\MATLAB实例\PCA\Reconstruction\', int2str(35 + i), '.bmp'));
end
%% for the train set reconstruction, we minus the mean face and divide by standard deviation during the train
% so in the reconstruction process, we need to multiby standard deviation first,
% and then add the mean face back
trainset_re = trainset_norm * Uk; % reduction
trainset_re = trainset_re * Uk'; % reconstruction
for i = 1:5
train = trainset_re(i, :);
train = train .* sigma;
train = train + mu;
train = reshape(train, 28, 23);
imwrite(uint8(train), strcat('E:\MATLAB实例\PCA\Reconstruction\', int2str(i), 'train.bmp'));
end
fprintf('job done.\n');
%% print the eigenface and reconstruct results
figure;
for j=1:20
subplot(4,5,j),imshow(strcat('E:\MATLAB实例\PCA\eigenface\eigenface',int2str(j),'.bmp'));
end
figure;
for j=1:5
subplot(1,5,j),imshow(strcat('E:\MATLAB实例\PCA\Reconstruction\',int2str(j),'train.bmp'));
end
figure;
for j=36:40
subplot(1,5,j-35),imshow(strcat('E:\MATLAB实例\PCA\Reconstruction\',int2str(j),'.bmp'));
end
平均脸
前20个特征脸
训练集样本重构
测试集样本重构
可以看出 训练集样本比测试机样本重构出来的效果好很多。当然,这也侧面反映出了训练集样本不足。