【发布时间】:2018-11-17 14:49:48
【问题描述】:
我正在尝试编写奇异值分解 (SVD) 的简单实现。我正在使用单边 Jacobi 算法,因为它看起来很简单。该算法描述为here,并且有一个简单的Matlab 代码用于here(练习4)。我已经实现了相同的代码,它工作正常,我的意思是 SVD(A) = U * S * V' (或任何其他使用的符号),对于某些矩阵,结果与 Matlab 的 SVD 产生的结果相同(除了这个函数不对奇异值进行排序)。但我的问题是,当矩阵 A 的奇异值为 0 时,U 和 V 不再是应有的酉矩阵!
有没有办法更新这个算法,使其也适用于奇异值为 0 的情况?如果没有,是否还有另一种易于实现的 SVD 算法? 任何帮助表示赞赏。
这是我的 Matlab 代码,与上面链接中的代码基本相同,刚刚完成并稍作改动。
function [U,S,V] = jacobi_SVD(A)
TOL=1.e-4;
n=size(A,1);
U=A';
V=eye(n);
converge=TOL+1;
while converge>TOL
converge=0;
for i=1:n-1
for j=i+1:n
% compute [alpha gamma;gamma beta]=(i,j) submatrix of U*U'
alpha=sumsqr(U(i, :));
beta=sumsqr(U(j, :));
gamma=sum(U(i, :).* U(j, :));
converge=max(converge,abs(gamma)/sqrt(alpha*beta));
% compute Jacobi rotation that diagonalizes
% [alpha gamma;gamma beta]
zeta=(beta-alpha)/(2*gamma);
t=sign(zeta)/(abs(zeta)+sqrt(1+zeta^2));
c= 1.0 / (sqrt(1 + t * t));
s= c * t;
% update columns i and j of U
t=U(i, :);
U(i, :)=c*t-s*U(j, :);
U(j, :)=s*t+c*U(j, :);
% update matrix V of right singular vectors
t=V(i, :);
V(i, :)=c*t-s*V(j, :);
V(j, :)=s*t+c*V(j, :);
end
end
end
% the singular values are the norms of the columns of U
% the left singular vectors are the normalized columns of U
for j=1:n
singvals(j)=norm(U(j, :));
U(j, :)=U(j, :)/singvals(j);
end
S=diag(singvals);
U = U';
V = V'; %return V, not V'
end
【问题讨论】: