Python 找出矩阵是否是正定的

Python 找出矩阵是否是正定的,python,matrix,numpy,scipy,Python,Matrix,Numpy,Scipy,我要看看matrix是不是真的。我的矩阵是numpy矩阵。我希望在numpy库中找到任何相关的方法,但没有成功。 非常感谢您的帮助。您可以尝试计算Cholesky分解()。如果矩阵不是正定的,这将产生LinAlgError。您还可以检查矩阵的所有特征值是否都是正定的,如果是,则矩阵是正定的: import numpy as np def is_pos_def(x): return np.all(np.linalg.eigvals(x) > 0) 我不知道为什么NPE的解决方案被

我要看看matrix是不是真的。我的矩阵是numpy矩阵。我希望在numpy库中找到任何相关的方法,但没有成功。
非常感谢您的帮助。

您可以尝试计算Cholesky分解()。如果矩阵不是正定的,这将产生
LinAlgError

您还可以检查矩阵的所有特征值是否都是正定的,如果是,则矩阵是正定的:

import numpy as np

def is_pos_def(x):
    return np.all(np.linalg.eigvals(x) > 0)

我不知道为什么NPE的解决方案被低估了。这是最好的方法。我发现复杂性是立方的

此外,据说它比Lu分解在数值上更稳定。Lu分解比求所有特征值的方法更稳定

而且,这是一个非常优雅的解决方案,因为这是一个事实:

矩阵具有Cholesky分解的充要条件是它是对称正的。


那为什么不用数学呢?也许有些人对异常的出现感到震惊,但这也是一个事实,用异常编程是非常有用的。

对于实矩阵$a$,我们有$x^TAx=\frac{1}{2}(x^T(a+a^T)x)$,而$a+a^T$是对称实矩阵。所以$A$是正定的,如果$A+A^T$是正定的,如果$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)

用一些现成的代码来说明@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 

上面所有的答案似乎都有点混乱(至少关于这个问题)

对于实矩阵,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)
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
矩阵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       ]])
它们是不同的

总之,我建议在上述任何函数中添加一行,以检查矩阵是否对称,例如:

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)
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.array_equal(A,A.T)替换为np.allclose(A,A.T),以避免由于浮点错误而产生的差异。

如果您特别想要对称(厄米特,如果复杂)半正定矩阵,则可以使用下面的方法。如果您不关心对称性(hermitian,如果复杂),请删除检查对称性的“If”状态。如果要正定而不是半正定,请删除正则化行(并将传递给'np.lingalg.cholesky()'的值从'regulated_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

对于非对称矩阵,可以使用主-辅测试:

正定的 半正定 注意:大多数情况下也是
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

您可以使用np.linalg.eigvals,它只计算特征值。即使如此,它也比@NPE的方法慢得多(10x10矩阵为3x,1000x1000矩阵为40x)。通常并非所有正特征值都意味着正定性,除非你知道矩阵是对称的(实数情况)或厄米特(复数情况)。例如,A=数组([[1,-100],[0,2]])不是正定的。有些可能包括对称或厄米特作为“正定”定义的一部分,但这不是普遍的。@WarrenWeckesser Oops,没错,不是迂腐的!事实上,如果使用
np.linalg.cholesky
,也需要检查对称性(它不会检查对称性,并且可能会返回错误的结果,正如您的示例所示)。我想知道如何用数字来检查非对称矩阵是否正定……你可以用
np.all(x-x.T==0)
来检查对称性这是非常低效的!对于大于6或7行/列的矩阵,请使用下面NPE指出的cholesky。cholesky路径感觉不太方便(捕捉异常等),但它的浪费性要小得多。这应该比特征值解有效得多。请注意,在半正定情况下,从数值上讲,也可以向矩阵添加一点恒等式(因此,将所有特征值移动一小部分,例如机器精度的几倍)然后像往常一样使用cholesky方法。从同一个维基百科页面上,似乎你的陈述是错误的。页面上说“如果矩阵A是厄米特半正定矩阵,那么如果允许L的对角项为零,它仍然具有形式A=LL*的分解。[3]因此,具有Cholesky分解的矩阵并不意味着该矩阵是对称正定的,因为它可以是半定的。我解释错了吗?而且,看起来你刚刚抛出了“对称”在整个含义中。也就是说,不是每个厄米特正定矩阵都有唯一的Cholesky分解吗?吹毛求疵:你可能应该检查
numpy.linalg.linalgeror
,除非你用
从numpy.linalg import linalgeror
导入它,如果我只抓住了这个特定点,这不是我想做的事情在我的代码中有一两次c异常。如果使用复杂矩阵,这可能会导致错误(即如果A是compl
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