Keras中class_weight处理不平衡数据:少数类精确率与召回率为0求助
解决不平衡二分类任务中少数类精确率/召回率为0的问题
嘿,我来帮你排查这个问题——这种高度不平衡数据集的二分类坑确实挺多的,尤其是少数类完全没被模型学到的情况,咱们一步步来拆解:
首先,先检查你的class_weight设置是否合理
你手动设置的{0:1,1:50}权重有点过高了。Keras里class_weight='balanced'其实是更稳妥的选择,它会自动根据样本占比计算权重:公式是n_samples / (n_classes * n_samples_per_class)。对你的数据集来说,类别1的合理权重应该是总样本数/(2*类别1样本数) ≈ 1/0.16 = 6.25,你设成50反而可能让模型陷入极端拟合,甚至反过来因为噪声太大学不到有效特征。先改成自动平衡试试:
class_weight = 'balanced'
然后,核心排查:你的训练数据里真的有足够的少数类样本吗?
如果你的训练集里类别1的样本几乎为0(比如随机划分时没做分层抽样),那再高的权重也没用,模型根本没见过少数类的特征,自然只会预测多数类0。这时候一定要用分层抽样划分数据集:
from sklearn.model_selection import train_test_split # stratify=y 保证训练集和测试集的类别占比和原数据一致 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=5)
先确认y_train里类别1的占比是不是接近16%,如果差很多,那就是划分的问题。
接下来检查模型结构和训练设置
- 输出层和损失函数是否正确:二分类任务必须用单神经元+
sigmoid激活,搭配binary_crossentropy损失函数,用softmax或者多神经元就会出问题:
# 补全你的模型输出层 model.add(Dense(1, activation='sigmoid')) # 编译时指定正确的损失 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
- 训练参数是否合适:
- 如果
batch_size太大,每个batch里可能根本没有类别1的样本,模型每次更新都只偏向多数类,试试缩小batch_size(比如16或32); epochs是不是太少?模型还没来得及学到少数类的特征,可以适当增加到50-100轮;- 学习率是否过高?可以试试调小学习率,比如
optimizer=Adam(learning_rate=0.0001)。
- 如果
数据增强/采样的辅助手段
如果训练集里少数类样本确实太少(比如只有几十条),仅靠权重调整不够,可以试试过采样方法,比如SMOTE:
from imblearn.over_sampling import SMOTE # 对训练集做过采样,平衡类别 sm = SMOTE(random_state=5) X_resampled, y_resampled = sm.fit_resample(X_train, y_train) # 用重采样后的数据训练模型 model.fit(X_resampled, y_resampled, epochs=100, batch_size=16, validation_split=0.2)
注意不要对测试集做采样,避免影响评估结果。
最后,用正确的指标评估模型
准确率在不平衡数据集里完全没用,一定要看混淆矩阵和分类报告,确认模型到底有没有预测过类别1:
from sklearn.metrics import confusion_matrix, classification_report # 把模型输出的概率转成类别标签(阈值设为0.5) y_pred = (model.predict(X_test) > 0.5).astype(int) print("混淆矩阵:") print(confusion_matrix(y_test, y_pred)) print("\n分类报告:") print(classification_report(y_test, y_pred))
如果混淆矩阵里第二行(真实为1的样本)全是0,那说明模型完全没学到少数类,回到前面的数据和模型设置再排查。
内容的提问来源于stack exchange,提问作者TigSh
相关产品推荐
相关产品推荐

