我有一个形状为(n,3)的行向量的numpy
数组和另一个形状为矩阵的numpy数组(n,3,3)。我想将n个向量中的每一个与相应的矩阵相乘,并返回结果向量的形状(n,3)数组。
到目前为止,我一直在使用for循环遍历n个向量/矩阵,并逐项进行乘法运算。
我想知道是否有更多的numpy-ish方式。没有for循环的方法甚至可能更快。
//编辑1:
根据要求,这是我的循环代码(使用n = 10
):
arr_in = np.random.randn(10, 3)
matrices = np.random.randn(10, 3, 3)
for i in range(arr_in.shape[0]): # 10 iterations
arr_out[i] = np.asarray(np.dot(arr_in[i], matrices[i]))
答案 0 :(得分:1)
dot-product
基本上沿着两个输入数组的axis=1
执行减少。尺寸可以表示为 -
arr_in : n 3
matrices : n 3 3
因此,解决问题的一种方法是推动"推动" arr_in
的维度前置一个axis/dimension
,从而在其3D阵列版本的axis=2
处创建单个维度。然后,沿axis = 1
减少元素的总和会给我们所需的输出。让我们展示一下 -
arr_in : n [3] 1
matrices : n [3] 3
现在,这可以通过两种方式实现。
1)使用np.einsum
-
np.einsum('ij,ijk->ik',arr_in,matrices)
2)使用NumPy broadcasting
-
(arr_in[...,None]*matrices).sum(1)
运行时测试和验证输出(适用于einsum
版本) -
In [329]: def loop_based(arr_in,matrices):
...: arr_out = np.zeros((arr_in.shape[0], 3))
...: for i in range(arr_in.shape[0]):
...: arr_out[i] = np.dot(arr_in[i], matrices[i])
...: return arr_out
...:
...: def einsum_based(arr_in,matrices):
...: return np.einsum('ij,ijk->ik',arr_in,matrices)
...:
In [330]: # Inputs
...: N = 16935
...: arr_in = np.random.randn(N, 3)
...: matrices = np.random.randn(N, 3, 3)
...:
In [331]: np.allclose(einsum_based(arr_in,matrices),loop_based(arr_in,matrices))
Out[331]: True
In [332]: %timeit loop_based(arr_in,matrices)
10 loops, best of 3: 49.1 ms per loop
In [333]: %timeit einsum_based(arr_in,matrices)
1000 loops, best of 3: 714 µs per loop
答案 1 :(得分:0)
您可以使用np.einsum
。要为每个矢量矩阵对获取v.dot(M)
,请使用np.einsum("...i,...ij", arr_in, matrices)
。要M.dot(v)
使用np.einsum("...ij,...i", matrices, arr_in)