2013-06-16 30 views
8

Tôi đang cố gắng làm một cái gì đó đơn giản trong gumpy, và tôi chắc chắn rằng phải có một cách dễ dàng để làm điều đó.Numpy: sản phẩm ngoài của n vectơ

Về cơ bản, tôi có danh sách các vector n có độ dài khác nhau. Nếu v1[i]i 'xâm nhập của các vector đầu tiên ngày sau đó tôi muốn tìm một mảng chiều n, A, như vậy mà

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

Vấn đề của tôi là:

  1. outer chỉ mất hai vectơ đối số.

  2. einsum yêu cầu thông số như "abcd ..." có vẻ không cần thiết.

  3. kron yêu cầu những gì có vẻ như định hình lại khá phức tạp và chỉ mất hai đối số.

Tôi muốn tránh nhiều phức tạp nhất có thể, để tránh giới thiệu lỗi. Tốt nhất là tôi muốn một lệnh duy nhất.

Cho đến nay, là tốt nhất Tôi có một số lên với là:

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) 
+0

Số lượng vectơ không được biết cho đến khi thời gian chạy? – DarenW

+0

@ DarenW có, điều đó là chính xác. – Lucas

+1

Tôi thích điều này 'giảm ​​(lambda a, b: a [..., np.newaxis] * b, vs)' nhưng tôi không chắc liệu điều đó có thể được coi là "một lệnh duy nhất" hay không. Hoặc nếu có cách nhanh hơn. – jorgeca

Trả lời

8

Bạn sử dụng sử dụng mã sau đây một dòng:

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

np.ix_() sẽ làm phát sóng bên ngoài, bạn cần phải giảm, nhưng bạn có thể vượt qua ufunc np.multiply mà không có hàm lambda.

Dưới đây là so sánh:

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) 

Các reuslt:

True 
+5

+1 Nó có thể là một sự cải tiến không đáng kể, trừ khi danh sách vectơ của bạn thực sự dài, nhưng tôi nghĩ rằng 'np.multiply.reduce (np-ix_ (vs))' có thể sẽ hoạt động tốt hơn cấu trúc Python. – Jaime

1

Có một dòng thay thế mã:

reduce(np.multiply.outer, vs) 

Đó là minh bạch hơn đối với tôi hơn np.ix_(*vs) xây dựng và hỗ trợ các mảng đa chiều như trong this question.

Thời gian đều giống nhau trong một sự khoan dung:

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 
+0

Vâng, tôi thích sử dụng nó hơn. – Lucas

Các vấn đề liên quan