当准确率不够用时,如何选择正确的评估指标?

一、为什么需要多种平均方式?

在二分类问题中,我们常用 Accuracy(准确率) 评估模型。但在多分类场景(如新闻分类、情感分析、图像识别),单一指标往往具有欺骗性:

典型案例:一个10分类模型,某个类别占比90%,其余9个类别各占比1.1%。

  • 模型全部预测为 majority class(多数类)

  • 准确率 = 90% ❌ 看似优秀,实则完全没学到其他类别

这就是类别不平衡带来的陷阱。我们需要更精细的评估方式:Macro、Micro、Weighted


二、核心概念:从混淆矩阵出发

2.1 单类别的四大指标

对于任意一个类别(以"体育"类为例):

表格

指标 公式 含义
Precision(精确率) TP / (TP + FP) 预测为体育的,有多少真的是体育
Recall(召回率) TP / (TP + FN) 真的是体育的,有多少被找出来了
F1-Score 2 × P × R / (P + R) 精确率和召回率的调和平均
Support TP + FN 该类别真实样本数

TP(真正例):预测体育,实际体育
FP(假正例):预测体育,实际其他
FN(假负例):预测其他,实际体育

2.2 多分类的困境

假设一个3分类问题(猫、狗、鸟),我们得到每个类别的指标:

表格

类别 Precision Recall F1 Support(样本数)
0.95 0.90 0.92 900
0.60 0.55 0.57 80
0.20 0.25 0.22 20
总计 - - - 1000

问题:如何用一个数字衡量整体模型性能?

这就是 Macro / Micro / Weighted 三种平均方式的用武之地。


三、三种平均方式详解

3.1 Macro(宏平均)—— 平等对待每个类别

计算方式:先计算每个类别的指标,再简单平均

Macro-F1=3F1猫​+F1狗​+F1鸟​​=30.92+0.57+0.22​=0.57

特点

  • 每个类别同等重要,不受样本数量影响

  • ✅ 能暴露小类别的性能问题(本例中鸟类的0.22拉低了整体)

  • ❌ 当类别极度不平衡时,少数类的噪声会显著影响结果

适用场景

  • 类别相对平衡

  • 特别关注小类别表现(如欺诈检测、罕见病诊断)

  • 需要公平评估每个类别的模型能力


3.2 Micro(微平均)—— 平等对待每个样本

计算方式汇总所有类别的TP/FP/FN,计算全局指标

Micro-Precision=∑TP+∑FP∑TP​=855+45+44+5+16+5+5+36+15855+44+5​=0.90

Micro-Recall=∑TP+∑FN∑TP​=1000904​=0.904

Micro-F1≈0.90

特点

  • 每个样本同等重要,大类主导结果

  • ✅ 与 Accuracy 在单标签分类中数值相等

  • ❌ 小类别的错误被"淹没"在大类中

适用场景

  • 类别不平衡严重

  • 只关心整体预测能力,不关注特定类别

  • 样本权重即重要性的任务(如搜索引擎、推荐系统)


3.3 Weighted(加权平均)—— 按样本数加权

计算方式:按各类别的 Support(样本数) 加权平均

Weighted-F1=1000900×0.92+80×0.57+20×0.22​=0.88

特点

  • ✅ 介于 Macro 和 Micro 之间

  • 考虑类别分布,结果更贴近实际数据

  • ✅ 大类权重高,但小类仍有贡献

适用场景

  • 类别不平衡,但不希望完全忽略小类

  • 需要与业务指标对齐(如按流量/收入加权的场景)


四、可视化对比

plain

复制

┌─────────────────────────────────────────────────────────┐
│  类别分布: 猫(90%) | 狗(8%) | 鸟(2%)                     │
│  各类F1:    0.92   | 0.57  | 0.22                        │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Macro-F1:     (0.92 + 0.57 + 0.22) / 3  =  0.57        │
│           ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░  57%   │
│           [每个类别一票,鸟类严重拉低分数]                 │
│                                                         │
│  Micro-F1:   ≈ 0.90  (接近准确率)                        │
│           ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓  90%   │
│           [样本说了算,猫类主导结果]                     │
│                                                         │
│  Weighted-F1:  0.9×0.92 + 0.08×0.57 + 0.02×0.22 = 0.88  │
│           ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░  88%   │
│           [按样本加权,平衡整体与分布]                    │
│                                                         │
└─────────────────────────────────────────────────────────┘

