Cách khắc phục lỗi 'ValueError: operands could not be broadcast together' trong NumPy

intermediate🐍 Python2026-06-28| Python 3.x, NumPy (any version), Windows/macOS/Linux

Error Message

ValueError: operands could not be broadcast together with shapes (3,) (4,)
#python#numpy#broadcasting#data-science#debugging

Vấn đề

Có lẽ bạn đã cố gắng thực hiện một phép toán số học—như phép cộng hoặc phép nhân—giữa hai mảng NumPy không khớp với nhau. NumPy sử dụng một quy trình gọi là "broadcasting" để kéo giãn các mảng qua các chiều khác nhau. Tuy nhiên, quy trình này tuân theo một logic nghiêm ngặt. Khi các chiều của mảng xung đột, Python sẽ ném ra lỗi này:

ValueError: operands could not be broadcast together with shapes (3,) (4,)

Trong trường hợp này, bạn có một mảng với 3 phần tử và một mảng khác có 4 phần tử. Vì không có kích thước nào bằng 1 và tổng số phần tử không khớp nhau, NumPy không biết cách sắp xếp các phép toán. Về cơ bản, nó sẽ dừng thực hiện.

Nguyên nhân gốc rễ: Quy tắc chiều cuối cùng (Trailing Dimension Rule)

Hãy coi NumPy như một kế toán viên nghiêm ngặt. Nó so sánh hình dạng các mảng từ phải sang trái (các chiều cuối cùng). Hai chiều được coi là tương thích chỉ khi:

  • Các con số hoàn toàn bằng nhau.
  • Một trong các con số là 1.

Với các hình dạng (3,)(4,), NumPy nhìn vào 3 và 4. Chúng không bằng nhau và cũng không có số nào là 1. Phép toán thất bại ngay lập tức vì không có cách nào rõ ràng để ánh xạ 3 giá trị vào 4 vị trí.

Cách khắc phục 1: Thay đổi hình dạng (Reshaping) để tạo ma trận

Nếu bạn muốn tạo một lưới kết quả (giống như tích ngoài - outer product), bạn cần chuyển một trong các mảng 1D thành một cột 2D. Điều này tạo ra một chiều có kích thước là 1, đáp ứng được các quy tắc. Ví dụ, nhân một mảng (3, 1) với một mảng (4,) sẽ tạo ra một ma trận (3, 4).

import numpy as np

a = np.array([10, 20, 30])      # Hình dạng (3,)
b = np.array([1, 2, 3, 4])      # Hình dạng (4,)

# Sửa: Thay đổi hình dạng 'a' thành (3, 1).
# Bây giờ (3, 1) và (4,) đã tương thích.
result = a[:, np.newaxis] + b

print(result)
print(f"Hình dạng mới: {result.shape}") # Đầu ra: (3, 4)

Cách khắc phục 2: Cắt mảng (Slicing) để khớp độ dài

Đôi khi các mảng của bạn có độ dài khác nhau do việc thu thập dữ liệu không đồng nhất. Nếu cảm biến A ghi lại 3 kết quả nhưng cảm biến B ghi lại 4, bạn có thể chỉ muốn so sánh phần dữ liệu trùng lặp. Cắt mảng (Slicing) là cách nhanh nhất để ép chúng khớp nhau.

import numpy as np

a = np.array([1, 2, 3])
b = np.array([10, 20, 30, 40])

# Tìm độ dài ngắn nhất và cắt mảng dài hơn
min_len = min(len(a), len(b))
result = a[:min_len] + b[:min_len]

print(result) # Đầu ra: [11, 22, 33]

Cách khắc phục 3: Chuyển vị (Transposing) mảng 2D

Khi làm việc với ma trận, lỗi này thường có nghĩa là hàng và cột của bạn bị đảo ngược. Một ma trận (3, 4) không thể cộng trực tiếp với một ma trận (4, 3). Bạn phải chuyển vị một trong hai để làm cho các chiều khớp nhau.

matrix_a = np.ones((3, 4))
matrix_b = np.ones((4, 3))

# Sửa: Sử dụng .T để chuyển vị ma trận thứ hai
result = matrix_a + matrix_b.T
print(result.shape) # Đầu ra: (3, 4)

Cách gỡ lỗi khi không khớp hình dạng

Để không còn phải đoán mò, hãy kiểm tra thuộc tính .shape của các mảng ngay trước khi thực hiện phép toán. Tôi thường thêm một dòng in nhanh vào mã để xem chính xác NumPy đang thấy gì:

print(f"Mảng A: {arr_a.shape}, Mảng B: {arr_b.shape}")

Nếu các con số ngoài cùng bên phải không khớp và không có số nào là 1, bạn đã tìm ra nguyên nhân gây lỗi.

Mẹo chuyên gia: Kiểm tra nguồn dữ liệu của bạn

Hình dạng không khớp thường chỉ ra một vấn đề sâu xa hơn, chẳng hạn như tệp CSV bị hỏng hoặc lỗi khi tải xuống từ API. Nếu hình dạng mảng thay đổi mỗi khi bạn chạy tập lệnh, hãy xác minh tính toàn vẹn của tệp dữ liệu.

Bạn có thể sử dụng Hash Generator để kiểm tra mã băm MD5 hoặc SHA-256 của các bộ dữ liệu. Nếu mã băm của tệp thay đổi bất thường, quá trình tải dữ liệu của bạn có thể đang bỏ qua các hàng hoặc làm cắt cụt tệp, dẫn đến những lỗi NumPy khó chịu đó.

Danh sách kiểm tra phòng ngừa

  • Sử dụng np.newaxis: Sử dụng nó để thêm các chiều một cách rõ ràng khi làm việc với các vectơ có kích thước khác nhau.
  • Kiểm tra hình dạng (Assert Shapes): Thêm assert array.shape == (expected_rows, expected_cols) để phát hiện lỗi sớm.
  • Xác thực đầu vào: Kiểm tra số lượng bản ghi trong dữ liệu thô trước khi chuyển đổi chúng thành các đối tượng NumPy.
  • Hình dạng động: Sử dụng array.shape[0] thay vì viết cứng các con số như 3 hoặc 4 trong các vòng lặp của bạn.

Related Error Notes