简化循环 np.tensordot 表达式
Simplifying looped np.tensordot expression
目前,我的脚本如下所示:
import numpy as np
a = np.random.rand(10,5,2)
b = np.random.rand(10,5,50)
c = np.random.rand(10,2,50)
for i in range(a.shape[0]):
c[i] = np.tensordot(a[i], b[i], axes=(0,0))
我想在不使用 for 循环的情况下复制相同的行为,因为它可以并行完成。但是,我还没有找到使用 tensordot 函数执行此操作的巧妙方法。有没有办法为这个操作创建一个单行?
可以使用numpy.einsum函数,在本例中
c = np.einsum('ijk,ijl->ikl', a, b)
einsum
的替代方法是 matmul/@
。第一个数组必须转置,因此乘积和维度在最后:
In [162]: a = np.random.rand(10,5,2)
...: b = np.random.rand(10,5,50)
In [163]: c=a.transpose(0,2,1)@b
In [164]: c.shape
Out[164]: (10, 2, 50)
In [165]: c1 = np.random.rand(10,2,50)
...:
...: for i in range(a.shape[0]):
...: c1[i] = np.tensordot(a[i], b[i], axes=(0,0))
...:
In [166]: np.allclose(c,c1)
Out[166]: True
tensordot
重塑和转换参数,将任务简化为 dot
。因此,虽然可以切换哪个轴获得乘积和,但它处理 batches
的效果并不比 dot
好多少。这是添加 matmul
的重要原因。 np.einsum
提供相同的功能(甚至更多),但性能通常不是那么好(除非它被“优化”为等效的 matmul
)。
目前,我的脚本如下所示:
import numpy as np
a = np.random.rand(10,5,2)
b = np.random.rand(10,5,50)
c = np.random.rand(10,2,50)
for i in range(a.shape[0]):
c[i] = np.tensordot(a[i], b[i], axes=(0,0))
我想在不使用 for 循环的情况下复制相同的行为,因为它可以并行完成。但是,我还没有找到使用 tensordot 函数执行此操作的巧妙方法。有没有办法为这个操作创建一个单行?
可以使用numpy.einsum函数,在本例中
c = np.einsum('ijk,ijl->ikl', a, b)
einsum
的替代方法是 matmul/@
。第一个数组必须转置,因此乘积和维度在最后:
In [162]: a = np.random.rand(10,5,2)
...: b = np.random.rand(10,5,50)
In [163]: c=a.transpose(0,2,1)@b
In [164]: c.shape
Out[164]: (10, 2, 50)
In [165]: c1 = np.random.rand(10,2,50)
...:
...: for i in range(a.shape[0]):
...: c1[i] = np.tensordot(a[i], b[i], axes=(0,0))
...:
In [166]: np.allclose(c,c1)
Out[166]: True
tensordot
重塑和转换参数,将任务简化为 dot
。因此,虽然可以切换哪个轴获得乘积和,但它处理 batches
的效果并不比 dot
好多少。这是添加 matmul
的重要原因。 np.einsum
提供相同的功能(甚至更多),但性能通常不是那么好(除非它被“优化”为等效的 matmul
)。