3 cách để nhân ma trận trong Python

Spread the love

Trong hướng dẫn này, bạn sẽ học cách nhân hai ma trận trong Python.

Bạn sẽ bắt đầu bằng cách tìm hiểu điều kiện để nhân ma trận hợp lệ và viết một hàm Python tùy chỉnh để nhân ma trận. Tiếp theo, bạn sẽ thấy cách bạn có thể đạt được kết quả tương tự bằng cách sử dụng các cách hiểu danh sách lồng nhau.

Cuối cùng, bạn sẽ tiến hành sử dụng NumPy và các hàm tích hợp của nó để thực hiện phép nhân ma trận hiệu quả hơn.

Cách kiểm tra xem phép nhân ma trận có hợp lệ không

Trước khi viết mã Python cho phép nhân ma trận, hãy xem lại kiến ​​thức cơ bản về phép nhân ma trận.

Phép nhân ma trận giữa hai ma trận A và B chỉ hợp lệ nếu số cột trong ma trận A bằng số hàng trong ma trận B.

Bạn có thể đã gặp điều kiện này cho phép nhân ma trận trước đây. Tuy nhiên, bạn có bao giờ thắc mắc tại sao lại như vậy không?

Chà, đó là do cách hoạt động của phép nhân ma trận. Hãy xem hình ảnh bên dưới.

Trong ví dụ chung của chúng ta, ma trận A có m hàng và n cột. Và ma trận B có n hàng và p cột.

Hình dạng của Ma trận Sản phẩm là gì?

Phần tử ở chỉ số (i, j) trong ma trận kết quả C là tích số chấm của hàng i của ma trận A và cột j của ma trận B.

Vì vậy, để có được một phần tử tại một chỉ số cụ thể trong ma trận kết quả C, bạn sẽ phải tính tích số chấm của hàng và cột tương ứng trong ma trận A và B tương ứng.

Lặp lại quá trình trên, bạn sẽ nhận được ma trận sản phẩm C của hình dạng mxp — với m hàng và p cột, như được hiển thị bên dưới.

Và tích chấm hoặc tích trong giữa hai vectơ a và b được cho bởi phương trình sau.

Hãy tóm tắt ngay bây giờ:

  • Rõ ràng là tích chấm chỉ được xác định giữa các vectơ có độ dài bằng nhau.
  • Vì vậy, để tích chấm giữa một hàng và một cột là hợp lệ — khi nhân hai ma trận — bạn cần cả hai ma trận có cùng số phần tử.
  • Trong ví dụ chung trên, mọi hàng trong ma trận A có n phần tử. Và mọi cột trong ma trận B cũng có n phần tử.

Nếu bạn xem xét kỹ hơn, n là số cột trong ma trận A và nó cũng là số hàng trong ma trận B. Và đây chính xác là lý do tại sao bạn cần số cột trong ma trận A bằng số của các hàng trong ma trận B.

Tôi hy vọng bạn hiểu điều kiện để phép nhân ma trận là hợp lệ và cách lấy từng phần tử trong ma trận tích.

Hãy tiến hành viết một số mã Python để nhân hai ma trận.

Viết một hàm Python tùy chỉnh để nhân ma trận

Bước đầu tiên, chúng ta hãy viết một hàm tùy chỉnh để nhân ma trận.

  Cách xem tin nhắn đã lưu trữ trong Messenger

Hàm này sẽ thực hiện như sau:

  • Chấp nhận hai ma trận, A và B, làm đầu vào.
  • Kiểm tra xem phép nhân ma trận giữa A và B có hợp lệ không.
  • Nếu hợp lệ, hãy nhân hai ma trận A và B và trả về ma trận tích C.
  • Nếu không, trả về một thông báo lỗi rằng ma trận A và B không thể nhân được.

Bước 1: Tạo hai ma trận số nguyên bằng cách sử dụng hàm random.randint () của NumPy. Bạn cũng có thể khai báo ma trận dưới dạng danh sách Python lồng nhau.

import numpy as np
np.random.seed(27)
A = np.random.randint(1,10,size = (3,3))
B = np.random.randint(1,10,size = (3,2))
print(f"Matrix A:n {A}n")
print(f"Matrix B:n {B}n")

# Output
Matrix A:
 [[4 9 9]
 [9 1 6]
 [9 2 3]]

Matrix B:
 [[2 2]
 [5 7]
 [4 4]]

Bước 2: Hãy tiếp tục và xác định hàm nhân_matrix (A, B). Hàm này nhận hai ma trận A và B làm đầu vào và trả về ma trận sản phẩm C nếu phép nhân ma trận là hợp lệ.

def multiply_matrix(A,B):
  global C
  if  A.shape[1] == B.shape[0]:
    C = np.zeros((A.shape[0],B.shape[1]),dtype = int)
    for row in range(rows): 
        for col in range(cols):
            for elt in range(len(B)):
              C[row, col] += A[row, elt] * B[elt, col]
    return C
  else:
    return "Sorry, cannot multiply A and B."

Phân tích cú pháp định nghĩa hàm

Hãy tiến hành phân tích cú pháp định nghĩa hàm.

