Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Numpy: outer product of n vectors

I'm trying to do something simple in numpy, and I'm sure there should be an easy way of doing it.

Basically, I have a list of n vectors with various lengths. If v1[i] is the i'th entry of the first vector then I want to find a n-dimensional array, A, such that

A[i,j,k...] = v1[i] v2[j] v3[k] ...

My problem is that:

  1. outer only takes two vector arguments.

  2. einsum requires a parameter like "abcd..." which seems unnecessary.

  3. kron requires what seems like rather complex reshaping, and takes only two arguments.

I'd like to avoid as much complexity as possible, so as to avoid introducing bugs. So preferably I would like a single command.

So far, the best I have some up with is:

 vs = [v1, v2, v3 ...]
 shape = map(len, vs)

 # specify the orientation of each vector
 newshapes = diag(array(shape)-1)+1
 reshaped = [x.reshape(y) for x,y in zip(vs, newshapes)]

 # direct product
 A = reduce(lambda a,b: a*b, reshaped, 1)
like image 842
Lucas Avatar asked Jun 16 '13 22:06

Lucas


People also ask

How do you find the outer product of two vectors?

In linear algebra, the outer product of two coordinate vectors is a matrix. If the two vectors have dimensions n and m, then their outer product is an n × m matrix.

What does NP Outer do in Python?

outer() function – Python. numpy. outer() function compute the outer product of two vectors.

Is outer product same as cross product?

(Cross products are sometimes called outer products, sometimes called vector products.) Although we'll define u × v algebraically, its geometric meaning is more understandable.


2 Answers

You use use following one line code:

reduce(np.multiply, np.ix_(*vs))

np.ix_() will do the outer broadcast, you need reduce, but you can pass the ufunc np.multiply without lambda function.

Here is the comparing:

import numpy as np
vs = [np.r_[1,2,3.0],np.r_[4,5.0],np.r_[6,7,8.0]]
shape = map(len, vs)

 # specify the orientation of each vector
newshapes = np.diag(np.array(shape)-1)+1
reshaped = [x.reshape(y) for x,y in zip(vs, newshapes)]

# direct product
A = reduce(lambda a,b: a*b, reshaped, 1)
B = reduce(np.multiply, np.ix_(*vs))

np.all(A==B)

The reuslt:

True
like image 77
HYRY Avatar answered Oct 29 '22 04:10

HYRY


There is an alternative line of code:

reduce(np.multiply.outer, vs)

It is more transparent for me than np.ix_(*vs) construction and support multidimensional arrays like in this question.

Timings are the same within a tolerance:

import numpy as np
from functools import reduce

def outer1(*vs):
    return np.multiply.reduce(np.ix_(*vs))
def outer2(*vs):
    return reduce(np.multiply.outer, vs)

v1 = np.random.randn(100)
v2 = np.random.randn(200)
v3 = np.random.randn(300)
v4 = np.random.randn(50)

%timeit outer1(v1, v2, v3, v4)
# 1 loop, best of 3: 796 ms per loop

%timeit outer2(v1, v2, v3, v4)
# 1 loop, best of 3: 795 ms per loop

np.all(outer1(v1, v2, v3, v4) == outer2(v1, v2, v3, v4))
# True
like image 29
ybeltukov Avatar answered Oct 29 '22 03:10

ybeltukov