web-dev-qa-db-ja.com

特異行列の効率的でPython的なチェック

ここでいくつかの行列代数に取り組んでいます。ときどき、特異な条件や悪条件の行列を反転させる必要があります。私はこれを単純に行うのがPythonicであると理解しています:

try:
    i = linalg.inv(x)
except LinAlgErr as err:
    #handle it

それがどれほど効率的かはわかりません。これはもっと良いのではないでしょうか?

if linalg.cond(x) < 1/sys.float_info.epsilon:
    i = linalg.inv(x)
else:
    #handle it

Numpy.linalgは、私が禁止したテストの前に実行するだけですか?

27
Dr. Drew

したがって、ここでの入力に基づいて、ソリューションとして明示的なテストで元のコードブロックをマークしています。

if linalg.cond(x) < 1/sys.float_info.epsilon:
    i = linalg.inv(x)
else:
    #handle it

驚いたことに、numpy.linalg.inv関数はこのテストを実行しません。私はコードをチェックし、それがすべての陰謀を通過していることを確認し、次にlapackルーチンを呼び出すだけです-かなり非効率的です。また、DavePが作成した2つ目のポイントは、明示的に必要でない限り、行列の逆行列を計算しないことです。

12
Dr. Drew

最初の解決策は、行列が非常に特異で、numpyがまったく対処できないケースをキャッチします-かなり極端なケースになる可能性があります。 2番目のソリューションの方が優れています。numpyが回答を返すケースをキャッチするためですが、その回答は丸め誤差によって破損する可能性があります。これははるかに賢明なようです。

悪条件の行列を反転しようとしている場合は、 特異値分解 の使用を検討する必要があります。注意深く使用すると、他のルーチンが失敗した場合の賢明な回答が得られます。

SVDが必要ない場合は、invの代わりにlu_factorを使用することについての私のコメントも参照してください。

15
DaveP

行列の 条件番号 を計算して、それが反転可能かどうかを確認する必要があります。

import numpy.linalg

if numpy.isfinite(numpy.linalg.cond(A)):
    B = numpy.linalg.inv(A)
else:
    # handle it
4
Nicolas Barbey

行列式が非ゼロかどうかを確認しないのはなぜですか?

det = numpy.linalg.det(A)
if det != 0:
   #proceed
1