Khai báo C là một biến toàn cục: Theo mặc định, tất cả các biến bên trong một hàm Python đều có phạm vi cục bộ. Và bạn không thể truy cập chúng từ bên ngoài chức năng. Để làm cho ma trận sản phẩm C có thể truy cập từ bên ngoài, chúng ta sẽ phải khai báo nó như một biến toàn cục. Chỉ cần thêm bộ định lượng toàn cục trước tên biến.

Kiểm tra xem phép nhân ma trận có hợp lệ không: Sử dụng thuộc tính shape để kiểm tra xem A và B có thể nhân được không. Đối với bất kỳ arr, arr.shape mảng nào[0] và arr.shape[1] cho số hàng và số cột tương ứng. Vì vậy, nếu A.shape[1] == B.shape[0] kiểm tra xem phép nhân ma trận có hợp lệ không. Chỉ khi điều kiện này là Đúng, ma trận sản phẩm sẽ được tính. Khác, hàm trả về một thông báo lỗi.

Sử dụng vòng lặp lồng nhau để tính giá trị: Để tính toán các phần tử của ma trận kết quả, chúng ta phải lặp qua các hàng của ma trận A và vòng lặp for bên ngoài thực hiện điều này. Vòng lặp for bên trong giúp chúng ta lặp qua cột của ma trận B. Và vòng lặp for trong cùng giúp truy cập từng phần tử trong cột đã chọn.

▶ ️ Bây giờ chúng ta đã học cách hoạt động của hàm Python để nhân ma trận, hãy gọi hàm với ma trận A và B mà chúng ta đã tạo trước đó.

multiply_matrix(A,B)

# Output
array([[ 89, 107],
       [ 47,  49],
       [ 40,  44]])

Vì phép nhân ma trận giữa A và B là hợp lệ, hàm Multi_matrix () trả về ma trận tích số C.

Sử dụng tính năng hiểu danh sách lồng nhau trong Python để nhân ma trận

Trong phần trước, bạn đã viết một hàm Python để nhân ma trận. Bây giờ, bạn sẽ thấy cách bạn có thể sử dụng cách hiểu danh sách lồng nhau để làm điều tương tự.

Đây là cách hiểu danh sách lồng nhau để nhân ma trận.

Lúc đầu, điều này có thể trông phức tạp. Nhưng chúng tôi sẽ phân tích cú pháp để hiểu danh sách lồng nhau từng bước.

Hãy tập trung vào một lần hiểu danh sách và xác định những gì nó làm.

  Lyrics Finder Tìm lời bài hát và thêm chúng vào tệp MP3 của bạn

Chúng tôi sẽ sử dụng mẫu chung sau để hiểu danh sách:

[<do-this> for <item> in <iterable>]

where,
<do-this>: what you'd like to do—expression or operation
<item>: each item you'd like to perform the operation on
<iterable>: the iterable (list, tuple, etc.) that you're looping through

▶ ️ Hãy xem hướng dẫn của chúng tôi về Khả năng hiểu danh sách bằng Python – với các ví dụ để hiểu sâu hơn.

Trước khi tiếp tục, xin lưu ý rằng chúng tôi muốn xây dựng ma trận kết quả C một hàng tại một thời điểm.

Giải thích hiểu danh sách lồng nhau

Bước 1: Tính một giá trị duy nhất trong ma trận C

Cho hàng i của ma trận A và cột j của ma trận B, biểu thức dưới đây đưa ra mục nhập tại chỉ số (i, j) trong ma trận C.

