我尝试做一个Cholesky因式分解,但是要么这个特性没有在scipy中实现,要么是我不理解。我在这里发帖以防是后者。下面是我正在做的一个简化的例子:
import numpy
import scipy.linalg
numpy.random.seed(0)
X = numpy.random.normal(size=(10,4))
V = numpy.dot(X.transpose(),X)
R = V.copy()
scipy.linalg.cholesky(R,False,overwrite_a=True)
print V
print R
我认为应该发生的是R被上三角矩阵覆盖。然而,当我运行这段代码时,我的V和R是相同的(cholesky没有覆盖R)。我是否误解了overwrite_a的目的,或者犯了其他错误?如果这只是scipy中的一个bug,有没有解决方法或者其他方法可以在Python中进行适当的Cholesky因式分解?
3条答案
按热度按时间dluptydi1#
再试一次,用
它工作得很完美:
输出为:
ftf50wuq2#
如果你足够勇敢,你可以避开
scipy
,去低级别调用linalg.lapack_lite.dpotrf
你必须了解lapack的DPOTRF、fortran调用约定、内存布局。不要忘记在退出时检查
result['info'] == 0
。尽管如此,你会看到它只是一行代码,通过丢弃所有的健全性检查和linalg.cholesky
所做的复制,这也会更有效。o2gm4chl3#
为了完整性起见,下面的代码基于Warren的注解解决了这个问题:
我所做的只是将R的底层存储格式从C顺序更改为Fortran顺序,这将使
overwrite_a
的行为符合预期。如果你的矩阵是真实的值的,你可以通过简单地将转置传递给cholesky来完成这个操作而不需要复制。我不认为转置修复在你的矩阵是复值的情况下会起作用,因为复Hermitian矩阵的转置通常不等于它的共轭转置。然而,如果你首先确定你的矩阵使用的是fortran order(
R.flags['F_CONTIGUOUS'] == True
),那么你应该不会有问题。但是,请参阅Setting the default data order (C vs. Fortran) in Numpy了解使用该策略的困难。