Computing product of ith row of array1 and ith column of array2 - NumPy
<p>I have a matrix <code>M1</code> of shape <code>(N*2)</code> and another matrix <code>M2</code> <code>(2*N)</code>, I want to obtain a result of <code>(N)</code>, each element <code>i</code> is the product of <code>i</code>th row of <code>M1</code> and <code>i</code>th column of <code>M2</code>. 
I tried to use dot in NumPy, but it can only give me the matrix multiplication result, which is <code>(N*N)</code>, 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?</p>

<p><strong>Approach #1</strong></p>

<p>You can use <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html" rel="nofollow"><code>np.einsum</code></a> -</p>

<pre><code>np.einsum('ij,ji-&gt;i',M1,M2)
</code></pre>

<p><strong>Explanation :</strong> </p>

<p>The original loopy solution would look something like this -</p>

<pre><code>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
</code></pre>

<p>Thus, for each iteration, we have :</p>

<pre><code>out[i] = M1[i].dot(M2[:,i])
</code></pre>

<p>Looking at the iterator, we need to align the first axis of <code>M1</code> with the second axis of <code>M2</code>. Again, since we are performing <code>matrix-multiplication</code> and that by its very definition is aligning the second axis of <code>M1</code> with the first axis of <code>M2</code> and also sum-reducing these elements at each iteration.</p>

<p>When porting over to <code>einsum</code>, 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 <code>'ij,ji</code> for <code>M1</code> and <code>M2</code> respectively. The output after losing the second string from <code>M1</code>, which is same as first string from <code>M2</code> in that sum-reduction, should be left as <code>i</code>. Thus, the complete string notation would be : <code>'ij,ji-&gt;i'</code> and the final solution as : <code>np.einsum('ij,ji-&gt;i',M1,M2)</code>.</p>

<p><strong>Approach #2</strong></p>

<p>The number of cols in <code>M1</code> or number of rows in <code>M2</code> is <code>2</code>. So, alternatively, we can just slice, perform the element-wise multiplication and sum up those, like so -</p>

<pre><code>M1[:,0]*M2[0] + M1[:,1]*M2[1]
</code></pre>

<hr>

<p><strong>Runtime test</strong></p>

<pre><code>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-&gt;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-&gt;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
</code></pre>

<p>Massive speedup there!</p>

python numpy matrix