Làm Chủ Ma Trận Numpy: Khởi Tạo, Truy Cập và Các Phép Toán Cơ Bản

Trong thế giới của khoa học dữ liệu và học máy, thư viện NumPy của Python đóng vai trò nền tảng cho việc xử lý các mảng đa chiều, đặc biệt là ma trận. Bài viết này sẽ đi sâu vào cách sử dụng NumPy để làm việc với ma trận, từ khởi tạo, truy cập các phần tử, đến thực hiện các phép toán cơ bản, giúp bạn làm chủ sức mạnh của NumPy trong việc xử lý dữ liệu.

2.0. Mảng Nhiều Chiều với NumPy

NumPy sử dụng mảng NumPy hai chiều để biểu diễn ma trận. Mảng hai chiều này có thể được hình dung như một mảng của các mảng một chiều, mỗi mảng một chiều đại diện cho một hàng của ma trận.

Ma trận minh họaMa trận minh họa

Ví dụ, một mảng NumPy hai chiều a biểu diễn ma trận sau:

[[1, 2],
 [3, 4]]

Trong đó:

  • [1, 2][3, 4] là các mảng một chiều, mỗi mảng đại diện cho một hàng của ma trận.
  • [[1, 2], [3, 4]] là mảng hai chiều chứa hai phần tử, mỗi phần tử là một hàng của ma trận.

Theo quy ước của NumPy, chúng ta duyệt từ mảng ngoài cùng vào trong:

  • Mảng ngoài cùng [[1, 2], [3, 4]] tương ứng với axis = 0. Thành phần thứ nhất là [1, 2], thành phần thứ hai là [3, 4].
  • Các mảng bên trong [1, 2][3, 4] tương ứng với axis = 1.

Lưu ý quan trọng:

  • Mảng NumPy có thể có nhiều hơn hai chiều, và cách truy cập vẫn tuân theo quy tắc duyệt từ ngoài vào trong, với axis tăng dần từ 0.
  • Các mảng con phải có số lượng phần tử bằng nhau, đảm bảo tính nhất quán về số chiều của mỗi hàng trong ma trận.
  • Trong Machine Learning, mỗi điểm dữ liệu thường được biểu diễn dưới dạng một mảng một chiều, và tập hợp các điểm dữ liệu được lưu trữ trong một ma trận, trong đó mỗi hàng tương ứng với một điểm dữ liệu. Điều này ngược với cách biểu diễn toán học, nơi mỗi điểm dữ liệu thường là một vector cột.

2.1. Khởi Tạo Ma Trận NumPy

2.1.1. Khởi tạo trực tiếp

Cách đơn giản nhất để tạo một ma trận là nhập trực tiếp các phần tử. Phương pháp này phù hợp với các ma trận nhỏ.

import numpy as np

A = np.array([[1, 2], [3, 4]])
print(A)

Nếu một trong các phần tử là số thực (float), tất cả các phần tử trong mảng sẽ được chuyển đổi thành kiểu numpy.float64. Ngược lại, nếu tất cả các phần tử là số nguyên, kiểu dữ liệu sẽ là numpy.int64.

Để chỉ định kiểu dữ liệu, sử dụng tham số dtype:

A = np.array([[1, 2], [3, 4]], dtype=np.float32)
print(A.dtype)

Khởi tạo ma trận NumPy với kiểu dữ liệu float32Khởi tạo ma trận NumPy với kiểu dữ liệu float32

2.1.2. Ma trận đơn vị

Để tạo ma trận đơn vị (ma trận vuông với các phần tử trên đường chéo chính bằng 1), sử dụng hàm np.eye():

I = np.eye(3)  # Ma trận đơn vị 3x3
print(I)

Hàm np.eye() cũng có thể tạo ma trận với các phần tử bằng 1 trên đường chéo phụ:

B = np.eye(3, k=1)  # Đường chéo phụ trên đường chéo chính
print(B)

2.1.3. Ma trận đường chéo

Hàm np.diag() được sử dụng để tạo ma trận đường chéo hoặc trích xuất đường chéo của ma trận:

  • Nếu đầu vào là một mảng một chiều, hàm trả về ma trận đường chéo với các phần tử của mảng trên đường chéo chính.
  • Nếu đầu vào là một mảng hai chiều, hàm trả về mảng một chiều chứa các phần tử trên đường chéo chính.
v = np.array([1, 2, 3])
D = np.diag(v)
print(D)
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
diag_A = np.diag(A)
print(diag_A)

Ma trận đường chéo được tạo từ mảng một chiềuMa trận đường chéo được tạo từ mảng một chiều

2.2. Kích Thước Ma Trận

Để xác định kích thước của mảng hai chiều (ma trận), sử dụng thuộc tính shape:

A = np.array([[1, 2, 3], [4, 5, 6]])
print(A.shape)  # Kết quả: (2, 3) - 2 hàng, 3 cột

Số hàng và số cột của ma trận có thể được tính bằng:

