Python 是否有一个「;增强型;numpy/scipy点法? 问题
我想使用numpy或scipy计算以下内容:Python 是否有一个「;增强型;numpy/scipy点法? 问题,python,math,numpy,scipy,Python,Math,Numpy,Scipy,我想使用numpy或scipy计算以下内容: Y = A**T * Q * A 其中A是mxn矩阵,A**T是A的转置,Q是mxm对角矩阵 因为Q是一个对角矩阵,所以我只把它的对角元素存储为向量 解决Y 目前,我可以想出两种方法来计算Y: Y=np.dot(np.dot(A.T,np.diag(Q)),A) Y=np.dot(A.T*Q,A) 显然,选项2比选项1好,因为不必使用diag(Q)创建实数矩阵(如果numpy真的这样做的话… 然而,这两种方法都存在必须分配比实际需要更多内存的缺陷,
Y = A**T * Q * A
其中A
是mxn
矩阵,A**T
是A
的转置,Q
是mxm
对角矩阵
因为Q是一个对角矩阵,所以我只把它的对角元素存储为向量
解决Y
目前,我可以想出两种方法来计算Y
:
Y=np.dot(np.dot(A.T,np.diag(Q)),A)
Y=np.dot(A.T*Q,A)
diag(Q)
创建实数矩阵(如果numpy真的这样做的话…然而,这两种方法都存在必须分配比实际需要更多内存的缺陷,因为
A.T*Q
和np.dot(A.T,np.diag(Q))
必须与A
一起存储以计算Y
问题:
numpy/scipy中是否有一种方法可以消除不必要的额外内存分配,即只传递两个矩阵a
和B
(在我的例子中B
是a.T
)和一个加权向量Q
(w/r/t OP的最后一句话:我不知道有这样的numpy/scipy方法,但w/r/t OP标题中的问题(即,提高numpy dot性能)下面的内容应该会有所帮助。换句话说,我的答案是针对提高包含Y函数的大多数步骤的性能)。
首先,这应该会给你一个明显的提升,超过香草NumPydot方法:
>>> from scipy.linalg import blas as FB
>>> vx = FB.dgemm(alpha=1., a=v1, b=v2, trans_b=True)
请注意,这两个数组v1、v2都是C_FORTRAN顺序
您可以通过数组的flags属性访问NumPy数组的字节顺序,如下所示:
>>> c = NP.ones((4, 3))
>>> c.flags
C_CONTIGUOUS : True # refers to C-contiguous order
F_CONTIGUOUS : False # fortran-contiguous
OWNDATA : True
MASKNA : False
OWNMASKNA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
要更改其中一个数组的顺序以使两者对齐,只需调用NumPy数组构造函数,传入数组并将相应的顺序标志设置为True
>>> c = NP.array(c, order="F")
>>> c.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : True
MASKNA : False
OWNMASKNA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
您可以通过利用阵列顺序对齐来进一步优化,以减少由于复制原始阵列而导致的过量内存消耗
但是为什么数组在传递给dot之前要被复制呢
点积依赖于BLAS操作。这些操作需要以C-连续顺序存储数组——正是这种约束导致数组被复制
另一方面,转置不会影响副本,但不幸的是,它会以Fortran顺序返回结果:
因此,要消除性能瓶颈,需要消除谓词数组复制步骤;要做到这一点,只需将两个数组以C连续顺序*传递给点
因此,要计算点(A.T.,A),而无需额外复制:
>>> import scipy.linalg.blas as FB
>>> vx = FB.dgemm(alpha=1.0, a=A.T, b=A.T, trans_b=True)
总之,上面的表达式(连同谓词导入语句)可以替代点,以提供相同的功能,但性能更好
可以将该表达式绑定到如下函数:
>>> super_dot = lambda v, w: FB.dgemm(alpha=1., a=v.T, b=w.T, trans_b=True)
我只是想把它放在上面,但是这个pull请求应该会很有帮助,并且不需要为numpy.dot提供单独的函数 这应该在numpy 1.7中提供 同时,我使用上面的示例编写了一个函数,该函数可以替换numpy dot,无论数组的顺序如何,并正确调用fblas.dgemm。
希望这能有所帮助,numpy.einsum是您需要的:
numpy.einsum('ij, i, ik -> jk', A, Q, A)
这不需要任何额外的内存(尽管通常einsum的工作速度比BLAS操作慢)这确实是访问BLAS例程的一种很好的方式。我相信我将来可以很好地利用它。但是,仍然有一个
Q
要插入到这里的某个地方…:)当然,我应该用“我不知道您在OP的最后一句中描述的numpy/scipy方法,但这里介绍了如何提高构成Y函数的大多数步骤的性能;抱歉,如果这是误导(我的回答相应地编辑)。@doug速度呢?在我的测试中,无论矩阵的阶数是多少,dgemm似乎比np.dot慢得多。dgemm应该比numpy.dot快吗?你能解释一下“trans_b=True”是什么意思吗?参考资料没有对此进行详细描述。您是否有任何关于np.dot(在numpy 1.8中)何时复制/不复制arg的示例?或者,我怎么知道?