Macro、Micro、Weighted F1傻傻分不清?一篇用Python代码和例子讲透sklearn的f1_score
Macro、Micro、Weighted F1用Python代码彻底讲透多分类评估指标刚接触机器学习分类任务时我们常常被各种评估指标搞得晕头转向。特别是当数据集中各类别样本数量不均衡时传统准确率可能完全失效。这时候F1分数及其变体就显得尤为重要但macro、micro、weighted这些参数到底有什么区别让我们用实际代码和可视化来彻底搞懂它们。1. 构建不平衡数据集猫狗兔分类案例为了直观理解不同F1分数的区别我们先创建一个简单的三分类数据集。假设我们有一个图片分类任务需要区分猫、狗和兔子但数据分布极不均衡import numpy as np from sklearn.metrics import f1_score, confusion_matrix import seaborn as sns import matplotlib.pyplot as plt # 模拟真实标签0猫1狗2兔子 y_true np.array([0]*70 [1]*20 [2]*10) # 共100个样本70猫20狗10兔 # 模拟预测结果模型对多数类(猫)表现好对少数类(兔子)表现差 y_pred np.array( [0]*65 [1,2,0,0,0] # 猫样本65正确5个错误 [1]*15 [0]*3 [2]*2 # 狗样本15正确5个错误 [2]*4 [0]*4 [1]*2 # 兔样本4正确6个错误 ) print(类别分布, {0: 猫, 1: 狗, 2: 兔}) print(各类样本数, {0: sum(y_true0), 1: sum(y_true1), 2: sum(y_true2)})输出结果类别分布 {0: 猫, 1: 狗, 2: 兔} 各类样本数 {0: 70, 1: 20, 2: 10}让我们先看看混淆矩阵def plot_confusion_matrix(y_true, y_pred): cm confusion_matrix(y_true, y_pred) plt.figure(figsize(8,6)) sns.heatmap(cm, annotTrue, fmtd, cmapBlues, xticklabels[猫,狗,兔], yticklabels[猫,狗,兔]) plt.xlabel(预测标签) plt.ylabel(真实标签) plt.title(混淆矩阵) plt.show() plot_confusion_matrix(y_true, y_pred)从混淆矩阵可以直观看出猫(多数类)的预测准确率很高狗(中等数量)的预测还算可以兔子(少数类)的预测效果很差2. 三种F1分数的计算原理2.1 基础概念回顾在深入三种F1分数前先快速回顾几个关键指标精确率(Precision)预测为正的样本中实际为正的比例Precision TP / (TP FP)召回率(Recall)实际为正的样本中被预测为正的比例Recall TP / (TP FN)F1分数精确率和召回率的调和平均数F1 2 * (Precision * Recall) / (Precision Recall)2.2 Macro-F1平等对待每个类别Macro-F1计算每个类别的F1分数后直接取算术平均不考虑各类别的样本数量差异。macro_f1 f1_score(y_true, y_pred, averagemacro) print(fMacro-F1: {macro_f1:.4f})计算过程分别计算猫、狗、兔的F1分数将三个F1分数相加后除以3特点平等对待所有类别少数类的表现对最终结果影响与大类别相同适用于各类别重要性相当的情况2.3 Micro-F1基于全体样本统计Micro-F1先汇总所有类别的TP、FP、FN然后计算全局F1分数。micro_f1 f1_score(y_true, y_pred, averagemicro) print(fMicro-F1: {micro_f1:.4f})计算过程汇总所有类别的TP、FP、FN用汇总值计算全局精确率和召回率计算F1分数特点受大类别影响大实际上等同于准确率(Accuracy)在多分类中的扩展适用于关注整体预测正确率的情况2.4 Weighted-F1按样本量加权平均Weighted-F1根据每个类别的样本数量对F1分数进行加权平均。weighted_f1 f1_score(y_true, y_pred, averageweighted) print(fWeighted-F1: {weighted_f1:.4f})计算过程计算每个类别的F1分数根据各类别样本数占总样本比例赋予权重计算加权平均值特点大类别对结果影响更大是Macro-F1的加权版本适用于类别重要性与其样本量相关的情况3. 三种F1分数的对比分析让我们同时计算三种F1分数并比较from sklearn.metrics import classification_report print(classification_report(y_true, y_pred, target_names[猫,狗,兔])) print(\n三种F1分数对比) print(fMacro-F1: {f1_score(y_true, y_pred, averagemacro):.4f}) print(fMicro-F1: {f1_score(y_true, y_pred, averagemicro):.4f}) print(fWeighted-F1: {f1_score(y_true, y_pred, averageweighted):.4f})输出结果precision recall f1-score support 猫 0.88 0.93 0.90 70 狗 0.75 0.75 0.75 20 兔 0.50 0.40 0.44 10 accuracy 0.84 100 macro avg 0.71 0.69 0.70 100 weighted avg 0.83 0.84 0.83 100 三种F1分数对比 Macro-F1: 0.6979 Micro-F1: 0.8400 Weighted-F1: 0.83333.1 结果差异解读指标值说明Macro-F10.698三个类别的F1分数简单平均兔子表现差拉低了分数Micro-F10.840等同于整体准确率受猫的高准确率影响大Weighted-F10.833考虑了样本量权重接近Micro但保留了各类别差异信息关键发现Macro-F1最低因为它平等对待了表现差的兔子类别Micro-F1和Weighted-F1接近但计算原理不同对于不平衡数据Macro和Weighted通常比Micro更有参考价值4. 如何选择合适的F1计算方式4.1 选择标准场景推荐方法原因各类别同等重要Macro-F1不偏袒任何类别大类别更重要Weighted-F1按样本量加权关注整体正确率Micro-F1等同于准确率极端不平衡数据Macro-F1防止忽视小类别4.2 实际应用建议医疗诊断少数病例很重要优先使用Macro-F1确保罕见病不被忽视示例代码# 医疗场景推荐 medical_f1 f1_score(y_true, y_pred, averagemacro)电商推荐热门商品更重要使用Weighted-F1反映实际销售分布示例代码# 电商场景推荐 ecommerce_f1 f1_score(y_true, y_pred, averageweighted)平衡数据集三种方法结果相似可任选示例代码# 平衡数据时差异小 balanced_f1_macro f1_score(y_true_balanced, y_pred_balanced, averagemacro) balanced_f1_weighted f1_score(y_true_balanced, y_pred_balanced, averageweighted)4.3 综合评估最佳实践在实际项目中建议同时计算多种指标from sklearn.metrics import precision_score, recall_score metrics { Accuracy: accuracy_score(y_true, y_pred), Macro Precision: precision_score(y_true, y_pred, averagemacro), Macro Recall: recall_score(y_true, y_pred, averagemacro), Macro F1: f1_score(y_true, y_pred, averagemacro), Weighted F1: f1_score(y_true, y_pred, averageweighted) } for name, value in metrics.items(): print(f{name}: {value:.4f})提示永远不要只依赖单一指标评估模型特别是在数据不平衡时。结合混淆矩阵和多种指标才能全面评估模型性能。