num_rows = A.shape[0]
num_cols = A.shape[1]
print(f"Số hàng: {num_rows}, số cột: {num_cols}")

2.3. Truy Cập Phần Tử Ma Trận

2.3.1. Truy cập phần tử đơn lẻ

Có hai cách để truy cập một phần tử cụ thể trong mảng hai chiều:

  • Cách 1: Sử dụng cú pháp giống list

    Để truy cập phần tử ở hàng i, cột j (chỉ số bắt đầu từ 0), sử dụng A[i][j]:

    A = np.array([[1, 2, 3], [4, 5, 6]])
    element = A[1][2]  # Truy cập phần tử ở hàng 1, cột 2 (giá trị 6)
    print(element)
  • Cách 2: Sử dụng cú pháp giống Matlab

    Sử dụng A[i, j] (chỉ số bắt đầu từ 0):

    A = np.array([[1, 2, 3], [4, 5, 6]])
    element = A[1, 2]  # Truy cập phần tử ở hàng 1, cột 2 (giá trị 6)
    print(element)

2.3.2. Truy cập hàng và cột

  • Để truy cập hàng i của ma trận A, sử dụng A[i] hoặc A[i, :]:

    A = np.array([[1, 2, 3], [4, 5, 6]])
    row = A[0]  # Truy cập hàng 0
    print(row)
  • Để truy cập cột j của ma trận A, sử dụng A[:, j]:

    A = np.array([[1, 2, 3], [4, 5, 6]])
    col = A[:, 1]  # Truy cập cột 1
    print(col)

Lưu ý:

Trong NumPy, kết quả trả về của một cột hoặc hàng là một mảng một chiều, không phải vector cột như trong Matlab.

Truy cập các phần tử của ma trận NumPyTruy cập các phần tử của ma trận NumPy

2.4. Các Phép Toán Cơ Bản trên Ma Trận

NumPy cung cấp các hàm để thực hiện các phép toán cơ bản trên ma trận một cách hiệu quả.

2.4.1. Tổng, Min, Max, Mean

Các hàm np.sum(), np.min(), np.max(), np.mean() có thể được sử dụng để tính tổng, giá trị nhỏ nhất, giá trị lớn nhất và giá trị trung bình của các phần tử trong ma trận:

A = np.array([[1, 2, 3], [4, 5, 6]])
total = np.sum(A)  # Tính tổng tất cả các phần tử
minimum = np.min(A)  # Tìm giá trị nhỏ nhất
maximum = np.max(A)  # Tìm giá trị lớn nhất
mean = np.mean(A)  # Tính giá trị trung bình

print(f"Tổng: {total}, Min: {minimum}, Max: {maximum}, Mean: {mean}")

Các hàm này cũng có thể được sử dụng để tính toán theo hàng hoặc cột bằng cách chỉ định tham số axis:

sum_cols = np.sum(A, axis=0)  # Tính tổng theo cột
sum_rows = np.sum(A, axis=1)  # Tính tổng theo hàng

print(f"Tổng theo cột: {sum_cols}, Tổng theo hàng: {sum_rows}")

2.4.2. Phép Toán Tác Động Lên Mọi Phần Tử

Các phép toán số học (+, -, *, /) có thể được áp dụng trực tiếp lên ma trận, và chúng sẽ được thực hiện trên từng phần tử:

A = np.array([[1, 2], [3, 4]])
B = A * 2  # Nhân mỗi phần tử của A với 2
print(B)

2.4.3. Chuyển Vị và Thay Đổi Kích Thước Ma Trận

  • Chuyển vị ma trận: Sử dụng thuộc tính .T hoặc hàm np.transpose():

    A = np.array([[1, 2], [3, 4]])
    A_T = A.T
    print(A_T)
  • Thay đổi kích thước ma trận: Sử dụng hàm np.reshape():

    A = np.array([[1, 2, 3], [4, 5, 6]])
    B = np.reshape(A, (3, 2))  # Thay đổi thành ma trận 3x2
    print(B)

2.4.4. Tích Ma Trận và Tích Vector

  • Tích ma trận: Sử dụng toán tử @ hoặc hàm np.matmul():

    A = np.array([[1, 2], [3, 4]])
    B = np.array([[5, 6], [7, 8]])
    C = A @ B  # Hoặc C = np.matmul(A, B)
    print(C)
  • Tích giữa ma trận và vector:

    A = np.array([[1, 2], [3, 4]])
    v = np.array([1, 2])
    b = A @ v
    print(b)

Kết luận

Bài viết này đã cung cấp một cái nhìn tổng quan về cách làm việc với ma trận trong NumPy, từ khởi tạo, truy cập các phần tử, đến thực hiện các phép toán cơ bản. Nắm vững những kiến thức này sẽ giúp bạn xây dựng nền tảng vững chắc để khám phá sâu hơn các ứng dụng của NumPy trong khoa học dữ liệu và học máy. Hãy tiếp tục luyện tập và khám phá để làm chủ sức mạnh của NumPy!