You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不平衡二分类:自定义逆加权平均F1-Score的合理性与实现问题

类别不平衡二分类的自定义F1指标问题

我正在处理类别不平衡的二分类(类别0/1)问题,需要计算以下指标:

  • 类别0的F1-Score
  • 类别1的F1-Score
  • 加权平均F1-Score
  • 逆加权平均F1-Score

其中逆加权平均F1-Score为自定义指标:逻辑与加权平均F1-Score(按类别实际样本数(support)加权)一致,但权重采用support的倒数(与support成反比),目的是提升少数类F1-Score的权重,更好地关注少数类样本。

问题1

该自定义指标是否可行?存在哪些弊端?为何网上相关资料极少?

问题2

如何在Python中正确实现该指标?

我的尝试代码

from sklearn.metrics import f1_score
import numpy as np

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

f1_class0 = f1_score(y_true, y_pred, pos_label=0)
f1_class1 = f1_score(y_true, y_pred, pos_label=1)

f1_weighted = f1_score(y_true, y_pred, average = 'weighted')

class_counts = np.bincount(y_true)
class_weights = class_counts / len(y_true)
inverse_class_weights = 1 - class_weights
inverse_sample_weights = np.array([inverse_class_weights[label] for label in y_true])
f1_inverse = f1_score(y_true, y_pred, average = 'weighted', sample_weight = inverse_sample_weights)

print("F1-Score for class 0:", f1_class0)
print("F1-Score for class 1:", f1_class1)
print("Weighted Average F1-Score:", f1_weighted)
print("Inverse Weighted Average F1-Score:", f1_inverse)

输出结果

F1-Score for class 0: 0.6666666666666666
F1-Score for class 1: 0.8
Weighted Average F1-Score: 0.7666666666666667
Inverse Weighted Average F1-Score: 0.8285714285714286

前三个指标计算正确,但自定义指标结果不符合预期:类别0的support占比为0.25,类别1为0.75,按预期逆加权平均应为(0.6666666666666666 * 0.75) + (0.8 * 0.25) = 0.7,但实际得到0.8285714285714286。请帮忙分析错误原因,以及为何该指标未被广泛研究?


解答

问题2:代码错误分析与正确实现

错误原因

你使用sample_weight参数的方式不符合预期逻辑:sklearn的f1_score中average='weighted'结合sample_weight时,是对每个样本对应的混淆矩阵元素(TP/FP/FN)加权,而非直接对类别F1值按权重求和。这种机制和你想给类别分配权重后计算加权平均的逻辑完全不符,因此得到错误结果。

正确实现方式

既然逆加权平均是对每个类别的F1值按与support成反比的权重加权求和,直接手动计算即可,无需借助sample_weight:

from sklearn.metrics import f1_score
import numpy as np

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

# 计算各类别F1
f1_class0 = f1_score(y_true, y_pred, pos_label=0)
f1_class1 = f1_score(y_true, y_pred, pos_label=1)

# 计算各类别样本数
class_counts = np.bincount(y_true)

# 计算逆权重(与样本数成反比),归一化确保权重和为1
inverse_weights = 1 / class_counts
inverse_weights = inverse_weights / inverse_weights.sum()

# 计算逆加权平均F1
f1_inverse = f1_class0 * inverse_weights[0] + f1_class1 * inverse_weights[1]

print("F1-Score for class 0:", f1_class0)
print("F1-Score for class 1:", f1_class1)
print("Inverse Weighted Average F1-Score:", f1_inverse)

输出结果

F1-Score for class 0: 0.6666666666666666
F1-Score for class 1: 0.8
Inverse Weighted Average F1-Score: 0.7

该结果与预期一致,若需支持多分类,只需遍历所有类别计算F1后加权即可。

问题1:自定义指标的可行性、弊端与资料少的原因

可行性

该指标在特定极端场景下可行:当业务目标完全以少数类性能为核心,且完全不在乎多数类的区分能力时,它能直观提升少数类F1在整体指标中的占比,帮助聚焦少数类优化。

弊端

  1. 权重极端化风险:若少数类样本占比极低(比如0.01%),其逆权重会被放大到极致,导致整体指标几乎完全由少数类F1决定,多数类的性能波动被完全忽略,模型可能过度拟合少数类,丧失基本的泛化能力。
  2. 缺乏理论支撑:该指标未经过系统的统计验证,无法保证在不同数据集上的稳定性和合理性,类别分布稍有变化,权重就会剧烈波动,指标可解释性极差。
  3. 脱离实际业务需求:多数不平衡场景中,即使关注少数类,也需要兼顾多数类的性能(比如欺诈检测中,误判正常交易为欺诈会造成用户损失),逆加权平均会过度放大少数类权重,可能偏离实际业务的损失函数。
  4. 丢失样本层面细节:加权平均F1基于每个样本的贡献计算,而逆加权平均是对类别F1的简单加权,无法反映少数类内部TP/FN分布对整体的影响,信息损耗严重。

为何资料极少

  1. 已有成熟替代方案:针对类别不平衡问题,业界已有大量经过实践验证的方法,比如F1-macro(平等加权每个类别)、F2-Score(提升召回率权重)、Precision-Recall曲线,以及重采样、类别权重损失函数等建模手段,这些方案比自定义逆加权平均更可靠。
  2. 指标合理性不足:逆加权平均的权重逻辑容易走向极端,且缺乏统计理论基础,学术和工业界更倾向于使用有理论支撑、可解释性强的指标。
  3. 应用场景狭窄:只有当业务目标是100%优先少数类、完全放弃多数类时,该指标才有意义,但这种场景极为罕见,大部分不平衡问题都需要兼顾两类性能。

内容的提问来源于stack exchange,提问作者AngelMarcos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 18:57:49