尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

强化学习中的蒙特卡洛方法:从经验到价值估计的实践指南

强化学习中的蒙特卡洛方法:从经验到价值估计的实践指南 很多人在学强化学习时会遇到一个奇怪的错位前面刚接触马尔可夫决策过程、贝尔曼方程觉得数学推导好像也不难一旦到了蒙特卡洛方法这一课突然听到“随机采样”“完整回合”“平均回报”反而会问这个方法到底在解决什么问题这不是你的错觉。蒙特卡洛方法表面上比动态规划简单但它换了一套完全不同的认知方式——不再通过环境模型推导所有状态的价值而是让智能体一局一局地试从完整经验里总结出“哪些状态更值得待”。我的判断是蒙特卡洛方法不是一门随机采样的“笨办法”而是强化学习里把“经验”直接沉淀为“价值估计”的最朴素起点。它的价值不在于公式高级而在于它逼着你理解四个关键细节完整回报、回合边界、访问口径、增量更新。如果你能把这四件事彻底想清楚后面学时序差分、Q-learning、Actor-Critic都会顺畅很多。1. 蒙特卡洛方法到底改变了什么1.1 真正核心的转变不再需要环境模型在蒙特卡洛方法出现之前强化学习的理论基础主要围绕动态规划展开。动态规划解决一个小型马尔可夫决策过程的方法是先知道状态转移概率再不断迭代贝尔曼方程最终求出每个状态的价值。这套方法干净、优雅、有理论保证但它有一个巨大的前提——你必须拿到环境的“说明书”。很多现实环境根本没有说明书。你不可能知道一个机械臂所有关节动作转移的确切概率也不可能列出无人车在每一帧图像上的完整状态转移矩阵。这时候你能获得的信息只有一个不断和环境交互记录“我看到了什么状态、做了什么动作、最后得到了多少奖励”。蒙特卡洛方法的核心转变就在这里它把价值估计从“基于模型的推导”变成了“基于经验的统计”。不再问“如果从这个状态出发理论期望回报是多少”而是问“我实际从这个状态出发试了很多次平均回报是多少”。这个转变有点像学生备考动态规划是照着教材目录一章一章把所有公式推一遍蒙特卡洛是直接做历年真题从错题和得分里反推哪些知识点重要。前者要求你拥有完整的知识地图后者只需要你愿意花时间做题并且能从结果里总结规律。也正因为这种转变蒙特卡洛方法成为很多入门教程里第一个真正意义上“不需要环境模型”的强化学习算法。1.2 一个公式理解蒙特卡洛的价值估计蒙特卡洛方法估计状态价值的逻辑非常朴素。假设在回合制任务中智能体在一个回合里访问了状态序列(s_0, s_1, s_2, ..., s_T)每一步都会获得一个即时奖励 (r_1, r_2, ..., r_T)。那么在时刻 (t) 之后累计获得的带折扣回报是[ G_t r_{t1} \gamma r_{t2} \gamma^2 r_{t3} \cdots \gamma^{T-t} r_T ]这个 (G_t) 就叫回报Return。它和单步奖励的区别在于单步奖励只代表“这一步做得好不好”而回报代表“从这一步开始到回合结束整个后续过程的总收益”。状态 (s) 的价值理论上是“从状态 (s) 出发后续所有可能的回报的期望”。蒙特卡洛方法不计算这个期望而是用大量采样后的平均回报来逼近[ V(s) \approx \frac{1}{N(s)} \sum_{i1}^{N(s)} G_t^{(i)} ]其中 (N(s)) 是所有回合中访问过状态 (s) 的次数(G_t^{(i)}) 是第 (i) 次访问该状态时得到的回报。这个公式看起来非常简单但它隐含了三个非常关键的工程决策回报必须是一个完整回合结束后才能计算的值每个状态要有足够多的访问次数多次访问同一个状态时哪些回报应该进入平均。很多人写代码时发现结果不稳定问题几乎都出在这三个决策没有做对。1.3 为什么动态规划的“一键求解”在这里不适用要真正理解蒙特卡洛方法的位置最好把它和动态规划放在一起对比。动态规划依赖贝尔曼方程每轮迭代都会用当前所有状态的估计值去更新一轮新的估计。它的信息是全局的更新是同步的理论上可以一步步收敛到精确解。代价是你必须知道状态转移概率 (P(s|s,a)) 和奖励函数 (R(s,a))。蒙特卡洛方法则完全不同。它不做全局扫描只采样一条完整的轨迹再往回更新这条轨迹中出现的状态。换句话说它把“环境模型”这个前置条件换成了“大量样本”这个后置成本。这个取舍导致了两个直接后果好处只要你能在环境里跑回合就能估计价值不需要任何模型。代价样本量要求高方差大。单次采样得到的回报可能非常极端比如你玩一个随机性很强的游戏某一局可能因为运气好得到巨额奖励另一局可能立刻失败。平均很多局之后数字才会慢慢稳定下来。这也是蒙特卡洛方法所有后续讨论的总源头它不是不正确而是噪声大。不是不能用而是需要足够多的经验才能得到可靠估计。对比维度动态规划蒙特卡洛方法是否需要环境模型需要状态转移概率和奖励函数只需要可以从环境中采样更新方式全局扫描所有状态同步更新按回合采样只更新访问过的状态估计目标贝尔曼方程的精确解完整回报的样本平均方差低高典型场景小规模、模型已知的规划问题回合制、可反复试错的学习问题这张表值得反复看。你后面遇到的很多强化学习算法争议本质上都逃不开“是否需要模型”和“如何平衡偏差与方差”这两个问题。2. 四个概念把蒙特卡洛从公式变成直觉2.1 回报Return不是单步奖励而是整条轨迹的“总账”很多初学者会犯一个非常自然的错误以为状态价值就是“从这个状态出发下一步能拿多少奖励”。这是把即时奖励和回报混为一谈了。在强化学习里一个状态的价值从来不是看眼前这一步而是看从这个状态出发后续整个过程的总体收益。蒙特卡洛方法之所以强调“完整回合”就是因为它必须等到一条轨迹全部走完后才能把所有后续奖励汇总成一个总账。这个“总账”要用折扣因子把未来的奖励折算到现在。为什么要折扣两个原因数学上无限长度任务的回报可能发散折扣之后才能保证收敛。直觉上未来的奖励具有不确定性今天拿到100元和一年后拿到100元价值不同。回报计算还有一个对代码影响很大的特性它必须从回合末尾开始反向累加。最后一个状态的回报就是它拿到的最后一个奖励倒数第二个状态的回报等于它的即时奖励加上折扣后的后续回报。如果你在代码里正向遍历轨迹并试图累加回报很容易把后续奖励算错。这个细节看着小但几乎所有第一次实现蒙特卡洛方法的人都会在这个位置返工。它会直接影响价值估计的正确性而且报错不一定出现很可能只是数值偏得离谱。2.2 回合Episode是蒙特卡洛方法成立的前提蒙特卡洛方法要做样本平均前提是“样本”是完整且有界的。换句话说你得有“一局结束”的概念。回合制任务天然满足这个条件。棋类游戏有一局终局二十一点会有加牌或停牌直到分出胜负这些任务中都存在明确的终止状态。蒙特卡洛方法等到终止状态出现后才能回过头更新整个过程中所有访问过的状态。如果任务不是回合制的呢比如一个机械臂需要持续跟踪目标没有明确的终止点。这时回报会一直累积无法从“完整轨迹”的角度计算总账。虽然可以人为设置一个“截断点”但截断会破坏回报的完整性导致估计出现偏差。这就是蒙特卡洛方法最本质的边界之一它天然适合“会结束的任务”不适合“理论上永远持续的任务”。后面学到的时序差分方法解决的核心问题之一就是不需要等到回合结束也能更新价值这是它比蒙特卡洛方法更灵活的原因。但在入门阶段理解这个边界很重要。不是因为蒙特卡洛方法“落后”而是因为它的假设造就了它的适用场景。2.3 首次访问 vs 每次访问一个影响偏差与统计效率的选择在一个回合里同一个状态很可能出现不止一次。比如走迷宫时智能体可能绕了一圈回到同一个格子。那这个状态在这个回合里有多次回报可以累计如何处理这多次访问蒙特卡洛方法有两种口径首次访问first-visit只记录每个状态在本回合中第一次被访问时对应的回报。每次访问every-visit记录每个状态在本回合中每一次被访问时对应的回报。两者都能用但性质略有不同。首次访问的估计更“干净”因为它每回合最多只给一个状态贡献一个回报样本避免了同一回合内多次访问带来的依赖。每次访问能用上更多数据但同一回合内多个回报之间本身不独立可能让统计推断更复杂。实际工程中我见过不少代码默认每次访问因为实现最简单但在讨论理论和收敛性时很多教材会优先讲首次访问。对于入门来说重要的是不要忽略这个口径选择至少在代码里明确写清楚自己用的是哪一种。因为当两个价值估计结果不一致时你首先要审查的是这类基础设定而不是去怀疑算法本身有问题。2.4 平均回报价值的本质是“期望”不是“某一次运气”蒙特卡洛方法用“平均回报”来估计状态价值。这里要特别强调一个容易被忽略的点价值不是一个确定数值而是一个期望。假设某个状态可能出现三种后续结果回报为10、20、30对应概率各占三分之一。那么理论上这个状态的价值是20。但如果你只采样到一次回报30蒙特卡洛估计就会把价值误认为30。只有当你采样足够多次让三种结果都按比例出现平均值才会慢慢靠近20。理解这一点后你就能明白为什么蒙特卡洛方法需要足够的回合数。不是跑几局就能得到稳定价值的。你得到的不是一个确定的答案而是“在当前样本量下对期望的估计”。样本越少方差越大样本越多估计越稳定但代价是需要在真实环境里跑很多局。这个“用样本平均逼近期望”的思想是蒙特卡洛方法的引擎。它不复杂却贯穿了几乎所有基于采样的强化学习算法。3. 从零实现一次蒙特卡洛策略评估3.1 环境怎么选先满足“可重复、回合制、有限步”我第一次写蒙特卡洛代码时踩过一个不算大但很烦的坑选了一个状态空间很大的连续控制环境结果回合长度太长每次跑一个完整的轨迹都要等很久而且价值表根本没法用离散表存。蒙特卡洛方法入门最好的环境需要有四个特点回合制任务有明确的终止点最好是很快能结束。状态可重复访问同一个状态在多次采样中能反复出现。状态空间有限或可以离散化因为经典蒙特卡洛方法通常用查表方式存价值。奖励有区分度不同状态带来的回报差异要能观察得到。如果你只是想理解代码二十一点、简单的格栅世界、或者一个自定义的“走迷宫到终点”的回合制任务都可以。关键是别在一开始就引入高维连续环境。先在小环境上把蒙特卡洛的回报计算、访问判定、价值更新搞清楚比跑一个大而花哨的工程更重要。3.2 最小示例结构轨迹、回报、价值表三件套下面给出一个通用结构不是某个具体框架的完整代码而是用来展示蒙特卡洛策略评估内部发生的三件事生成轨迹、反向累加回报、按访问口径更新价值。import numpy as np def generate_episode(env, policy): 跑出一个完整回合返回 (状态, 动作, 奖励) 的轨迹。 episode [] state env.reset() done False while not done: action policy(state) next_state, reward, done env.step(action) episode.append((state, action, reward)) state next_state return episode def mc_first_visit_evaluate(env, policy, num_episodes5000, gamma0.9): returns_sum {} returns_count {} for _ in range(num_episodes): episode generate_episode(env, policy) visited_states set() G 0 # 关键从轨迹末尾反向遍历累加完整回报 for state, _, reward in reversed(episode): G reward gamma * G if state not in visited_states: visited_states.add(state) returns_sum[state] returns_sum.get(state, 0.0) G returns_count[state] returns_count.get(state, 0) 1 V {} for state in returns_sum: V[state] returns_sum[state] / returns_count[state] return V这个结构里最值得注意的就是G reward gamma * G这一行。从轨迹末尾开始每一步的回报都等于当前奖励加上折扣后的后续回报。如果你从正向去累加你会把顺序搞反得到完全错误的估计。同样值得注意的位置是if state not in visited_states它对应首次访问口径。如果你想用每次访问就删掉这个判断让每个状态在本回合中每次被访问时都更新一次。两种口径的结果可能差异不大但你要知道自己选择了哪一种。3.3 单任务跑通的判断标准代码能运行不等于代码正确。跑完一次蒙特卡洛策略评估后我会按下面几个标准检查结果价值表是否覆盖了所有“有意义的可达状态”。如果某些状态从未被访问过说明环境初始状态分布或策略导致这些状态根本没有机会出现。访问次数是否足够。某个状态如果只被访问了两三次它的价值估计会非常不稳定不能当作可靠结论。价值趋势是否符合直觉。比如离终点越近的状态价值应该越高奖励为正的状态价值大概率不应该为负。重复运行结果是否稳定。由于使用了随机采样两次运行之间会有波动但价值的大体排序和数值范围应该接近。如果两次结果差别极大说明回合数太少或探索策略太极端。这些检查不复杂却能拦住大部分运行“成功”但逻辑有误的代码。3.4 最容易写错的三个位置结合我见过的代码和初学时的教训下面三个位置是大多数问题所在。第一回报计算方向反了。很多人在正向遍历轨迹时试图用“已收集的奖励和”作为回报这样算出来的不是一个状态到回合结束的完整回报而是从回合开始到当前步的部分奖励语义完全错误。第二在回合结束前更新价值。蒙特卡洛方法必须等一个完整回合结束后才能知道后续回报是多少。如果你在轨迹生成到一半时就开始累计更新你用的就不是完整回报。第三访问口径没写清楚。有些代码把首次访问和每次访问混在一起或者在不同环境下计算结果飘忽却不知道原因。建议在每个实现里明确注释当前是用首次访问还是每次访问方便后续排查。这些都不涉及高深数学但会决定你的蒙特卡洛实现是“看似运行”还是“真正正确”。4. 工程与调试采样策略比公式更容易决定结果4.1 探索策略epsilon 不是越大越好也不是越小越好蒙特卡洛方法的价值估计依赖采样到足够的轨迹。如果策略总是选同一条固定路径那么很多状态根本不会被访问价值表会出现大片空白。解决这个问题最常用的办法是 (\epsilon)-greedy 策略以大概率选择当前认为最优的动作以小概率随机选择其他动作。这个随机选择的部分就是“探索”。但探索的比例要控制。(\epsilon) 太大策略会变得非常随机采集到的轨迹很难反映策略本身的水平(\epsilon) 太小又可能错过很多重要状态。作为入门起点把 (\epsilon) 设成 0.1 左右通常是一个稳妥的选择。动手实验的时候可以固定随机种子先跑一个较小的 (\epsilon)比如 0.05再跑一个 0.2 的结果做对比。你会直观看到探索不足时价值表很多状态是空的探索过多时价值表虽然满但数值波动更大。这个对比比任何理论学习都更能帮助理解“探索与利用的平衡”。4.2 回合数量与收敛一次评估至少跑多少局这个问题没有标准答案因为它取决于环境本身的随机性和状态空间大小。但可以从经验上给一个参考先跑一个比较小的数量比如 1000 回合把价值表打印出来再跑 5000 回合对比差异如果差异仍然很显著就继续增加。不要一上来就把回合数设成 100 万。那样只会浪费时间而且因为输出巨大反而不容易观察趋势。先跑少量回合确认流程正确再逐步增加是效率最高的做法。观察的手段也不是只看最终数字。你可以每隔若干回合记录一次某个关键状态的价值看看它是否在波动中逐渐稳定。如果一条价值曲线始终在剧烈震荡问题往往不是回合数不够而是回报方差太大、探索策略过激、或者环境随机性极强。4.3 折扣因子 gamma改动一个数字回报语义全变(\gamma) 看起来只是一个 0 到 1 之间的数字但它决定了你如何评价未来奖励。(\gamma 0) 时回报只等于下一步奖励价值完全无视长期收益。 (\gamma 1) 时回报是所有后续奖励的累加模型会平等对待每一个未来时刻。 (\gamma) 在 0 到 1 之间时越靠后的奖励对当前价值的影响越小。如果你在一个回合长度有限的任务上做蒙特卡洛评估(\gamma) 设成 0.9 或 1.0 都能接受。但要注意改动 (\gamma) 之后同一个状态的“正确答案”也变了。不能拿 (\gamma0.9) 的结果和 (\gamma1.0) 的结果直接比较说某个实现不对。它们估计的根本不是同一个价值。4.4 排查链路从现象到原因的固定顺序如果你发现蒙特卡洛方法的结果不对不要急着怀疑算法更不要急着换更复杂的模型。按以下顺序排查先看现象。价值表是空、震荡、还是整体偏大偏小这决定了排查方向。再看输入。状态表示是否正确奖励是否在正确位置赋值回合终止条件是否触发了再看环境。是否设置了随机种子环境每次重置后是否回到相同初始状态奖励尺度是否极端再看参数。回合数、(\epsilon)、(\gamma)、首次访问/每次访问这些改动是否会改变结果方向。最后才考虑算法边界。如果任务本身不是回合制或者状态空间大到不可能遍历那蒙特卡洛方法就不适合直接使用。这个顺序不要颠倒。很多问题最后都出在最基础的那层奖励赋值位置错了或者状态没有正确更新。5. 蒙特卡洛方法的边界哪些场景该用哪些场景千万别硬上5.1 适合的场景回合制、离线数据、策略评估与诊断蒙特卡洛方法的天然主场是回合制任务。只要每个“局”都有明确结束点并且你可以在环境中反复试错蒙特卡洛方法就非常适合作为第一个价值估计工具。它还有一个容易被忽视的价值离线评估。如果手头已经有一批与环境交互产生的轨迹数据不需要再重新部署智能体直接用蒙特卡洛方法对这些轨迹做平均就能估计某个策略的价值。这个思路在离线强化学习里非常重要因为离线强化学习的核心问题之一就是如何从“固定历史数据”中做出靠谱的价值估计。在强化学习入门阶段蒙特卡洛方法也是最好的诊断工具。它能让你亲手看到“状态价值来自完整回报的平均”而不是来自某一次运气。后续学到的很多概念比如优势函数、GAE、n步回报都能从这里找到根源。5.2 不适合的场景连续任务、高维状态、实时决策蒙特卡洛方法不适合连续任务。没有终止点就无法定义“完整回报”样本平均也就无从谈起。它也不适合高维状态空间。经典查表式价值表达要求你为每个状态保存一个数值。一旦状态是你无法穷举的连续值查表方式就失效了。你可以用函数近似代替查表但那已经不是最原始的蒙特卡洛策略评估。样本效率也是一个大问题。蒙特卡洛方法必须等到回合结束才能更新如果你的环境一个回合要跑很久或者每次交互都需要大量真实成本那么只靠蒙特卡洛方法做学习会非常慢。机械臂强化学习实战里经常要面对连续动作空间和昂贵采样单纯用蒙特卡洛评估策略通常很难在实际算力内拿到可用的价值估计。这类场景需要的是把“完整回报”和“逐步更新”结合起来的更现代的方法。5.3 从 MC 到 TD为什么说 TD 是更“在线”的升级要理解蒙特卡洛方法的位置必须知道你下一步会遇到什么。时序差分Temporal Difference, TD方法和蒙特卡洛方法最核心的区别是TD 不需要等到回合结束它只根据下一步的奖励和下一步状态的估计值就能更新当前状态的价值。这个行为叫“自举”因为它用估计值来更新估计值。对比维度蒙特卡洛方法时序差分方法更新时机回合结束后每一步都可以更新是否自举否用真实完整回报是用下一步的估计值偏差无偏在首次访问口径下有偏方差高低适合任务回合制任务优先分段或连续任务更灵活这张表的背后是一个经典的偏差与方差权衡。蒙特卡洛方法使用真实完整回报所以无偏但需要大量采样方差高。TD 方法只用一步真实奖励和已有估计方差低但会引入偏差。TD 的灵活性让它成为 Q-learning、SARSA 等经典强化学习算法的基础。不过也正因为 TD 引入了自举它的理论分析比蒙特卡洛方法更复杂。对于入门者来说先掌握蒙特卡洛方法再理解 TD 的“一步自举”学习曲线会更平稳。5.4 在深度强化学习和离线强化学习里MC 还有位置吗很多人学完蒙特卡洛方法后就开始学深度强化学习会误以为 MC 只是历史包袱。实际上在深度强化学习中MC 的思想依然存在只是换了一种形态。比如 n 步回报就是一种介于 MC 和 TD 之间的折中用 n 步真实奖励加上后续状态的估计值作为回报目标。当 n 趋于一个完整回合的长度时它就更接近蒙特卡洛方法。再比如一些策略梯度算法中用完整回报估计优势函数本质上也是在使用蒙特卡洛采样经验。离线强化学习里“从固定数据集中估计策略价值”这个需求更容易让人想到 MC 式平均。像 IQLImplicit Q-Learning这类离线强化学习方法会特别关注如何避免使用超出数据集分布的动作价值其中一个核心问题就是如何从已有轨迹中做可靠的价值评估。虽然它们不会只靠 MC但 MC 提供的“完整回报平均”思想依然是理解这些方法的重要基础。因此不要因为蒙特卡洛方法简单就不重视它。很多深度强化学习中的采样效率、回报计算、方差控制问题翻来覆去还是在和“如何从经验里估计期望”打交道。如果你正准备照着课程代码跑一遍蒙特卡洛我的建议很简单先别急着把神经网络接上去。找一个小型回合制环境自己把轨迹生成、回报累加、访问口径、价值平均这四个步骤逐一写清楚。当你亲眼看到某个状态的价值从第一次采样的极端值慢慢落到一个稳定数字附近时你对“强化学习如何从经验中学习”这件事的理解才算真正落了地。
返回列表