在MATLAB中进行主成分分析

10
我正在使用特征值分解来实现稀疏数据的主成分分析(PCA)。我知道 MATLAB 已经实现了 PCA,但是当我编写代码时,这有助于我理解所有技术细节。我一直在遵循这里的指导,但与内置函数 princomp 相比,结果有所不同。
请问能否帮我看一下代码,并指点我正确的方向?
以下是代码:
function [mu, Ev, Val ] = pca(data)

% mu - mean image
% Ev - matrix whose columns are the eigenvectors corresponding to the eigen
% values Val 
% Val - eigenvalues

if nargin ~= 1
 error ('usage: [mu,E,Values] = pca_q1(data)');
end

mu = mean(data)';

nimages = size(data,2);

for i = 1:nimages
 data(:,i) = data(:,i)-mu(i);
end

L = data'*data;
[Ev, Vals]  = eig(L);    
[Ev,Vals] = sort(Ev,Vals);

% computing eigenvector of the real covariance matrix
Ev = data * Ev;

Val = diag(Vals);
Vals = Vals / (nimages - 1);

% normalize Ev to unit length
proper = 0;
for i = 1:nimages
 Ev(:,i) = Ev(:,1)/norm(Ev(:,i));
 if Vals(i) < 0.00001
  Ev(:,i) = zeros(size(Ev,1),1);
 else
  proper = proper+1;
 end;
end;

Ev = Ev(:,1:nimages);
1个回答

14

这是我如何做到的:

function [V newX D] = myPCA(X)
    X = bsxfun(@minus, X, mean(X,1));           %# zero-center
    C = (X'*X)./(size(X,1)-1);                  %'# cov(X)

    [V D] = eig(C);
    [D order] = sort(diag(D), 'descend');       %# sort cols high to low
    V = V(:,order);

    newX = X*V(:,1:end);
end

同时提供一个示例,与统计工具箱中的PRINCOMP函数进行比较:

load fisheriris

[V newX D] = myPCA(meas);
[PC newData Var] = princomp(meas);

你可能也对这篇关于使用SVD进行PCA的相关帖子感兴趣:PCA by SVD


我想问一些问题,princomp默认是否按latentCOEFF数据进行排序(参考:http://www.mathworks.com/help/stats/princomp.html)? 您的函数与princomp有什么区别? - user3396151
我想使用coefflatent,其中coefflatents一起排序。我可以使用内置函数princomp还是您的myPCA - user3396151
@AhsanAli:显然,如上面的示例所示,两个函数产生相同的输出(精度到一定程度); COEFF(主成分)的列按照组件方差LATENT的降序排序。此外,请查看上面提到的最后一个链接,了解使用SVD而不是EIG执行PCA的方法。请注意,在最近的版本中,princomp正在被pca函数替换(实际上检查源代码以查看对princomp的调用是否在内部路由到pca)。 - Amro
2
PCA归根结底是一种正交变换,将数据转换为一个新的坐标系(使得数据在新方向上的方差按降序排列最大)。主成分(COEFF矩阵的列)是描述这个新系统方向的向量。现在,如果(I,J,K)是向量空间的基,则(a*I,b*J,c*K)也是基,对应的数据坐标为(SCORE矩阵)。因此,特征向量不是唯一的(可以独立缩放/乘以常数),只要它们跨越相同的子空间。 - Amro
让我们在聊天中继续这个讨论 - user3396151
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接