Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I produce the result of np.outer using np.dot?

I am trying to improve my understanding of numpy functions. I understand the behaviour of numpy.dot. I'd like to understand the behaviour of numpy.outer in terms of numpy.dot.

Based on this Wikipedia article https://en.wikipedia.org/wiki/Outer_product I'd expect for array_equal to return True in the following code. However it does not.

X = np.matrix([
    [1,5],
    [5,9],
    [4,1]
])

r1 = np.outer(X,X)
r2 = np.dot(X, X.T)
np.array_equal(r1, r2)

How can I assign r2 so that np.array_equal returns True? Also, why does numpy's implementation of np.outer not match the definition of outer multiplication on Wikipedia?

Using numpy 1.9.2

like image 923
Selah Avatar asked Feb 09 '23 14:02

Selah


2 Answers

In [303]: X=np.array([[1,5],[5,9],[4,1]])
In [304]: X
Out[304]: 
array([[1, 5],
       [5, 9],
       [4, 1]])
In [305]: np.inner(X,X)
Out[305]: 
array([[ 26,  50,   9],
       [ 50, 106,  29],
       [  9,  29,  17]])
In [306]: np.dot(X,X.T)
Out[306]: 
array([[ 26,  50,   9],
       [ 50, 106,  29],
       [  9,  29,  17]])

The Wiki outer link mostly talks about vectors, 1d arrays. Your X is 2d.

In [310]: x=np.arange(3)
In [311]: np.outer(x,x)
Out[311]: 
array([[0, 0, 0],
       [0, 1, 2],
       [0, 2, 4]])
In [312]: np.inner(x,x)
Out[312]: 5
In [313]: np.dot(x,x)   # same as inner
Out[313]: 5
In [314]: x[:,None]*x[None,:]   # same as outer
Out[314]: 
array([[0, 0, 0],
       [0, 1, 2],
       [0, 2, 4]])

Notice that the Wiki outer does not involve summation. Inner does, in this example 5 is the sum of the 3 diagonal values of the outer.

dot also involves summation - all the products followed summation along a specific axis.

Some of the wiki outer equations use explicit indices. The einsum function can implement these calculations.

In [325]: np.einsum('ij,kj->ik',X,X)
Out[325]: 
array([[ 26,  50,   9],
       [ 50, 106,  29],
       [  9,  29,  17]])
In [326]: np.einsum('ij,jk->ik',X,X.T)
Out[326]: 
array([[ 26,  50,   9],
       [ 50, 106,  29],
       [  9,  29,  17]])
In [327]: np.einsum('i,j->ij',x,x)
Out[327]: 
array([[0, 0, 0],
       [0, 1, 2],
       [0, 2, 4]])
In [328]: np.einsum('i,i->',x,x)
Out[328]: 5

As mentioned in the comment, np.outer uses ravel, e.g.

return a.ravel()[:, newaxis]*b.ravel()[newaxis,:]

This the same broadcasted multiplication that I demonstrated earlier for x.

like image 152
hpaulj Avatar answered Feb 13 '23 20:02

hpaulj


numpy.outer only works for 1-d vectors, not matrices. But for the case of 1-d vectors, there is a relation.

If

import numpy as np
A = np.array([1.0,2.0,3.0])

then this

np.matrix(A).T.dot(np.matrix(A))

should be the same as this

np.outer(A,A)
like image 31
JARS Avatar answered Feb 13 '23 21:02

JARS