class_weight="balanced"仅补偿类别频次差异,不建模非对称误诊代价;sample_weight支持逐样本加权但需严格对齐;真正代价敏感需自定义业务损失函数+阈值调优。

class_weight 是最直接、最常用的入口,但它的行为常被误读——它不等于代价矩阵,而是近似加权后的先验调整。
为什么 class_weight="balanced" 不等于医疗场景下的代价敏感?
scikit-learn 的 class_weight="balanced" 会按 n_samples / (n_classes * n_samples_in_class) 自动计算权重,本质是补偿类别频次差异,不是建模误诊代价。比如阳性样本占 5%,它给阳性类赋权 ≈ 10,但这无法区分「漏诊(FN)代价 5000 元」和「误诊(FP)代价 1000 元」这种非对称风险。
- 它只调整训练时的样本损失权重,不改变决策阈值或混淆矩阵中的代价结构
- 对随机森林、逻辑回归等支持
class_weight的模型有效;但对 SVC 默认不生效,需显式传入class_weight参数 - 若你已有明确代价比(如
C(1,0)/C(0,1) == 5),更稳妥的做法是手动设class_weight={0: 1, 1: 5}
sample_weight 比 class_weight 更灵活,但容易漏掉关键步骤
当你有逐样本的业务含义(例如某高龄患者漏诊风险更高),sample_weight 是唯一选择。但它必须在 fit() 时显式传入,且不能和 class_weight 混用——后者会被忽略。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 构造
sample_weight数组时,务必与y_train严格对齐:索引顺序错一位,权重就全错 - 常见错误:用 pandas DataFrame 直接切片生成 weight,结果因 index 不连续导致长度不匹配,报
ValueError: sample_weight.shape == (n_samples,) expected - 示例片段:
weight = np.ones(len(y_train))<br>weight[y_train == 1] = 5 # 阳性样本权重为 5<br>model.fit(X_train, y_train, sample_weight=weight)
代价矩阵真正起作用的地方:自定义评估 + 阈值调优
scikit-learn 没有内置代价矩阵接口,但你可以用 business_cost() 这类函数替代 accuracy_score 来驱动模型选择和阈值搜索。
立即学习“Python免费学习笔记(深入)”;
- 别只看
f1_score或roc_auc:它们隐含等代价假设,和医疗/金融场景冲突 - 用
predict_proba()获取预测概率,再遍历阈值计算业务损失:np.where(y_prob >= threshold, 1, 0) - 关键细节:
confusion_matrix返回的是 [[TN, FP], [FN, TP]],对应代价项要按行×列顺序映射,不是直觉上的「左上到右下」
真正难的不是写那几行 class_weight,而是把临床判断(比如“30 岁女性乳腺癌漏诊代价是误诊的 8 倍”)无损地翻译成数值权重,并在验证集上用真实业务损失而非指标曲线来锁定阈值。这步做不好,模型再“平衡”也只是统计幻觉。

















