我有2个阵列,目前形状为v1 =(3000,3),v2 =(3,2,3000)。 3000是时间维度,因此v1具有3000(1,3)个样本,v2具有3000(3,2)个样本。我希望沿着3000维进行矩阵乘法和广播,以便得到3000(1,2)个向量作为回报。
我尝试过重塑,以便v1 =(1,3,3000)和v2 =(3,2,300),这会产生一个错误,表示形状没有对齐。
码:
v1 = np.ones((1,3,3000)) +1
v2 = np.ones((3,2,3000)) - 0.5
np.dot(v1,v2)
随着qazxsw poi的形状qazxsw poi和qazxsw poi作为qazxsw poi,我们可以使用v1
-
(3000,3)
这给了我们一个形状v2
的输出。
我们可以在(3,2,3000)
玩np.einsum
arg。使用np.einsum('ij,jki->ik',v1,v2)
,它在内部利用(3000,2)
,并使用optimize
度假村进行简单的C循环。那种np.einsum
方式也需要一些设置工作。因此,如果轴的长度适当减少,我们可能希望将该标志设置为optimize = True
和BLAS
。在这种情况下,似乎那些轴确实很短,所以我们可能更好地使用默认值:optimize = False
输入。
我建议你不要使用BLAS
旗,因为它有效率,出于一些奇怪的原因。此外,我建议您明确地将2D数组推广到3D,执行批处理矩阵乘法,然后挤压结果数组的单例维度,如果最后需要2D数组作为最终结果。请找到以下代码:
True
因此,正如我们从上面的时间中看到的那样,我们获得了大约。通过不使用False
标志2倍加速。此外,明确地将数组整形为3D可以更好地理解当我们使用optimize = False
时发生的事情。
注意:时间是使用最新的NumPy版本optimize=True
进行的
附:了解更多关于# sample arrays
In [25]: v1 = np.random.random_sample((3000, 3))
In [26]: v2 = np.random.random_sample((3, 2, 3000))
# Divakar's approach
In [27]: %timeit np.einsum('ij,jki->ik',v1,v2, optimize=True)
80.7 µs ± 792 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# needed for future use
In [28]: res_optimized = np.einsum('ij,jki->ik',v1,v2, optimize=True)
# promoting to 3D array and swapping axes
In [29]: v1 = v1[:, np.newaxis, :]
In [30]: v2 = np.moveaxis(v2, 2, 0)
# perform batch matrix multiplication
In [31]: %timeit np.einsum("bij, bjk -> bik", v1, v2)
47.9 µs ± 496 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# for sanity checking
In [32]: res = np.einsum("bij, bjk -> bik", v1, v2)
In [33]: res.shape, res_optimized.shape
Out[33]: ((3000, 1, 2), (3000, 2))
# squeeze the singleton dimension and perform sanity check with Divakar's approach
In [34]: np.allclose(res.squeeze(), res_optimized)
Out[34]: True
的信息