通过两种方式获取Sympy矩阵逆的分歧
我正在尝试在 Sympy
中求一个简单数字矩阵的逆矩阵。我开始时有一个矩阵:
In [56]: A_MATRIX_M
Out[56]:
⎡0.174683794941032 0.174688696013867 0.174688696013957 0.174683794941032 0.174688696013867 0.174688696013957 ⎤
⎢ ⎥
⎢0.152985639387222 0.153053070078189 0.153053070078123 0.152985677401143 0.153053070078189 0.153053070078123 ⎥
⎢ ⎥
⎢0.122289719307085 0.12255894161074 0.12255894161075 0.122289780080333 0.12255894161074 0.12255894161075 ⎥
⎢ ⎥
⎢0.0888623464387251 0.0894599879866164 0.0894599879864983 0.0888623905998649 0.0894599879866165 0.0894599879864984⎥
⎢ ⎥
⎢0.0584375462953993 0.0593271595778474 0.0593271595779078 0.0584375753365935 0.0593271595778473 0.0593271595779078⎥
⎢ ⎥
⎣0.034711924284652 0.0356325950288525 0.035632595028856 0.0347119415351321 0.0356325950288525 0.035632595028856 ⎦
我可以通过 .inv()
来得到这个逆矩阵:
In [59]: A_M_INV.inv()
Out[59]:
⎡-4.20862006694537e-38 -3.64678015602041e-38 -4.89393679687261e-39 -5.26008046298975e-38 -1.29781892788192e-38 1.12107780599699e-37 ⎤
⎢ ⎥
⎢-1.19250990841802e-38 -1.17838767512258e-38 -5.49930182641769e-39 -1.79347381150519e-38 -3.76673961453884e-39 3.67594291864767e-38 ⎥
⎢ ⎥
⎢1.27521806859415e-38 1.38241733868129e-38 1.33016305680983e-39 1.89098712400354e-38 7.63333345652249e-39 -4.07574230117266e-38⎥
⎢ ⎥
⎢-3.71566091342595e-39 -3.69178932808298e-39 -1.37147644288023e-39 -4.68481431180264e-39 -3.97158856857654e-39 8.39451101073365e-39 ⎥
⎢ ⎥
⎢1.47794212524182e-38 1.21859956435038e-38 7.46216287435121e-40 2.08223967916098e-38 8.25097707225834e-39 -4.0465253879286e-38 ⎥
⎢ ⎥
⎣-2.5158985894826e-39 -3.62021834376681e-39 -3.99023376900161e-40 -5.881653010039e-39 -3.44892577031322e-39 6.50635833262352e-39 ⎦
不过,我也应该能通过把伴随矩阵除以矩阵的行列式来得到逆矩阵。但是,这样得到的结果完全不同:
In [57]: A_M_INV = A_MATRIX_M.adjugate() / A_MATRIX_M.det()
In [58]: A_M_INV
Out[58]:
⎡-1.03014934740997e+38 9.76285991918083e+37 -2.61712726811554e+38 -2.91755290755826e+38 2.02091254231468e+37 8.60970411767247e+37 ⎤
⎢ ⎥
⎢-1.0350460657459e+38 1.09196345494244e+38 1.65391718422458e+38 -4.62921116834264e+37 -4.10946591995717e+38 -2.93534695043802e+38⎥
⎢ ⎥
⎢3.44664755653471e+37 -1.86912642859017e+38 -8.76351586189679e+37 -2.26077970623935e+38 -1.67328014514703e+37 1.00789976403353e+38 ⎥
⎢ ⎥
⎢1.82916593489888e+37 -8.10152924803704e+37 -1.33638262519626e+38 2.88888937621382e+38 1.19814518627368e+38 -3.22157029803083e+38⎥
⎢ ⎥
⎢6.14049097203001e+37 2.94210971355518e+37 5.88396356342516e+37 -2.59752889211905e+38 1.036688778158e+38 1.24211877586664e+38 ⎥
⎢ ⎥
⎣-4.62263666898771e+37 2.94055576923073e+37 -1.04165393746291e+38 -2.89791317977202e+37 -5.86035000752247e+37 -1.95539341633241e+38⎦
这里有个例子,别人用这种方法来求逆矩阵:
为什么结果会不同呢?尝试用这个逆矩阵来解一个简单的方程时发现,两个结果似乎都不是正确的逆矩阵。我不太确定问题出在哪里,是因为矩阵的指数太大,或者描述矩阵时需要的精度不够吗?
提前谢谢你的帮助!
编辑:在 @Jared 的帮助下,我进一步调查,发现了这个问题:MATLAB 和 Python 的逆矩阵结果不同,现在我知道我的矩阵是病态的/基本上是奇异的,这使得它无法有一个明确的逆矩阵。
1 个回答
以下是我作为回答发布的评论:
首先,注意到你的“逆矩阵”其实就是一个零矩阵。我创建了你的矩阵并计算了行列式,结果大约是0。
import sympy as smp
A = smp.Matrix([[0.174683794941032, 0.174688696013867, 0.174688696013957, 0.174683794941032, 0.174688696013867, 0.174688696013957],
[0.152985639387222, 0.153053070078189, 0.153053070078123, 0.152985677401143, 0.153053070078189, 0.153053070078123],
[0.122289719307085, 0.12255894161074, 0.12255894161075, 0.122289780080333, 0.12255894161074, 0.12255894161075],
[0.0888623464387251, 0.0894599879866164, 0.0894599879864983, 0.0888623905998649, 0.0894599879866165, 0.0894599879864984],
[0.0584375462953993, 0.0593271595778474, 0.0593271595779078, 0.0584375753365935, 0.0593271595778473, 0.0593271595779078],
[0.034711924284652, 0.0356325950288525, 0.035632595028856, 0.0347119415351321, 0.0356325950288525, 0.035632595028856]])
print(A.det()) # -9.86673942982700e-57
当你用第二种方法计算逆矩阵时,得到的数字很大,因为你在用一个很小的数字去除。你的矩阵条件不好,基本上是奇异的(也就是说,它没有逆矩阵)。
记住,在这种情况下,你处理的是浮点数,所以行列式的值,sympy计算得大约是0,就是0。我不太明白为什么sympy不认为这个矩阵是奇异的,还返回了一个逆矩阵(我不知道它内部做了什么检查)。sympy似乎认为它是可逆的(sympy在检查A.rank()
时说它是满秩的),但结果似乎并不支持这个说法。
我们还可以检查矩阵的特征值。(特征值是通过Matrix.eigenvals()
返回的字典的键。)
print(A.eigenvals()) # {0.633575259554063: 1, 4.07013965394438e-9: 1, -6.35328826990267e-17: 1, -2.95260889975432e-15: 1, -3.59523027736480e-14: 1, 0.000542688212375667: 1}
注意到其中有3个(可以说是4个)特征值基本上是0。一个矩阵必须有非零的特征值才能是可逆的。
这里有一个矩阵可逆的条件列表:https://mathworld.wolfram.com/InvertibleMatrixTheorem.html。