直接用f1_score(y_true, y_pred, average='weighted')即可,它按各类别在y_true中的样本数加权平均f1值,要求标签类型一致、长度相同,且输入为一维整数或字符串标签,不可用one-hot或概率矩阵。

sklearn.metrics.f1_score 的 average='weighted' 参数怎么用?
直接用 f1_score(y_true, y_pred, average='weighted') 就行,但必须确保标签是整数或字符串类型一致,且 y_true 和 y_pred 长度相同。这个参数会按每个类别的支持度(即样本数)加权求和,公式是 ∑(F1i × supporti) / ∑supporti。
常见错误是传入 one-hot 编码的 y_true 或 y_pred —— f1_score 只接受一维标签数组,不是二维概率或 one-hot 矩阵。
- 如果模型输出是概率(如
model.predict_proba()),先用np.argmax()转成类别索引 - 若类别名是字符串(如
['cat', 'dog', 'bird']),y_true和y_pred必须都用相同字符串,不能混用数字和字符串 - 当某个类别在
y_true中完全没出现,average='weighted'仍能计算(它只基于实际出现的类别加权),但若该类在y_pred中有预测而y_true中为 0,则其 F1 视为 0
为什么 weighted 和 macro 结果经常差很多?
因为 average='weighted' 把多数类的 F1 拉高了,而 average='macro' 对所有类等权重平均。比如三分类中,类别 A 占 80% 样本、F1=0.9,B 占 15%、F1=0.4,C 占 5%、F1=0.2:weighted 结果 ≈ 0.9×0.8 + 0.4×0.15 + 0.2×0.05 = 0.79;macro 是 (0.9+0.4+0.2)/3 = 0.5。
实际选哪个取决于业务目标:要反映整体预测质量且数据不平衡,用 weighted;要强调每个类都得过关(比如医疗诊断里罕见病不能被忽略),就得看 macro 或单类 F1。
-
weighted对类别分布敏感,训练集和测试集类别比例差异大时,指标可能失真 - 如果某类支持度为 0(即
y_true中没这个类),weighted会自动跳过它,但macro会报ZeroDivisionError(除非设zero_division=0)
多分类 F1 加权平均和 classification_report 的关系
classification_report(y_true, y_pred) 默认最后一行 weighted avg 列就是调用 f1_score(..., average='weighted') 算出来的,但 report 还同时给出 precision 和 recall 的加权平均 —— 它们各自加权,不是从 F1 推导来的。
注意:classification_report 的加权逻辑和 f1_score 一致,但如果你手动算 F1 加权值,别误用 report 里 precision 或 recall 的加权值去“组合”出 F1(F1 不是 precision 和 recall 加权后的调和平均)。
- 想验证一致性?对比
f1_score(y_true, y_pred, average='weighted')和classification_report(..., output_dict=True)['weighted avg']['f1-score'] - report 默认不显示 support 数为 0 的类别,但
f1_score在average='weighted'下也只基于非零 support 类别计算
使用 predict_proba 后怎么安全地算 weighted F1?
必须显式取 argmax,不能直接把概率矩阵喂给 f1_score,否则会报错 ValueError: multiclass format is not supported。
import numpy as np from sklearn.metrics import f1_score <h1>假设 model.predict_proba(X_test) 输出 shape=(n, 3)</h1><p>y_proba = model.predict_proba(X_test) # 不要直接传这个 y_pred = np.argmax(y_proba, axis=1) # ✅ 正确:转成整数标签 f1_w = f1_score(y_true, y_pred, average='weighted')</p>
容易漏掉的是标签映射一致性:如果训练时用 LabelEncoder 编码过,预测时也要用同一个 encoder.transform() 或确保 argmax 结果对应原始类别顺序。
- 如果模型输出是 logits(没 softmax),同样先
softmax再argmax,或直接argmax(logits 最大值位置和概率最大值一致) - 用
predict()方法通常更安全,因为它已封装好类别映射;但自定义后处理时,务必检查输出维度和类别对齐
加权 F1 看似简单,真正麻烦的是标签类型、编码方式、以及「支持度」到底按哪边算(y_true 还是 y_pred)——这些细节不盯紧,结果可能差 0.2 以上。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











