Chuyển đến nội dung chính

Micro-F1 và Macro-F1 trong Multi-label Classification

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.

Tóm tắt nội dung
  • 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:

“Tôi rất vui vì cuối cùng cũng hoàn thành được việc này, nhưng vẫn hơi lo về kết quả.”

có thể được gán đồng thời hai nhãn:

{joy, fear}

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:

Precision = TP / (TP + FP)
Recall = TP / (TP + FN)

F1-score là trung bình điều hòa của precision và recall [1], [3]:

F1 = 2 × Precision × Recall / (Precision + Recall)

Có thể viết trực tiếp theo TP, FP và FN:

F1 = 2TP / (2TP + FP + 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?

So sánh cách tính Micro-F1 và Macro-F1 Micro-F1 Joy TP FP FN Anger TP FP FN Sadness TP FP FN Cộng TP, FP, FN của mọi label Micro-F1 Macro-F1 Joy F1 = ... Anger F1 = ... Sadness F1 = ... Trung bình F1 của các label Macro-F1
Micro-F1 gộp các quyết định trước khi tính F1; Macro-F1 tính F1 từng label trước rồi mới lấy trung bình.

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].

TPmicro = Σ TPk
FPmicro = Σ FPk
FNmicro = Σ FNk
Micro-F1 = 2TPmicro / (2TPmicro + FPmicro + FNmicro)

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ó:

TP = 40 + 15 + 2 = 57
FP = 5 + 10 + 3 = 18
FN = 10 + 5 + 8 = 23
Micro-F1 = 2 × 57 / (2 × 57 + 18 + 23) ≈ 0,7355

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].

Macro-F1 = (1 / K) × Σ F1k

Với số liệu ở ví dụ trên:

F1joy = 80 / (80 + 5 + 10) ≈ 0,8421
F1anger = 30 / (30 + 10 + 5) ≈ 0,6667
F1sadness = 4 / (4 + 3 + 8) ≈ 0,2667
Macro-F1 ≈ (0,8421 + 0,6667 + 0,2667) / 3 ≈ 0,5918

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ụ:

multilabel_f1.py
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:

p = [0,82; 0,31; 0,57]

Nếu threshold bằng 0,5, vector trên trở thành:

ŷ = [1, 0, 1]

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.

tune_threshold.py
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:

Ví dụ báo cáo
Micro-F1: 0,84
Macro-F1: 0,67
Joy F1: 0,91
Anger F1: 0,78
Sadness F1: 0,53
Grief F1: 0,46

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.

© The CS Note · THE CS NOTE

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

Về trang chủ Về đầu bài

Bài Đăng Phổ Biến

Bài toán tháp Hà nội

Trải nghiệm Tháp Hà Nội Kéo thả đĩa hoặc chạm vào các nút bên dưới để di chuyển. Bạn phải chuyển toàn bộ đĩa sang cột ngoài cùng bên phải (Cột 3) mà không đặt đĩa to lên đĩa nhỏ. Cột 1 Cột 2 Cột 3 Điều khiển & Chế độ Số lượng đĩa 4 Tốc độ máy giải ↪ Undo ↻ Chơi lại 🤖 Máy tự giải Thống kê ván chơi Nước đã đi 0 Thời gian 00:00 Tối thiểu cần 15 Kỷ lục của bạn - Lịch sử và Nguồn gốc Truyền thuyết Bài toán Tháp Hà Nội (hay Tháp Brahma) là một trò chơi xếp hình toán học kinh điển được giới thiệu lần đầu vào năm 1883 bởi nhà toán học người Pháp Édouard L...

Bài toán phân tích cảm xúc trong văn bản

Bài toán phân tích cảm xúc (sentiment analysis) là một bài toán NLP nhằm xác định thái độ hoặc cảm xúc được thể hiện trong văn bản. Ví dụ, từ một đánh giá như “Điện thoại đẹp, chạy nhanh nhưng pin hơi yếu”, hệ thống có thể nhận biết rằng người dùng có cả nhận xét tích cực và tiêu cực. Điểm thú vị của bài toán nằm ở khoảng cách giữa cách con người hiểu ngôn ngữ và cách máy tính xử lý dữ liệu. Một hệ thống phân tích cảm xúc cần biến văn bản tự nhiên thành dữ liệu có cấu trúc, học được các mẫu ngôn ngữ từ dữ liệu huấn luyện và đưa ra dự đoán hợp lý trên những câu chưa từng gặp. 1. Bài toán phân tích cảm xúc bắt đầu từ đâu? Hãy tưởng tượng một cửa hàng trực tuyến có hàng nghìn đánh giá mỗi ngày. Con người có thể đọc từng đánh giá để biết khách hàng hài lòng hay không, nhưng việc này nhanh chóng trở nên tốn thời gian khi dữ liệu tăng lên. NLP có thể biến bài toán đó thành một bài toán phân loại. Với mỗi văn bản, hệ thống nhận vào một chuỗi ký...

