强化学习顿悟记:从 Q 表到 DQN,三个击穿本质的思维跃迁

强化学习顿悟记:从 Q 表到 DQN,三个击穿本质的思维跃迁

在学习强化学习(RL)从传统算法迈向深度强化学习(DQN)的过程中,很多人会被密密麻麻的数学公式、神经网络结构、复杂的循环搞得晕头转向。

但当你真正看透代码底层的那一刻,你会发现:复杂的 DQN 本质上只是传统 Q-Learning 的一种“自然演化”。

本文记录我在剖析源码时的三次关键顿悟,带你一眼看穿 DQN 的核心底牌。


顿悟一:反向传播,不过是传统“改表格”的暗度陈仓

很多人把深度强化学习当成一个全新的黑盒,但对比下面两段代码,你会发现它们在物理意义上完全等价:

epiphany_tabular_vs_dqn.png

1. 传统 Q-Learning:显式“硬改表格”

在状态少的小游戏(如走格子)里,Q 值是一张矩阵大表:

# 1. 算出目标与当前预测的差距
update = target - value
# 2. 乘以学习率,直接把对应格子的数值挪过去
Q[row, col, action] += lr * update

逻辑非常朴素:算出来差多少,就直接修改内存矩阵里 (状态, 动作) 那个格子的数字,强行对齐。

2. 深度强化学习 DQN:隐式“反向传播”

当游戏变得像王者荣耀、Atari 画面那样,状态多到几亿种,内存存不下这张大表了。
于是,我们用神经网络充当“查表函数”:输入状态 s,输出每个动作的价值 Q(s, a)。

但神经网络没有格子给你直接赋值,该怎么更新?

# 1. 计算均方误差损失 (MSE)
loss = loss_fn(value, target)  # 相当于 (value - target)^2
# 2. 反向传播更新网络参数
loss.backward()
optimizer.step()

核心结论

DQN 的反向传播,本质上就是在用梯度下降,去实现传统表格里那句 Q += 步长 * (target - value)!

  • 传统方法:状态有限,直接修改格子的绝对数值(显式硬改)。
  • 深度学习:状态无限,把 Target 当作临时标签,通过损失函数与反向传播调整全网权重,间接让输出逼近 Target(隐式逼近)。

顿悟二:双模型之谜——动作模型(model)vs 经验模型(prev_model)

在 DQN 训练中,最让人头疼的代码往往是为什么需要两个模型:一个动作模型 model,一个经验模型 prev_model。

epiphany_two_models.png

1. 贪吃蛇打靶隐喻:移动的靶子

强化学习的 Target 是通过下一步的预估算出来的:
\text{Target} = \text{Reward} + \gamma \max Q(S_{next}, A')

如果你只用一个模型:

  • 你射出一箭(预测当前 value)。
  • 同时靶子也在跑(target 也由正在更新的模型实时计算)。
  • 结果就是:边打靶,靶子边晃,网络参数剧烈震荡,训练彻底崩溃。

2. 角色分工与协作

模型角色 代码变量名 实际输入 核心职责
动作模型 model (state, action) 负责做决策、算当前 value,每一步都在反向传播更新(动态射手)
经验模型 prev_model (next_state) 负责算未来的最大期望 target,权重暂时冻结(静止靶子)

每隔固定步数(例如 10 步),才会把 model 的最新参数同步给 prev_model:

if (i + 1) % 10 == 0:
    prev_model.load_state_dict(model.state_dict())

核心本质

经验模型 prev_model,本质上就是“上一个阶段沉淀下来的老模型”。

用历史阶段沉淀下的稳定自己(prev_model,冻结参数定出固定靶心),来考核当前正在努力学习的自己(model,反向传播往前跨一步)。靶子定住,训练自然稳定!


顿悟三:目标同步的艺术——游戏镜头“弹簧缓动(Spring)”式的软更新

在看到每隔 10 步生硬地全盘拷贝权重时(if (i + 1) % 10 == 0:),很多人的第一直觉是:

“能不能根据指标来?比如等 Loss 降低到指定阈值 才同步,是不是更科学?”

1. 强化学习的陷阱:Loss 变小 ≠ 策略变强

在监督学习里,Loss 越低越好;但在强化学习中,直接拿 Loss 当阈值是个巨大陷阱:

  • 局部死锁:模型如果陷入原地打转的死胡同,行为极度单一,Loss 也会趋近于 0,容易“假性早熟”,把 Target 锁死在错误目标上。
  • 探索剧震:当 Agent 偶然吃到大奖探索到全新领域,Loss 会瞬间暴增。
  • 门槛两难:阈值高了震荡,阈值低了可能一辈子也达不到,导致 prev_model 永远无法更新。

2. 游戏开发者的灵感:摄像机弹簧缓动(Spring / Lerp)

现代强化学习(如 DDPG、TD3、SAC)采用了一种极其优雅且物理感十足的方案——软更新(Soft Update / Polyak 平均)。

这与游戏引擎里第三人称摄像机的弹簧臂(Spring Arm / Lerp 缓动跟随)完全是同一个数学原理:

# 游戏镜头跟踪角色:避免镜头瞬移生硬,使用线性插值平滑跟随
camera_pos = Lerp(camera_pos, player_pos, tau)

# 强化学习软更新:避免 Target 断崖式跳跃,让经验模型像弹簧阻尼一样丝滑跟随
for prev_param, param in zip(prev_model.parameters(), model.parameters()):
    prev_param.data.copy_(0.005 * param.data + 0.995 * prev_param.data)

\theta_{\text{prev}} \leftarrow \tau \cdot \theta_{\text{model}} + (1 - \tau) \cdot \theta_{\text{prev}} \quad (\tau = 0.005)

  • 硬更新(% 10):就像摄像机每隔 10 秒“瞬移”一次,画面产生突兀的跳跃。
  • 软更新(Spring 跟随):经验模型 prev_model 带着惯性和微小阻尼,永远在每一步悄悄向主模型靠拢一点点。既不会让靶子乱晃,又告别了生硬顿挫,训练曲线稳如磐石!

终极总结

  1. 表格 vs DQN:查表是手动填数,DQN 是借反向传播调权重,两者都在把 value 拉向 target。
  2. 动作模型 vs 经验模型:一个是活泼好学的当前射手(model),一个是沉稳冻结的历史靶子(prev_model),靶子定住,射手才能练出神准枪法。
  3. 硬同步 vs 软跟随:别用 Loss 阈值防踩坑,用游戏镜头式的“弹簧阻尼缓动(Lerp)”,让经验模型丝滑跟随,稳步迭代!
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容