多单元LSTM RNN训练损失为NaN的代码问题排查求助
问题定位与修复方案
我帮你梳理了代码里导致训练损失NaN的几个核心问题,以及对应的修复方案:
1. 重复定义占位符Y导致计算图关联错误
你在代码里先后两次定义了Y占位符:
Y = tf.placeholder(tf.float32, [None, n_steps, NUM_OF_OUTPUTS]) # ... 中间模型构建代码 ... Y = tf.placeholder(tf.float32, [None, n_steps, NUM_OF_OUTPUTS])
第二次定义会覆盖第一次的占位符节点,但损失计算逻辑关联的是第一次的Y,而训练时喂入的是第二次的Y,导致损失计算时Y没有被正确赋值,直接引发NaN。
修复方法:删除重复的占位符定义,只保留一次。
2. 损失计算的数值稳定性问题
你当前的损失计算路径是「先算L2范数→再平方→求和求平均」,两次开方+平方的操作容易放大数值误差,当差值较大时可能触发数值溢出导致NaN。实际上,tf.norm(..., ord=2)的平方等价于直接计算差值的平方和,后者的数值稳定性更好。
修改后的损失计算代码:
# 直接计算差值的平方和,替代先norm再平方的冗余操作 diff = prediction[:,:,6:75] - Y[:,:,6:75] distance_square = tf.square(diff) reduced_distance = tf.math.reduce_sum(distance_square, axis=2) # 每个时间步的平方和 reduced_distance = tf.math.reduce_sum(reduced_distance, axis=1) # 每个样本所有时间步的总和 train_loss = tf.math.reduce_mean(reduced_distance, axis=0)
3. 深层LSTM的梯度爆炸问题
4层LSTM结构很容易出现梯度爆炸,这是训练损失NaN的高频诱因。你需要在优化流程中加入梯度裁剪,限制梯度的最大范数,避免参数更新幅度过大导致数值溢出。
修改后的优化器代码:
learning_rate = 0.001 optimizer = tf.train.AdamOptimizer(learning_rate) # 添加梯度裁剪,最大范数设为5.0(可根据实际情况调整) grads, vars = zip(*optimizer.compute_gradients(train_loss)) grads, _ = tf.clip_by_global_norm(grads, 5.0) trainOptimizer = optimizer.apply_gradients(zip(grads, vars), global_step=global_step)
4. 数据标准化的合理性优化
你当前对拼接后的输入+输出数据做了全局标准化,但输入(G_t + m_t)和输出(P_t + m_t+1)的分布可能差异较大,分开标准化能避免输出部分被输入分布干扰,进一步提升数值稳定性。
修改后的标准化代码:
# 单独标准化输入部分 train_input_mean = np.mean(train_input) train_input_std = np.std(train_input) train_input = (train_input - train_input_mean) / train_input_std valid_input = (valid_input - train_input_mean) / train_input_std # 单独标准化标签部分 train_label_mean = np.mean(train_label) train_label_std = np.std(train_label) train_label = (train_label - train_label_mean) / train_label_std valid_label = (valid_label - train_label_mean) / train_label_std
修复后的核心代码片段
# 仅定义一次占位符 X = tf.placeholder(tf.float32, [None, n_steps, NUM_OF_INPUTS]) Y = tf.placeholder(tf.float32, [None, n_steps, NUM_OF_OUTPUTS]) encoded_inputs = tf.layers.dense(X, 256) layers = [tf.contrib.rnn.LSTMCell(num_units = n_neurons, activation=tf.nn.tanh) for layer in range(n_layers)] multi_layer_cell = tf.contrib.rnn.MultiRNNCell(layers) outputs, _ = tf.nn.dynamic_rnn(multi_layer_cell, encoded_inputs, dtype=tf.float32) prediction = tf.layers.dense(outputs, NUM_OF_OUTPUTS) # 优化后的损失计算 diff = prediction[:,:,6:75] - Y[:,:,6:75] distance_square = tf.square(diff) reduced_distance = tf.math.reduce_sum(distance_square, axis=2) reduced_distance = tf.math.reduce_sum(reduced_distance, axis=1) train_loss = tf.math.reduce_mean(reduced_distance, axis=0) # 带梯度裁剪的优化器 learning_rate = 0.001 optimizer = tf.train.AdamOptimizer(learning_rate) grads, vars = zip(*optimizer.compute_gradients(train_loss)) grads, _ = tf.clip_by_global_norm(grads, 5.0) trainOptimizer = optimizer.apply_gradients(zip(grads, vars), global_step=global_step)
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

