tensorflow不支持class_weight='balanced',需手动计算类别权重字典或用compute_class_weight;smote须在tf.data前完成预处理;评估应避免accuracy,改用pr-auc、recall等不平衡感知指标。

为什么 class_weight=’balanced’ 不总管用
TensorFlow 本身不直接支持 class_weight='balanced' 这种 scikit-learn 风格的快捷写法——它只认字典格式的权重映射。如果你直接传 class_weight='balanced' 给 model.fit(),会报 TypeError: unhashable type: 'dict' 或静默失效,模型根本没加权。
真正起作用的是手动计算每个类别的权重:用总样本数 × 类别频率的倒数。例如 3 类数据中,类别 0 占 80%,那它的权重应 ≈ 1 / 0.8 ≈ 1.25;类别 1 占 10%,权重 ≈ 1 / 0.1 = 10。
- 用
sklearn.utils.class_weight.compute_class_weight()最稳妥,它默认按'balanced'策略返回数组,再转成{0: w0, 1: w1, ...}字典 - 注意传给它的
y必须是一维整数标签(不是 one-hot),且需和模型输出层的类别索引对齐 - 如果用了
tf.data.Dataset,不能在fit()里传class_weight,得改用重采样或损失函数加权
用 tf.keras.losses.CategoricalCrossentropy 加权更可控
当数据已做 one-hot 编码、输出层是 softmax 时,CategoricalCrossentropy 的 sample_weight 参数比全局 class_weight 更灵活——你可以为每个样本动态指定权重,比如结合难例挖掘或代价敏感学习。
关键点是:权重必须和 batch 中样本一一对应,shape 为 (batch_size,),且要在 tf.data.Dataset 的 map() 里提前算好。
华为云 Python SDK 查询工具。自动发现已安装 SDK 的服务包、Client类、API 方法、入参详情、类信息(__init__ 参数、属性、类型、描述),支持关键字搜索,快速定位目标 API 使用方法。
- 先用
compute_class_weight得到各类权重字典cls_w - 在
map(lambda x, y: (x, y, tf.gather(cls_w_tensor, tf.argmax(y, axis=-1))))中为每个样本查权重 - 训练时传
sample_weight_mode='temporal'仅适用于 RNN;分类任务用默认None,并在model.compile(loss=...)里设loss=loss_fn,然后fit(x, y, sample_weight=sw)
过采样 SMOTE 在 TensorFlow 流水线里怎么接
SMOTE 是 CPU 实现,不能直接塞进 tf.data.Dataset 的 map()(会破坏图执行)。常见错误是试图在 tf.function 里调用 smote.fit_resample(),结果报 OperatorNotAllowedInGraphError。
正确做法是把过采样当成预处理步骤,在构建 Dataset 前完成,且只对训练集做——验证/测试集绝不能碰。
- 用
imblearn.over_sampling.SMOTE处理原始 numpy 数组X_train, y_train,得到新数组X_train_sm, y_train_sm - 确保
y_train_sm是 int 类型一维数组,再转成 one-hot 或保持 sparse 标签,与模型输入对齐 - 如果特征含图像或高维张量,SMOTE 默认只处理二维 flat 特征,需先
X_train.reshape(X_train.shape[0], -1),过采样完再reshape回原 shape - 别在
tf.data.Dataset.from_tensor_slices()后再想“动态 SMOTE”,那是反模式
验证时 metrics 容易被假准确率带偏
不平衡下 accuracy 几乎没意义。比如 99% 负样本的数据集,全猜负就能得 99% 准确率。但 tf.keras.metrics.Precision 和 Recall 默认按阈值 0.5 计算,而最优阈值往往远低于 0.5(尤其正样本极少时)。
- 务必加
tf.keras.metrics.AUC(curve='PR')(PR 曲线下面积),它对不平衡更鲁棒 - 用
tf.keras.metrics.SpecificityAtSensitivity或自定义 callback 在验证时扫阈值,找 F1 最大点 - 避免在
model.compile(metrics=[...])里只写'accuracy',至少补上tf.keras.metrics.Recall(class_id=1)(假设正类是 1) - 验证集本身也要检查是否被意外重采样——有些 pipeline 会把 SMOTE 应用到整个数据集,导致验证泄露
权重设置、采样时机、评估指标这三处,任一环节错位都会让模型看似收敛实则失效。尤其是把 SMOTE 塞进 tf.data 流水线,或者用 class_weight='balanced' 想当然替代字典映射,这两类问题最常导致线上效果归零。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










