class_weight="balanced"按公式n_samples/(n_classes×n_samples_in_class)计算各类权重,使稀有类损失贡献放大;键必须匹配真实标签类型,与sample_weight相乘叠加,CV中需在模型构造时传入。

class_weight="balanced" 是怎么算出来的
它不是简单按类别频次倒数缩放,而是用 n_samples / (n_classes * n_samples_in_class) 公式自动计算每个类的权重。比如训练集共 1000 条样本,其中正类 50 条、负类 950 条,那么正类权重是 1000 / (2 * 50) = 10.0,负类是 1000 / (2 * 950) ≈ 0.526。这个机制本质是让稀有类的损失贡献被放大,从而推动模型更关注少数类。
手动传入字典时 key 必须是真实标签值
如果你的标签是字符串(如 "spam" 和 "ham"),class_weight 字典就得写成 {"spam": 10, "ham": 1};如果是整数标签(如 0 和 1),就必须用 {0: 10, 1: 1}。传错类型或键不存在会直接报错:ValueError: Class label not found。
常见错误包括:
- 用
{1: 10, 0: 1}但实际标签是["A", "B"] - 标签含
np.nan或未去重,导致字典 key 不全 - 训练前做了
LabelEncoder,但没同步更新class_weight字典的 key
和 sample_weight 混用时优先级关系
class_weight 在拟合前就转换为内部的 sample_weight,所以它和显式传入的 sample_weight 参数是相乘关系。也就是说,最终每个样本的权重 = class_weight[标签] × sample_weight[i]。
立即学习“Python免费学习笔记(深入)”;
创建 Flask + Vue.js 全栈项目,采用单端口架构、uv 依赖管理、结构化日志和生产级前端设计。当用户要求以下操作时触发:创建新的 Flask+Vue 项目、搭建 Web 应用、构建全栈 Python+Vue 应用、初始化 Flask Web 项目、设置单端口 Flask 前后端项目。触发词:新建项目、创建项目、搭建项目、Flask项目、Vue项目。
这意味着:
- 如果同时设了
class_weight="balanced"和自定义sample_weight,效果不是“二选一”,而是叠加 - 当你要对某几个难分样本额外加权时,得先确认
class_weight已经拉高了整个类的基线权重,再微调个别样本 - 调试时建议先固定
class_weight,单独验证sample_weight的影响,避免干扰源太多
别忽略 cross-validation 中的 class_weight 传递
用 sklearn.model_selection.cross_val_score 或 GridSearchCV 时,class_weight 必须通过 estimator 构造时传入,不能在 fit() 阶段临时加——因为 CV 会反复新建模型实例。
正确写法是:
from sklearn.linear_model import LogisticRegression from sklearn.model_selection import cross_val_score <p>lr = LogisticRegression(class_weight="balanced") # ✅ 这里传 scores = cross_val_score(lr, X, y, cv=5, scoring="f1")
错误写法是:
# ❌ 下面这行不会生效:cv 过程中每个 fold 都会重新 init LogisticRegression,不带 class_weight
cross_val_score(LogisticRegression(), X, y, cv=5, fit_params={"class_weight": "balanced"})另外注意:class_weight="balanced" 是按**每次 CV fold 的训练子集**独立计算的,不是用全量数据算一次再复用。这点在小数据集上会导致 fold 间权重波动较大。

















