2013-07-02 23 views
6

Tôi đang tìm cách nhanh chóng để tính tổng n sản phẩm bên ngoài.Python - cách nhanh chóng để tổng hợp các sản phẩm bên ngoài?

Về cơ bản, tôi bắt đầu với hai ma trận được tạo ra từ phân phối chuẩn - có n vectơ với các yếu tố v:

A = np.random.normal(size = (n, v)) 
B = np.random.normal(size = (n, v)) 

Những gì tôi muốn là để tính toán các sản phẩm ngoài của mỗi vector kích thước v A và B và tổng hợp chúng lại với nhau.

Lưu ý rằng A * B.T không hoạt động - A có kích thước n x v trong khi B có kích thước v x n.

Điều tốt nhất tôi có thể làm là tạo vòng lặp nơi các sản phẩm bên ngoài được xây dựng, sau đó tổng hợp lại sau. Tôi có nó như vậy:

outers = np.array([A[i] * B[i].T]) 

này tạo ra một n x v x v mảng (vòng lặp nằm trong phạm vi hiểu biết danh sách, mà sau đó được chuyển thành một mảng), mà tôi sau đó có thể tổng hợp lại với nhau bằng cách sử dụng np.sum(outers, axis = 0). Tuy nhiên, điều này là khá chậm, và tôi đã tự hỏi nếu có một chức năng vectorized tôi có thể sử dụng để tăng tốc độ này lên.

Nếu có ai có lời khuyên nào, tôi thực sự sẽ đánh giá cao điều đó!

Trả lời

7

Dường như với tôi tất cả những gì bạn cần làm là thay đổi thứ tự của các chuyển vị và làm A.T * B thay vì A * B.T.

Nếu đó không hoàn toàn là những gì bạn đang theo dõi, hãy xem np.einsum, điều này có thể thực hiện một số thông điệp rất mạnh mẽ. Đối với ví dụ trên, bạn sẽ làm:

np.einsum('ij,ik->jk', A, B) 
+0

einsum hoạt động đẹp mắt. Cảm ơn! – Adam

2

Đồng thời xem xét np.outer.

np.array([np.outer(A, B) for i in xrange(n)]).sum(0) 

mặc dù np.einsum được đề xuất bởi @Jamie là người chiến thắng rõ ràng.

In [63]: %timeit np.einsum('ij,ik->jk', A, B) 
100000 loops, best of 3: 4.61 us per loop 

In [64]: %timeit np.array([np.outer(A[i], B[i]) for i in xrange(n)]).sum(0) 
10000 loops, best of 3: 169 us per loop 

và, để chắc chắn, kết quả của họ là giống hệt nhau:

In [65]: np.testing.assert_allclose(method_outer, method_einsum) 

Nhưng, như một sang một bên, tôi không thấy rằng A.T * B hoặc A * B.T phát sóng thành công.

+0

Anh ta nhân các đối tượng 'np.matrix', không phải' np.ndarray'. 'A * B.T' sau đó tương đương với' np.dot (A, B.T) ', và' A.T * B' thành 'np.dot (A.T, B)'. Nó sẽ đồng hồ rất, rất gần với 'np.einsum'. – Jaime

+0

+1 để có sự so sánh tốt đẹp giữa hai phương pháp – elaRosca

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