问题描述
我有一个形状为(N*2)
的矩阵M1
和另一个矩阵M2
(2*N)
,我想获得一个(N)
的结果,每个元素i
是第i
行的乘积M2
的M1
和i
列中的第一个.我尝试在NumPy中使用点,但是它只能给我矩阵乘法结果,即(N*N)
,当然,我可以取对角线,这是我想要的,我想知道是否有更好的方法可以这样吗?
I have a matrix M1
of shape (N*2)
and another matrix M2
(2*N)
, I want to obtain a result of (N)
, each element i
is the product of i
th row of M1
and i
th column of M2
.I tried to use dot in NumPy, but it can only give me the matrix multiplication result, which is (N*N)
, of course, I can take the diagonal which is what I want, I would like to know is there a better way to do this?
推荐答案
方法1
您可以使用 np.einsum
-
You can use np.einsum
-
np.einsum('ij,ji->i',M1,M2)
说明:
原始的循环解决方案看起来像这样-
The original loopy solution would look something like this -
def original_app(M1,M2):
N = M1.shape[0]
out = np.zeros(N)
for i in range(N):
out[i] = M1[i].dot(M2[:,i])
return out
因此,对于每次迭代,我们都有:
Thus, for each iteration, we have :
out[i] = M1[i].dot(M2[:,i])
看一下迭代器,我们需要将M1
的第一个轴与M2
的第二个轴对齐.同样,由于我们正在执行matrix-multiplication
,并且按照其定义,就是将M1
的第二个轴与M2
的第一个轴对齐,并且在每次迭代时也将这些元素求和.
Looking at the iterator, we need to align the first axis of M1
with the second axis of M2
. Again, since we are performing matrix-multiplication
and that by its very definition is aligning the second axis of M1
with the first axis of M2
and also sum-reducing these elements at each iteration.
移植到einsum
时,在为其指定字符串符号时,应使两个输入之间要对齐的轴具有相同的字符串.因此,对于M1
和M2
,输入分别为'ij,ji
.丢失M1
中的第二个字符串后的输出(与该和中的M2
中的第一个字符串相同)应保留为i
.因此,完整的字符串符号为:'ij,ji->i'
,最终解决方案为:np.einsum('ij,ji->i',M1,M2)
.
When porting over to einsum
, keep the axes to be aligned between the two inputs to have the same string when specifying the string notation to it. So, the inputs would be 'ij,ji
for M1
and M2
respectively. The output after losing the second string from M1
, which is same as first string from M2
in that sum-reduction, should be left as i
. Thus, the complete string notation would be : 'ij,ji->i'
and the final solution as : np.einsum('ij,ji->i',M1,M2)
.
方法2
M1
中的列数或M2
中的行数是2
.因此,或者,我们可以像这样对切片,执行逐元素乘法并将其求和,-
The number of cols in M1
or number of rows in M2
is 2
. So, alternatively, we can just slice, perform the element-wise multiplication and sum up those, like so -
M1[:,0]*M2[0] + M1[:,1]*M2[1]
运行时测试
In [431]: # Setup inputs
...: N = 1000
...: M1 = np.random.rand(N,2)
...: M2 = np.random.rand(2,N)
...:
In [432]: np.allclose(original_app(M1,M2),np.einsum('ij,ji->i',M1,M2))
Out[432]: True
In [433]: np.allclose(original_app(M1,M2),M1[:,0]*M2[0] + M1[:,1]*M2[1])
Out[433]: True
In [434]: %timeit original_app(M1,M2)
100 loops, best of 3: 2.09 ms per loop
In [435]: %timeit np.einsum('ij,ji->i',M1,M2)
100000 loops, best of 3: 13 µs per loop
In [436]: %timeit M1[:,0]*M2[0] + M1[:,1]*M2[1]
100000 loops, best of 3: 14.2 µs per loop
大量加速!
这篇关于array1的第i行和array2的第i列的计算乘积-NumPy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!