なぜnumpy.linalg.solve()
がより正確な答えを出すのか、numpy.linalg.inv()
が幾分壊れて(私が信じている)推定値を与える理由はよくわかりません。
具体例として、式_C^{-1} * d
_を解いています。ここで、C
は行列を示し、d
はベクトル配列です。説明のために、C
の寸法は形状_(1000,1000)
_であり、d
は形状_(1,1000)
_です。
numpy.linalg.solve(A, b)
はxの方程式_A*x=b
_を解きます、つまり_x = A^{-1} * b.
_したがって、この方程式を解くには
(1)
_inverse = numpy.linalg.inv(C)
result = inverse * d
_
または(2)
_numpy.linalg.solve(C, d)
_
方法(2)では、はるかに正確な結果が得られます。どうしてこれなの?
一方が他方よりも「うまく機能する」ように正確に何が起こっているのでしょうか?
np.linalg.solve(A, b)
はnot[〜#〜] a [〜#〜]の逆を計算します。代わりに、 gesv
LAPACKルーチン の1つを呼び出します。これは、最初に[〜#〜] a [〜#〜]を因数分解しますLU分解してから、前方置換と後方置換を使用してxを解決します( here を参照)。
np.linalg.inv
は、同じ方法を使用して[〜#〜] a [〜#〜]の逆数を計算します。これはA-1 in A・A-1 = Iここで[〜#〜] i [〜#〜]はID *です。因数分解の手順は上記とまったく同じですが、A-1(n×nマトリックス)-x(n-longベクトル)よりも。さらに、IDを介してxを取得する場合A-1・b = xこの場合、余分な行列乗算によりさらに浮動小数点演算が発生するため、パフォーマンスが低下し、数値エラーが増加します。
計算の中間ステップは必要ありませんA-1-xを直接取得する方が高速で正確です。
* inv
のソースの関連ビットは here です。残念ながら、テンプレートCであるため、理解するのは少し難しいです。注意すべき重要なことは、アイデンティティマトリックスがパラメーターB
としてLAPACKソルバーに渡されることです。