矩阵乘以逆不产生标识

Yoa*_*a G 3 python numpy matrix

我正在尝试使用该np.linalg.inv()函数找到给定矩阵的逆矩阵。inv产生一个看起来不错的矩阵,但是当尝试将原始矩阵乘以逆矩阵时,输出不是逆矩阵定义所假设的身份。

from numpy.linalg import inv

M = np.random.random((4, 4))
Mi = inv(M)
I = M @ Mi # using matrix multiplication operator
I.astype(int) #as the output looks like 2.77555756e-17

>>> array([[0, 0, 0, 0],
           [0, 0, 0, 0],
           [0, 0, 0, 0],
           [0, 0, 0, 1]])
Run Code Online (Sandbox Code Playgroud)

这显然不是身份(多次运行时给出的答案略有不同)

Muh*_*mad 5

在转换为 int 之前先尝试对其进行四舍五入。

np.around(I).astype(int)
Run Code Online (Sandbox Code Playgroud)

创建随机矩阵:

>>> M = np.random.random((4,4))
>>> M
array([[0.51351957, 0.57864882, 0.0489495 , 0.85066216],
       [0.60052988, 0.93844708, 0.74651889, 0.17237584],
       [0.26191596, 0.46451226, 0.46514401, 0.81917544],
       [0.19247662, 0.82801899, 0.83839146, 0.08531949]])
Run Code Online (Sandbox Code Playgroud)

取反:

>>> from numpy.linalg import inv
>>> Mi = inv(M)
>>> Mi
array([[-1.3515514 ,  3.53647196,  1.0391335 , -3.64654487],
       [ 2.76188122, -2.23981308, -2.74634579,  3.35680468],
       [-2.44320291,  1.47102487,  2.36135635, -1.28451339],
       [ 0.2533113 , -0.69591469,  1.10498293, -0.00818495]])
Run Code Online (Sandbox Code Playgroud)

现在,乘以MMi应出示身份。

>>> M @ Mi
array([[ 1.00000000e+00, -4.44089210e-16, -1.11022302e-16, -6.93889390e-18],
       [-4.16333634e-17,  1.00000000e+00, -8.32667268e-17, -8.60856525e-17],
       [ 5.55111512e-17, -2.22044605e-16,  1.00000000e+00, -1.57859836e-16],
       [ 6.24500451e-17, -8.32667268e-17, -2.35922393e-16, 1.00000000e+00]])
Run Code Online (Sandbox Code Playgroud)

但这显然不是身份。但是如果仔细观察,对角线值非常接近 1,而所有其他值都是非常小的数字(几乎为零),例如指数中的-16-17

这个错误是,因为浮点值从来都不是精确值,所以它们总是有一些错误。看看文章15. Floating Point Arithmetic: Issues and Limitations and Is floating point math crashed?.

现在,如果我们只是将其转换为 int,则很有可能它仍然不是身份。因为一个非常接近 1 的值,它实际上可能比 1 小一点,当转换为 0 时会导致 0 int

>>> (M @ Mi).astype(int)
array([[1, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 1, 0],
       [0, 0, 0, 0]])
Run Code Online (Sandbox Code Playgroud)

但是,如果您在转换为 之前先将其舍入int,您将获得一个身份。

>>> np.around(M @ Mi).astype(int)
array([[1, 0, 0, 0],
       [0, 1, 0, 0],
       [0, 0, 1, 0],
       [0, 0, 0, 1]])
Run Code Online (Sandbox Code Playgroud)