简体   繁体   English

将数组矩阵与矢量相乘; 返回向量数组?

[英]Multiply array of vectors with array of matrices; return array of vectors?

I've got a numpy array of row vectors of shape (n,3) and another numpy array of matrices of shape (n,3,3). 我有一个numpy形状的行向量(N,3)和形状的矩阵的另一numpy的阵列的阵列(N,3,3)。 I would like to multiply each of the n vectors with the corresponding matrix and return an array of shape (n,3) of the resulting vectors. 我想将n个向量中的每一个与相应的矩阵相乘,并返回所得向量的形状(n,3)数组。

By now I've been using a for loop to iterate through the n vectors/matrices and do the multiplication item by item. 到目前为止,我一直在使用for循环遍历n个向量/矩阵,并逐项进行乘法运算。

I would like to know if there's a more numpy-ish way of doing this. 我想知道是否有更多的numpy-ish方式这样做。 A way without the for loop that might even be faster. 没有for循环的方式甚至可能更快。

//edit 1: //编辑1:

As requested, here's my loopy code (with n = 10 ): 根据要求,这是我的循环代码( 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]))

That dot-product is essentially performing reduction along axis=1 of the two input arrays. dot-product基本上沿着两个输入阵列的axis=1执行减少。 The dimensions could be represented like so - 尺寸可以表示如此 -

arr_in   :     n   3 
matrices : n   3   3

So, one way to solve it would be to "push" the dimensions of arr_in to front by one axis/dimension , thus creating a singleton dimension at axis=2 in a 3D array version of it. 因此,解决它的一种方法是将arr_in的尺寸“推”到前面一个axis/dimension ,从而在它的3D阵列版本中在axis=2处创建单个尺寸。 Then, sum-reducing the elements along axis = 1 would give us the desired output. 然后,沿axis = 1减少元素的总和将给出我们所需的输出。 Let's show it - 让我们展示一下 -

arr_in   : n   [3]   1 
matrices : n   [3]   3

Now, this could be achieved through two ways. 现在,这可以通过两种方式实现。

1) With np.einsum - 1)使用np.einsum -

np.einsum('ij,ijk->ik',arr_in,matrices)

2) With NumPy broadcasting - 2)借助NumPy broadcasting -

(arr_in[...,None]*matrices).sum(1)

Runtime test and verify output (for einsum version) - 运行时测试和验证输出(对于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

You could use np.einsum . 你可以使用np.einsum To get v.dot(M) for each vector-matrix pair, use np.einsum("...i,...ij", arr_in, matrices) . 要获得每个向量 - 矩阵对的v.dot(M) ,请使用np.einsum("...i,...ij", arr_in, matrices) To get M.dot(v) use np.einsum("...ij,...i", matrices, arr_in) 获取M.dot(v)使用np.einsum("...ij,...i", matrices, arr_in)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM