检查正确性或正半定性

sra*_*mij 10 python math matrix linear-algebra scipy

我想用Python检查矩阵是正定的还是正半定的.

我怎样才能做到这一点?SciPy中是否有针对该模块或其他模块的专用功能?

Ale*_* C. 16

我假设你已经知道你的矩阵是对称的.

对正定性的一个很好的测试(实际上是标准的!)是试图计算其Cholesky分解.如果你的矩阵是正定的,它就会成功.

这是最直接的方式,因为它需要O(n ^ 3)运算(具有小常数),并且您需要至少n个矩阵向量乘法来"直接"测试.

  • @sramij这是最直接的测试方式 (5认同)
  • @sramij:这*是一个直接的方法,并且比其他任何方法都快,除非你有关于矩阵的其他*先验*信息. (2认同)
  • 对于正半确定情况,它仍然是[一个抽象命题](http://en.wikipedia.org/wiki/Cholesky_decomposition#Proof_for_positive_semi-definite_matrices),一个实对称(或复Hermitian)矩阵是正半定的当且仅当Cholesky分解存在时.使用正定矩阵,[通常算法](http://www.scipy.org/doc/api_docs/SciPy.linalg.decomp.html#cholesky)成功,因为L st A = LL'的所有对角线条目都是正数(正方形根).如果我们达到零枢轴,计算停止,但理论成立. (2认同)

Tom*_*oim 10

如果您使用正定(PD)矩阵,Cholesky分解是一个不错的选择.

但是,它会在正无限(PSD)矩阵上抛出以下错误,比方说,

A = np.zeros((3,3)) // the all-zero matrix is a PSD matrix
np.linalg.cholesky(A)
LinAlgError: Matrix is not positive definite -
Cholesky decomposition cannot be computed
Run Code Online (Sandbox Code Playgroud)

对于PSD矩阵,您可以使用scipy/numpy的eigh()来检查所有特征值是否为非负的.

>> E,V = scipy.linalg.eigh(np.zeros((3,3)))
>> E
array([ 0.,  0.,  0.])
Run Code Online (Sandbox Code Playgroud)

但是,您很可能会遇到数值稳定性问题.要克服这些,您可以使用以下功能.

def isPSD(A, tol=1e-8):
  E = np.linalg.eigvalsh(A)
  return np.all(E > -tol)
Run Code Online (Sandbox Code Playgroud)

在大约PSD到达给定容差的矩阵上返回True.

  • 我相信`scipy.linalg.eigh(A)`应改为`np.linalg.eigh(A)` (4认同)
  • 实际上,您可以通过将eigh()替换为仅计算特征值的eigvalsh()来加速isPSD()(我尚未对此进行测试)。 (2认同)

Lit*_*leQ 5

A如果A非常大,检查对称矩阵的整个特征值是否为非负很耗时,而该模块scipy.sparse.linalg.arpack提供了一个很好的解决方案,因为可以通过指定参数来自定义返回的特征值。(Scipy.sparse.linalg.arpack更多信息请参阅)

我们知道,如果 的谱的两端A都是非负的,那么其余的特征值也一定是非负的。所以我们可以这样做:

from scipy.sparse.linalg import arpack
def isPSD(A, tol = 1e-8):
    vals, vecs = arpack.eigsh(A, k = 2, which = 'BE') # return the ends of spectrum of A
    return np.all(vals > -tol)
Run Code Online (Sandbox Code Playgroud)

通过这个我们只需要计算两个特征值来检查PSD,我认为这对于大 A


sra*_*mij 1

一种好的解决方案是计算行列式的所有次式并检查它们都是非负数。

  • 这不是 O(n!) 吗?Cholesky 分解速度更快 (2认同)