TensorFlow自定义训练循环验证失效,模型预测值全部相同求助
问题原因分析
1. 训练循环缩进错误(核心问题)
你的自定义训练循环存在严重的缩进错误,导致实际有效训练几乎没有执行:
predictions、loss_value的计算代码没有缩进在with tf.GradientTape()的上下文管理器范围内,梯度带根本没有记录损失计算的计算图,无法生成有效梯度- 梯度计算
grads = tape.gradient(...)和参数更新optimizer.apply_gradients(...)的代码写在了训练batch的循环外部,相当于每个epoch只对最后一个训练batch计算一次梯度、更新一次参数,前面29个batch的训练完全无效,10个epoch总共只更新了10次参数,模型几乎没有学习
2. 死ReLU现象
你当前的训练配置很容易触发ReLU神经元死亡问题:
两层ReLU激活的全连接层如果初始权重不合适、或者梯度更新太小,会导致所有ReLU神经元的输入都小于0,输出恒为0,此时后续层只能输出固定的偏置值,不管输入是什么输出都不会变化,你看到的1.97左右的固定输出就是最后一层偏置的数值,刚好接近你的标签均值(你的标签是2X+2,X是标准正态分布,标签均值就是2)。
3. 训练配置不合理
- SGD学习率设置为1e-3太小,配合极少的有效更新步数,模型参数几乎没有变化
- 仅训练10个epoch,迭代次数不足以让模型学习到映射关系
修正方案
先修正训练循环的缩进,调整训练配置,参考代码如下:
epochs = 50 # 增加训练轮次 optimizer = optimizers.SGD(learning_rate=1e-2) # 调大学习率,也可以换成Adam优化器加快收敛 loss_fn = mean_squared_error for epoch in range(epochs): train_loss_total = 0 for step, (x_batch_train, y_batch_train) in enumerate(zip(Train_X, Train_Y)): with tf.GradientTape() as tape: # 缩进修正:前向传播、损失计算放在梯度带上下文内 predictions = model(x_batch_train, training=True) loss_value = tf.reduce_mean(loss_fn(y_batch_train, predictions)) # 显式求损失均值更稳妥 # 缩进修正:梯度计算、参数更新放在batch循环内部 grads = tape.gradient(loss_value, model.trainable_weights) optimizer.apply_gradients(zip(grads, model.trainable_weights)) train_loss_total += loss_value print(f"Epoch {epoch+1}/{epochs}, 训练损失: {train_loss_total/(step+1):.4f}") # 验证逻辑 val_loss_total = 0 for step, (x_batch_val, y_batch_val) in enumerate(zip(Val_X, Val_Y)): val_predictions = model(x_batch_val, training=False) val_loss_total += tf.reduce_mean(loss_fn(y_batch_val, val_predictions)) print(f"Epoch {epoch+1}/{epochs}, 验证损失: {val_loss_total/(step+1):.4f}")
如果调整后还是出现固定输出,可以把ReLU换成LeakyReLU避免神经元死亡,或者直接换用Adam优化器。
内容的提问来源于stack exchange,提问作者Lahi S
相关产品推荐
相关产品推荐

