行列が 正定値 かどうかを調べる必要があります。私の行列はnumpy行列です。私はnumpyライブラリで関連するメソッドを見つけることを期待していましたが、成功しませんでした。私は助けに感謝します。
また、行列のすべての固有値が正であるかどうかを確認できます。そうであれば、行列は正定です。
import numpy as np
def is_pos_def(x):
return np.all(np.linalg.eigvals(x) > 0)
コレスキー分解( numpy.linalg.cholesky
)。行列が正定値でない場合、これはLinAlgError
を発生させます。
(少なくとも質問に関して)上記のすべての回答には小さな混乱があるようです。
実数行列の場合、np.linalg.choleskyの正の固有値と正の項のテストは、行列が対称の場合にのみ適用されます。そのため、最初に行列が対称かどうかをテストしてから、それらの方法(正の固有値またはコレスキー分解)のいずれかを適用する必要があります。
例えば:
import numpy as np
#A nonsymmetric matrix
A = np.array([[9,7],[6,14]])
#check that all eigenvalues are positive:
np.all(np.linalg.eigvals(A) > 0)
#take a 'Cholesky' decomposition:
chol_A = np.linalg.cholesky(A)
行列Aは対称ではありませんが、固有値は正であり、Numpyは間違ったコレスキー分解を返します。以下を確認できます。
chol_A.dot(chol_A.T)
aとは異なります.
また、上記のすべてのpython関数が 'positive-definiteness'に対して肯定的にテストされることを確認できます。これは、コレスキー分解を使用して逆を計算しようとした場合、深刻な問題になる可能性があります。以来:
>np.linalg.inv(A)
array([[ 0.16666667, -0.08333333],
[-0.07142857, 0.10714286]])
>np.linalg.inv(chol_A.T).dot(np.linalg.inv(chol_A))
array([[ 0.15555556, -0.06666667],
[-0.06666667, 0.1 ]])
異なっています。
要約すると、上記の関数のいずれかに行を追加して、マトリックスが対称かどうかを確認することをお勧めします。たとえば、
def is_pos_def(A):
if np.array_equal(A, A.T):
try:
np.linalg.cholesky(A)
return True
except np.linalg.LinAlgError:
return False
else:
return False
上記の関数のnp.allclose(A、A.T)のnp.array_equal(A、A.T)を置き換えて、浮動小数点エラーによる違いを回避することができます。
すぐに使えるコードで@NPEの答えを説明するには:
import numpy as np
def is_pd(K):
try:
np.linalg.cholesky(K)
return 1
except np.linalg.linalg.LinAlgError as err:
if 'Matrix is not positive definite' in err.message:
return 0
else:
raise
NPEのソリューションがそれほど過小評価されている理由はわかりません。これを行うのに最適な方法です。 Wkipedia で、複雑さはキュービックであることを見つけました。
さらに、Lu分解よりも数値的に安定していると言われています。また、Lu分解は、すべての固有値を見つける方法よりも安定しています。
そして、それは事実なので、非常にエレガントなソリューションです:
行列が対称正である場合にのみ、コレスキー分解があります。
では、なぜ数学を使用しないのですか?例外の発生を恐れている人もいるかもしれませんが、それは事実であり、例外を使用してプログラムすることは非常に便利です。
実行列$ A $に対して、$ x ^ TAx =\frac {1} {2}(x ^ T(A + A ^ T)x)$があり、$ A + A ^ T $は対称実行列です。 。したがって、$ A + A ^ T $のすべての固有値が正である場合、$ A + A ^ T $が正定値である場合、$ A $は正定値です。
import numpy as np
def is_pos_def(A):
M = np.matrix(A)
return np.all(np.linalg.eigvals(M+M.transpose()) > 0)