2014-02-17 164 views
4

在numpy中計算矩陣求逆(求解線性系統)時,我得到了看似不可接受的高誤差。Numpy不準確的矩陣求逆

  • 這是不正常的正常水平?
  • 如何提高此計算的準確性?
  • 此外,有沒有辦法更有效地解決這個系統在numpy或scipy(scipy.linalg.cho_solve似乎很有前途,但沒有做我想要的)?

在下面的代碼中,cholM是一個128 x 128矩陣。矩陣數據太大而不能包含在這裏,但位於pastebin:cholM.txt

此外,原始矢量ovec是隨機選擇的,因此對於不同的ovec的準確度會有所不同,但是對於大多數情況下,錯誤仍然看起來高得令人無法接受。

編輯使用奇異值分解求解系統產生的誤差明顯低於其他方法。

import numpy.random as rnd 
import numpy.linalg as lin 
import numpy as np 

cholM=np.loadtxt('cholM.txt') 

dims=len(cholM) 
print 'Dimensions',dims 

ovec=rnd.normal(size=dims) 
rvec=np.dot(cholM.T,ovec) 
invCholM=lin.inv(cholM.T) 

svec=np.dot(invCholM,rvec) 
svec1=lin.solve(cholM.T,rvec) 

def back_substitute(M,v): 
    r=np.zeros(len(v)) 
    k=len(v)-1 
    r[k]=v[k]/M[k,k] 
    for k in xrange(len(v)-2,-1,-1): 
     r[k]=(v[k]-np.dot(M[k,k+1:],r[k+1:]))/M[k,k] 

    return r 

svec2=back_substitute(cholM.T,rvec) 

u,s,v=lin.svd(cholM) 
svec3=np.dot(u,np.dot(np.diag(1./s),np.dot(v,rvec))) 

for k in xrange(dims): 
    print '%20.3f%20.3f%20.3f%20.3f'%(ovec[k]-svec[k],ovec[k]-svec1[k],ovec[k]-svec2[k],ovec[k]-svec3[k]) 

assert np.all(np.abs(ovec-svec)<1e-5) 
assert np.all(np.abs(ovec-svec1)<1e-5) 
+5

通常情況下,這是一個跡象,表明您的矩陣病態。對於您提供的下三角矩陣,似乎最大奇異值與最小奇異值的比值(條件號)大約爲10^16。這絕對是一個問題。 –

+0

爲什麼條件號碼在這裏?我正在採取逆向行動,所以通常情況下,如果矩陣接近單數,我會擔心。 'cholM'矩陣是三角形的,所以對角線上的非常小的值肯定會影響解,但這不會發生。 – user1149913

+1

您可以嘗試乘以cholM和invCholM,然後減去單位矩陣以說服您自己條件數是否重要 –

回答

-1

http://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html

我們可以利用矩陣求逆找到解向量: ... 然而,最好是使用linalg.solve命令,它可以更快,更穩定的數值

編輯 - 從史蒂夫主在MATLAB http://www.mathworks.com/matlabcentral/newsreader/view_thread/63130

你爲什麼反轉?如果您想要解決系統問題,請不要 - 一般而言,您希望使用反斜槓。

但是,對於圍繞1E17條件數系統(條件數 必須大於或等於1,所以我假設1E17數字在 您的文章是從RCOND的倒數條件數)你在任何情況下,都不會去 獲得非常準確的結果。

2

如@CraigĴCOPI和@pv指出的,cholM矩陣的condition number是高的,大約10^16,表明在逆來實現更高的精度,更大的數值精度可能是必需的。

條件數可以通過最大奇異值與最小奇異值的比率來確定。在這種情況下,這個比率與特徵值的比率不一樣。