三分类任务训练损失为负且模型始终输出固定值的问题求助
问题解答
1. 代码存在的明显错误
你的代码是典型的二分类任务配置,和三分类任务需求完全不匹配,具体错误如下:
- 输出层配置错误:三分类任务需要输出3个类别的概率,你当前输出层仅1个神经元,用的
sigmoid激活是二分类专用配置,只能输出0~1之间的单个值,根本无法区分三类结果。 - 损失函数不匹配:
binary_crossentropy是二分类交叉熵损失,仅适用于二分类场景,强行用在三分类任务上会导致损失计算完全错误,这就是你出现负数损失的核心原因。 - 指标配置错误:
categorical_accuracy仅用于标签为独热编码的场景,你当前标签是整数形式,且和任务类型不匹配,所以打印出来的1.0准确率完全是无效错误数值。 - 标签取值不符合要求:分类任务的类别索引要求从0开始计数,你的标签是-1、0、1,传入损失函数计算时会出现索引越界类的计算错误,进一步导致损失异常。
- 批次大小设置不合理:
batch_size设为100000过大,梯度更新会极其粗糙,模型很难收敛,最终只会输出占比最高的类别,也就是你看到的始终输出0。
2. 排查与解决思路
按照以下步骤依次调整即可解决问题:
- 修正标签编码:把原始标签做映射,将-1转为0、0转为1、1转为2,符合分类损失的输入要求。
- 调整模型结构:输出层改为
Dense(3, activation='softmax'),输出三个类别的概率。 - 修正编译配置:损失函数换成
sparse_categorical_crossentropy(适配整数标签,不需要额外做独热编码),指标替换为sparse_categorical_accuracy,删掉原有的不匹配指标。 - 调小批次大小:建议将
batch_size调整为32~1024之间的常规值,保证梯度更新的有效性。 - 排查类别分布:统计三类样本的占比,如果存在严重的类别不平衡,可通过添加类别权重、过采样少数类、欠采样多数类的方式优化,避免模型只学习多数类。
- 增加收敛校验:拆分10%左右的训练数据作为验证集,训练时传入
validation_data参数,每个epoch同时查看训练集和验证集的指标,避免模型过拟合或者不收敛。 - 可选优化:如果调整后还有输出固定的问题,可以在全连接层后添加Dropout层,或者加入L2正则,避免模型过拟合。
内容的提问来源于stack exchange,提问作者Stijn
相关产品推荐
相关产品推荐

