有人可以推荐一种在python中进行Cholesky分解的不太尴尬的方法吗?特别是最后一行让我烦恼。
SigmaSqrt = matrix(Sigma)
cvxopt.lapack.potrf(SigmaSqrt)
SigmaSqrt = matrix(np.tril(SigmaSqrt))
我有问题,那一条整线和一条线。 column(例如,第一行中的所有元素和第一列中的所有元素)都为零,lapack失败,并且矩阵不是正定的错误。解决这个问题的最佳方法是什么?
目前我这样做:(看起来很尴尬......)
try:
SigmaSqrt = matrix(Sigma)
cvxopt.lapack.potrf(SigmaSqrt)
SigmaSqrt = matrix(np.tril(SigmaSqrt))
except ArithmeticError:
SigmaSqrt = matrix(Sigma.ix[1:,1:])
cvxopt.lapack.potrf(SigmaSqrt)
SigmaSqrt = matrix(np.tril(SigmaSqrt))
SigmaSqrt = sparse([[v0],[v0[1:].T, SigmaSqrt]])
答案 0 :(得分:1)
您可以使用numpy.linalg.cholesky
。此外,如果一行中的所有一列或全部都是零,则矩阵将是单数的,至少在特征值上将为零,因此不是正定的。由于Cholesky仅定义为“Hermitian(对称,如果是实值)和正定”,它不适用于它。
编辑:来“处理”您的问题取决于您的需求。你做的任何事情都会使一个cholesky成为原始矩阵的Cholesky。如果你正在进行一个迭代过程并且它可以稍微有点软,如果它已经是对称的,那么使用numpy.linalg.eigvalsh
来找到矩阵的特征值。设d是最负的特征值。然后设置A += (abs(d) + 1e-4) * np.indentity(len(A))
。这将使其肯定。
编辑:这是Levenberg-Marquardt算法中使用的技巧。这链接到关于Newton's Method的维基百科文章提到它,因为关于Levenberg-Marquard的文章没有涉及到这一点。另外,here也是一篇论文。基本上,这会将所有特征值移动(abs(d) + 1e-4)
,从而使它们全部为正,这是矩阵为正定的充分条件。
答案 1 :(得分:1)
另一种选择是chompack模块:chompack homepage chompack.cholesky
我自己和cvxopt模块一起使用它。它与cvxopt的(稀疏)矩阵完美配合。