所谓的主成分分析,不过是在高维的空间中寻找一个低维的正交坐标系,比如说在三维空间中寻找一个二维的直角坐标系。那么这个二维的直角坐标系就会构成一个平面,将三维空间中的各个点在这个二维平面上做投影,就得到了各个点在二维空间中的一个表示,由此数据点就从三维降成了二维。
这个过程的关键在于,我们如何选取这个低维的坐标系,即坐标系原点在哪?各个轴朝哪个方向?一个原则就是使得各个点到到这个平面的距离平方和达到最小。由此,通过简单地数学推导,就能得到原点的表达公式和坐标系的各个基向量的表达公式。
下面以基于矩阵的视角写出PCA算法的算法流程,输入为p*N矩阵X,输出为d*N矩阵Y。矩阵的每一列都表示一个对象,每一行都表示对象的一个特征表示。
%%
%编写程序,实现PCA和LEE算法
%对图像进行降维实验,并显示降维重建后的图像
%运行已有程序,和自己的对比
%实验报告(伪代码(或流程图)、源代码、实验结果及分析)
%%
%编写程序,实现PCA和LEE算法
%对图像进行降维实验,并显示降维重建后的图像
%运行已有程序,和自己的对比
%实验报告(伪代码(或流程图)、源代码、实验结果及分析)
clc
clear
addpath(genpath(pwd));%将子孙文件添加到工作目录
load AR %导入数据
d = 20;
%%
AR = double(AR);%双进度化
[p ,N] = size(AR);%特征维度和对象数目
% for i = 1:N
% image = AR(:,i);
% image = reshape(image,50,40);
% imshow(mat2gray(image));%对原矩阵归一化
% end
x0 = mean(AR,2);%计算样本均值
AR_shift = AR - repmat(x0,1,N);%中心平移每个训练样本
%计算协方差矩阵的(n-1)倍,不用内置函数cov,提高代码的重用率和运行速度
Sigma = AR_shift*AR_shift';
%Sigma = cov(AR')*(N-1);
[W,D] = eigs(Sigma,d);%前d个特征向量作为wi
Lambda = diag(D);%提取特征值
%%
close all;
k = 1;
Y = W'*AR_shift(:,k);%第k个图像的输出表示
X_rebuid = W*Y + x0;%第k个图像的重建还原
image = AR(:,k);
image = reshape(image,50,40);
imshow(mat2gray(image));%对原矩阵归一化
figure;
image_re = X_rebuid;
image_re = reshape(image_re,50,40);
imshow(mat2gray(image_re));%对原矩阵归一化
选取了2000x1680的数据集进行了测试,选取降维后维数为20,其降维前后的图像(降维后的图像指的是投影点还原到原空间对应的坐标值重构出的图像)如下所示(选取第一个点为代表):
我们使用别人制作的降维工具箱“drtoolbox”重新进行计算并和我的程序结果进行比较。工具箱的使用代码和结果如下:
%% 使用工具箱进行进行降维来和我的实验结果进行比较
%% 使用工具箱进行进行降维来和我的实验结果进行比较
clc
clear
close all
method = 'LLE';%可选LLE或者PCA
addpath(genpath(pwd));
% 产生测试数据
%[X, labels] = generate_data('helix', 2000);
if strcmp(method,'PCA')
load AR %导入数据
[p,N] = size(AR);
X = double(AR);%导入数据
else
load face_images %导入数据
[p,N] = size(images);
X = double(images);%导入数据
end
% 估计本质维数
%no_dims = round(intrinsic_dim(X, 'MLE'));
%disp(['MLE estimate of intrinsic dimensionality: ' num2str(no_dims)]);
d = 2;
k = 12;
% PCA降维或LLE降维
[mappedX, mapping] = compute_mapping(X', method,d);
Y = mappedX';
if strcmp(method,'PCA')
x0 = (mapping.mean)';
W = (mapping.M);
AR_shift = X - repmat(x0,1,N);
%%
close all;
k = 1;
y = Y(:,k);
X_rebuid = W*y + x0;%第k个图像的重建还原
image = AR(:,k);
image = reshape(image,50,40);
imshow(mat2gray(image));%对原矩阵归一化
figure;
image_re = X_rebuid;
image_re = reshape(image_re,50,40);
imshow(mat2gray(image_re));%对原矩阵归一化
end
当然,我们也可以比较我的程序和工具箱程序的误差的大小,比如 L2 L 2 误差。都很简单,暂且不提。