sum(a*b for a,b in zip(A_row, B_col)

# zip(A_row, B_col) returns an iterator of tuples
# If A_row = [a1, a2, a3] & B_col = [b1, b2, b3]
# zip(A_row, B_col) returns (a1, b1), (a2, b2), and so on

Nếu i = j = 1, biểu thức sẽ trả về mục nhập c_11 của ma trận C. Vì vậy, bạn có thể lấy một phần tử trong một hàng theo cách này.

Bước 2: Xây dựng một hàng trong ma trận C

Mục tiêu tiếp theo của chúng tôi là xây dựng toàn bộ một hàng.

Đối với hàng 1 trong ma trận A, bạn phải lặp qua tất cả các cột trong ma trận B để có được một hàng hoàn chỉnh trong ma trận C.

Quay lại mẫu hiểu danh sách.

  • Thay thế bằng biểu thức từ bước 1, vì đó là những gì bạn muốn làm.
  • Tiếp theo, thay thế bằng B_col — mỗi cột trong ma trận B.
  • Cuối cùng, thay thế bằng zip (* B) —danh sách chứa tất cả các cột trong ma trận B.

Và đây là danh sách đầu tiên hiểu được.

[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] 

# zip(*B): * is the unzipping operator
# zip(*B) returns a list of columns in matrix B

Bước 3: Xây dựng tất cả các hàng và thu được ma trận C

Tiếp theo, bạn sẽ phải điền vào ma trận sản phẩm C bằng cách tính toán các hàng còn lại.

Và đối với điều này, bạn phải lặp qua tất cả các hàng trong ma trận A.

Quay lại phần hiểu danh sách một lần nữa và thực hiện như sau.

  • Thay thế bằng cách hiểu danh sách từ bước 2. Nhớ lại rằng chúng ta đã tính toán toàn bộ một hàng trong bước trước.
  • Bây giờ, hãy thay thế bằng A_row — mọi hàng trong ma trận A.
  • của bạn chính là ma trận A, khi bạn đang lặp qua các hàng của nó.

Và đây là phần hiểu danh sách lồng nhau cuối cùng của chúng tôi.🎊

[[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] 
    for A_row in A]

Đã đến lúc xác minh kết quả! ✔

# cast into <a href="https://techpoe.com.com/numpy-reshape-arrays-in-python/">NumPy array</a> using np.array()
C = np.array([[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] 
    for A_row in A])

# Output:
[[ 89 107]
 [ 47  49]
 [ 40  44]]

Nếu bạn xem xét kỹ hơn, điều này tương đương với các vòng lặp for lồng nhau mà chúng ta đã có trước đó — chỉ là nó ngắn gọn hơn.

Bạn cũng có thể làm điều này một cách hiệu quả hơn bằng cách sử dụng một số chức năng được tích hợp sẵn. Hãy cùng tìm hiểu về chúng trong phần tiếp theo.

Sử dụng NumPy matmul () để Nhân ma trận trong Python

Np.matmul () nhận vào hai ma trận làm đầu vào và trả về tích nếu phép nhân ma trận giữa các ma trận đầu vào là hợp lệ.

C = np.matmul(A,B)
print(C)

# Output:
[[ 89 107]
 [ 47  49]
 [ 40  44]]

Lưu ý rằng phương pháp này đơn giản hơn so với hai phương pháp chúng ta đã học trước đó. Trên thực tế, thay vì np.matmul (), bạn có thể sử dụng toán tử @ tương đương và chúng ta sẽ thấy điều đó ngay lập tức.

Cách sử dụng toán tử @ trong Python để nhân ma trận

Trong Python, @ là một toán tử nhị phân được sử dụng để nhân ma trận.

Nó hoạt động trên hai ma trận và nói chung là mảng NumPy N chiều và trả về ma trận sản phẩm.

Lưu ý: Bạn cần có Python 3.5 trở lên để sử dụng toán tử @.

Đây là cách bạn có thể sử dụng nó.

C = [email protected]
print(C)

# Output
array([[ 89, 107],
       [ 47,  49],
       [ 40,  44]])

Chú ý rằng ma trận sản phẩm C giống như ma trận mà chúng ta đã thu được trước đó.

Bạn có thể sử dụng np.dot () để nhân ma trận không?

Nếu bạn đã từng gặp mã sử dụng np.dot () để nhân hai ma trận, thì đây là cách nó hoạt động.

C = np.dot(A,B)
print(C)

# Output:
[[ 89 107]
 [ 47  49]
 [ 40  44]]

Bạn sẽ thấy rằng np.dot (A, B) cũng trả về ma trận sản phẩm mong đợi.

Tuy nhiên, theo Tài liệu NumPybạn chỉ nên sử dụng np.dot () để tính tích số chấm của hai vectơ một chiều và không dùng cho phép nhân ma trận.

Nhớ lại phần trước, phần tử ở chỉ số (i, j) của ma trận tích C là tích điểm của hàng i của ma trận A và cột j của ma trận B.

Khi NumPy truyền phát ngầm hoạt động sản phẩm chấm này đến tất cả các hàng và tất cả các cột, bạn sẽ có được ma trận sản phẩm kết quả. Nhưng để giữ cho mã của bạn có thể đọc được và tránh sự mơ hồ, hãy sử dụng np.matmul () hoặc toán tử @ để thay thế.

Sự kết luận

🎯 Trong hướng dẫn này, bạn đã học được những điều sau.

  • Điều kiện để phép nhân ma trận có giá trị: số cột trong ma trận A = số hàng trong ma trận B.
  • Cách viết một hàm Python tùy chỉnh để kiểm tra xem phép nhân ma trận có hợp lệ không và trả về ma trận sản phẩm. Phần thân của hàm sử dụng các vòng lặp for lồng nhau.
  • Tiếp theo, bạn đã học cách sử dụng khả năng hiểu danh sách lồng nhau để nhân ma trận. Chúng ngắn gọn hơn vòng lặp for nhưng dễ gặp các vấn đề về khả năng đọc.
  • Cuối cùng, bạn đã học cách sử dụng hàm np.matmul () tích hợp sẵn của NumPy để nhân ma trận và cách này là hiệu quả nhất về tốc độ.
  • Bạn cũng đã học về toán tử @ để nhân hai ma trận trong Python.

Và điều đó kết thúc cuộc thảo luận của chúng tôi về phép nhân ma trận trong Python. Bước tiếp theo, hãy tìm hiểu cách kiểm tra xem một số có phải là số nguyên tố hay không trong Python. Hoặc giải quyết các vấn đề thú vị trên chuỗi Python.

Chúc bạn học vui vẻ! 🎉

x