使用Keras实现二分类时损失值下降但准确率固定的问题排查
二分类任务准确率固定异常的原因与修复方案
问题根源
嘿,我一眼就揪出问题所在了——你最后一层的激活函数用错啦!
- 你的任务是二分类,最后一层只设了1个神经元,却搭配了
softmax激活函数。 - Softmax的作用是把输出归一化为总和为1的概率分布,当只有1个神经元时,它的输出永远是1(毕竟只有一个值,归一化后必然等于1)。
- 这就导致模型不管输入是什么,都只会无脑预测类别1,准确率自然固定为训练集中类别1的占比(你的训练集里类别1刚好占50.67%),验证集的0.44也是同理——验证集里类别1的占比就是44%。
- 至于损失持续下降,那是L2正则项在起作用,模型一直在缩小权重,但完全没学到任何分类特征。
修复方案
针对二分类任务,有两种正确的配置方式,优先推荐第一种:
方式一:使用Sigmoid激活(最常用)
把最后一层的激活函数换成sigmoid,它会输出0到1之间的概率值,完美适配BinaryCrossentropy损失函数:
model = tf.keras.Sequential() model.add(tf.keras.layers.Dense(6, activation=tf.keras.activations.sigmoid, input_shape=(2,), kernel_regularizer='l2')) model.add(tf.keras.layers.Dense(6, activation=tf.keras.activations.sigmoid, kernel_regularizer='l2')) # 把softmax替换为sigmoid model.add(tf.keras.layers.Dense(1, activation=tf.keras.activations.sigmoid)) model.compile(optimizer=tf.keras.optimizers.RMSprop(), loss=tf.keras.losses.BinaryCrossentropy(), metrics=[tf.keras.metrics.BinaryAccuracy()])
方式二:使用Softmax+双神经元(可选)
如果坚持要用softmax,需要把最后一层神经元数量改成2,同时将标签转换为one-hot编码,损失函数换成CategoricalCrossentropy:
# 先把原始标签转换成one-hot格式 y_train_onehot = tf.keras.utils.to_categorical(y_train, num_classes=2) y_val_onehot = tf.keras.utils.to_categorical(y_val, num_classes=2) model = tf.keras.Sequential() model.add(tf.keras.layers.Dense(6, activation=tf.keras.activations.sigmoid, input_shape=(2,), kernel_regularizer='l2')) model.add(tf.keras.layers.Dense(6, activation=tf.keras.activations.sigmoid, kernel_regularizer='l2')) # 改为2个神经元搭配softmax model.add(tf.keras.layers.Dense(2, activation=tf.keras.activations.softmax)) model.compile(optimizer=tf.keras.optimizers.RMSprop(), loss=tf.keras.losses.CategoricalCrossentropy(), metrics=[tf.keras.metrics.CategoricalAccuracy()]) # 训练时传入one-hot后的标签 model.fit(X_train, y_train_onehot, validation_data=(X_val, y_val_onehot), epochs=10)
额外小建议
- 二分类任务优先选Sigmoid+BinaryCrossentropy的组合,既简洁又高效,还不用额外处理标签。
- 训练时可以加上
verbose=1查看更细节的过程,或者用tf.keras.utils.plot_model可视化模型结构,能更快发现这类层配置错误。
内容的提问来源于stack exchange,提问作者Wael Dimassi
相关产品推荐
相关产品推荐