KAN cho phân đoạn khối u não với bộ BraTS 2020

Kolmogorov-Arnold Network (KAN) mở ra một hướng khác với MLP truyền thống: thay vì chỉ học các trọng số vô hướng trên mỗi kết nối, KAN có thể học những hàm phi tuyến một biến trên các cạnh . Khi đưa ý tưởng này vào kiến trúc encoder-decoder như U-Net, ta có thể sử dụng convolution để giữ cấu trúc không gian của ảnh MRI và dùng KAN để thực hiện các phép biến đổi phi tuyến mạnh hơn trên representation trung gian. Một bài toán phù hợp để nghiên cứu hướng này là phân đoạn u thần kinh đệm trên BraTS 2020 . Dataset cung cấp MRI đa mô thức và yêu cầu xác định các vùng Whole Tumor (WT), Tumor Core (TC) và Enhancing Tumor (ET). Đây là bài toán 3D có sự mất cân bằng voxel lớn, hình dạng khối u rất đa dạng và ranh giới giữa các mô bệnh lý không đơn giản. Lưu ý học thuật quan trọng: U-KAN gốc được công bố cho nhiều benchmark phân đoạn ảnh y tế nhưng không báo cáo kết quả BraTS 2020. Một công trình sau đó đã mở rộng U-KAN sang 3D MRI brain tumor segmentation , nhưng đánh giá trên BraTS 2...

Tách từ trong tiếng Việt Word Segmentation

Tách từ tiếng Việt là bài toán xác định ranh giới giữa các từ trong một chuỗi văn bản. Khó khăn nằm ở chỗ khoảng trắng trong tiếng Việt thường phân cách các âm tiết , nhưng một từ hoàn chỉnh có thể gồm nhiều âm tiết như “sinh viên” , “đại học” , “công nghệ” hay “tự nhiên” . Tách từ đúng giúp các hệ thống NLP dựa trên từ biểu diễn văn bản hợp lý hơn, đặc biệt trong tìm kiếm, TF-IDF, phân loại văn bản, gán nhãn từ loại và một số mô hình ngôn ngữ tiếng Việt. Tuy nhiên, với các Transformer sử dụng tokenizer dưới mức từ như subword hoặc SentencePiece, tách từ thủ công không phải lúc nào cũng là bước bắt buộc . Việc có cần tách từ trước hay không phụ thuộc vào mô hình và pipeline cụ thể. Tóm tắt nội dung Khoảng trắng trong tiếng Việt không phải lúc nào cũng là ranh giới từ ; nhiều từ gồm hai hoặc nhiều âm tiết. Word segmentation và tokenization có liên quan nhưng không hoàn toàn đồng nghĩa. Ba hướng chính gồm dựa trên từ điển, mô hình thống kê và mô hình học sâu . Tron...

KAN là gì? Mạng Kolmogorov-Arnold khác MLP thế nào?

Kolmogorov-Arnold Network (KAN) là một kiến trúc mạng nơ-ron trong đó mỗi cạnh không chỉ chứa một trọng số vô hướng mà mang một hàm một biến có thể học được . Đây là khác biệt cốt lõi so với Multi-Layer Perceptron (MLP), nơi các cạnh chủ yếu thực hiện phép nhân với trọng số còn hàm kích hoạt thường được áp dụng tại các node. KAN được lấy cảm hứng từ định lý biểu diễn Kolmogorov-Arnold và đặc biệt đáng chú ý trong các bài toán xấp xỉ hàm, mô hình hóa khoa học và symbolic regression. Tuy nhiên, KAN không nên được hiểu là kiến trúc đã thay thế MLP trong mọi bài toán Deep Learning; khả năng biểu diễn, chi phí tính toán và mức độ phù hợp của hai kiến trúc khác nhau theo từng nhiệm vụ. Tóm tắt nội dung MLP học chủ yếu trọng số trên các cạnh , còn KAN đặt hàm một biến học được trên từng cạnh . Một KAN layer cộng kết quả của nhiều hàm cạnh để tạo activation của node tiếp theo. KAN gốc sử dụng B-spline để tham số hóa các hàm phi tuyến trên cạnh. KAN có lợi thế đáng chú ý về trực...