2012-08-07 73 views
22

Giả sử bạn có n ma trận vuông A1, ..., An. Có anyway để nhân các ma trận một cách gọn gàng? Theo như tôi biết chấm trong numpy chấp nhận chỉ có hai đối số. Một cách rõ ràng là định nghĩa một hàm để gọi chính nó và nhận kết quả. Có cách nào tốt hơn để hoàn thành nó không?Nhân một số ma trận trong numpy

Trả lời

38

Đây có thể là một tính năng tương đối gần đây, nhưng tôi thích:

A.dot(B).dot(C) 

hoặc nếu bạn đã có một chuỗi dài bạn có thể làm:

reduce(numpy.dot, [A1, A2, ..., An]) 

Cập nhật:

Có nhiều thông tin về việc giảm here. Đây là một ví dụ có thể hữu ích.

>>> A = [np.random.random((5, 5)) for i in xrange(4)] 
>>> product1 = A[0].dot(A[1]).dot(A[2]).dot(A[3]) 
>>> product2 = reduce(numpy.dot, A) 
>>> numpy.all(product1 == product2) 
True 

Cập nhật 2016: Tính đến python 3.5, có một biểu tượng mới matrix_multiply, @:

R = A @ B @ C 
+0

Cảm ơn bạn đã phản hồi. Tùy chọn đầu tiên hoạt động tốt; nhưng cái thứ hai thì không; hoặc ít nhất tôi không thể làm cho nó hoạt động được. Bạn có thể vui lòng giải thích thêm một chút hoặc có thể đưa ra một ví dụ? Cảm ơn rất nhiều – NNsr

+4

Tôi chạy vào tất cả các thời gian và kết thúc bằng văn bản một chức năng trợ giúp. Điều này là một phần của NumPy: 'def xdot (* args): return reduce (np.dot, args)' – rd11

+0

Chỉ cần thêm một chú thích rằng nó hoạt động khi A, B, và C thuộc kiểu numpy.ndarray. Điều này có thể làm việc cho các loại khác, nhưng tôi đã không kiểm tra. – OfLettersAndNumbers

3

Nếu bạn tính tất cả các ma trận một mức ưu tiên thì bạn nên sử dụng lược đồ tối ưu hóa cho phép nhân chuỗi ma trận. Xem this Wikipedia article.

+2

Cám ơn nhận xét của bạn; nhưng tôi không nghĩ cho các ma trận vuông quan trọng. Đúng? – NNsr

+0

@Nikandish: Đúng. Tôi đã bỏ lỡ phần đó trong câu trả lời ban đầu của bạn. –

2
A_list = [np.random.randn(100, 100) for i in xrange(10)] 
B = np.eye(A_list[0].shape[0]) 
for A in A_list: 
    B = np.dot(B, A) 

C = reduce(np.dot, A_list) 

assert(B == C) 
16

Đang phục hồi một câu hỏi cũ với một bản cập nhật:

Tính đến November 13, 2014 hiện tại có chức năng np.linalg.multi_dot thực hiện chính xác những gì bạn muốn. Nó cũng có lợi ích của việc tối ưu hóa thứ tự cuộc gọi, mặc dù điều đó là không cần thiết trong trường hợp của bạn.

Lưu ý rằng bắt đầu có sẵn này với phiên bản khó khăn 1.10.

0

Một cách khác để đạt được điều này là sử dụng einsum, triển khai Einstein summation convention cho NumPy.

Để giải thích rất ngắn gọn ước này đối với vấn đề này với: Khi bạn viết ra sản phẩm nhiều ma trận của bạn như là một tổng lớn của sản phẩm, bạn sẽ có được một cái gì đó như:

P_im = sum_j sum_k sum_l A1_ij A2_jk A3_kl A4_lm 

nơi P là kết quả của bạn sản phẩm và A1, A2, A3A4 là các ma trận đầu vào. Lưu ý rằng bạn tổng hợp chính xác các chỉ số đó xuất hiện hai lần trong tổng kết, cụ thể là j, kl. Như một tổng với tài sản này thường xuất hiện trong vật lý, tính toán vector, và có lẽ một số lĩnh vực khác, có một công cụ NumPy cho nó, cụ thể là einsum.

Trong ví dụ trên, bạn có thể sử dụng nó để tính toán ma trận của bạn như sau:

P = np.einsum("ij,jk,kl,lm", A1, A2, A3, A4) 

Ở đây, số đầu tiên kể chức năng mà chỉ số để áp dụng cho các ma trận đối số và sau đó tất cả các chỉ số gấp đôi xuất hiện được tổng kết lại, cho kết quả mong muốn.

Lưu ý rằng hiệu quả tính toán phụ thuộc vào nhiều yếu tố (do đó bạn có lẽ giảm giá tốt nhất chỉ với thử nghiệm nó):

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