還在為學習數學而發愁嗎?看完這篇文章,希望Python能幫助你消滅數學恐懼症。
用NumPy進行線性代數運算
線性代數是數學的一個重要分支,比如,我們可以使用線性代數來解決線性回歸問題。子程序包numpy.linalg提供了許多線性代數例程,我們可以用它來計算矩陣的逆、計算特徵值、求解線性方程或計算行列式等。對於NumPy來說,矩陣可以用ndarray的一個子類來表示。
用NumPy求矩陣的逆在線性代數中,假設A是一個方陣或可逆矩陣,如果存在一個矩陣A -1 ,滿足矩陣A -1 與原矩陣A相乘後等於單位矩陣I這一條件,那麼就稱矩陣A -1 是A的逆,相應的數學方程如下所示:
A A-1 = I
子程序包numpy.linalg中的inv()函數就是用來求矩陣的逆的。下面通過一個例子進行說明,具體步驟如下所示。
1.創建一個示例矩陣。
利用mat()函數創建一個示例矩陣:
A = np.mat("2 4 6;4 2 6;10 -4 18")print "A\n", A
矩陣A的內容如下所示:
A[[ 2 4 6][ 4 2 6] [10 -4 18]]]
2.求矩陣的逆。
現在可以利用inv()子例程來計算逆矩陣了:
inverse = np.linalg.inv(A)print "inverse of A\n", inverse
逆矩陣顯示如下:
inverse of A[[-0.41666667 0.66666667 -0.08333333][ 0.08333333 0.16666667 -0.08333333] [ 0.25 -0.33333333 0.08333333]]
小技巧:
如果該矩陣是奇異的,或者非方陣,那麼就會得到LinAlgError消息。如果你喜歡的話,也可以通過手算來驗證這個計算結果。這就當作是留給你的一個作業吧。NumPy庫中的pinv()函數可以用來求偽逆矩陣,它適用於任意矩陣,包括非方陣。
3.利用乘法進行驗算。
下面,我們將inv()函數的計算結果乘以原矩陣,驗算結果是否正確:
print "Check\n", A * inverse
不出所料,果然得到了一個單位矩陣(當然,前提是一些小誤差忽略不計):
Check[[ 1.00000000e+00 0.00000000e+00 -5.55111512e-17][ -2.22044605e-16 1.00000000e+00 -5.55111512e-17] [ -8.88178420e-16 8.88178420e-16 1.00000000e+00]]
將上面的計算機結果減去3×3的單位矩陣,會得到求逆過程中出現的誤差:
print "Error\n", A * inverse - np.eye(3)
一般來說,這些誤差通常忽略不計,但是在某些情況下,細微的誤差也可能導致不良後果:
[[ -1.11022302e-16 0.00000000e+00 -5.55111512e-17][ -2.22044605e-16 4.44089210e-16 -5.55111512e-17] [ -8.88178420e-16 8.88178420e-16 -1.11022302e-16]]
這種情況下,我們需要使用精度更高的數據類型,或者更高級的算法。上面,我們使用了numpy.linalg子程序包的inv()例程來計算矩陣的逆。下面,我們用矩陣乘法來驗證這個逆矩陣是否符合我們的要求(詳見本書代碼包中的inversion.py文件):
import numpy as npA = np.mat("2 4 6;4 2 6;10 -4 18")print "A\n", Ainverse = np.linalg.inv(A)print "inverse of A\n", inverseprint "Check\n", A * inverseprint "Error\n", A * inverse - np.eye(3)
用NumPy解線性方程組矩陣可以通過線性方式把一個向量變換成另一個向量,因此從數值計算的角度看,這種操作對應於一個線性方程組。Numpy.linalg中的solve()子例程可以求解類似Ax = b這種形式的線性方程組,其中A是一個矩陣,b是一維或者二維數組,而x是未知量。下面介紹如何使用dot()函數來計算兩個浮點型數組的點積(dot product)。
這裡舉例說明解線性方程組的過程,具體步驟如下所示。
1.創建矩陣A和數組b,代碼如下所示:
A = np.mat("1 -2 1;0 2 -8;-4 5 9")print "A\n", Ab = np.array([0, 8, -9])print "b\n", b
矩陣A和數組(向量)b的定義如下所示:
2.調用solve()函數。
接下來,我們用solve()函數來解這個線性方程組:
x = np.linalg.solve(A, b)print "Solution", x
線性方程組的解如下所示:
Solution [ 29. 16. 3.]
3.利用dot()函數進行驗算。
利用dot()函數驗算這個解是否正確:
print "Check\n", np.dot(A , x)
結果不出所料:
Check[[ 0. 8. -9.]]
前面,我們通過NumPy的linalg子程序包中的solve()函數求出了線性方程組的解,並利用dot()函數(詳見本書代碼包中的solution.py文件)驗算了結果,下面把這些代碼放到一起:
import numpy as npA = np.mat("1 -2 1;0 2 -8;-4 5 9")print "A\n", Ab = np.array([0, 8, -9])print "b\n", bx = np.linalg.solve(A, b)print "Solution", xprint "Check\n", np.dot(A , x)