class_weight≠代价敏感学习,因其仅按类别频率倒数加权,而代价敏感需显式建模错判代价;应通过sample_weight、CostSensitiveClassifier或XGBoost自定义目标函数实现。

为什么 class_weight 不等于代价敏感学习?
很多人以为给 sklearn 分类器传个 class_weight="balanced" 就算做了代价敏感学习——其实这只是对类别频率做倒数加权,没真正建模「错判不同类别的实际业务代价」。真正的代价敏感学习需要你明确指定:把正类判成负类(假阴性)比把负类判成正类(假阳性)贵 5 倍?还是反过来?这得靠显式代价矩阵或样本级权重来驱动模型优化目标。
用 sample_weight 手动注入代价信号
这是最直接、兼容性最强的方式,适用于几乎所有 sklearn 分类器(LogisticRegression、RandomForestClassifier、SVC 等)。核心思路是:对每个样本,按其真实标签和你定义的误判代价,算出它在损失函数里的相对重要性。
- 假设二分类,标签为
y=0(负类)和y=1(正类),你定义代价:C(1→0)=10(漏检正样本代价高),C(0→1)=2(误报代价低) - 那么每个样本的
sample_weight可设为:C(y_true → y_pred_wrong),但训练时我们不知道y_pred_wrong,所以退而求其次——对所有y=1样本赋予权重10,所有y=0样本赋予权重2 - 代码上就是:
sample_weight = np.where(y == 1, 10, 2),然后传给fit(X, y, sample_weight=sample_weight)
注意:这个权重不是“让模型多学正样本”,而是告诉模型“判错一个正样本,惩罚力度是判错负样本的 5 倍”。效果比 class_weight 更可控,但需你提前量化代价。
用 imblearn 的 CostSensitiveClassifier 做封装
如果你不想手动算权重,imbalanced-learn(imblearn)提供了更贴近代价敏感定义的封装器:CostSensitiveClassifier。它内部基于代价矩阵重采样 + 集成,适合代价不对称极强的场景。
- 安装:
pip install imbalanced-learn - 代价矩阵格式是二维数组:
cost_matrix[i][j]表示真实为类i却被预测为类j的代价;对角线应为 0(正确预测无代价) - 例如二分类:
cost_matrix = [[0, 2], [10, 0]]表示0→1代价为 2,1→0代价为 10 - 用法:
clf = CostSensitiveClassifier(estimator=RandomForestClassifier(), cost_matrix=cost_matrix),再调用fit
缺点是它底层依赖重采样,可能放大噪声;且不支持所有 estimator(比如不兼容 XGBoost 原生接口)。
绕过 sklearn:用 XGBoost / LightGBM 的 scale_pos_weight 或自定义目标函数
树模型框架原生支持代价建模,比 sklearn 更灵活。XGBoost 的 scale_pos_weight 是简化版代价控制,只适用于二分类且仅调节正负样本梯度比例;真要精细控制,得写自定义损失函数。
-
scale_pos_weight值 ≈ 负样本数 / 正样本数 ×(正类误判代价 / 负类误判代价),但它仍是启发式,不改变 Hessian - LightGBM 支持
focal_loss类似机制,但更推荐用objective='custom'+ 自定义 gradient/hessian:在梯度里嵌入代价项,例如对正样本错判,梯度放大 10 倍 - 示例片段(XGBoost):
def custom_obj(y_pred, dtrain): y_true = dtrain.get_label() grad = np.zeros(len(y_true)) hess = np.zeros(len(y_true)) for i in range(len(y_true)): if y_true[i] == 1 and y_pred[i] 0.5: # 误报 grad[i] = y_pred[i] hess[i] = y_pred[i] * (1 - y_pred[i]) return grad, hess
自定义目标函数威力大,但也容易写错梯度导致收敛失败;上线前务必用小数据验证梯度数值近似是否匹配。
真正难的不是怎么写代码,而是把业务里的“漏检一个客户流失要损失 2 万”“误推营销给沉默用户会降低品牌信任”这种模糊表述,翻译成可计算的、一致的、可验证的代价数字——这个过程没法交给算法库自动完成。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











