You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Keras训练CIFAR10数据集的20层DNN时出现NaN Loss问题的求助

Keras训练CIFAR10数据集的20层DNN时出现NaN Loss问题的求助

我在做Aurelien Geron的《Hands-On ML》里的练习,尝试用20层隐藏层的DNN训练CIFAR10数据集,但不管用自己的代码还是抄答案,训练时的loss和val_loss全是NaN,准确率也完全没提升,而且没有任何Python或TensorFlow的报错。以下是我的代码和训练输出:

我的代码

import tensorflow as tf
import datetime

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.cifar10.load_data()
X_val, y_val = X_train[:5000], y_train[:5000]
X_train, y_train = X_train[5000:], y_train[5000:]
tf.random.set_seed(42)

model = tf.keras.Sequential()
model.add(tf.keras.layers.Input(shape=[32,32,3]))
model.add(tf.keras.layers.Flatten())

## 20 Hidden layers 
for _ in range(20):
    model.add(tf.keras.layers.Dense(100, activation='swish', 
    kernel_initializer='he_normal'))

# Output layer
model.add(tf.keras.layers.Dense(10, activation='softmax'))

optimizer = tf.keras.optimizers.Nadam(learning_rate=5e-6)
model.compile(optimizer=opimizer,
         loss='sparse_categorical_crossentropy',
         metrics=['accuracy'])

early_stopping = tf.keras.callbacks.EarlyStopping(patience=20, 
                                   restore_best_weights=True)

log_dir = "logs/my_cifar10_model/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir)

model.fit(X_train, y_train, epochs=100, callbacks=[early_stopping, 
     tensorboard_callback],
     validation_data=(X_val, y_val))

训练输出

Epoch 1/100
1407/1407 ━━━━━━━━━━━━━━━━━━━━ 8s 3ms/step - accuracy: 0.1005 - loss: nan - val_accuracy: 0.0996 - val_loss: nan
Epoch 2/100
1407/1407 ━━━━━━━━━━━━━━━━━━━━ 3s 2ms/step - accuracy: 0.1007 - loss: nan - val_accuracy: 0.0996 - val_loss: nan
...
Epoch 21/100
1407/1407 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.1007 - loss: nan - val_accuracy: 0.0996 - val_loss: nan
<keras.src.callbacks.history.History at 0x7801cde19fa0>

问题分析与解决方法

我帮你定位到了两个核心问题,修正后模型就能正常训练了:

  • 拼写错误导致优化器未正确配置:在model.compile()里,你把定义好的optimizer拼成了opimizer——这个笔误会让TensorFlow无法识别优化器,直接导致训练逻辑异常,最终出现NaN Loss。
  • 缺少数据归一化处理:CIFAR10的图像像素值范围是0-255,直接输入到20层的全连接网络中,会让模型的输入数值过大,极易引发梯度爆炸或数值不稳定,这也是Loss变成NaN的重要原因。我们需要把像素值缩放到0-1的范围。

修正后的完整代码

import tensorflow as tf
import datetime

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.cifar10.load_data()
X_val, y_val = X_train[:5000], y_train[:5000]
X_train, y_train = X_train[5000:], y_train[5000:]

# 数据归一化:将0-255的像素值缩放到0-1区间
X_train = X_train / 255.0
X_val = X_val / 255.0
X_test = X_test / 255.0

tf.random.set_seed(42)

model = tf.keras.Sequential()
model.add(tf.keras.layers.Input(shape=[32,32,3]))
model.add(tf.keras.layers.Flatten())

## 20 Hidden layers 
for _ in range(20):
    model.add(tf.keras.layers.Dense(100, activation='swish', 
    kernel_initializer='he_normal'))

# Output layer
model.add(tf.keras.layers.Dense(10, activation='softmax'))

optimizer = tf.keras.optimizers.Nadam(learning_rate=5e-6)
# 修正拼写错误:opimizer → optimizer
model.compile(optimizer=optimizer,
         loss='sparse_categorical_crossentropy',
         metrics=['accuracy'])

early_stopping = tf.keras.callbacks.EarlyStopping(patience=20, 
                                   restore_best_weights=True)

log_dir = "logs/my_cifar10_model/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir)

history = model.fit(X_train, y_train, epochs=100, callbacks=[early_stopping, 
     tensorboard_callback],
     validation_data=(X_val, y_val))

额外训练建议

  1. 调整学习率:你当前用的5e-6学习率过小,模型收敛会非常慢,可以尝试调到1e-4左右,后续再根据训练的Loss曲线微调。
  2. 加入Batch Normalization:对于20层的深度全连接网络,建议在每个Dense层后添加tf.keras.layers.BatchNormalization(),能有效缓解深度网络的数值不稳定问题,让训练更顺畅。
  3. 可选:添加Dropout层:如果后续出现过拟合,可以在部分Dense层后加入tf.keras.layers.Dropout(0.2)来提升模型的泛化能力。

备注:内容来源于stack exchange,提问作者vmmgame

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 12:23:01