矩阵求逆方法
Matrix Inversion Methods
当遇到矩阵与向量的逆乘问题时,例如:
可以对 A 进行 Cholesky 分解并反向代入 b 以找到结果向量 x.然而,当问题不是如上表述时,有时需要逆矩阵。我的问题是处理这种情况的最佳方法是什么。下面,我比较了各种方法(使用 numpy)来反转正定矩阵:
首先,生成矩阵:
>>> A = np.random.rand(5,5)
>>> A
array([[ 0.13516074, 0.2532381 , 0.61169708, 0.99678563, 0.32895589],
[ 0.35303998, 0.8549499 , 0.39071336, 0.32792806, 0.74723177],
[ 0.4016188 , 0.93897663, 0.92574706, 0.93468798, 0.90682809],
[ 0.03181169, 0.35059435, 0.10857948, 0.36422977, 0.54525 ],
[ 0.64871162, 0.37809219, 0.35742865, 0.7154568 , 0.56028468]])
>>> A = np.dot(A.transpose(), A)
>>> A
array([[ 0.72604206, 0.96959581, 0.82773451, 1.10159817, 1.05327233],
[ 0.96959581, 1.94261607, 1.53140854, 1.80864185, 1.9766411 ],
[ 0.82773451, 1.53140854, 1.52338262, 1.89841402, 1.59213299],
[ 1.10159817, 1.80864185, 1.89841402, 2.61930178, 2.01999385],
[ 1.05327233, 1.9766411 , 1.59213299, 2.01999385, 2.10012097]])
直接反演的方法结果如下:
>>> np.linalg.inv(A)
array([[ 5.49746838, -1.92540877, 2.24730018, -2.20242449,
-0.53025806],
[ -1.92540877, 95.34219156, -67.93144606, 50.16450952,
-85.52146331],
[ 2.24730018, -67.93144606, 57.0739859 , -40.56297863,
58.55694127],
[ -2.20242449, 50.16450952, -40.56297863, 30.6441555 ,
-44.83400183],
[ -0.53025806, -85.52146331, 58.55694127, -44.83400183,
79.96573405]])
使用Moore-Penrose Pseudoinverse时,结果如下(您可能会注意到,显示的精度,结果与直接反演的结果相同):
>>> np.linalg.pinv(A)
array([[ 5.49746838, -1.92540877, 2.24730018, -2.20242449,
-0.53025806],
[ -1.92540877, 95.34219156, -67.93144606, 50.16450952,
-85.52146331],
[ 2.24730018, -67.93144606, 57.0739859 , -40.56297863,
58.55694127],
[ -2.20242449, 50.16450952, -40.56297863, 30.6441555 ,
-44.83400183],
[ -0.53025806, -85.52146331, 58.55694127, -44.83400183,
79.96573405]])
最后,用单位矩阵求解时:
>>> np.linalg.solve(A, np.eye(5))
array([[ 5.49746838, -1.92540877, 2.24730018, -2.20242449,
-0.53025806],
[ -1.92540877, 95.34219156, -67.93144606, 50.16450952,
-85.52146331],
[ 2.24730018, -67.93144606, 57.0739859 , -40.56297863,
58.55694127],
[ -2.20242449, 50.16450952, -40.56297863, 30.6441555 ,
-44.83400183],
[ -0.53025806, -85.52146331, 58.55694127, -44.83400183,
79.96573405]])
同样,您可能会注意到,粗略检查一下,结果与前两种方法相同。
众所周知,由于数值不稳定性,矩阵求逆是一个病态问题,应尽可能避免。然而,在它似乎不可避免的情况下,什么是更好的方法,为什么?澄清一下,我指的是在软件中实现此类方程式时的最佳方法。
中的另一个示例提供了此类问题的示例
避免逆矩阵的原因只与效率有关。直接求解线性系统更快。如果您对链接问题中的问题有一点不同的看法,您可以应用相同的原则。
为了找到矩阵inv(K) * Y * T(Y) * inv(K) - D * inv(K)
,您可以求解以下方程组:
K * R * K = Y * T(Y)
分两部分解决:
R2 * K = R1
K * R1 = Y * T(Y)
所以你首先用你通常的方法解决R1
,然后解决R2
(认识到如果你必须的话你可以解决T(K) * T(R2) = T(R1)
)。
但是,目前我不知道这是否比显式计算逆更有效,除非 K
是对称的。 (可能有一种方法可以有效地从 K
得到 T(K)
的分解,但我不知道)
如果 K
是对称的,那么您可以在 K
上计算一次分解并将其重复用于两个反向替换步骤,这可能比显式计算逆运算更有效。
当遇到矩阵与向量的逆乘问题时,例如:
可以对 A 进行 Cholesky 分解并反向代入 b 以找到结果向量 x.然而,当问题不是如上表述时,有时需要逆矩阵。我的问题是处理这种情况的最佳方法是什么。下面,我比较了各种方法(使用 numpy)来反转正定矩阵:
首先,生成矩阵:
>>> A = np.random.rand(5,5)
>>> A
array([[ 0.13516074, 0.2532381 , 0.61169708, 0.99678563, 0.32895589],
[ 0.35303998, 0.8549499 , 0.39071336, 0.32792806, 0.74723177],
[ 0.4016188 , 0.93897663, 0.92574706, 0.93468798, 0.90682809],
[ 0.03181169, 0.35059435, 0.10857948, 0.36422977, 0.54525 ],
[ 0.64871162, 0.37809219, 0.35742865, 0.7154568 , 0.56028468]])
>>> A = np.dot(A.transpose(), A)
>>> A
array([[ 0.72604206, 0.96959581, 0.82773451, 1.10159817, 1.05327233],
[ 0.96959581, 1.94261607, 1.53140854, 1.80864185, 1.9766411 ],
[ 0.82773451, 1.53140854, 1.52338262, 1.89841402, 1.59213299],
[ 1.10159817, 1.80864185, 1.89841402, 2.61930178, 2.01999385],
[ 1.05327233, 1.9766411 , 1.59213299, 2.01999385, 2.10012097]])
直接反演的方法结果如下:
>>> np.linalg.inv(A)
array([[ 5.49746838, -1.92540877, 2.24730018, -2.20242449,
-0.53025806],
[ -1.92540877, 95.34219156, -67.93144606, 50.16450952,
-85.52146331],
[ 2.24730018, -67.93144606, 57.0739859 , -40.56297863,
58.55694127],
[ -2.20242449, 50.16450952, -40.56297863, 30.6441555 ,
-44.83400183],
[ -0.53025806, -85.52146331, 58.55694127, -44.83400183,
79.96573405]])
使用Moore-Penrose Pseudoinverse时,结果如下(您可能会注意到,显示的精度,结果与直接反演的结果相同):
>>> np.linalg.pinv(A)
array([[ 5.49746838, -1.92540877, 2.24730018, -2.20242449,
-0.53025806],
[ -1.92540877, 95.34219156, -67.93144606, 50.16450952,
-85.52146331],
[ 2.24730018, -67.93144606, 57.0739859 , -40.56297863,
58.55694127],
[ -2.20242449, 50.16450952, -40.56297863, 30.6441555 ,
-44.83400183],
[ -0.53025806, -85.52146331, 58.55694127, -44.83400183,
79.96573405]])
最后,用单位矩阵求解时:
>>> np.linalg.solve(A, np.eye(5))
array([[ 5.49746838, -1.92540877, 2.24730018, -2.20242449,
-0.53025806],
[ -1.92540877, 95.34219156, -67.93144606, 50.16450952,
-85.52146331],
[ 2.24730018, -67.93144606, 57.0739859 , -40.56297863,
58.55694127],
[ -2.20242449, 50.16450952, -40.56297863, 30.6441555 ,
-44.83400183],
[ -0.53025806, -85.52146331, 58.55694127, -44.83400183,
79.96573405]])
同样,您可能会注意到,粗略检查一下,结果与前两种方法相同。
众所周知,由于数值不稳定性,矩阵求逆是一个病态问题,应尽可能避免。然而,在它似乎不可避免的情况下,什么是更好的方法,为什么?澄清一下,我指的是在软件中实现此类方程式时的最佳方法。
中的另一个示例提供了此类问题的示例避免逆矩阵的原因只与效率有关。直接求解线性系统更快。如果您对链接问题中的问题有一点不同的看法,您可以应用相同的原则。
为了找到矩阵inv(K) * Y * T(Y) * inv(K) - D * inv(K)
,您可以求解以下方程组:
K * R * K = Y * T(Y)
分两部分解决:
R2 * K = R1
K * R1 = Y * T(Y)
所以你首先用你通常的方法解决R1
,然后解决R2
(认识到如果你必须的话你可以解决T(K) * T(R2) = T(R1)
)。
但是,目前我不知道这是否比显式计算逆更有效,除非 K
是对称的。 (可能有一种方法可以有效地从 K
得到 T(K)
的分解,但我不知道)
如果 K
是对称的,那么您可以在 K
上计算一次分解并将其重复用于两个反向替换步骤,这可能比显式计算逆运算更有效。