Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using numpy einsum to compute inner product of column-vectors of a matrix

Suppose I have a numpy matrix like this:

[[   1    2    3]
 [  10  100 1000]]

I would like to compute the inner product of each column with itself, so the result would be:

[1*1 + 10*10    2*2 + 100*100    3*3 + 1000*1000] == [101, 10004, 1000009]

I would like to know if this is possible using the einsum function (and to better understand it).

So far, the closest result I could have is:

import numpy as np

arr = np.array([[1, 2, 3], [10, 100, 1000]])

res = np.einsum('ij,ik->jk', arr, arr)

# [[    101    1002   10003]
#  [   1002   10004  100006]
#  [  10003  100006 1000009]]

The diagonal contains the expected result, but I would like to know if I can avoid edge calculations.

like image 546
Delgan Avatar asked Jan 27 '26 04:01

Delgan


2 Answers

Use np.einsum, like so -

np.einsum('ij,ij->j',arr,arr)

Sample run -

In [243]: np.einsum('ij,ij->j',arr,arr)
Out[243]: array([    101,   10004, 1000009])

Or with np.sum -

In [244]: (arr**2).sum(0)
Out[244]: array([    101,   10004, 1000009])

Or with numexpr module -

In [248]: import numexpr as ne

In [249]: ne.evaluate('sum(arr**2,0)')
Out[249]: array([    101,   10004, 1000009])
like image 99
Divakar Avatar answered Jan 28 '26 18:01

Divakar


What you're expecting here can be understood intuitively, with one intermediate step from Divakar's einsum answer.

In [19]: arr
Out[19]: 
array([[   1,    2,    3],
       [  10,  100, 1000]])

# simply take element-wise product with the array itself
In [20]: np.einsum('ij, ij -> ij', arr, arr)
Out[20]: 
array([[      1,       4,       9],
       [    100,   10000, 1000000]])

But, this doesn't give the result that you expected. So, if you observe the above result, we just need to sum along the first dimension (i.e. axis 0). So, we omit the subscript i after -> in the einsum result, which means we ask it to sum along that axis, and that yields the expected result which is:

In [21]: np.einsum('ij, ij -> j', arr, arr)
Out[21]: array([    101,   10004, 1000009])

P.S. Also, for a general understanding of np.einsum, see the detailed discussion here: understanding-numpy-einsum

like image 21
kmario23 Avatar answered Jan 28 '26 17:01

kmario23



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!