SVD Matlab实现

时间:2016-02-27 02:47:21

标签: matlab svd

我尝试编写将矩阵分解为SVD格式的matlab代码。

“理论”:

为了得到U,我找到了AA'的特征向量,为了得到V,我找到了A'A的特征向量。最后,Sigma是一个与A相同维度的矩阵,在对角线上的特征值的根是有序序列。

但是,它似乎无法正常工作。

A=[2 4 1 3; 0 0 2 1];

% Get U, V
[aatVecs, aatVals] = eig(A*A');
[~, aatPermutation] = sort(sum(aatVals), 'descend');
U = aatVecs(:, aatPermutation);

[ataVecs, ataVals] = eig(A'*A);
[~, ataPermutation] = sort(sum(ataVals), 'descend');
V = ataVecs(:, ataPermutation);

% Get Sigma
singularValues = sum(aatVals(:, aatPermutation)).^0.5;
sigma=zeros(size(A));
for i=1:nnz(singularValues)
    sigma(i, i) = singularValues(i);
end

A
U*sigma*V'

U * sigma * V'似乎以-1的系数返回:

ans =

-2.0000   -4.0000   -1.0000   -3.0000
0.0000    0.0000   -2.0000   -1.0000

导致它的代码或“理论”中的错误是什么?

1 个答案:

答案 0 :(得分:6)

特征向量不是唯一的(因为根据定义Av==λv,任何w μw==vμ~=0也是一个特征向量。恰好,eig返回的特征向量不能以正确的方式匹配SVD(即使它们被标准化)。

但是,我们可以在U后构建V,我们会在算法中找到A'*A的特征向量。找到V作为已排序的特征向量后,您必须找到要匹配的U。由于V是正交的,A*V == U*sigma。所以我们可以设置

U = [A*V(:,1)./singularValues(1) A*V(:,2)./singularValues(2)];

实际上,A == U*sigma*V',特别是此处找到的U与您的算法中找到的U完全相反。