簡體   English   中英

為什么在 Matlab 和 Octave 中 inv() 和 pinv() 的輸出不相等?

[英]Why is the output of inv() and pinv() not equal in Matlab and Octave?

我注意到如果 A 是 NxN 矩陣並且它有逆矩陣。 但是 inv() 和 pinv() 函數輸出的是什么不同。 - 我的環境是 Win7x64 SP1、Matlab R2012a、Cygwin Octave 3.6.4、FreeMat 4.2

看看 Octave 的例子:

A = rand(3,3)
A =
0.185987   0.192125   0.046346
0.140710   0.351007   0.236889
0.155899   0.107302   0.300623

pinv(A) == inv(A)
ans =
0 0 0
0 0 0
0 0 0
  • 這一切都同ans運行上面在Matlab相同的命令造成的。

  • 我計算inv(A)*AA*inv(A) ,結果是 Octave 和 Matlab 中的恆等 3x3 矩陣。
  • A*pinv(A)pinv(A)*A是 Matlab 和 FreeMat 中的恆等 3x3 矩陣。
  • A*pinv(A)是 Octave 中的恆等 3x3 矩陣。
  • pinv(A)*A的結果不是Octave 中的恆等 3x3 矩陣。

我不知道為什么inv(A) != pinv(A) ,我已經考慮了矩陣中元素的細節。 似乎是浮動精度問題導致了這個問題。

點后的 10+ 位數字可能會不同,如下所示:

  • 6.65858991579923298331777914427220821380615200000000 inv(A)(1,1)中的元素反對

  • 6.65858991579923209513935944414697587490081800000000 pinv(A)(1,1)元素

這個問題很老了,但無論如何我都會回答它,因為它似乎在一些谷歌搜索中幾乎排在最前面。

我將在我的例子中使用魔法(N)函數,該函數返回N-by-N魔方。

我將創建一個3x3魔方M3,取偽逆PI_M3並乘以它們:

prompt_$ M3 = magic(3) , PI_M3 = pinv(M3) , M3 * PI_M3
M3 =

    8   1   6
    3   5   7
    4   9   2

  PI_M3 =

     0.147222  -0.144444   0.063889
    -0.061111   0.022222   0.105556
    -0.019444   0.188889  -0.102778

  ans =

     1.0000e+00  -1.2212e-14   6.3283e-15
     5.5511e-17   1.0000e+00  -2.2204e-16
    -5.9952e-15   1.2268e-14   1.0000e+00

正如您所看到的,答案是單位矩陣,以節省一些舍入誤差。 我將用4x4魔方重復操作:

prompt_$ M4 = magic(4) , PI_M4 = pinv(M4) , M4 * PI_M4
M4 =

     16    2    3   13
      5   11   10    8
      9    7    6   12
      4   14   15    1

  PI_M4 =

     0.1011029  -0.0738971  -0.0613971   0.0636029
    -0.0363971   0.0386029   0.0261029   0.0011029
     0.0136029  -0.0113971  -0.0238971   0.0511029
    -0.0488971   0.0761029   0.0886029  -0.0863971

  ans =

     0.950000  -0.150000   0.150000   0.050000
    -0.150000   0.550000   0.450000   0.150000
     0.150000   0.450000   0.550000  -0.150000
     0.050000   0.150000  -0.150000   0.950000

結果不是單位矩陣,這意味着4x4魔方不具有逆。 我可以通過嘗試Moore-Penrose偽逆的一個規則來驗證這一點:

prompt_$ M4 * PI_M4 * M4
ans =

   16.00000    2.00000    3.00000   13.00000
    5.00000   11.00000   10.00000    8.00000
    9.00000    7.00000    6.00000   12.00000
    4.00000   14.00000   15.00000    1.00000

滿足規則A * B * A = A. 這表明pinv在可用時返回逆矩陣,而當逆矩陣不可用時返回偽逆。 這就是為什么在某些情況下你會得到一個小的差異,只是一些舍入錯誤,在其他情況下你會得到更大的差異。 為了顯示它,我將獲得兩個魔術象限的倒數並從偽逆中減去它們:

prompt_$ I_M3 = inv(M3) , I_M4 = inv(M4) , DIFF_M3 = PI_M3 - I_M3, DIFF_M4 = PI_M4 - I_M4
I_M3 =

     0.147222  -0.144444   0.063889
    -0.061111   0.022222   0.105556
    -0.019444   0.188889  -0.102778

  warning: inverse: matrix singular to machine precision, rcond = 1.30614e-17
  I_M4 =

     9.3825e+13   2.8147e+14  -2.8147e+14  -9.3825e+13
     2.8147e+14   8.4442e+14  -8.4442e+14  -2.8147e+14
    -2.8147e+14  -8.4442e+14   8.4442e+14   2.8147e+14
    -9.3825e+13  -2.8147e+14   2.8147e+14   9.3825e+13

  DIFF_M3 =

     4.7184e-16  -1.0270e-15   5.5511e-16
    -9.9226e-16   2.0470e-15  -1.0825e-15
     5.2042e-16  -1.0270e-15   4.9960e-16

  DIFF_M4 =

    -9.3825e+13  -2.8147e+14   2.8147e+14   9.3825e+13
    -2.8147e+14  -8.4442e+14   8.4442e+14   2.8147e+14
     2.8147e+14   8.4442e+14  -8.4442e+14  -2.8147e+14
     9.3825e+13   2.8147e+14  -2.8147e+14  -9.3825e+13

在我看來,你在底部回答了自己的問題。 原因是浮點運算。 inv()pinv()不完全相同,因為pinv()必須能夠處理非方形矩陣。 因此答案將不完全相同。

如果你看一下pinv(A)*A ,你會發現它非常接近單位矩陣。

我明白了:

ans =

   1.0000e+00   6.1062e-16  -3.0809e-15
  -5.8877e-15   1.0000e+00   6.3942e-15
   2.4425e-15  -3.0184e-16   1.0000e+00

不要將矩陣與==進行比較,而是使用< tolerance_limit

c = A*pinv(A);
d = pinv(A)*A;

(c-d) < 1e-10

邊注:

x = A^-1*b不應解決x = inv(A)*b; ,而是x = A \\ b; 請參閱Shai發布的鏈接以獲取解釋。

浮點運算具有一定的精度,可以不依賴於等式。 為避免此類錯誤,您可以嘗試使用matlab的符號工具箱。

非常簡單的八度代碼行來演示問題:

>>> (1/48)*48==(1/49)*49
ans = 0
>>> (1/48)*48-(1/49)*49
ans =  1.1102e-16
>>>

我通過使用pinv(A)計算了A=[1,1,0;1,0,1;2,1,1] (等級為 2)的偽逆矩陣。 A*pinv(A)給出了一個非單位矩陣,即A*pinv(A)=[0.667, -0.333, 0.333; -0.333, 0.667,0.333; 0.333, 0.333, 0.667] A*pinv(A)=[0.667, -0.333, 0.333; -0.333, 0.667,0.333; 0.333, 0.333, 0.667] A*pinv(A)=[0.667, -0.333, 0.333; -0.333, 0.667,0.333; 0.333, 0.333, 0.667] 我認為對於奇異矩陣,最好使用svd()手動計算偽逆矩陣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM