Matlab SVD的单边Jacobi实现

Matlab SVD的单边Jacobi实现,matlab,svd,Matlab,Svd,我正在尝试编写奇异值分解(SVD)的一个简单实现。我使用单边雅可比算法,因为它看起来很简单。描述了算法,有一个简单的Matlab代码(练习4)。我已经实现了相同的代码,它工作正常,我的意思是SVD(A)=U*S*V'(或使用的任何其他符号),对于某些矩阵,结果与Matlab的SVD产生的结果相同(除了此函数不排序奇异值)。但我的问题是,当矩阵A的奇异值为0时,U和V不再是应该的酉矩阵 是否有办法更新此算法,使其也适用于奇异值为0的情况?如果没有,是否有另一种SVD算法同样容易实现? 感谢您的帮助

我正在尝试编写奇异值分解(SVD)的一个简单实现。我使用单边雅可比算法,因为它看起来很简单。描述了算法,有一个简单的Matlab代码(练习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

我不能让你的代码运行,因为当你计算alpha和beta时,你有你没有定义的sumsq。我在Matlab上找到了一些简单的代码,它使用QR分解(Gram schmidt)

现在看起来就像你有零。但如果你仔细看

format long 
>> S(4,4)

ans =

     3.418057860623250e-16


   S(5,5)

ans =

     9.725444388260210e-17

我会注意到,这是机器ε,对于所有密集型用途,它是0

我解决了这个问题,它应该是Matlab中的sumsqr,它是八度的sumsq。但其余的应该是一样的。我知道奇异值可以是0,但我的问题是当一列U用Jacobi方法变成0时。谢谢你的代码,我宁愿有一个不使用其他功能(如QR)的实现,但如果我能找到其他方法,我会使用这个,因为结果似乎是好的!你能举个例子吗?只有当奇异值正好为0时才会发生。我想修正的一个例子是A=0(例如3x3的0矩阵),其中U和V必须是I,但由于被0除,代码返回NaN。这里是另一个例子,其中d和v是正确的,但U的一列是NaN A=0.064-0.53-0.0 0.57 0.065 0.0 0 0.0.23-0.23 0.0我不确定这是否与代码有关,但雅可比方法的工作方式正确。
A = randn(5,3)*randn(5,3);
[U,S,Vt] = svdsim(A,1e-8);


S =

    6.3812         0         0         0         0
         0    2.0027         0         0         0
         0         0    1.0240         0         0
         0         0         0    0.0000         0
         0         0         0         0    0.0000
format long 
>> S(4,4)

ans =

     3.418057860623250e-16


   S(5,5)

ans =

     9.725444388260210e-17