检查正定义或正半定义

2024-04-23 05:29:25 发布

您现在位置:Python中文网/ 问答频道 /正文


Tags: python
3条回答

如果使用正定(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

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

>> E,V = scipy.linalg.eigh(np.zeros((3,3)))
>> E
array([ 0.,  0.,  0.])

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

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

它在矩阵上返回True,该矩阵在给定公差范围内近似为PSD。

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

一个很好的确定性测试(实际上是标准测试!)试图计算它的Cholesky因子分解。如果你的矩阵是正定的,它就成功了。

这是最直接的方法,因为它需要O(n^3)运算(用一个小常数),而且您至少需要n个矩阵向量乘法来“直接”测试。

如果A非常大,检查对称矩阵A的整个特征值是否为非负是很耗时的,而模块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)

因此,我们只需要计算两个特征值来检查PSD,我认为这对于大型A非常有用

相关问题 更多 >