Wol*_*tan 27 python math numpy scipy
我想使用numpy或scipy来计算以下内容:
Y = A**T * Q * A
Run Code Online (Sandbox Code Playgroud)
其中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
与它一起?
dou*_*oug 25
(w/r/t OP的最后一句话:我不知道这样的numpy/scipy方法但是没有知道OP标题中的问题(即,提高NumPy点性能)下面应该是什么换句话说,我的答案是针对改善包含 Y功能的大多数步骤的性能.
首先,这应该会给你一个明显的推动香草NumPy 点方法:
>>> from scipy.linalg import blas as FB
>>> vx = FB.dgemm(alpha=1., a=v1, b=v2, trans_b=True)
Run Code Online (Sandbox Code Playgroud)
需要注意的是两个数组,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
Run Code Online (Sandbox Code Playgroud)
要更改其中一个数组的顺序,以便两者都对齐,只需调用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
Run Code Online (Sandbox Code Playgroud)
您可以通过利用数组顺序对齐来进一步优化,以减少因复制原始数组而导致的过多内存消耗.
但为什么在传递给dot之前复制数组?
点积依赖于BLAS操作.这些操作需要以C连续顺序存储的数组 - 这是导致数组被复制的约束.
在另一方面,转置也不会影响副本,但不幸的返回结果中的Fortran顺序:
因此,要消除性能瓶颈,需要消除谓词数组复制步骤 ; 要做到这一点,只需要将两个数组以C连续顺序传递给点*.
所以要计算点(AT,A) 而不需要额外的副本:
>>> import scipy.linalg.blas as FB
>>> vx = FB.dgemm(alpha=1.0, a=A.T, b=A.T, trans_b=True)
Run Code Online (Sandbox Code Playgroud)
总而言之,上面的表达式(以及谓词import语句)可以替代dot,以提供相同的功能但性能更好
你可以将该表达式绑定到这样的函数:
>>> super_dot = lambda v, w: FB.dgemm(alpha=1., a=v.T, b=w.T, trans_b=True)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3711 次 |
最近记录: |