DQN实战:把Q-Table换成神经网络后发生了什么
如果状态空间大到离谱,比如直接用游戏画面像素作为输入,传统的Q-Table绝对会瞬间崩溃,因为你不可能给宇宙中所有可能的画面都开一行表格。这就是为什么需要DQN(Deep Q-Network)。
Bellman方程和$\epsilon$-greedy策略都没变,变的是数据的来源。神经网络最强的地方在于“泛化”,它能识别模式。如果状态3和状态7长得很像,网络能推断出它们同样危险,而Q-Table必须得真实踩坑两次才能知道。
下一篇
用 Anthropic SDK 调 gpt-oss-120b 的踩坑 →
其实DQN的核心逻辑极其简单,就是把查表变成了模型推理:
- Q-learning:
q_value = q_table[state, action] - DQN:
q_values = neural_network(state)(直接输出每个动作的Q值)
Bellman方程和$\epsilon$-greedy策略都没变,变的是数据的来源。神经网络最强的地方在于“泛化”,它能识别模式。如果状态3和状态7长得很像,网络能推断出它们同样危险,而Q-Table必须得真实踩坑两次才能知道。
但在实际部署大模型或强化学习工作流时,直接套神经网络经常会训练崩溃。DeepMind当年解决了两个关键痛点,这现在也是所有RL代码的标配:
- 样本相关性问题: 强化学习的连续状态(状态4→5→6)高度相关。如果直接顺序训练,就像连续给AI看32张同一只猫的照片,模型很容易过拟合。
replay_buffer.add(state, action, reward, next_state, done)
batch = replay_buffer.sample(batch_size=32) # 随机采样,打破相关性- 目标值漂移问题: 更新网络时,计算目标值(Target)所用的网络也是正在被更新的那个。这就像你在追一个会跑的靶心,永远追不上。
# 使用 target_network 提供稳定的贝尔曼目标
target = reward + gamma * max(target_network(next_state))
# 仅更新 online_network
loss = (target - online_network(state)[action]) ** 2我试着用JAX写了个三层神经网络跑4x4的网格世界,输入是state的one-hot编码。虽然环境简单,但这种从零实现部署的过程能让人清晰地感受到DQN是如何通过Buffer和Target Network把不稳定的强化学习给“驯服”的。