Micro-F1 và Macro-F1 là hai cách tổng hợp F1-score thường gặp khi đánh giá bài toán nhiều lớp và đặc biệt quan trọng trong multi-label classification. Hai mô hình có thể có Micro-F1 gần giống nhau nhưng khả năng xử lý các nhãn hiếm lại rất khác, vì cách Micro-F1 và Macro-F1 cộng gộp lỗi không giống nhau [1].
Bài viết này giải thích sự khác biệt bằng một ví dụ nhận diện đa cảm xúc, trong đó một câu có thể đồng thời mang các nhãn như joy, anger hoặc sadness. Đây cũng là tình huống thực tế giúp thấy rõ vì sao chỉ nhìn accuracy hoặc một F1-score duy nhất có thể dẫn đến kết luận sai về chất lượng mô hình.
- Micro-F1 cộng toàn bộ TP, FP và FN của các nhãn rồi mới tính F1.
- Macro-F1 tính F1 riêng cho từng nhãn rồi lấy trung bình không trọng số.
- Micro-F1 thường chịu ảnh hưởng lớn hơn từ các nhãn xuất hiện nhiều, trong khi Macro-F1 làm lộ rõ hiệu năng kém ở nhãn hiếm.
- Trong multi-label classification, nên xem đồng thời Micro-F1, Macro-F1 và F1 từng nhãn thay vì chọn một metric duy nhất.
Trước hết, multi-label classification khác multi-class ở đâu?
Multi-class classification yêu cầu mỗi mẫu thuộc đúng một lớp. Ví dụ, một ảnh có thể được phân thành cat, dog hoặc bird. Nếu chọn cat thì mẫu đó không đồng thời thuộc dog.
Trong multi-label classification, một mẫu có thể mang nhiều nhãn cùng lúc [2]. Ví dụ, một câu:
có thể được gán đồng thời hai nhãn:
Nếu có ba emotion cần nhận diện là joy, anger và sadness, nhãn của mỗi mẫu có thể được biểu diễn thành vector nhị phân:
| Văn bản | Joy | Anger | Sadness |
|---|---|---|---|
| “Tôi rất vui nhưng cũng khá buồn vì phải rời đi.” | 1 | 0 | 1 |
| “Tôi thực sự tức giận.” | 0 | 1 | 0 |
Như vậy, với ba emotion, một mẫu thực chất tạo ra ba quyết định nhị phân. Khi dataset có 20 nhãn và 10.000 mẫu, ta đang đánh giá rất nhiều quyết định label–sample cùng lúc. Đây chính là lý do cần xác định cách tổng hợp precision, recall và F1.
Nếu bạn đang tìm hiểu từ đầu về multi-label classification, có thể xem thêm các nội dung liên quan trên The CS Note với từ khóa multi-label.
F1-score được tính từ đâu?
Trước khi phân biệt Micro-F1 và Macro-F1, cần quay lại F1-score của một nhãn. Với một emotion cụ thể, chẳng hạn joy, ta có bốn trường hợp:
- TP — True Positive: mẫu thật sự có joy và mô hình cũng dự đoán joy.
- FP — False Positive: mẫu không có joy nhưng mô hình dự đoán có.
- FN — False Negative: mẫu có joy nhưng mô hình bỏ sót.
- TN — True Negative: mẫu không có joy và mô hình cũng không dự đoán joy.
Precision và recall được tính như sau:
F1-score là trung bình điều hòa của precision và recall [1], [3]:
Có thể viết trực tiếp theo TP, FP và FN:
Ở bài toán nhị phân, mọi thứ khá đơn giản vì chỉ có một lớp dương cần quan tâm. Khi xuất hiện nhiều label, câu hỏi mới phát sinh: chúng ta nên cộng kết quả của các label như thế nào?
Micro-F1 được tính như thế nào?
Micro-F1 bỏ qua ranh giới giữa các label trong bước cộng số lượng lỗi. Đầu tiên, ta cộng TP của tất cả label, làm tương tự với FP và FN. Sau đó mới tính một F1-score duy nhất [1].
Giả sử mô hình nhận diện ba emotion có kết quả:
| Emotion | TP | FP | FN |
|---|---|---|---|
| Joy | 40 | 5 | 10 |
| Anger | 15 | 10 | 5 |
| Sadness | 2 | 3 | 8 |
Ta có:
Micro-F1 của mô hình xấp xỉ 0,736. Điều đáng chú ý là joy đóng góp 40 TP trong tổng số 57 TP, trong khi sadness chỉ đóng góp 2. Vì vậy, hiệu năng tốt ở một label phổ biến có thể ảnh hưởng mạnh đến Micro-F1 tổng thể.
Nói chính xác hơn, Micro-F1 không trực tiếp gán “trọng số theo tần suất” cho từng label. Nó cộng các quyết định label–sample lại với nhau, nên label xuất hiện nhiều thường tạo ra nhiều TP, FP và FN hơn và vì vậy tác động lớn hơn đến kết quả cuối.
Macro-F1 cho thấy điều mà Micro-F1 có thể che khuất
Macro-F1 thực hiện phép tính theo thứ tự ngược lại. Trước tiên, F1-score được tính riêng cho từng label. Sau đó lấy trung bình số học, trong đó mỗi label có trọng số bằng nhau [1].
Với số liệu ở ví dụ trên:
Micro-F1 của mô hình là khoảng 0,736 nhưng Macro-F1 chỉ khoảng 0,592. Khoảng cách này cung cấp một tín hiệu hữu ích: mô hình đang có hiệu năng không đồng đều giữa các label.
Sadness chỉ có F1 khoảng 0,267 nhưng vẫn đóng góp đúng một phần ba vào Macro-F1. Do đó, Macro-F1 đặc biệt hữu ích khi các lớp hiếm vẫn quan trọng về mặt ứng dụng.
Ví dụ trong hệ thống phân tích phản hồi khách hàng, complaint nghiêm trọng có thể hiếm hơn các phản hồi thông thường. Một Micro-F1 tốt không đủ để khẳng định hệ thống nhận diện complaint hiếm tốt. Khi đó, Macro-F1 và F1 riêng của từng label cần được kiểm tra song song.
| Đặc điểm | Micro-F1 | Macro-F1 |
|---|---|---|
| Cách tính | Gộp TP, FP, FN rồi tính F1 | Tính F1 từng label rồi lấy trung bình |
| Label phổ biến | Thường tác động lớn hơn | Có trọng số bằng label hiếm |
| Label hiếm | Có thể bị che khuất | Ảnh hưởng trực tiếp đến trung bình |
| Câu hỏi chính | Mô hình xử lý toàn bộ quyết định tốt đến đâu? | Mô hình có hoạt động tương đối tốt trên mọi label không? |
Tính Micro-F1 và Macro-F1 bằng scikit-learn
Trong scikit-learn, dữ liệu multi-label thường được biểu diễn dưới dạng ma trận indicator. Mỗi hàng là một mẫu và mỗi cột là một label. Giá trị 1 nghĩa là label xuất hiện trong mẫu đó [1].
Ví dụ:
import numpy as np
from sklearn.metrics import f1_score
# Các cột lần lượt là: joy, anger, sadness
y_true = np.array([
[1, 0, 1],
[0, 1, 0],
[1, 0, 0],
[0, 1, 1]
])
y_pred = np.array([
[1, 0, 0],
[0, 1, 0],
[1, 1, 0],
[0, 1, 0]
])
micro_f1 = f1_score(
y_true,
y_pred,
average="micro"
)
macro_f1 = f1_score(
y_true,
y_pred,
average="macro"
)
per_label_f1 = f1_score(
y_true,
y_pred,
average=None
)
print("Micro-F1:", micro_f1)
print("Macro-F1:", macro_f1)
print("F1 từng label:", per_label_f1)
Trong API của scikit-learn, average="micro" cộng tổng true positive, false positive và false negative trước khi tính metric. average="macro" tính metric cho từng label rồi lấy trung bình không trọng số [1].
Ngoài hai lựa chọn này còn có:
average="weighted": trung bình F1 từng label nhưng có trọng số theo support.average="samples": tính metric trên từng mẫu rồi lấy trung bình; lựa chọn này đặc biệt có ý nghĩa với multi-label.average=None: trả F1 riêng cho từng label.
Trong báo cáo thực nghiệm, một cách trình bày dễ đọc là báo cáo Micro-F1, Macro-F1 và bảng F1 của từng label. Weighted-F1 có thể bổ sung nhưng không nên thay thế hoàn toàn Macro-F1 nếu khả năng nhận diện các label hiếm là mục tiêu quan trọng.
Threshold có thể làm Micro-F1 và Macro-F1 thay đổi mạnh
Trong nhiều neural network multi-label, lớp cuối sử dụng sigmoid. Mô hình không trực tiếp sinh 0 hoặc 1 mà tạo một score cho từng label:
Nếu threshold bằng 0,5, vector trên trở thành:
Nhưng 0,5 chỉ là một ngưỡng khởi đầu thuận tiện, không phải một hằng số tối ưu cho mọi dataset. Khi giảm threshold, recall thường có xu hướng tăng vì mô hình dự đoán nhiều label hơn, nhưng số false positive cũng có thể tăng. Khi tăng threshold, điều ngược lại có thể xảy ra.
Vì F1 phụ thuộc vào cả FP và FN, lựa chọn threshold có thể thay đổi đáng kể cả Micro-F1 lẫn Macro-F1.
import numpy as np
from sklearn.metrics import f1_score
best_threshold = None
best_score = -1.0
for threshold in np.arange(
0.10,
0.91,
0.05
):
y_pred = (
y_dev_prob >= threshold
).astype("int32")
score = f1_score(
y_dev,
y_pred,
average="macro",
zero_division=0
)
if score > best_score:
best_score = score
best_threshold = threshold
print("Best threshold:", best_threshold)
print("Dev Macro-F1:", best_score)
Điểm quan trọng là threshold phải được lựa chọn trên validation set, không phải test set. Nếu thử nhiều threshold rồi chọn giá trị tốt nhất dựa trên test, tập test đã tham gia vào quá trình tối ưu và kết quả cuối không còn phản ánh một đánh giá độc lập.
Ngoài một threshold chung, có thể chọn threshold riêng cho từng label. Phương án này có thể hữu ích khi tần suất và độ khó giữa các label khác nhau nhiều, nhưng cũng làm số tham số cần tune tăng lên và tăng nguy cơ overfit validation set.
Nên chọn Micro-F1 hay Macro-F1?
Không có một câu trả lời đúng cho mọi bài toán. Metric cần phản ánh điều mà hệ thống thực sự cần tối ưu.
Micro-F1 phù hợp khi bạn quan tâm đến chất lượng tổng thể của toàn bộ quyết định label–sample và muốn các quyết định xuất hiện nhiều đóng góp tương ứng vào metric. Ví dụ, một hệ thống tự động gán hàng triệu tag có thể quan tâm nhiều đến số lượng quyết định đúng trên toàn bộ traffic.
Macro-F1 phù hợp khi mọi label đều quan trọng dù tần suất khác nhau. Trong nhận diện đa cảm xúc, nếu grief hoặc fear hiếm nhưng vẫn cần được nhận diện tốt, Macro-F1 giúp tránh trường hợp mô hình đạt điểm đẹp chủ yếu nhờ các emotion phổ biến.
Trong nhiều bài toán, cách an toàn hơn là không chọn một trong hai mà báo cáo cả hai:
Chỉ nhìn Micro-F1 = 0,84 có thể tạo cảm giác mô hình đã khá tốt. Nhưng bảng per-label cho thấy một số emotion vẫn còn rất yếu. Macro-F1 = 0,67 phản ánh vấn đề này rõ hơn.
Một lỗi khác là gọi Macro-F1 là “F1 tính từ macro-precision và macro-recall”. Đây không nhất thiết là cùng một phép tính. Cách dùng phổ biến trong thư viện như scikit-learn là tính F1 riêng cho từng label rồi lấy trung bình các F1 đó [1].
Accuracy cũng cần được hiểu cẩn thận. Với multi-label, một định nghĩa thường gặp là subset accuracy: dự đoán chỉ được xem là đúng nếu toàn bộ tập nhãn của mẫu khớp chính xác. Một mẫu thật có {joy, surprise} nhưng dự đoán {joy} sẽ bị tính sai hoàn toàn, dù mô hình nhận đúng một trong hai emotion. Vì vậy accuracy không thể thay thế các metric như Micro-F1 và Macro-F1 trong nhiều tình huống multi-label.
Nếu bạn đang xây dựng chuỗi bài về nhận diện đa cảm xúc, có thể tiếp tục tra cứu các nội dung liên quan tại The CS Note với từ khóa emotion recognition. Việc kết nối phần xây mô hình với phần đánh giá giúp tránh tình trạng tập trung quá nhiều vào kiến trúc nhưng lại chọn metric không phù hợp.
Kết luận
Micro-F1 và Macro-F1 không phải hai cách viết khác nhau của cùng một con số. Micro-F1 gộp TP, FP và FN trên toàn bộ label trước khi tính F1, trong khi Macro-F1 cho mỗi label một F1 riêng rồi lấy trung bình bằng nhau.
Nếu Micro-F1 cao nhưng Macro-F1 thấp, hãy kiểm tra ngay F1 của từng label: mô hình có thể đang hoạt động tốt ở các nhãn phổ biến nhưng bỏ sót những nhãn hiếm. Trong multi-label classification, đặc biệt với bài toán nhận diện đa cảm xúc, báo cáo Micro-F1, Macro-F1 và per-label F1 cùng nhau thường cung cấp bức tranh đáng tin cậy hơn một metric duy nhất.
References
[1] Scikit-learn Developers, “Metrics and scoring: quantifying the quality of predictions,” scikit-learn User Guide. https://scikit-learn.org/stable/modules/model_evaluation.html.
[2] G. Tsoumakas and I. Katakis, “Multi-Label Classification: An Overview,” International Journal of Data Warehousing and Mining, vol. 3, no. 3, pp. 1–13, 2007. DOI: 10.4018/jdwm.2007070101.
[3] M. Sokolova and G. Lapalme, “A systematic analysis of performance measures for classification tasks,” Information Processing & Management, vol. 45, no. 4, pp. 427–437, 2009. DOI: 10.1016/j.ipm.2009.03.002.
Nội dung gốc thuộc tác giả. Vui lòng không đăng lại toàn văn khi chưa được phép, trừ trường hợp pháp luật hoặc giấy phép áp dụng cho phép. Nội dung của bên thứ ba tuân theo quyền và giấy phép tương ứng.
Nguồn gốc: Micro-F1 và Macro-F1 trong Multi-label Classification