从MDP到贝尔曼方程:Agentic RL必备的数学地基

发布时间:2026/10/19 5:19:39
从MDP到贝尔曼方程:Agentic RL必备的数学地基
最近总有人来问我想做 Agentic RL 方向的实战项目应该先把什么数学补上我的回答几乎永远是同一句话——马尔可夫决策过程MDP和贝尔曼方程。这两个概念在教材里看起来只有三四十页但后续的 RLHF、偏好优化、带工具调用的 agent 训练本质上全是在求解一个 MDP、拟合一个贝尔曼方程。与其一上来就钻进采样和梯度估计不如先把这块地基看透后面少走一半弯路。这篇文章我按自己当初从零啃强化学习的路径来写不打算堆公式吓人。我会先把 MDP 的五元组讲清楚再把回报、价值函数、贝尔曼方程一层层拆开最后落到 Agentic RL 里常见的奖励建模和状态设计问题上。中途会插入一些我实际调模型时踩过的坑。适合刚入门 RL、或者已经跑过几个环境但数学感觉还比较模糊的读者如果你准备用强化学习训 agent 做多步工具调用这篇文章正好当作基础补课。1. 为什么 MDP 是 Agentic RL 绕不开的骨架1.1 先回到经典的五元组MDP 是“马尔可夫决策过程”Markov Decision Process的缩写。它其实就是一套描述“智能体在环境中按步骤做决策”的数学框架。一个 MDP 可以用五元组表示(S, A, P, R, γ)分别对应状态集合、动作集合、状态转移概率、奖励函数、折扣因子。看起来很简单但每个部分都有讲究。状态 S 是所有可能环境状态的集合。动作 A 是智能体在每个状态下能做的事情集合。转移概率 P 描述“在当前状态 s执行动作 a 之后环境会变成哪个新状态”的概率分布。奖励函数 R 给出这一步到底得到多少数值回报。折扣因子 γ 则决定了未来收益在当前视角下值多少钱。我用一个送货机器人举例。假设机器人在一层办公楼里送文件它当前所在的房间是状态它可以做出的移动选择是动作它移动之后可能顺利到达下一个房间也可能被走廊杂物挡住停在原地这种不确定性就是转移概率它成功把文件送到指定房间可以获得奖励如果每走一步都扣一点电量和时间成本那每一步的奖励就是负数。整个任务可以无限循环下去所以需要用折扣因子让远期收益“缩水”避免总和发散。这看起来和 Agentic RL 有什么关系实际上关系很大。语言模型 agent 在解决一个需要多步推理的任务时完全可以套进这个框架当前的对话上下文和工具返回结果是状态下一步生成什么内容或调用哪个工具是动作环境返回的下一条消息是状态转移任务是否成功或过程质量如何是奖励。把问题写进 MDP 之后很多模糊的“训练技巧”就变成有明确数学含义的设计决策了。1.2 马尔可夫性质到底意味着什么MDP 的另一个关键性质是“马尔可夫性”下一个状态只依赖当前状态和当前动作不依赖更早的历史。有点像你打牌时手里的牌已经被重新洗过——过去发生了什么只要已经反映在当前状态里就不再需要额外记忆。这个性质初学者经常忽略但它在实际建模时其实是一个“设计目标”而不是天然成立的东西。语言模型 agent 的原始输入是完整的历史文本如果你把整个历史作为状态那它当然满足马尔可夫性质因为历史没丢但如果你只保留最近几轮对话那状态就没有完全包含决策所需的信息马尔可夫性质就被破坏了。真实世界里智能体往往不能观测到完整状态只能看到部分信息这时候问题会升级为 POMDP部分可观测马尔可夫决策过程。Agentic RL 里这种情形非常常见比如 agent 看不到环境内部的真实变量只能通过工具返回的文本猜测。理解 MDP恰恰是理解 POMDP 的前提也是后面设计 observation 时决定“到底该把哪些信息塞进状态”的理论出发点。2. 回报、折扣和价值函数先学会给策略打分2.1 从单步奖励到折扣回报如果只看每一步的即时奖励很难判断一个策略到底好不好。因为很可能这一小步拿了正奖励但后续几步代价很高也可能当前一步是负的但能把整体局面推向成功。所以我们需要一个“全程视角”的量回报记作 G_t。回报的定义是从 t 时刻开始的所有未来奖励的折扣求和G_t R_{t1} γ R_{t2} γ² R_{t3} ...注意下标从 t1 开始。这是一个约定智能体在时刻 t 处于状态 S_t选择动作 A_t然后环境返回奖励 R_{t1} 并转移到 S_{t1}。这个细节很多人第一次都会看错实际写代码时也非常容易把奖励的时序弄反。折扣因子 γ 取值在 0 到 1 之间。γ 0 意味着只看下一条奖励γ 越接近 1远期奖励权重越大γ 1 在无限时域任务里回报可能发散所以一般取 0.9 到 0.99 之间。在基于语言的任务里γ 也代表“你有多在意长程目标”。如果 agent 每做一步都消耗算力那折扣因子也算是对“过多中间步数”的一种隐式惩罚。2.2 策略与两个价值函数策略 π(a|s) 给出了在状态 s 下选择动作 a 的概率。确定性策略可以直接写成 a π(s)但概率形式更通用因为很多真实环境的最优策略本身就带随机性。现在我们关心一件事给定一个策略它在某个状态下到底有多好于是就有了状态价值函数V^π(s) E[G_t | S_t s]这就是从状态 s 出发按照策略 π 行动所得到回报的期望。期望的意思是把所有随机因素都平均掉动作是采样出来的状态转移是概率性的求期望之后就得到一个确定数字。相应地动作价值函数表示“在状态 s 下先执行动作 a之后按策略 π 继续执行得到的期望回报”Q^π(s, a) E[G_t | S_t s, A_t a]两者的区别V 是评价“在某个状态待着好不好”Q 是评价“在某个状态下做某个具体动作好不好”。实际操作中从 Q 直接得到策略很方便因为你可以选择 Q 值最大的动作而从 V 推出策略还需要额外知道转移概率或策略分布。两者之间有一个恒等式V^π(s) Σ_a π(a|s) Q^π(s, a)也就是当前状态的价值等于所有动作价值的加权平均权重就是策略选择每个动作的概率。这个关系后面推导贝尔曼方程时会反复用到。2.3 用一个极小的例子手算价值我建议初学者一定要亲手算一次价值函数而不是只看公式。举一个两状态例子。状态 s0 是“工作中”状态 s1 是“任务完成”s1 是终止状态。策略π在 s0 时有 50% 概率选择“继续等待”50% 概率选择“放弃”。如果选择“继续等待”环境有 90% 概率回到 s0奖励为 -1有 10% 概率转移到 s1奖励为 10。如果选择“放弃”任务直接终止奖励为 0。折扣因子 γ 0.9。终止状态的 V(s1) 0。手算 V^π(s0)V^π(s0) 0.5 × [0.9 × (-1 0.9 V^π(s0)) 0.1 × (10 0.9 V^π(s1))] 0.5 × 0简化V^π(s0) 0.5 × [ -0.9 0.81 V^π(s0) 1 ] 0.5 × [ 0.1 0.81 V^π(s0) ]得到 V^π(s0) 0.05 0.405 V^π(s0)解得 V^π(s0) ≈ 0.084。这个数字很小因为“继续等待”这条路多数时候都在扣分只有少数时候拿到大奖励。手算的价值意义在于让你真切体会到“按概率折算”到底怎么回事。如果你连这个两层期望都理不顺后面推导贝尔曼方程会很容易被符号绕晕。3. 贝尔曼方程把未来拆开再拼回去的镜子3.1 一次推导胜过十次背诵贝尔曼方程的核心思想只有一句话当前状态的价值 当前这一步的奖励期望 下一状态的折扣价值期望。听起来像废话但它给了我们一个递归结构把无限长的未来压缩成一个方程。从价值定义出发V^π(s) E[G_t | S_t s]把 G_t 拆成第一项和剩余项G_t R_{t1} γ (R_{t2} γ R_{t3} ...)后面括号里的部分其实就是从 S_{t1} 出发的回报 G_{t1}。所以V^π(s) E[R_{t1} γ V^π(S_{t1}) | S_t s]再展开期望明确考虑动作选择和状态转移V^π(s) Σ_a π(a|s) Σ_{s} P(s|s, a) [ R(s, a, s) γ V^π(s) ]这个式子就是状态价值的贝尔曼方程。它说明了三件事策略决定了每个动作被选中的概率转移概率决定了动作之后可能到达哪些状态即时奖励加下一状态的折扣价值构成当前状态的估计初学者最需要注意的是贝尔曼方程里面有 V^π(s)也就是它自己。这个“自我指涉”不是循环错误而是整个动态规划方法的精髓。因为我们可以把这个方程当成一个不动点方程去迭代求解一开始随便给 V 赋初值然后反复套用等式右边更新左边最终会收敛到一个稳定值。3.2 动作价值版本的贝尔曼方程Q 函数也有对应的贝尔曼方程Q^π(s, a) Σ_{s} P(s|s, a) [ R(s, a, s) γ Σ_{a} π(a|s) Q^π(s, a) ]注意第二层求和变成了“在下一状态按照策略选择新动作”的期望。这是正确的因为你已经固定了当前动作 a但到了新状态之后后面所有动作都要按策略 π 来选。从实现角度看Q 版本在实际强化学习算法中更常用。因为 Q 函数可以直接用来做决策选择 Q 值最大的动作。许多经典算法如 Q-learning、DQN 都是围绕 Q 的贝尔曼方程设计的。3.3 从贝尔曼方程到可执行的迭代算法有了贝尔曼方程我们可以把它变成算法。策略评估的迭代公式是V_{k1}(s) Σ_a π(a|s) Σ_{s} P(s|s, a) [ R(s, a, s) γ V_k(s) ]做法很简单把当前估计 V_k 代入等式右边计算得到新的 V_{k1}不断重复直到数值变化足够小。这个过程在动态规划里叫“策略评估”相当于给定一个策略算出它的价值函数。如果我们要找最优策略则使用“价值迭代”V_{k1}(s) max_a Σ_{s} P(s|s, a) [ R(s, a, s) γ V_k(s) ]唯一区别是求和变成了取最大值。含义是在每个状态都假设自己会选最好的动作然后把未来的价值传回来。最终收敛到的 V* 满足贝尔曼最优性方程V*(s) max_a Σ_{s} P(s|s, a) [ R(s, a, s) γ V*(s) ]我不建议你把最优性方程当成独立知识去背把它理解成“在某个状态果断选最好动作然后把未来同样按最好方式处理”就足够了。确定性最优策略只需要对每个状态选让上式取最大值的动作。4. Agentic RL 需要的两次概念升级4.1 第一层升级不再假设环境已知改用估计经典 MDP 里转移概率 P 和奖励函数 R 都是已知的所以可以用动态规划直接解出最优策略。但真实 agent 任务里P 和 R 几乎不可知工具返回什么、用户如何评价结果、环境内部怎么变化都不是我们预先写死的。这时候强化学习从“使用已知模型计算”变成“从数据中估计”。最常见的思路是用策略去和环境交互收集轨迹然后用观测到的奖励和状态转移去逐步修正价值函数。而贝尔曼方程在这里依然有效只是不再用于一次性精确计算而是变成了一个“回归目标”。比如最简单的 TD 学习它定义了一个时间差误差δ_t R_{t1} γ V(S_{t1}) - V(S_t)这个误差的意思是当前状态的价值估计和“实际奖励 下一状态价值估计”之间差了多少。如果 δ_t 很大说明 V(S_t) 被低估了如果 δ_t 为负说明被高估了。然后我们朝正方向调整 V(S_t)直到两者一致。我在做 agent 类项目时最常感受到的一点是很多人容易把价值网络的学习想成“监督式回归”但实际上它拟合的目标本身就是模型自己产生的估计。这种“自举”机制如果不理解贝尔曼方程很难调试。因为一旦训练震荡你会分不清是采样方差问题还是价值网络的目标更新方式有问题。4.2 第二层升级奖励不再天然存在需要建模Agentic RL 里另一个大问题是奖励竞争。一个语言模型执行多步任务最终成功与否有时很容易判断比如代码能否正确运行但更多时候结果质量没有明确标准。于是奖励本身也需要通过学习得到。现在行业里常见的做法有两类一类是用结果模型或者过程奖励模型分别给“最终结果”和“中间步骤”打分另一类是让模型在多个输出之间做偏好排序再用某种偏好模型把这些排序转化成一个标量奖励。无论哪种本质上都是在为 MDP 中的 R 构造一个替代函数。有了替代奖励函数之后仍然要用贝尔曼方程把“当前步骤的局部质量”和“后续过程的长期影响”叠加起来。过程奖励模型特别适合贝尔曼结构你既不想只看最后一步也不想把每个中间奖励简单相加因为不同步骤的质量对最终结果的影响不一样。用价值函数来做长期累积才能避免每次都只盯着眼前一步。我在实际项目里的体会是奖励建模设计和贝尔曼更新是绑在一起的。如果奖励模型给中间步骤打了分但没有用折扣累积去训练价值网络那智能体很容易陷入“每步都做得像局部最优但整体路径很差”的局面。相反合理的价值函数会告诉模型某个中间步骤虽然当前得分不高但它是拿到最终高奖励的必经之路。这个因果关系正是贝尔曼方程的表达方式。5. 最小实现与避坑清单我自己踩过的四个坑5.1 一份可以跑的价值迭代代码为了让上面的数学落到代码我贴一段最简单的价值迭代实现。假设状态、动作、转移概率、奖励都已经字典形式给出。def value_iteration(states, actions, P, R, gamma0.9, theta1e-4): V {s: 0.0 for s in states} while True: delta 0.0 for s in states: v_old V[s] V[s] max( sum(P[s][a][s2] * (R[s][a][s2] gamma * V[s2]) for s2 in states) for a in actions ) delta max(delta, abs(v_old - V[s])) if delta theta: break policy {} for s in states: policy[s] max( actions, keylambda a: sum(P[s][a][s2] * (R[s][a][s2] gamma * V[s2]) for s2 in states) ) return V, policy这段代码把上面讲的价值迭代公式直接翻译成了 Python。theta 是收敛阈值通常取 1e-4 到 1e-6 之间delta 记录一轮迭代中所有状态价值变化的最大值小于阈值就认为已经收敛到不动点。唯一需要注意的是字典结构里三个维度的排列约定P[s][a][s2] 表示从状态 s 采取动作 a 转移到状态 s2 的概率R[s][a][s2] 表示这次转移的即时奖励。大家自己定义数据时要保持三个维度的顺序一致否则索引取错会得到完全错误的答案。5.2 初学时最容易掉进去的四个坑第一忘记折扣因子会导致发散。无限时域任务里如果 γ 1 且奖励每次都不为 0回报的总和很可能无穷大价值函数没法收敛。实际工程里折扣因子通常会设成 0.9 到 0.99不要天真地认为“不折扣更准确”。尤其在长任务 agent 里γ 过大容易让价值网络学习不稳定。第二奖励时序容易弄反。很多教材写 R_{t1}初学总想写成 R_t。从状态转移的角度看先有 S_t 和 A_t再有 R_{t1} 和 S_{t1}。如果你写 R_t会导致当前状态价值混入了上一个动作的结果策略更新方向会偏移。第三转移概率没有归一化。概率分布求和必须等于 1。实践中我见过有人从日志里手动统计转移频次却忘了除以总数结果每个分支概率都小于 1价值被系统性地低估。写代码时最好加一个检查对每个状态动作对把 P[s][a] 里所有 s2 的概率求和必须在允许的误差范围内等于 1。第四过早把 V 和 Q 混用。V 函数不能直接推出“最优动作”除非你再知道策略分布和转移概率。有些初学者在 Q-learning 里误用 V 网络的输出做 argmax这毫无疑问是错的。经验法则很简单要做动作选择就用 Q要评估状态质量才用 V。智能体设计里实际返回动作的往往是 Q 函数而不是 V 函数。6. 马尔可夫性质被破坏时agent 的状态该怎么设计6.1 与其说环境不满足不如说状态没有铺满我在第一部分说马尔可夫性是一个设计目标这一点在 agent 任务里尤其关键。你完全可以把“整个历史文本”作为状态这样马尔可夫性质是天然满足的因为当前状态包含了过去所有信息。问题在于这样做计算成本太高而且很多信息对当前决策影响微乎其微。所以实践中的做法是在“信息完整”和“特征简洁”之间做平衡。我通常先做一件事把 agent 的观测来源列出来比如用户请求、工具返回结果、已执行动作列表、当前工作区文件状态然后写成一个统一的 context 模板。在模板里保留和未来决策高度相关的信息比如关键中间结果、报错信息、任务约束把无关细节丢到摘要里。这个过程本质上是做一个“近似马尔可夫的状态压缩”。如果压缩后信息不够你会观察到一种典型现象两个完全相同的上下文状态agent 执行同一个动作却因为“上一次循环的潜在信号”不同而产生不同结果。这时候算法本身没问题问题出在状态表示上。6.2 我会放在状态里的三类信息从实际项目经验来看MDP 的状态表示失败通常都是因为少了某几类信息。我总结成三块。第一块是任务进度信息也就是当前已经完成了哪些子目标这相当于告诉价值函数“你现在离终点还有多远”。没有进度信息价值函数很难区分“刚开始探索”和“马上要收尾”。第二块是最近一步的反馈尤其是工具输出中的关键信号例如报错类型、返回字段是否为空、执行时间是否异常。这些是转移概率中最能影响后续决策的部分。第三块是约束条件比如“最多还能调用几次工具”或“剩余预算”。如果你把这些写死成全局常数而不放入状态智能体在最后几步的决策会明显不同于前几步但价值函数却感知不到。我见过一次让我印象很深的调试一个代码生成 agent 反复在同一个问题上产生低质量答案表面看是策略收敛不好。最后发现状态里根本没有“当前尝试过的方案列表”导致 agent 无法感知重复尝试马尔可夫性质被破坏后价值函数无论怎么训都是一团糨糊。补上这部分信息后训练稳定性立刻上去了。6.3 从 MDP 到 POMDP 的思维转变前面动不动就提 POMDP核心区别是如果智能体无法直接观测完整状态它只能凭观测来推断一个置信状态。agent 场景天然符合这个设定因为模型不了解任务背后的真实环境变量。但在工程实现里大多数人不会真的去维护一个完整的置信状态分布而是用循环结构或者长期记忆模块去近似这种推断。理解 MDP 的价值在于面对复杂 agent 问题时你至少能识别自己的近似在哪里失效。也就是说当训练效果不对劲时先用马尔可夫性质这把尺子去量一量状态描述是否完整这比调整网络结构和超参数更基础也往往更见效。我个人现在做项目的习惯是拿到任何 agent 强化学习任务第一步不是选择算法也不是定义网络结构而是先把任务写成五元组明确状态边界、动作空间、转移结果集、奖励来源。哪怕最终实现的算法完全不是动态规划这一步也能帮我提前暴露一半的坑。贝尔曼方程不是某个需要绕过的高深公式它就是你在设计奖励、调整策略、判断价值网络是否收敛时随时可以用来回到问题原点的标尺。