如何找到近似奇异矩阵的逆?

时间:2014-01-05 03:07:31

标签: c++ matlab math matrix

我正在实现一种使用C ++和CUDA的算法。但是当我试图找到一个特殊矩阵的逆时,我遇到了麻烦。 该矩阵具有以下特征:

  1. 它是一个方阵(假设:(m + 3)x(m + 3),m> 0);
  2. 它的转置矩阵是它的自我;
  3. 其主对角线必须为零;
  4. 它的右下角必须有一个3x3的零矩阵;
  5. 你可以用这种形式考虑这个矩阵:H = [A,B; B',0];
  6. 我尝试了一些方法,但都失败了:

    1. 伪逆矩阵:

      我首先使用了matlab,当我尝试使用inv(H'* H)时出现错误或警告: 警告:Matrix对于工作精度是单数的 或< strong> 矩阵接近单一或严重缩放

    2. 一些近似方法:

      参考资料在这里:approximation我发现了两种方法:Gauss-Jordan消除和Cholesky分解。当我在matlab中尝试chol时,我得到以下 错误:Matrix必须是正定的

    3. 任何人都可以给我一些建议吗?

2 个答案:

答案 0 :(得分:1)

最好了解一些有关特定问题的信息,特别是如果您需要反向本身,或者您只需要反转一个线性方程组。我会尽力给你两个案例的指示。

让我首先考虑你的矩阵几乎是单数,因此你的系统是病态的。

确定近似奇异矩阵的反转

正如上面的评论和答案中所阐明的那样,寻找近似奇异矩阵的逆是没有意义的。有意义的是构造矩阵的正则化逆。您可以通过使用矩阵的谱分解(奇异值分解或SVD)来做到这一点。更详细地说,您可以构造奇异系统,去除最不重要的奇异值,这些奇异值是矩阵的近似奇异行为的来源,然后使用奇异值和向量来形成近似逆。当然,在这种情况下,A*A_inv仅给出单位矩阵的近似值。

如何在GPU上完成?首先,我要说在C ++或CUDA中实现SVD算法绝非易事。根据您需要的精度,您应该选择几种技术,例如,确定奇异值。无论如何,Matlab有一组linear algebra functions working on GPU。此外,CULAMagma是提供SVD计算例程的两个库。此外,您可以考虑使用Arrayfire,它还提供线性代数例程,包括SVD。

倒置一个奇异的奇异系统

在这种情况下,您应该考虑使用某种Tikhonov正则化,其中包括将线性系统的反演作为优化问题并添加正则化项,这可能取决于您已知的有关您的未知数的特征。

对于上述两种情况,我建议阅读一些理论。这本书

M. Bertero, P. Boccacci, Introduction to Inverse Problems in Imaging

如果你必须找到一个近似的逆或者你明确地反转了线性系统,那么

会很有用。

答案 1 :(得分:0)

伪逆矩阵是inv(H'*H)*H',因为H的条件数非常高(try cond(H)),你可能需要一个正则化因子来获得伪逆矩阵:inv(H'*H + lambda*eye(size(H)))*H'lambda越小,这种估计的偏差越小。但lambda的值太小会导致高度差异(病态)。您可以尝试最佳套装价值。

您当然可以直接使用pinv(H)pinv(H)*H ~= eye(size(H))之所以是因为pinv(H)只是矩阵H的倒数的近似值,其等级低于size(H,1)。换句话说,H中的列并非完全独立。

我想向您展示一个非常简单的例子:

>>a =

     0     1     0
     0     0     1
     0     1     0

  pinv(a) * a
>>
   ans =

     0         0         0
     0    1.0000         0
     0         0    1.0000
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>>a =  
     1     0
     0     1
     1     0

 pinv(a) * a
>>

 ans =

1.0000         0
     0    1.0000

注意a * pinv(a)不是单位矩阵,因为a的列是线性独立的,而不是a的行。有关详细信息,请查看此page