五、实战代码(Python + sklearn)

5.1 基础用法

Python

复制

from sklearn.metrics import classification_report, f1_score, precision_score, recall_score

y_true = [0, 0, 0, 1, 1, 1, 2, 2]  # 真实标签
y_pred = [0, 0, 1, 1, 1, 2, 2, 2]  # 预测标签

# 三种平均方式
print("Macro-F1:", f1_score(y_true, y_pred, average='macro'))      # 0.67
print("Micro-F1:", f1_score(y_true, y_pred, average='micro'))      # 0.75
print("Weighted-F1:", f1_score(y_true, y_pred, average='weighted')) # 0.71

# 完整报告
print(classification_report(y_true, y_pred, target_names=['猫', '狗', '鸟']))

5.2 输出解读

plain

复制

              precision    recall  f1-score   support    ← 各类别样本数
           猫       1.00      0.67      0.80         3
           狗       0.67      0.67      0.67         3
           鸟       0.67      1.00      0.80         2

    accuracy                           0.75         8    ← Micro = Accuracy
   macro avg       0.78      0.78      0.76         8    ← Macro
weighted avg       0.79      0.75      0.75         8    ← Weighted

5.3 自定义计算(理解原理)

Python

复制

import numpy as np
from sklearn.metrics import precision_recall_fscore_support

# 获取每个类别的详细指标
precision, recall, f1, support = precision_recall_fscore_support(y_true, y_pred)

# 手动验证三种平均方式
macro_f1 = np.mean(f1)  # 简单平均
weighted_f1 = np.average(f1, weights=support)  # 加权平均

# Micro 等价于全局计算
global_tp = sum((y_true == y_pred) & (y_true == i).sum() for i in set(y_true))
micro_precision = global_tp / len(y_true)

六、选择决策树

plain

复制

开始评估多分类模型
        │
        ▼
    类别是否平衡?
    /          \
  是            否
  │              │
  ▼              ▼
使用 Macro    关注小类别?
(最公平)    /          \
            是            否
            │              │
            ▼              ▼
        使用 Macro      使用 Micro
        (强制公平)    (整体最优)
            │
            └──── 或尝试 Weighted(折中方案)

场景对照表

表格

应用场景 推荐指标 理由
医学诊断(罕见病检测) Macro 不能忽视任何疾病类别
内容审核(垃圾信息识别) Macro 小类别(极端内容)更重要
搜索引擎(查询分类) Micro 流量即正义,整体准确优先
电商分类(商品类目) Weighted 考虑各类目GMV贡献
论文审稿(研究方向分类) Macro 小众领域同样值得尊重
情感分析(多情感分类) Weighted 中性情感样本多,但正负情感更重要

七、进阶:多标签分类的特殊处理

上述讨论针对单标签多分类(每个样本只属于一个类别)。对于多标签分类(如一条新闻同时属于"科技"和"财经"):

表格

方式 适用性 说明
Macro ✅ 常用 计算每个标签的F1后平均
Micro ✅ 常用 全局统计所有标签的TP/FP/FN
Weighted ⚠️ 较少 按标签频率加权,但标签共存使"样本数"定义复杂

Python

复制

# 多标签示例(每个样本可有多个标签)
from sklearn.metrics import f1_score

y_true = [[1, 0, 1], [0, 1, 0], [1, 1, 0]]  # 3个标签
y_pred = [[1, 0, 0], [0, 1, 1], [1, 0, 0]]

print(f1_score(y_true, y_pred, average='macro'))   # 标签维度平均
print(f1_score(y_true, y_pred, average='micro'))   # 样本-标签对维度平均
print(f1_score(y_true, y_pred, average='samples')) # 样本维度平均(多标签特有)

八、总结与记忆口诀

表格

指标 核心思想 记忆口诀
Macro 类别平等 "观公平,每类一票"
Micro 样本平等 "观统计,样本说了算"
Weighted 按样本加权 "权平衡,大类的声音"

最终建议

  1. 报告所有三种指标 —— 让读者自行判断

  2. 结合业务目标选择 —— 没有绝对最好的指标

  3. 关注混淆矩阵 —— 数字背后的错误模式更重要

"指标是灯塔,不是目的地。理解模型在哪些类别上犯错,比追求某个数字更重要。"

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