五个词,就够描述整件事
强化学习的论文看起来吓人,一半是因为符号多。但那些符号背后只有五个概念,而且你玩任何一款游戏的时候都在用它们。这一章你自己走一局,边走边把名字对上。
五个词
先摆出来,然后一个一个说:
| 中文 | 英文 | 符号 | 一句话 |
|---|---|---|---|
| 状态 | state | s | 此刻你能看到的一切 |
| 动作 | action | a | 此刻你能做的选择 |
| 奖励 | reward | r | 做完之后当场拿到的那个数字 |
| 策略 | policy | π | 看到什么状态就做什么动作的那套习惯 |
| 回报 | return | G | 从现在起,一直到这局结束,总共能拿多少 |
其中最容易混的是最后两个,所以先把它们钉死:
- 奖励是当场的,回报是一辈子的。吃一颗糖,奖励 +1;但如果这颗糖让你蛀牙,回报可能是负的。
- agent 要最大化的是回报,不是奖励。这一个字的差别,撑起了整个卷 II。
自己走一局
下面这个世界你会在这本书里见到很多次。它来自 Russell & Norvig《人工智能:一种现代方法》第 17 章,是强化学习教材里最经典的那个玩具世界:4 列 3 行,中间一堵墙,右上角 +1,它下面一格 −1,起点在左下角。
用四个按钮走。走个七八步,注意三件事:
① 每走一步都会付 −0.04,哪怕什么也没发生。
② 有时候你按了 ↑,它却往旁边去了。
③ 撞墙的时候,你留在原地——但那一步的 −0.04 照付。
一个一个说
状态:此刻你能看到的一切
在这个格子世界里,状态就是「你在哪一格」,一共 11 个(12 格减掉那堵墙)。简单到有点侮辱智商。
但状态可以变得非常复杂。在 Atari 里,状态是连续四帧的画面(为什么是四帧?因为一帧看不出球在往哪飞)。在 QWOP 里,状态是躯干和四个关节的角度加角速度,十几个实数。在 ChatGPT 的 RLHF 里,状态是到目前为止的整段对话。
整套理论都建立在一个假设上,叫马尔可夫性:知道当前状态,就足以做出最好的决策,过去怎么来的不重要。
听起来很抽象,但违反它的后果非常具体。假设你把 Atari 的状态定义成「当前这一帧」——那么屏幕上有一个球,你看不出它是在往上飞还是往下落。同一张图,最优动作可能完全相反。这个 agent 无论训练多久都学不好,不是因为算法不行,是因为你给的状态里根本没有那个信息。
DQN 那篇论文堆四帧,就是在给状态补速度信息。这是最朴素也最有效的修法。
还有一个反方向的坑:状态里塞太多没用的东西(比如画面上的时钟、玩家名字),会让状态空间白白爆炸,学习变慢。「状态里该放什么」是一个人做的设计决定,而且它比大多数人以为的更影响成败。
动作:此刻你能做的选择
这里是四个方向。分两大类,这个分类会一路影响到你该选哪个算法:
- 离散动作:上下左右、按或不按。Atari 是 18 个离散动作。DQN 这一系只能处理离散动作,因为它要对所有动作取
max。 - 连续动作:关节该用多大力矩,方向盘该打多少度。这类问题上你不可能「枚举所有动作取最大」,所以要用第 17 章之后的策略梯度那一系。
奖励:当场拿到的那个数字
这一章最重要的一句话在这里:奖励是环境给的,但环境是人写的。
上面那个格子世界里的 −0.04,是有人坐下来决定的。它不是物理定律,是一个设计选择。第 6 章你会看到,把这个数字从 −0.04 改成 −2,最优策略会变成直接冲进那个 −1 的格子把这局了结掉——活着太贵了,不如早死早超生。
没有任何规则被改动,改的只有一个数字。
策略:那套习惯
策略 π 是一个函数:给它一个状态,它告诉你做什么动作。这就是我们最后真正要的东西——训练完成后,你保存下来的就是这个 π。
它有两种形态,对应两大流派:
- 确定性策略:π(s) = a。「在这一格,就往右。」上面那个 demo 里网格上的琥珀色箭头就是它。
- 随机策略:π(a|s) = 概率。「在这一格,70% 往右,20% 往上,10% 往下。」
为什么要随机?两个原因,都很实在:一是探索(下一章的主题);二是有些问题的最优策略本来就是随机的——比如石头剪刀布,任何确定性策略都会被人摸清。
回报:从现在起到结束,总共能拿多少
这是唯一一个需要一点符号的地方。回报是从当前这一步开始,往后所有奖励的(打了折的)总和:
G = r + γr + γ²r + γ³r + ……
t t+1 t+2 t+3 t+4
那个 γ 是折扣因子,下一卷第 6 章整整一章都在讲它。现在你只要知道:它介于 0 和 1 之间,作用是让远处的奖励值钱少一点。
关键在于——agent 要最大化的是 G,不是 r。这一个字的差别,就是「贪吃」和「有远见」的差别,也是整个卷 II 存在的理由。
┌─────────────────────────────┐
│ │
↓ 动作 a │
┌───────┐ ─────────────→ ┌──────────┐
│ agent │ │ 环境 │
└───────┘ ←───────────── └──────────┘
状态 s' 奖励 r
就这一张图。这本书剩下的二十二章,全部是在回答同一个问题:拿到那个 r 之后,该怎么改进 π。
顺带把边界划清楚:左边那个框是你训练的,右边那个框是你写的。算法在左边,奖励函数在右边。而这本书认为,右边那个框被严重低估了。
回合与轨迹
还有两个词,顺手认了:
- 回合(episode):一局。从开始到「摔倒了」或者「走到终点了」。有些问题没有回合——比如一台永远运行的推荐系统,那叫持续性任务,第 6 章会说它为什么必须打折。
- 轨迹(trajectory):一局里发生的全部序列,
s₀ a₀ r₁ s₁ a₁ r₂ ……。上面 demo 里那个日志就是一条轨迹。所有强化学习算法,本质上都是在消化这种东西。
Gymnasium 的接口设计得非常直白——它就是上面那张图:
import gymnasium as gym
env = gym.make("CliffWalking-v0")
state, info = env.reset(seed=42) # ← 状态
total = 0
for t in range(200):
action = policy(state) # ← 策略:状态 → 动作
state, reward, terminated, truncated, info = env.step(action)
total += reward # ← 回报:奖励的累加
if terminated or truncated: # ← 回合结束
break
五个词,一个不多一个不少。你以后读到的任何一份训练脚本,剥掉外面那层库,核心都是这个循环。
一处容易踩的细节:step() 返回五个值,而且 terminated(真的结束了,比如摔倒)和 truncated(时间到了被掐断)是两回事。这不是啰嗦——第 11 章你会看到,被掐断的回合不能当成真的结束来算回报,否则 agent 会误以为「时间到」是一种终局,学出奇怪的策略。老版 gym 只返回 done 一个布尔值,正是因为这个坑才拆成了两个。
现在你可以把 QWOP 那个视频翻译成五个词了:
- 状态:躯干角度、两条腿四个关节的角度和角速度,大概十几个实数
- 动作:四个键各自按或不按,2⁴ = 16 种组合(或者更常见的:四个连续的力矩值)
- 奖励:这一帧往前挪了多少米,减去一点点能量消耗,摔倒扣一大笔
- 策略:一个小神经网络,十几个实数进去,四个数出来
- 回报:这一局总共跑了多远
你现在能看懂它的全部输入和全部输出了。中间那个「怎么改进」,是接下来二十二章的事。
这一章的一句话
状态、动作、奖励、策略、回报——五个词描述完整个领域。而其中只有一个是你亲手写的:奖励。
下一章:我们把这个循环砍到最小——去掉状态,去掉转移,只剩下「选哪个」。剩下的东西叫多臂老虎机,它只有一个矛盾,但那个矛盾贯穿整门学科:你该去试试新的,还是守着已知最好的?