了解 MATLAB 中的 PCA

Understanding PCA in MATLAB

下面两个函数有什么区别?

prepTransform.m

function [mu trmx] = prepTransform(tvec, comp_count)
% Computes transformation matrix to PCA space
% tvec - training set (one row represents one sample)
% comp_count - count of principal components in the final space
% mu - mean value of the training set
% trmx - transformation matrix to comp_count-dimensional PCA space

% this is memory-hungry version
% commented out is the version proper for Win32 environment

tic;
mu = mean(tvec);
cmx = cov(tvec); 

%cmx = zeros(size(tvec,2));
%f1 = zeros(size(tvec,1), 1);
%f2 = zeros(size(tvec,1), 1);
%for i=1:size(tvec,2)
%  f1(:,1) = tvec(:,i) - repmat(mu(i), size(tvec,1), 1);
%  cmx(i, i) = f1' * f1;
%  for j=i+1:size(tvec,2)
%    f2(:,1) = tvec(:,j) - repmat(mu(j), size(tvec,1), 1);
%    cmx(i, j) = f1' * f2;
%   cmx(j, i) = cmx(i, j);
%  end
%end
%cmx = cmx / (size(tvec,1)-1);

toc
[evec eval] = eig(cmx);
eval = sum(eval);

[eval evid] = sort(eval, 'descend');
evec = evec(:, evid(1:size(eval,2)));

% save 'nist_mu.mat' mu
% save 'nist_cov.mat' evec 
trmx = evec(:, 1:comp_count);

pcaTransform.m

function [pcaSet] = pcaTransform(tvec, mu, trmx)
% tvec - matrix containing vectors to be transformed
% mu - mean value of the training set
% trmx - pca transformation matrix
% pcaSet -  output set transforrmed to PCA  space

pcaSet = tvec - repmat(mu, size(tvec,1), 1);

%pcaSet = zeros(size(tvec));
%for i=1:size(tvec,1)
%  pcaSet(i,:) = tvec(i,:) - mu;
%end

pcaSet = pcaSet * trmx;

哪个在做PCA?

如果一个人在做 PCA,另一个人在做什么?

第一个函数 prepTransform 实际上是对您的训练数据执行 PCA,您在其中确定新轴以将数据表示到较低维度 space。它所做的是找到数据的协方差矩阵的特征向量,然后对特征向量进行排序,使得具有最大特征值的特征向量出现在特征向量矩阵的第一列 evec 和具有最小特征值的特征向量出现在最后一列。此函数的重要之处在于,您可以通过保留 evec 的前 N 列来定义要将数据减少到多少维度,这将允许您将数据减少到 N 维度。丢弃其他列并仅保留第一个 N 是代码中设置为 trmx 的内容。变量 NprepTransform 函数中的 prep_count 变量定义。

第二个函数 pcaTransform 最终将定义在与训练数据相同的域中但不一定是训练数据本身(如果您愿意也可以)的数据转换到较低维度 space 由协方差矩阵的特征向量定义。要最终执行降维,或众所周知的 dimensionality reduction,您只需将训练数据从其均值中减去每个特征,然后将训练数据乘以矩阵 trmx。请注意,prepTransform 输出向量 mu 中每个特征的平均值很重要,以便在您最终调用 pcaTransform 时减去数据。


如何使用这些功能

要有效地使用这些函数,首先要确定 trmx 矩阵,其中包含数据的 主要成分,方法是首先定义要减少的维数数据以及存储在 mu:

中的每个特征的平均值
N = 2; % Reduce down to two dimensions for example
[mu, trmx] = prepTransform(tvec, N);

接下来,您最终可以对定义在与 tvec 相同的域(如果您愿意,甚至可以是 tvec,但不一定如此)的数据执行降维,方法是:

pcaSet = pcaTransform(tvec, mu, trmx);

就词汇而言,pcaSet 包含数据的 主要分数 ,这是用于将数据转换为低维 space.

如果我能推荐一些东西...

已知通过特征向量方法寻找 PCA 是不稳定的。我强烈建议您在协方差矩阵上使用 Singular Value Decomposition via svd,其中结果的 V 矩阵已经为您提供了与主成分相对应的特征向量:

mu = mean(tvec, 1);
[~,~,V] = svd(cov(tvec));

然后通过取每个特征的平均减去数据并乘以 V 矩阵来执行转换,一旦您子集化并获取 V 的前 N 列:

N = 2;
X = bsxfun(@minus, tvec, mu); 
pcaSet = X*V(:, 1:N);

X 是平均减去数据,它执行与 pcaSet = tvec - repmat(mu, size(tvec,1), 1); 相同的操作,但您没有明确地在每个训练示例上复制平均向量,而是让 bsxfun 这样做为你内部。但是,利用 MATLAB R2016b,无需显式调用 bsxfun:

即可完成此重复
X = tvec - mu;

进一步阅读

如果您完全想理解所编写的代码及其背后的理论,我推荐以下两本 Stack Overflow post我写的关于该主题的文章:

第一个 post 介绍了您提供的代码,它使用特征向量方法执行 PCA。第二个 post 涉及您如何在答案末尾使用 SVD 来做到这一点。我在这里写的这个答案是上面两个 post 的混合。