numpy.einsum 的替代品

计算科学 线性代数 Python 麻木的
2021-12-16 19:01:27

给定一个张量(即矩阵的集合)和一个张量(即向量的集合长度 ) 我想使用 Numpy 计算张量其中每个元素都是矩阵向量积n1××nk×g×gAg×gn1××nk×gbgn1××nk×gc

ci1,,ik=Ai1,,ikbi1,,ik.

我找到了一种方法来做到这一点,numpy.einsum但很好奇是否有另一种方法可以做到这一点,或者这个操作是否有一个特定的名称?如果有替代方案,该替代方案的性能与 using 相比如何einsum

下面是一个例子:

from numpy import dot, einsum, zeros_like
from numpy.linalg import norm
from numpy.random import randn

n = 10
g = 4

matrices = randn(n,n,g,g)
vectors = randn(n,n,g)

# "manual" mat-vec multiplication (slow)
out1 = zeros_like(vectors)
for i in range(n):
    for j in range(n):
        out1[i,j] = dot(matrices[i,j], vectors[i,j])

# using numpy.ensum (faster)
out2 = zeros_like(vectors)
out2 = einsum('...ij,...j->...i', matrices, vectors)

numpy.isclose(out1, out2).all()  # outputs `True`
1个回答

Pyhton 3.5 将引入一个新的算子@,它是 NumPy 开发人员提出的矩阵乘法算子。您可能想阅读PEP 465,但 NumPy 将为此运算符采用的语法是“堆叠矩阵乘法”,即正是您想要的。

可能会丢失一些零碎的东西,但是已经有一些工作,请参阅相关 PR,我认为如果您针对 Python 3.5 的 beta 版本构建最新的 NumPy 开发版本,您应该能够简单地执行以下操作:

out = matrices @ vectors

也许:

out = matrices @ vectors[..., None]

在张量的末尾添加一个 size-1 维度vectors

使用较早版本的 Python,如果您构建 NumPy 的最新开发版本,您应该能够:

import numpy as np

out = np.linalg.matmul(matrices, vectors)  # or vectors[..., None]

这些应该非常快,因为它们结合使用 BLAS 库来执行矩阵乘法(如果可用),并在所有堆叠矩阵上进行 C 迭代。

如果您不想进入不稳定的发布领域(尽管 NumPy 1.10 应该会在几周内推出),您必须选择:

  • einsum具有 C 迭代速度,但实际矩阵乘法无法匹配 BLAS,即使它使用 SIMD 比简单的 C 实现更快。可能最适合n大小g
  • 迭代加dot是慢迭代,但快速乘法(如果你有一个好的 BLAS 库),所以最适合 smalln和 large g.