我正在使用不同的方法求解矩陣。根據我對 numpy 描述的解釋,我測驗的所有三種方法(SVD 反演、摩爾-彭羅斯反演和最小二乘法)都應該得到相同的答案。然而,SVD 反演會產生非常不同的答案。我在 Numerical Recipes 中找不到數學原因。是否有導致這種情況的 Numpy 實作細微差別?
我在 jupyter 筆記本中的 Python 3.8.10、Numpy 1.21.4 上使用以下代碼
y = np.array([176, 166, 194])
x = np.array([324, 322, 376])
x = np.stack([x, np.ones_like(x)], axis=1)
# Solve the matrix using singular value decomposition
u, s, vh = np.linalg.svd(x, full_matrices=False)
s = np.where(s < np.finfo(s.dtype).eps, 0, s)
manual_scale, manual_offset = vh @ np.linalg.inv(np.diag(s)) @ u.T @ y
display(manual_scale, manual_offset, manual_scale * x manual_offset)
# Solve the matrix using Moore-Penrose Inversion
# Manually
manual_scale, manual_offset = np.linalg.inv(x.T @ x) @ x.T @ y
display(manual_scale, manual_offset, manual_scale * x manual_offset)
# Using supplied numpy methods
manual_scale, manual_offset = np.linalg.pinv(x) @ y
display(manual_scale, manual_offset, manual_scale * x manual_offset)
# Solve using lstsq
((manual_scale, manual_offset), residuals, rank, s) = np.linalg.lstsq(x, y)
display(manual_scale, manual_offset, manual_scale * x manual_offset)
輸出(為清晰起見進行了編輯)然后是
'SVD'
0.6091639943577222
29.167637174498772
array([[226.53677135, 29.77680117],
[225.31844336, 29.77680117],
[258.21329905, 29.77680117]])
'Manual Moore-Penrose'
0.4388335704125341
29.170697012800005
array([[171.35277383, 29.60953058],
[170.47510669, 29.60953058],
[194.17211949, 29.60953058]])
'Moore-Penrose'
0.43883357041251736
29.170697012802187
array([[171.35277383, 29.60953058],
[170.47510669, 29.60953058],
[194.17211949, 29.60953058]])
'LSTSQ'
/tmp/ipykernel_261995/387148285.py:24: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.
To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.
((manual_scale, manual_offset), residuals, rank, s) = np.linalg.lstsq(x, y)
0.43883357041251814
29.17069701280214
array([[171.35277383, 29.60953058],
[170.47510669, 29.60953058],
[194.17211949, 29.60953058]])
正如您所看到的,后面的三種方法得到了相同的結果,但是手動 svd 計算是不同的。到底是怎么回事?
uj5u.com熱心網友回復:
您缺少 的轉置vh。SVD解決方案應該是
manual_scale, manual_offset = vh.T @ np.linalg.inv(np.diag(s)) @ u.T @ y
順便說一下,您可以簡化對角因子的倒數:
manual_scale, manual_offset = vh.T @ np.diag(1/s) @ u.T @ y
(假設 中沒有零s。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/370329.html
標籤:麻木的
