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

Q-Learning(TensorFlow)中Q值过高引发NaN问题求助

解决Q-Learning训练中Q值发散为NaN的问题

我之前做强化学习项目时也踩过Q值变NaN的坑,结合你的4x4网格游戏场景和特征设计,咱们来一步步拆解问题根源和解决办法:

可能的问题根源

  1. 数值不稳定(梯度爆炸):你的奖励存在±5的跳变,加上未做梯度限制的话,高学习率会让Q值更新幅度越来越大,最终溢出成NaN。
  2. 输入特征未归一化:虽然你的输入是0-3的离散值,但神经网络对数值范围敏感,未归一化的输入容易导致权重更新时出现数值异常。
  3. 终端状态处理不当:当玩家踏入死亡/胜利区域触发重置时,没有正确设置终端状态的目标Q值(终端状态的后续奖励为0,不能再用奖励+γ*max(next_q)的公式)。
  4. 缺乏Q值范围约束:如果没有对模型输出的Q值做范围限制,随着训练迭代,Q值可能会无限累积增长,最终超出浮点数表示范围。

具体解决方案

1. 降低学习率+添加梯度裁剪

这是解决NaN最直接的手段:

  • 把优化器的学习率从默认的0.01降到0.001甚至更低,比如用Adam优化器:
optimizer = tf.keras.optimizers.Adam(learning_rate=0.0005)
  • 在反向传播时强制限制梯度范围,防止梯度爆炸:
with tf.GradientTape() as tape:
    q_values = model(state_input)
    loss = tf.reduce_mean(tf.square(target_q - q_values))
gradients = tape.gradient(loss, model.trainable_variables)
# 裁剪梯度,限制其L2范数不超过1.0
gradients = [tf.clip_by_norm(g, 1.0) for g in gradients]
optimizer.apply_gradients(zip(gradients, model.trainable_variables))

2. 归一化输入特征

把你的0-3范围的输入特征映射到[0,1]区间,让神经网络更稳定:

# 假设state是形状为(1,4)的输入数组
normalized_state = state / 3.0  # 将0-3的特征值归一化到0-1

3. 正确处理终端状态的Q值更新

当触发死亡/胜利重置时,这一步是终端状态,目标Q值应该直接等于当前奖励,不需要加上后续折扣奖励:

reward, next_state, is_terminal = env.step(action)
if is_terminal:
    # 终端状态:目标Q值=当前奖励
    target_q = reward
else:
    # 非终端状态:目标Q值=奖励+折扣*下一个状态的最大Q值
    next_q_values = model(next_state)
    target_q = reward + gamma * tf.reduce_max(next_q_values)

4. 限制Q值的输出范围

在模型输出Q值后,强制将其限制在一个合理区间内(比如[-10,10]),避免数值无限增长:

q_values = model(state_input)
q_values = tf.clip_by_value(q_values, -10.0, 10.0)

5. 增加训练过程的调试输出

在训练循环中打印每一步的奖励、Q值、损失值,定位异常开始的节点:

print(f"Step {step}: Reward={reward}, Q Values={q_values.numpy()}, Loss={loss.numpy()}")

比如你给出的示例中,当输入是[[1,1,1,1]]时所有方向都是已访问/网格外,AI每次选择都会得到-1奖励,这时候如果学习率过高,Q值很容易出现负向累积爆炸,通过调试能快速确认这类场景的影响。

内容的提问来源于stack exchange,提问作者lukasniessen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 10:17:57