是否有"增强的"numpy/scipy dot方法?

Wol*_*tan 27 python math numpy scipy

问题

我想使用numpy或scipy来计算以下内容:

Y = A**T * Q * A
Run Code Online (Sandbox Code Playgroud)

其中Am x n矩阵,A**T是的转置AQ是一个m x m对角矩阵.

由于Q是对角矩阵,因此我只将其对角线元素存储为矢量.

解决方法 Y

目前我可以想到两种计算方法Y:

  1. Y = np.dot(np.dot(A.T, np.diag(Q)), A)
  2. Y = np.dot(A.T * Q, A).

显然,选项2优于选项1,因为不必创建真正的矩阵diag(Q)(如果这是numpy真正做的......)
但是,这两种方法都存在必须分配比实际需要更多内存的缺陷,因为A.T * Qnp.dot(A.T, np.diag(Q))必须与之一起存储A以便计算Y.

是否有numpy的/ SciPy的方法,该方法将消除额外的内存不必要的分配,你将只通过两个矩阵AB(在我的情况BA.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)