← All writing
Evaluation · 5 min read · 3 Aug 2026

Macro, Micro, and Weighted Averages Explained Properly

A single accuracy number can hide a classifier that fails on every rare class. Here is how the three main averaging schemes actually work, with worked numbers.

Cover image for the article: Macro, Micro, and Weighted Averages Explained Properly

Why one accuracy number is not enough

When I first started evaluating multi-class text classifiers, I leaned on accuracy because it was easy to explain to anyone in the room. The trouble is that accuracy treats every prediction as equally informative, and in most real NLP tasks, whether that is sentiment with a neutral majority class or intent detection with a long tail of rare intents, the classes are not equally sized. A model can score a respectable accuracy by nailing the dominant class and quietly failing on everything else, and accuracy alone will not tell you that.

This is exactly the situation macro, micro, and weighted averages were designed to disentangle. They are not competing metrics so much as three different questions you can ask of the same confusion matrix. Macro asks: how well does the model do on each class, treated as equally important? Micro asks: across every single prediction, regardless of class, what fraction is correct? Weighted asks: how well does the model do on each class, but scaled by how often that class actually appears? Choosing the wrong one for your problem, or worse, reporting one without saying which, is a common source of misleading results in papers and portfolios alike.

I care about this because I have seen leaderboard-style comparisons where a model looks state of the art under one averaging scheme and mediocre under another, with no code change at all, just a different summary statistic. If you cannot explain which average you used and why, you cannot really defend your evaluation.

A worked example with three classes

Suppose I am building a text classifier for support tickets with three labels: billing, technical, and account. My test set has 100 billing tickets, 80 technical tickets, and 20 account tickets, so it is already imbalanced before the model does anything. After running inference, I compute per-class precision and recall from the confusion matrix: billing gets precision 0.90 and recall 0.95, technical gets precision 0.80 and recall 0.70, and account, the rare class, gets precision 0.50 and recall 0.30.

From these I derive per-class F1 scores: billing is roughly 0.92, technical is roughly 0.75, and account is roughly 0.375. The macro F1 is simply the unweighted mean of these three: (0.92 plus 0.75 plus 0.375) divided by 3, which comes out to about 0.68. Notice that account, despite having only 20 examples, pulls just as hard on this average as billing with 100 examples. Macro is punishing the model for its weak performance on the small class exactly as much as if that class were the largest one in the dataset.

The weighted F1 instead multiplies each class's F1 by its share of the test set, so it becomes (0.92 times 100 plus 0.75 times 80 plus 0.375 times 20) divided by 200 examples in total, which works out to roughly 0.82. That is noticeably higher than the macro score, because the model's weakest performance sits on the class that barely features in the data, so weighted F1 largely absorbs that weakness.

Micro F1 works differently again: it pools every true positive, false positive, and false negative across all classes into one big precision and recall calculation, then computes F1 from those totals. In a multi-class single-label setup like this, micro precision, micro recall, and micro F1 all end up equal to overall accuracy. If I total the correct predictions, roughly 95 billing, 56 technical, and 6 account, that is 157 correct out of 200, giving a micro F1 of about 0.785. It sits between the macro and weighted numbers here, but that is not a general rule, it depends entirely on the confusion matrix.

whiteboard with confusion matrix diagram

Choosing the right one, and reporting it honestly

The practical rule I follow is this: use macro averaging when every class matters regardless of its frequency, which is common in safety-relevant or fairness-sensitive tasks where failing silently on a rare category is exactly the failure mode you are trying to catch. A content moderation system that flags 99 percent of spam correctly but only 30 percent of a rare but serious abuse category has a real problem that macro F1 will expose and accuracy will hide.

Use micro averaging, or equivalently accuracy in the single-label case, when you genuinely care about overall correctness across all predictions and the class distribution in your test set reflects the distribution you expect in deployment. It answers a straightforward operational question: out of everything the model sees in production, how often is it right?

Use weighted averaging when you want a summary that reflects real-world class prevalence but still want the interpretability of per-class F1 rather than raw pooled counts. It is a reasonable default for a general-purpose leaderboard number, but be honest that it will understate problems on minority classes, sometimes the exact classes you care about most, such as rare disease mentions in clinical text or minority dialect detection.

Whichever you choose, the discipline that matters most is reporting the per-class breakdown alongside the summary statistic, and being explicit in any write-up about which averaging scheme produced the headline number. A single figure without that context, macro F1 of 0.68 quoted without the per-class table, tells a reader almost nothing they can trust. Pair the average with a confusion matrix or per-class table, use a leakage-aware, stratified test split so the class proportions you are averaging over are actually representative, and state your averaging choice in the same sentence as the number itself. That habit costs a paragraph and saves you from being quietly wrong.

← All writing See the project case studies →