Một hệ thống phân loại ticket có thể đưa ra con số tổng trông khá ổn dù bỏ sót toàn bộ ticket của nhóm ít xuất hiện. Khi đọc báo cáo F1, tên cách lấy trung bình là một phần của định nghĩa chỉ số. Macro F1 và weighted F1 cùng bắt đầu từ điểm từng lớp, nhưng trao trọng lượng khác nhau cho các lớp ấy.
Bài đối chiếu tài liệu scikit-learn 1.9.1 ngày 09/11/2026. Ví dụ số học chạy bằng Python 3.9.6, chỉ dùng thư viện chuẩn; không chạy scikit-learn, huấn luyện mô hình hay đánh giá dữ liệu khách hàng. Phiên bản Python ghi nhận môi trường thử, không phải khuyến nghị triển khai phiên bản cũ.
Chốt tập nhãn và đơn vị đánh giá
Ví dụ dùng phân loại một nhãn cho mỗi ticket, với ba lớp normal, urgent và billing. Mỗi ticket có đúng một nhãn thật và một nhãn dự đoán. Không dùng cách tính này như một bản triển khai đầy đủ cho bài toán multilabel, nơi một mẫu có thể mang nhiều nhãn cùng lúc.
Với từng lớp, coi lớp đó là dương và mọi lớp còn lại là âm. Tính F1 bằng 2 * TP / (2 * TP + FP + FN). Support là số mẫu thật thuộc lớp, không phải số lần mô hình dự đoán lớp ấy. Các định nghĩa này được mô tả trong f1_score.
Tạo dữ liệu mà lớp phổ biến chiếm tám phần mười
def f1_by_label(truth, predicted, labels):
if not truth or len(truth) != len(predicted):
raise ValueError("Expected non-empty, equally sized inputs")
if not labels or len(set(labels)) != len(labels):
raise ValueError("Expected distinct labels")
allowed = set(labels)
if any(value not in allowed for value in truth + predicted):
raise ValueError("Unknown label")
rows = []
for label in labels:
tp = sum(y == label and p == label for y, p in zip(truth, predicted))
fp = sum(y != label and p == label for y, p in zip(truth, predicted))
fn = sum(y == label and p != label for y, p in zip(truth, predicted))
support = truth.count(label)
denominator = 2 * tp + fp + fn
f1 = 2 * tp / denominator if denominator else 0.0
rows.append((label, support, f1))
return rows
labels = ["normal", "urgent", "billing"]
truth = ["normal"] * 8 + ["urgent", "billing"]
predicted = ["normal"] * 10
rows = f1_by_label(truth, predicted, labels)
for label, support, score in rows:
print(label, support, round(score, 6))
macro = sum(score for _, _, score in rows) / len(rows)
weighted = sum(support * score for _, support, score in rows) / len(truth)
print("macro", round(macro, 6))
print("weighted", round(weighted, 6))
Hàm nhận hai list nhãn và một list labels đã xác định. Kết quả từng lớp là normal với support 8, F1 0.888889; urgent và billing đều có support 1, F1 bằng 0. Macro là 0.296296, weighted là 0.711111. Đây là dữ liệu cố ý dựng để nhìn cách gộp điểm, không phải thành tích của một mô hình thực tế.
Giải thích khoảng cách giữa hai con số
Macro lấy trung bình ba điểm với trọng lượng bằng nhau. Weighted dùng support, nên lớp normal chiếm tám phần mười tổng trọng lượng. Vì thế, weighted trong ví dụ cao hơn đáng kể dù không có dự đoán đúng nào cho hai lớp còn lại.
Điều này không làm weighted trở thành chỉ số sai. Nó trả lời một câu hỏi khác. Nếu mọi lớp cần được nhìn ngang nhau trong báo cáo, macro là một góc xem hữu ích. Nếu bạn muốn trọng lượng phản ánh số mẫu thật, weighted có vai trò riêng. Trong cả hai cách, giữ bảng từng lớp để người đọc thấy nhóm nào đang yếu.
Cố định cách xử lý lớp vắng mặt
Hàm minh họa chọn điểm 0 khi mẫu số F1 bằng 0. Nếu thêm một nhãn không xuất hiện trong cả hai list vào labels, macro sẽ chịu ảnh hưởng của lựa chọn ấy; weighted không cộng trọng lượng cho nhãn có support bằng 0. Tài liệu scikit-learn có tùy chọn zero_division và cách chọn labels, nên cần ghi rõ chúng khi dùng thư viện thật.
Đừng thay tập nhãn giữa hai bản báo cáo mà vẫn giữ nguyên tên cột “macro F1”. Cũng không loại một lớp khó chỉ vì lượt đánh giá hiện tại không có mẫu của lớp đó mà không giải thích. Chốt chính sách trước giúp so sánh các lần chạy có ý nghĩa.
Kiểm tra trước khi dùng vào quyết định sản phẩm
Thử đầu vào dự đoán hoàn toàn đúng, đầu vào có nhãn lạ và hai list lệch chiều dài. Với dữ liệu ở bài, tính tay riêng normal: TP 8, FP 2, FN 0, rồi đối chiếu kết quả hàm. Sau đó đổi một ticket urgent thành dự đoán đúng và xem cả bảng từng lớp lẫn hai điểm tổng.
Ví dụ chưa xử lý trọng số từng mẫu, khoảng tin cậy hoặc chi phí nghiệp vụ. Một lớp urgent có thể quan trọng hơn tần suất xuất hiện của nó; lựa chọn hành động cần dựa thêm vào yêu cầu sản phẩm. Điểm tổng là cửa vào báo cáo, còn bảng từng lớp giúp biết cần kiểm tra điều gì tiếp theo.


