ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

强化学习基石:动态规划的策略迭代与价值迭代

强化学习基石:动态规划的策略迭代与价值迭代 第一次接触强化学习的人往往会被“智能体与环境交互”“奖励信号”“探索与利用”这些概念吸引觉得像是在训练一个有灵性的活物。但真正开始啃算法时会发现第一个能完整推导、亲手实现、可视化收敛过程的反而是“动态规划”这个听着有点古老的词。这一讲的核心其实就一句话在环境模型完全已知的前提下怎么系统地把每个状态的价值估准再从价值里反推出最优策略。它是强化学习课程里最接近传统算法的一讲也是后面所有无模型方法的理论地基。这篇内容适合三类人看正在跟着课程自学、对贝尔曼方程还有点懵的同学已经能跑一些深度学习框架、但回到底层迭代逻辑反而含糊的工程师以及准备算法岗面试、想快速把“策略迭代和价值迭代的联系与区别”讲清楚的人。我尽量不堆公式把每一步背后的“为什么”也一起说了。1. 先从“已知模型”说起动态规划站在什么位置1.1 强化学习四大类方法的分水岭强化学习方法通常被粗分成四类动态规划、蒙特卡洛方法、时序差分学习、策略梯度方法。这四者不是互相替代的关系而是沿一条“对模型依赖程度”的光谱依次排列。动态规划DP假设环境转移概率和奖励函数完全已知通过迭代计算精确的价值函数。蒙特卡洛方法MC不需要模型让智能体完整跑完一条轨迹用实际回报的平均值估计价值。时序差分方法TD也不需要模型但只需走一步就能更新估计把下一状态的估计值当作“部分真相”来用。策略梯度方法PG直接在策略参数空间里搜索最优方向绕开值函数估计这个中间层。这个分水岭就是“环境动力学是否已知”。有模型时你面对的是一个可解析计算的马尔可夫决策过程无模型时你只能靠和环境交互获得样本。动态规划之所以被摆在第一讲是因为它把“价值函数的定义”“贝尔曼方程”“迭代收敛”这些底层骨架先立起来后面所有方法几乎都在用不同手段逼近同一个方程。1.2 为什么动态规划值得认真学一遍很多人觉得现在工业界谁还手写动态规划环境模型基本都是未知的这个方向已经过时了。这个观点我不同意。原因有三点第一贝尔曼方程是几乎所有强化学习算法的数学底座。无论是 DQN 的损失函数还是 TD(0) 的更新公式本质上都在尝试满足同一条递推关系。把 DP 弄懂后面看任何算法论文都不会觉得公式是在变魔术。第二动态规划的迭代过程是最直观的“收敛演示”。你写一遍策略评估循环观察价值矩阵从乱跳、到缓慢变化、再到稳定不再动这一步对“强化学习到底在优化什么”的理解比看一百张网络结构图都有用。第三很多实际问题本身就是动态规划问题。比如机器人路径规划里的 Dijkstra 算法本质上是价值迭代的特殊形式再比如某些运筹学里的库存管理问题转移概率可以建模直接用策略迭代就能求出最优策略。这门课并不是教你死记一个过时算法而是教你一套“自举式更新”的思维范式。动态规划在强化学习里有两大经典内容策略迭代和价值迭代。这两者共享同一个基础组件——策略评估也就是把一个固定策略下的价值函数算到收敛。2.1 贝尔曼方程先搞清楚“价值”到底是什么定义一个策略 π 下的状态价值函数 Vπ(s)它表示从状态 s 出发按照策略 π 行动之后获得的期望折扣回报。折扣因子 γ 表示未来的回报相对现在要打几折γ ∈ [0, 1)。于是有Vπ(s) E[ Rt1 γ·Vπ(St1) | St s ]用人话说就是当前状态的得分等于“迈出这一步立刻拿到的奖励”加上“下个状态在打折扣后的价值”。很多初学者卡在这一步是因为不理解为什么 Vπ(s) 同时出现在等式两边。这里其实是把“一个无穷长序列的求和”变成了“一条关于 Vπ 自身的方程”。由于 Vπ(s) 是未知的且等式右侧 Vπ(St1) 也是未知的所以不能直接解只能通过迭代逼近。生活类比你评估一个区域的房产价值心里其实是在反复自我对齐——这间房的价值取决于周边房的价值而周边房的价值又反过来参考它。当整个小区所有房子的评估都自洽时这套评估才算稳定了。状态价值能算出来之后进一步定义动作价值 Qπ(s, a)表示在状态 s 先执行动作 a之后按策略 π 行动的期望回报。它的更新公式是Qπ(s, a) Σ_s p(s | s, a) · [ r γ·Vπ(s) ]这个字段后面会频繁用到策略改进步骤里需要它来比较“哪个动作更好”。2.2 策略评估一次迭代到底在算什么策略评估的目标是给定策略 π求出 Vπ。做法是迭代更新Vk1(s) Σ_a π(a | s) · Σ_s p(s | s, a) · [ r γ·Vk(s) ]这一步对策略 π 下可能选到的每个动作求期望再对可能到达的每个后继状态求期望。Vk 第 k 轮估计传到 Vk1 第 k1 轮形成一次扫描。实际操作时人们很少真的让 Vk 完全收敛而是设一个阈值 ε当 max_s |Vk1(s) - Vk(s)| ε 时停止。课程里常用 ε 1e-3 或 1e-4想拿到更精确的比较就设小一点。2.3 策略改进既然价值清楚了就朝着更好的方向走有了一组相对准确的 Vπ下一步是为每个状态选择一个“看起来更好”的动作。这里用贪心策略对每个状态 s选使 Qπ(s, a) 最大的动作π(s) argmax_a Σ_s p(s | s, a) · [ r γ·Vπ(s) ]之所以敢直接贪心背后的依据是策略改进定理如果策略 π 在每一步都选择了一个不差于 π 的动作那么 Vπ(s) ≥ Vπ(s) 对每个状态成立。也就是说局部贪心不会把整体带坏这给了迭代循环一个安全的下界。课程里最常举的例子是格栅世界智能体在 4x4 网格里移动每步奖励为 -1到达左上角或右下角终止。读者可以手推一遍从一个均匀随机策略开始评估两步、改进一次、再评估两步就能看到价值逐渐从周围往终点蔓延。3. 策略迭代与价值迭代两种收敛路线的选择3.1 策略迭代先评估到准再改进策略策略迭代的循环形式很简单随机初始化策略 π0。策略评估用迭代法算出当前策略的 Vπ。策略改进基于 Vπ 对每个状态贪心选动作得到 π。若 π ≠ π则把 π 更新为 π回到步骤2否则输出 π。这个流程的优点很明显每次改进之间策略是质量较高的迭代次数通常很少。对于规模可解的环境比如状态不超过几万个策略迭代往往比价值迭代更快收敛。缺点是每轮评估本身需要多次扫描单轮成本高。3.2 价值迭代省去显式策略的简化版价值迭代把策略评估压缩成一步直接将贝尔曼最优方程作为更新目标Vk1(s) max_a Σ_s p(s | s, a) · [ r γ·Vk(s) ]它不从某个初始策略开始而是直接收敛到最优价值函数最后再从 V* 反推最优策略。可以这样理解价值迭代把“评估后改进”的两个阶段合并成了“每次扫描时直接盯着最优值更新”相当于在每一步都对策略做了隐式改进。它的单轮扫描开销低代码也精简但需要更多轮次达到稳定尤其在奖励稀疏、折扣因子接近 1 的时候。3.3 怎么选一张对比表说清楚对比维度策略迭代价值迭代每轮是否包含显式策略有策略评估循环以策略稳定为收敛判据无显式策略循环以价值变化阈值为收敛判据单轮计算成本较高需评估多次较低一次贝尔曼最优更新收敛所需轮数较少较多实现难度稍复杂简单直接适用状态规模中小规模、模型可用中大规模、需要简单实现常见误用场景环境模型频繁变化重算代价高γ 接近 1、奖励非常稀疏时收敛极慢个人体会如果环境规模不大、离线求解一次就好策略迭代往往更“省总时间”如果要写一个在线模块、每步都要快速更新价值表价值迭代更顺手。不要迷信哪一种两者本质是一个问题的两面。4. 配套实操从零写一个格栅世界的动态规划4.1 实验环境设定与状态动作定义这一讲配的模拟项目通常叫“格栅世界”我用的是一个经典 4x4 版本。环境参数如下状态16 个网格编号 0 到 15其中 0 和 15 是终止状态。动作4 个方向上、下、左、右试图越界时停留在原地。奖励每走一步得到 -1直到进入终止状态。折扣因子γ 1课程演示常用但理论上终止状态价值固定为 0。这个环境小到可以打印价值矩阵看着数值慢慢变化非常适合理解更新公式。4.2 核心代码价值迭代实现课程配套代码比较精简我通常会让学生把价值迭代单独写一遍不要只跑现成库。下面是一份能直接运行的参考版本双数组和 in-place 的顺序问题我会在后面章节详细解释。import numpy as np # 环境定义 n_rows, n_cols 4, 4 n_states n_rows * n_cols n_actions 4 # up, down, left, right terminals [0, 15] def is_terminal(s): return s in terminals def step(s, a): 返回 (next_state, reward)若越界则原地停留但获得 -1 奖励。 r, c s // n_cols, s % n_cols if is_terminal(s): return s, 0 if a 0: # up r max(r - 1, 0) elif a 1: # down r min(r 1, n_rows - 1) elif a 2: # left c max(c - 1, 0) elif a 3: # right c min(c 1, n_cols - 1) return r * n_cols c, -1 def greedy_policy_from_values(V, gamma1.0): 根据价值表 V 贪心生成策略。 policy np.zeros(n_states, dtypeint) for s in range(n_states): if is_terminal(s): continue q_vals [] for a in range(n_actions): s_next, r step(s, a) q_vals.append(r gamma * V[s_next]) policy[s] int(np.argmax(q_vals)) return policy def value_iteration(gamma1.0, theta1e-4, max_iter1000): V np.zeros(n_states) for it in range(max_iter): delta 0.0 for s in range(n_states): if is_terminal(s): continue v V[s] q_vals [] for a in range(n_actions): s_next, r step(s, a) q_vals.append(r gamma * V[s_next]) V[s] max(q_vals) delta max(delta, abs(v - V[s])) if delta theta: print(fConverged at iteration {it 1}) break policy greedy_policy_from_values(V, gamma) return V, policy V_star, pi_star value_iteration() print(Optimal value matrix:) print(V_star.reshape((n_rows, n_cols))) print(Optimal policy matrix (0:up, 1:down, 2:left, 3:right):) print(pi_star.reshape((n_rows, n_cols)).astype(int))这段代码里有两个细节值得注意终止状态直接跳过更新价值固定为 0。若忘了加这一步终止状态会反复被周围状态拉高导致价值矩阵自激发散。更新时用的 V[s_next] 来自当前轮的旧表双数组等下一轮才把新值统一覆盖。实现时如果直接原地改 V 数组相当于用部分新值参与计算收敛行为会不同。4.3 收敛判据与可视化检查运行时程序会打印类似Converged at iteration 6 Optimal value matrix: [[ 0. -1. -2. -3.] [-1. -2. -3. -2.] [-2. -3. -2. -1.] [-3. -2. -1. 0.]]这个结果符合预期从任意格子出发最少要走 6 步左右才能到达终点的方向上价值恰好是负的步数。策略矩阵也基本指向能最快到达终点的方向。实际操作中我建议再加一个可视化把每一轮迭代的最大变化量 delta 打印出来观察它是否单调递减。如果出现反复很大的波动先别急着调参数检查一下终止状态跳步和折扣因子是否写对这类问题往往是环境实现的小错误导致的而不是算法本身的问题。5. 常见问题与排查技巧实录5.1 收敛阈值与最大迭代次数的平衡很多人把阈值调到特别小比如 1e-8结果在 4x4 格栅世界这种规模上还能跑一旦换成 20x20 或更复杂环境程序很久不出结果。经验做法是先设 θ1e-3 跑一遍看趋势再根据业务需求收紧。同时一定要设置最大迭代次数防止因为环境设计有缺陷或 γ1 时长期不满足收敛条件而卡死。还有一种情况是 γ 非常接近 1比如 0.99加上奖励很稀疏、状态链很长这时候价值迭代可能要几万轮才能收敛。解决办法是在迭代轮数上设上限同时中途打印 delta 下降率如果几百轮下来 delta 几乎不动但价值还在缓慢变化要考虑是不是折扣因子过大导致的“长尾传播”正常现象。5.2 双数组更新与原地更新的差异课程第 4 讲最容易出现理解的偏差就是“为什么代码里有人把 V 复制了一份有人直接原地改”。双数组同步方式第 k1 轮的所有更新统一参考第 k 轮的 V 数组不动原始数组更新完成后一起覆盖。价值迭代课内的标准写法常是这个。in-place异步方式第 k1 轮计算一个状态时可能已经用到了本轮的新值。这种方式收敛通常明显更快因为信息传播更高效。格栅世界样本里双数组能让你清楚看到每次迭代的“扩散边界”适合学习。实际工程项目我推荐 in-place迭代轮数可以省 30% 到 50%。唯一要注意的是迭代顺序会轻微影响中间结果但收敛终点相同。5.3 模型已知这个假设在实践里意味着什么“已知模型”听起来很简单但工程里做一个精确的转移概率映射表并不便宜。比如应用在工业机器人抓取场景状态是关节角度和工件位置动作是连续力矩想写清楚 p(s | s, a) 几乎是无法完成的任务。正因如此后面几讲才引入了蒙特卡洛和时序差分这类无模型方法。它们的思想就是既然没法手写环境模型那就让智能体通过与真实环境交互来“收集代替转移概率的样本”。理解了这层递进关系整门课程的主线就很清楚了——动态规划是那个“假设什么都给你算好的演算稿”后面的方法则一步步把假设松开。严格意义上动态规划属于“有模型”强化学习课程里通常把它看作理论起点。如果你将来做规划控制方向它依然能直接用到如果做游戏 AI 或推荐系统更多价值在于帮助你理解后续算法的推导而不是直接调用动态规划。5.4 动态规划的后续影子模型预测控制与深层强化学习动态规划的价值不止于这门课本身。在机器人控制里广泛使用的模型预测控制会在一个很短时间窗里反复做类似的规划求解用到的正是动态规划的分层决策思想。在深度强化学习里基于模型的强化学习也正逐渐回归因为人们发现纯粹无模型方法在样本效率上始终不够于是又把环境预估模型和规划式求解重新捡起来。另外策略迭代的“评估——改进”循环在深度强化学习中演化成了 Actor-Critic 框架Critic 负责价值评估Actor 负责策略提升两者交替更新本质上还是动态规划那套循环结构。只是把“查表更新”换成了“梯度下降”把“真实模型”换成了“经验回放”。如果有余力建议把 DDPG 或 PPO 的算法结构图摊开对照动态规划的循环来读很多模块设计会突然变清晰。个人体会是动态规划就像下棋时的把整盘棋摆在面前推演能算得很准但现实更多时候只能走一步看一步。把这一讲的迭代思想彻底消化后后续所有内容都是在问同一个问题“如果环境不能全知我该靠什么信息来代替那张状态迁移表”带着这个问题去学后面的课程推进会顺畅很多。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表