大模型- 强化学习-两种核心的方法 -76
Https://newfacade.github.io/notes-on-reinforcement-learning/03-approach.html
通俗易懂的讲解
这个网页主要介绍了在强化学习(Reinforcement Learning, RL)中,我们用什么方法来“训练”一个智能体(比如一个机器人或者游戏角色),让它学会在特定环境中做出最好的决策。
想象一下,你正在训练一只小狗(智能体)做各种动作。你怎么告诉它在什么情况下该做什么动作呢?网页里提到了两种核心方法:
- 基于策略的方法 (Policy-Based Methods)
这种方法最直接,就像是给小狗一本“行为手册”。
策略 (Policy) 是什么? 它就是智能体的“大脑”或者说“行为准则”。它直接告诉智能体,在看到某个状态时(比如“看到主人拿出球”),应该采取什么行动(比如“跑过去准备接球”)。
如何训练? 我们的目标就是直接优化这本“行为手册”,通过不断的尝试和调整,让手册里的指令变得越来越好,最终让小狗能根据手册做出最棒的决策,获得最多的奖励(比如零食)。
这个策略可以是确定性的(比如,每次看到红灯,都100%停下来),也可以是随机性的(比如,玩石头剪刀布时,以1/3的概率出石头、1/3的概率出剪刀、1/3的概率出布)。
简单来说,基于策略的方法就是直接学习“做什么”。
- 基于价值的方法 (Value-Based Methods)
这种方法不直接告诉小狗该做什么,而是让它学会判断一个处境的“好坏”,然后它会自然地选择走向“更好”的处境。
价值 (Value) 是什么? 它用来评估一个状态或者一个“状态-动作”组合有多好。这里的“好”指的是从这个状态出发,未来能获得的奖励总和的期望值。
两种价值函数:
状态价值函数 (State-Value Function): 评估的是“处在某个状态有多好”。比如,对小狗来说,“在饭碗旁边”这个状态的价值就很高,因为很可能马上就有吃的了;而“在吵闹的马路中间”这个状态的价值就很低,因为很危险。智能体会倾向于从价值低的状态转移到价值高的状态。
动作价值函数 (Action-Value Function): 评估的是“在某个状态下,做一个特定动作有多好”。比如,在“主人拿着飞盘”的状态下,“跑向飞盘”这个动作的价值就很高,而“原地睡觉”这个动作的价值就很低。
如何训练? 我们通过学习来准确地评估出所有状态或状态-动作的价值。一旦智能体知道了什么选择价值最高,它自然就会去选择那个能带来最高价值的动作。
简单来说,基于价值的方法就是通过学习“一个选择有多好”,来间接找到“做什么”。
总结与预告
无论是哪种方法,我们的最终目的都是找到一个最优策略 (Optimal Policy),让智能体在与环境的互动中获得最大的累积奖励。
文章最后也提到了一个挑战:直接计算这些价值函数会非常复杂,因为需要考虑未来所有可能的情况。因此,它预告了下一部分将介绍一个重要的工具——贝尔曼方程 (Bellman equation),这个方程可以大大简化价值的计算过程。
动态规划(Dynamic Programming,DP)的基础
这是一个非常聪明的选择,因为贝尔曼方程正是动态规划思想在强化学习中的核心体现。
一、动态规划的理论
核心思想是什么?
动态规划其实不是一个具体的算法,而是一种解决问题的思想或方法。它一般用来解决最优化问题(Optimization Problems)。
核心思想非常简单:
把一个大的复杂问题,拆分成一系列互相关联的小问题,
先把这些小问题求解出来,
把小问题的答案保存起来(避免重复计算),
最后根据这些小问题的答案,组合出大问题的最终答案。
哪些问题适合用动态规划?
能用动态规划解决的问题,一般需要满足两个特点:
✅ 最优子结构(Optimal Substructure)
通俗解释:
大问题的最优解,包含了它所有子问题的最优解。
举个例子:
如果你找到了北京到上海的最短路线,那么这条路线上从北京到济南这一段,肯定也是北京到济南的最短路线。
如果不是,说明你可以找到更短的路线把它替换掉,这样整个路线就会更短,这就和“最短”矛盾了。
✅ 重叠子问题(Overlapping Subproblems)
通俗解释:
在解决大问题的过程中,很多相同的子问题会被重复计算多次。
举个例子:
假设你在计算一个很复杂的数学表达式,里面 (2+3) 这个小计算重复出现了 5 次。
聪明的做法是:只算一次 2+3=5,然后把结果保存下来。
后面再遇到 (2+3),就直接用 5,而不是再重新算一遍。
动态规划就是这种“记笔记”的思路,编程里叫做记忆化(Memoization),
这样可以避免重复劳动,大大提高效率。
二、经典例子——斐波那契数列
斐波那契数列是讲解动态规划最经典的例子之一。
它的定义是:
F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2) (n > 1)
(1)普通的递归(没有动态规划)
直接按照定义写递归:
要算 F(6),需要先算 F(5) 和 F(4)
要算 F(5),需要 F(4) 和 F(3)
要算 F(4),需要 F(3) 和 F(2)
以此类推……
如果把这个过程画成一棵树,会发现:
F(4) 被算了 2 次
F(3) 被算了 3 次
F(2) 被算了 5 次……
当 n 变大时,这种重复计算会非常浪费时间,效率非常低。
(2)动态规划(避免重复计算)
有两种思路
✅ 方法 A:递归 + 记忆化(由上到下)
还是用递归,但加一个“备忘录”(数组或字典)保存算过的结果。
要算 F(n) 时,先看备忘录里有没有:
有,就直接用
没有,就递归计算 F(n-1) 和 F(n-2),然后把结果存到备忘录
算 F(6) 的过程大概是:
先算 F(2) -> 得到 1 -> 存起来
用 F(2) 和 F(1) 算出 F(3) -> 存起来
用 F(3) 和 F(2) 算出 F(4) -> 存起来
以此类推,直到 F(6)
这样,每个 F(k) 只算一次。
✅ 方法 B:表格法(由下到上)
完全不用递归,直接从小到大,一步步把结果“填表”出来。
建一个数组 dp,长度 n+1
先把 dp[0]=0 和 dp[1]=1 写好
从 i=2 开始,依次算:
dp[i] = dp[i-1] + dp[i-2]
比如:
dp[2] = dp[1] + dp[0] = 1 + 0 = 1
dp[3] = dp[2] + dp[1] = 1 + 1 = 2
dp[4] = dp[3] + dp[2] = 2 + 1 = 3
dp[5] = dp[4] + dp[3] = 3 + 2 = 5
dp[6] = dp[5] + dp[4] = 5 + 3 = 8
最后 dp[6] = 8,就是答案。
这就是动态规划:
用最优子结构:大问题依赖小问题的解
用重叠子问题 + 记忆化 或 表格化:避免重复计算

浙公网安备 33010602011771号