是否有“增强型”的numpy / scipy点方法?
问题
我想使用numpy或scipy计算以下内容:
Y = A**T * Q * A
其中A
是m x n
矩阵,A**T
是的转置A
和Q
是一个m x m
对角矩阵。
由于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的确实…)
但是,这两种方法不必分配更多的内存的故障影响不是真的有必要的,因为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点的性能)应该是下面的内容换句话说,我的答案是针对改善 组成 Y)函数的大多数 步骤的 性能。首先,这应该使您明显优于普通的NumPy 点 方法:
>>> 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
您可以通过利用数组顺序对齐来进一步优化,以 减少由于 复制 原始数组而导致的过多内存消耗。
但是为什么在传递给 点 之前复制数组?
点积依赖BLAS操作。这些操作需要以C连续顺序存储的数组-正是这种约束导致数组被复制。
在另一方面, 转置 也 不会 影响副本,但不幸的返回结果中 的Fortran顺序 :
因此,要消除性能瓶颈,您需要 消除谓词数组复制步骤 ;为此,只需将两个数组以C连续的顺序传递给 点即可 。
因此,要计算 dot(AT,A) 而无需 额外复制:
>>> import scipy.linalg.blas as FB >>> vx = FB.dgemm(alpha=1.0, a=A.T, b=A.T, trans_b=True)
总之,上面的表达式(以及谓词import语句)可以代替点,以提供相同的功能但性能更好
您可以将该表达式绑定到如下函数:
>>> super_dot = lambda v, w: FB.dgemm(alpha=1., a=v.T, b=w.T, trans_b=True)