Python Numpy-Cholesky分解线性误差

Python Numpy-Cholesky分解线性误差,python,numpy,scipy,linear-algebra,covariance,Python,Numpy,Scipy,Linear Algebra,Covariance,在我尝试对周期边界条件的2D数组的方差-协方差矩阵执行cholesky分解时,在某些参数组合下,我总是得到LinalError:矩阵不是正定的-无法计算cholesky分解。不确定这是numpy.linalg还是实现问题,因为脚本很简单: sigma = 3. U = 4 def FromListToGrid(l_): i = np.floor(l_/U) j = l_ - i*U return np.array((i,j)) Ulist = range(U**2)

在我尝试对周期边界条件的2D数组的方差-协方差矩阵执行cholesky分解时,在某些参数组合下,我总是得到
LinalError:矩阵不是正定的-无法计算cholesky分解
。不确定这是
numpy.linalg
还是实现问题,因为脚本很简单:

sigma = 3.
U = 4

def FromListToGrid(l_):
    i = np.floor(l_/U)
    j = l_ - i*U
    return np.array((i,j))

Ulist = range(U**2)

Cov = []
for l in Ulist:
    di = np.array([np.abs(FromListToGrid(l)[0]-FromListToGrid(i)[0]) for i, x in enumerate(Ulist)])
    di = np.minimum(di, U-di)

    dj = np.array([np.abs(FromListToGrid(l)[1]-FromListToGrid(i)[1]) for i, x in enumerate(Ulist)])
    dj = np.minimum(dj, U-dj)

    d = np.sqrt(di**2+dj**2)
    Cov.append(np.exp(-d/sigma))
Cov = np.vstack(Cov)

W = np.linalg.cholesky(Cov)

消除潜在奇点的尝试也未能解决问题。非常感谢您提供的任何帮助。

问题在于您向其提供的数据。根据解算器,矩阵是奇异的。这意味着一个零或接近零的对角线元素,所以不可能进行反演

如果你能提供一个小版本的矩阵,就更容易诊断了

零对角线不是创建奇点的唯一方法。如果两行是成比例的,那么在解决方案中不需要两行;它们是多余的。这比在对角线上寻找零要复杂得多

如果你的矩阵是正确的,你有一个非空的空空间。您需要将算法更改为类似SVD的内容


见下面我的评论

在这个问题上再深入一点,我试着打印Cov矩阵的特征值

print np.linalg.eigvalsh(Cov)
答案是这样的

[-0.0801339  -0.0801339   0.12653595  0.12653595  0.12653595  0.12653595 0.14847999  0.36269785  0.36269785  0.36269785  0.36269785  1.09439988 1.09439988  1.09439988  1.09439988  9.6772531 ]
啊哈!注意前两个负特征值?现在,矩阵是正定的当且仅当其所有特征值都是正的。所以,矩阵的问题不是它接近于“零”,而是它是“负的”。为了扩展@duffymo类比,这是一个线性代数,相当于尝试取负数的平方根

现在,让我们尝试执行相同的操作,但这次是使用scipy

scipy.linalg.cholesky(Cov, lower=True)
这不能说明更多的问题

numpy.linalg.linalg.LinAlgError: 12-th leading minor not positive definite
这说明了更多的事情(尽管我真的不明白为什么它在抱怨第12小调)


总之,矩阵不是很接近“零”,而是更像“负”

你做了什么来消除奇点?像Cov=Cov+numpy.diag(numpy.repeat(delta,k))这样的东西有用吗?(基本上是向Cov添加一个小的对角矩阵。这里的delta是一个小的浮点,k是Cov的维数)我只是得到了Cov=Cov+d*np.identity(k)。但是看看原始矩阵,没有一个值接近于零。当调用上述矩阵的
np.diagonal(Cov)
时,它输出一个1的数组。另一方面,上面的脚本生成的16x16矩阵是我发现的返回错误消息的最小矩阵,但可能它仍然太大,无法粘贴到这里?我不知道。你理解错误告诉你的数学意义,对吗?这是一个线性代数,等于除以零。它与矩阵有关,而不是NumPy或编码。我建议您需要仔细检查以确保正确填充矩阵。如果你确信这一点,但仍然会出现错误,我认为你应该将算法改为SVD,如果你告诉它如何处理奇异矩阵,它将处理奇异矩阵。非常好,做得很好。Cholesky需要正定值。我想我能应付。试着换成Ludecop;Cholesky是正定特例: