第4章 F1分数:调和平均的意义

讲完了精确率和召回率,你可能会问:有没有一个指标能同时照顾两边?

有,就是F1分数。

我个人习惯管它叫“调和平均下的综合分”。

调和平均到底调和了什么?

先看一个简单例子。有两个数:0.9和0.1。

  • 算术平均:(0.9+0.1)/2 = 0.5
  • 几何平均:√(0.9×0.1) ≈ 0.3
  • 调和平均:2/(1/0.9+1/0.1) ≈ 0.18

看到了吗?调和平均被0.1那个小值严重拉低。这正是我们想要的——如果精确率很高但召回率很低,或者反过来,这个模型其实不可用。调和平均会狠狠地惩罚这种偏科。

公式很简洁:

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

本质上就是精确率和召回率的调和平均。

我在项目里见过不少团队只看精确率,结果召回率掉到0.2,业务方直接炸毛。用F1就能有效避免这种自欺欺人。

F1的一个小陷阱

嗯,注意,如果精确率和召回率都是0,公式分母是0,代码里会报除零错误。sklearn的处理方式是填0。但如果你自己手写,记得加个epsilon。

def f1_score(p, r):
    if p + r == 0:
        return 0.0
    return 2 * p * r / (p + r)

Fβ:给精确率和召回率加权重

有时候我们更在意其中一方。比如癌症筛查,宁可误报也不能漏掉(更看重召回率)。反之,垃圾邮件过滤,宁可放过几封垃圾邮件,也别误删正常邮件(更看重精确率)。

这时候就轮到Fβ上场了:

Fβ = (1 + β²) × (Precision × Recall) / (β² × Precision + Recall)

β控制召回率的权重:

  • β=1 → F1,两者平衡
  • β<1 → 更看重精确率(比如β=0.5)
  • β>1 → 更看重召回率(比如β=2)
我做过一个欺诈检测项目,漏掉一笔欺诈单的损失远大于误判一次正常交易。所以我选F2,让召回率权重是精确率的4倍。效果比F1好很多。

多分类下的麻烦:宏平均 vs 微平均

二分类问题只有一个F1。但多分类呢?每个类别都有一个精确率和召回率,怎么合成一个数字?

两种主流做法:宏平均(Macro)和微平均(Micro)。

对比项宏平均(Macro)微平均(Micro)
计算方法对每个类别算F1,然后算术平均把所有类别的TP/FP/FN加起来,统一算一个F1
对类别数量的敏感性每个类别权重相同,小类和大类平等大类主导,小类很容易被淹没
适用场景类别均衡,希望每个类都被同等重视样本极不平衡时,更关心整体表现
风险小类别性能差但平均后还是高,可能虚高大类别做得好就掩盖了小类的糟糕

我举个实际例子。假设3个类别:A有900个样本,B有90个,C有10个。模型在A上F1=0.95,在B上F1=0.5,在C上F1=0.0。

Macro F1 = (0.95 + 0.50 + 0.00) / 3 = 0.483
Micro F1 = 先把混淆矩阵合计
全局TP = A的TP + B的TP + C的TP
全局FP = A的FP + B的FP + C的FP
全局FN = A的FN + B的FN + C的FN
然后带入公式 2TP/(2TP+FP+FN) = 0.92 (假设A表现很好)

你看,Micro F1高达0.92,但C类一个都没识别对。这个指标就失真了。反过来,Macro F1只有0.483,更诚实地反映了对少数类的失败。

我曾经在类别极度不平衡时只用Macro F1做评估,结果报告上写0.75,老板很开心。上线后C类全挂,用户投诉了一大堆。教训是:要么同时报告Macro和Micro,要么针对每个类别单独看F1。

动手算一算:sklearn里的用法

其实sklearn一行搞定:

from sklearn.metrics import f1_score, fbeta_score

y_true = [0, 1, 2, 0, 1, 2]
y_pred = [0, 2, 1, 0, 0, 1]

# F1 宏平均
print(f1_score(y_true, y_pred, average='macro'))
# F1 微平均
print(f1_score(y_true, y_pred, average='micro'))
# F2 宏平均(β=2)
print(fbeta_score(y_true, y_pred, beta=2, average='macro'))

记得传入标签一定要从0开始连续索引,否则参数得补labels。

个人习惯:做模型对比时,先看Micro F1;如果Micro还不错但业务反馈不行,再跑Macro F1和各别类F1,往往能定位到少数类的问题。几个指标配合着用,比单看一个数字靠谱十倍。

一张图理清关系

F1 及相关概念关系图 精确率 P 召回率 R 调和平均 F1 (β=1) P与R的平衡 Fβ = (1+β²)P·R/(β²P+R) β<1 重P,β>1 重R 多分类扩展 宏平均 × 微平均 加权平均 提示:F1 是 Fβ 的特例 (β=1);宏平均每个类别权重相同,微平均受大类主导。

说到这里,其实核心就一句话:F1是精确率和召回率的调和平均,调和平均对低值很敏感,所以F1会诚实地反映两者中的短板。Fβ让你能调节偏向哪一边;多分类里宏平均与微平均的选择取决于你更关心每个类还是整体。

下次别人问你模型好不好,别只丢一个F1。先把精确率和召回率亮了,再给F1,最后说明是宏平均还是微平均——这样才显得专业。