我需要找出矩阵是否为positive definite。我的矩阵是numpy矩阵。我期待在numpy库中找到任何相关的方法,但没有成功。 我感谢任何帮助。
答案 0 :(得分:47)
您还可以检查矩阵的所有特征值是否为正,如果是,矩阵是正定的:
import numpy as np
def is_pos_def(x):
return np.all(np.linalg.eigvals(x) > 0)
答案 1 :(得分:44)
您可以尝试计算Cholesky分解(numpy.linalg.cholesky
)。如果矩阵不是正定的,这将引发LinAlgError
。
答案 2 :(得分:11)
上述所有答案似乎都有一点混淆(至少在这个问题上是这样)。
对于实矩阵,np.linalg.cholesky中的正特征值和正前导项的测试仅适用于矩阵是对称的。因此,首先需要测试矩阵是否对称,然后应用其中一种方法(正特征值或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返回错误的Cholesky分解。你可以查看:
chol_A.dot(chol_A.T)
与A不同。
您还可以检查上面的所有python函数是否为“正定性”测试为正。如果您尝试使用Cholesky分解来计算逆,这可能是一个严重的问题,因为:
>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),以避免由浮点错误引起的差异。
答案 3 :(得分:4)
我不知道为什么NPE的解决方案被低估了。这是最好的方法。我在Wkipedia发现复杂性是立方的。
此外,据说它在数值上比Lu分解更稳定。并且Lu分解比找到所有特征值的方法更稳定。
而且,这是一个非常优雅的解决方案,因为它是一个事实:
当且仅当对象为正对称时,矩阵才会进行Cholesky分解。
那么为什么不使用数学呢?也许有些人对异常的提升感到害怕,但事实也是这样,用异常编程是非常有用的。
答案 4 :(得分:3)
用一些现成的代码来说明@ 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
答案 5 :(得分:2)
如果您特别想要对称的(埃尔密特数,如果是复数的话)正SEMI定矩阵,则下面将做。如果您不关心对称(埃尔米特数,如果是复数),则删除检查它的'if'状态。如果要使用正定而不是正SEMI定,则删除正则化行(并将传递给'np.lingalg.cholesky()'的值从'regularized_X'更改为'X')。下面
import numpy as np
def is_hermitian_positive_semidefinite(X):
if X.shape[0] != X.shape[1]: # must be a square matrix
return False
if not np.all( X - X.H == 0 ): # must be a symmetric or hermitian matrix
return False
try: # Cholesky decomposition fails for matrices that are NOT positive definite.
# But since the matrix may be positive SEMI-definite due to rank deficiency
# we must regularize.
regularized_X = X + np.eye(X.shape[0]) * 1e-14
np.linalg.cholesky(regularized_X)
except np.linalg.LinAlgError:
return False
return True
答案 6 :(得分:1)
对于非对称矩阵,您可以使用主要次要测试:
def isPD(Y):
row = X.shape [0]
i = 0
j = 0
for i in range(row+1) :
Step = Y[:i,:j]
j+=1
i+=1
det = np.linalg.det(Step)
if det > 0 :
continue
else :
return ("Not Positive Definite, Test Principal minor failed")
return ("Positive Definite")
答案 7 :(得分:0)
对于真实矩阵$ A $,我们有$ x ^ TAx = \ frac {1} {2}(x ^ T(A + A ^ T)x)$,$ A + A ^ T $是对称实矩阵。因此,如果$ A + A ^ T $是肯定的,那么$ A $是肯定的,如果$ A + A ^ T $的所有特征值都是正的。
import numpy as np
def is_pos_def(A):
M = np.matrix(A)
return np.all(np.linalg.eigvals(M+M.transpose()) > 0)
答案 8 :(得分:0)
numpy.linalg.cholesky(x) # just handle the error LinAlgError
np.all(np.linalg.eigvals(x) >= 0)
注意:如果你的矩阵是 np.all(np.linalg.eigvals(x) > 0)
,即使你看到 PSD
而不仅仅是 >
,大多数情况下 >=
也会给你,我进入了前几天这个问题。我认为这应该与舍入误差有关,因为我们的特征值非常小,甚至 cholesky 分解也可能会产生误差。
为了测试,您可能想要创建一些正半定矩阵和一些正定矩阵:
n_size=4
a = np.random.rand(n_size)
A_PSD = np.outer(a,a) # the outer product of any vector generates a PSD matrix
A_PD = A_PSD+np.identity(n_size) # little trick I found for PS matrix