☰
从MDP到贝尔曼方程:Agentic RL必备的数学地基
2026/10/19 5:19:24 网站建设 项目流程

最近总有人来问我:想做 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_{t+1} + γ R_{t+2} + γ² R_{t+3} + ...

注意下标从 t+1 开始。这是一个约定:智能体在时刻 t 处于状态 S_t,选择动作 A_t,然后环境返回奖励 R_{t+1} 并转移到 S_{t+1}。这个细节很多人第一次都会看错,实际写代码时也非常容易把奖励的时序弄反。

折扣因子 γ 取值在 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_{t+1} + γ (R_{t+2} + γ R_{t+3} + ...)

后面括号里的部分其实就是从 S_{t+1} 出发的回报 G_{t+1}。所以:

V^π(s) = E[R_{t+1} + γ V^π(S_{t+1}) | 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_{k+1}(s) = Σ_a π(a|s) Σ_{s'} P(s'|s, a) [ R(s, a, s') + γ V_k(s') ]

做法很简单:把当前估计 V_k 代入等式右边,计算得到新的 V_{k+1},不断重复,直到数值变化足够小。这个过程在动态规划里叫“策略评估”,相当于给定一个策略,算出它的价值函数。

如果我们要找最优策略,则使用“价值迭代”:

V_{k+1}(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_{t+1} + γ V(S_{t+1}) - 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, gamma=0.9, theta=1e-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, key=lambda 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_{t+1},初学总想写成 R_t。从状态转移的角度看,先有 S_t 和 A_t,再有 R_{t+1} 和 S_{t+1}。如果你写 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 强化学习任务,第一步不是选择算法,也不是定义网络结构,而是先把任务写成五元组,明确状态边界、动作空间、转移结果集、奖励来源。哪怕最终实现的算法完全不是动态规划,这一步也能帮我提前暴露一半的坑。贝尔曼方程不是某个需要绕过的高深公式,它就是你在设计奖励、调整策略、判断价值网络是否收敛时,随时可以用来回到问题原点的标尺。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询