低秩矩阵的计算

时间:2012-02-07 07:48:52

标签: performance algorithm math matrix

鉴于我有一个等级3的矩阵3x3 A. 我想在$ {l} _ {2} $ / Frobenius范数中创建一个最接近A的秩2矩阵。 我们称之为矩阵F.

通过SVD很容易实现,即,如果通过SVD分解$ F = U S {V} ^ {H} $ $ F = U \ hat {S} {V} ^ {H} $。 其中$ \ hat {S} $与$ S $相同,最后一个奇异值归零。

问题是,创建F但使用SVD分解的计算密集度较低吗?

感谢。

3 个答案:

答案 0 :(得分:5)

如果你知道矩阵是秩3,那么正好3个Householder变换就足以将nxm矩阵减少到3xm矩阵。现在可以很容易地将其转换为特征值问题。计算特征多项式。例如,考虑这个矩阵(我将使用MATLAB来完成工作):

>> A = rand(10,3);
>> B = A*rand(3,6);
显然,B将排名第3,但如果你不信任我,排名就会确认这一说法。

>> rank(B)
ans =
     3

>> size(B)
ans =
    10     6

所以B是10x6矩阵,等级3.SVD也确认了这个事实。

>> svd(B)
ans =
          6.95958965358531
          1.05904552889497
         0.505730235622534
      7.37626877572817e-16
      2.36322066654691e-16
      1.06396598411356e-16

我觉得懒得写Householder转换。 (我已经有了一些代码,但是......)所以我会用QR来帮助我。

>> [Q,R] = qr(B,0);
>> C = Q(:,1:3)'*B
C =
   -2.0815   -1.7098   -3.7897   -1.6186   -3.6038   -3.0809
    0.0000    0.91329   0.78347   0.44597  -0.072369   0.54196
    0.0000    0.0000   -0.2285   -0.43721  -0.85949  -0.41072

这里的乘法显示了在三次Householder变换后我们会看到的东西。看到它是我们所期望的上三角形。接下来,计算特征多项式。我在这里象征性地使用我自己的工具,但计算只是一些代数。

>> sympoly lambda
>> det(C*C' - lambda*eye(3))
ans =
    13.8942 + 66.9996*lambda + 49.8132*lambda^2 + lambda^3

>> P = det(C*C' - lambda*eye(3))
P =
    13.8942 - 66.9996*lambda + 49.8132*lambda^2 - lambda^3

P的根是什么,所以C * C'的特征值?

>> r = roots(P)
r =
       48.436
       1.1216
      0.25576

我们知道特征值必须是这里奇异值的平方,所以这里一个很好的测试是看我们是否恢复了svd发现的单元值。因此,再次扩展显示格式,我们看到它做得非常好。

>> sqrt(roots(P))
ans =
          6.95958965358531
          1.05904552889497
         0.505730235622533

数学在工作时会很有趣。我们可以对这些信息做些什么?如果我知道一个特定的特征值,我可以计算出相应的特征向量。基本上,我们需要求解线性3x3齐次方程组

(C*C' - eye(3)*r(3)) * X = 0

同样,我在这里懒得找到解决方案,而不是实际编写任何代码。高斯消除会做到这一点。

>> V = null((C*C' - eye(3)*r(3)))
V =
        -0.171504758161731
        -0.389921448437349
         0.904736084157367

所以我们得到V,C * C'的特征向量。我们可以通过以下对svd的调用来说服自己是一个。

>> svd(C - V*(V'*C))
ans =
           6.9595896535853
          1.05904552889497
      2.88098729108798e-16

因此,通过在V方向上减去C的那个分量,我们得到一个秩2矩阵。

类似地,我们可以将V转换为原始问题空间,并使用它将矩阵B(我们的原始矩阵)转换为B的一级更新。

>> U = Q(:,1:3)*V;
>> D = B - U*(U'*B);

D的等级是什么?

>> svd(D)
ans =
          6.95958965358531
          1.05904552889497
      2.62044567948618e-15
      3.18063391331806e-16
      2.16520878207897e-16
      1.56387805987859e-16

>> rank(D)
ans =
     2

正如你所看到的,即使我做了很多数学,多次调用svd,QR,rank等等,但最后,实际计算相对微不足道。我只需要......

  1. 3户主变换。 (存储它们以供以后使用。请注意,Householder转换只是对矩阵的一级更新。)
  2. 计算特征多项式。
  3. 使用您最喜欢的方法计算最小根,用于三次多项式。
  4. 恢复相应的特征向量。高斯消除就足够了。
  5. 使用我们最初做的户主变换将特征向量移回原始空间。
  6. 对矩阵进行一级更新。
  7. 所有这些计算步骤对于任何大小矩阵都是快速有效的,只要我们知道实际等级为3.甚至不值得关于该主题的论文。

    编辑:

    由于问题已被修改,使得矩阵本身仅为3x3,因此计算更加微不足道。然而,我将保留帖子的第一部分,因为它描述了任何大小为3级的一般矩阵的完全有效的解决方案。

    如果您的目标是消除3x3矩阵的最后一个奇异值,那么3x3上的svd似乎非常有效。通过间接方式产生最后的奇异值也会有一些精度损失。例如,在此比较由svd计算的最小奇异值,然后使用特征值。因此,您可能会在此处看到一些小错误,因为形成A'* A会导致一些精度。这种损失的程度可能取决于A的条件数。

    >> A = rand(3);
    >> sqrt(eig(A'*A))
    ans =
            0.0138948003095069
             0.080275195586312
              1.50987693453097
    >> svd(A)
    ans =
              1.50987693453097
            0.0802751955863124
            0.0138948003095054
    

    但是,如果你真的想自己做这项工作,你可以做到。

    1. 直接从3x3矩阵A'* A
    2. 计算特征多项式
    3. 计算该三次多项式的根。选择最小的根。
    4. 生成相应的特征向量。
    5. 对A进行一级更新,消除A方向那个特征向量的部分。
    6. 这比对svd的简单调用更简单或更少计算效率,然后是一级更新吗?我完全不确定3x3的努力是否值得。 3x3 svd的计算速度非常快。

答案 1 :(得分:0)

您可能已经考虑过了,但如果A是正常的,则可以通过特征值分解来计算SVD。这相当于求解特征多项式,并且由于它是秩3矩阵的3次多项式,因此根据众所周知的立方公式找到。

看起来SVD通常必须可以简化为3级矩阵的求解立方体,但我不记得在那里阅读任何内容。一个快速的google-around转向this piece of code声称以这种方式解决了3级SVD。不幸的是,没有随附的纸张。如果使用此代码,使用非正定矩阵进行测试应该是一个很好的测试用例。

编辑:在第二次阅读时,似乎作者也使用了特征分解。可能在非PD矩阵上并不好,但我想在这里被证明是错误的。

答案 2 :(得分:0)

您可以使用幂迭代来查找与最大奇异值对应的奇异向量。一旦你有了,你可以使用修改版本的幂迭代来找到第二大奇异值的向量;在每次迭代之后,您需要将部分解向量的投影减去最大奇异值的向量。

这对于找到所有奇异向量来说是一种糟糕的方法,但是对于前两个向量应该可以正常工作。