卷 I · 试错CH 02深度 2/24

五个词,就够描述整件事

强化学习的论文看起来吓人,一半是因为符号多。但那些符号背后只有五个概念,而且你玩任何一款游戏的时候都在用它们。这一章你自己走一局,边走边把名字对上。

state / action / rewardpolicy / return回合与轨迹

五个词

先摆出来,然后一个一个说:

中文英文符号一句话
状态states此刻你能看到的一切
动作actiona此刻你能做的选择
奖励rewardr做完之后当场拿到的那个数字
策略policyπ看到什么状态就做什么动作的那套习惯
回报returnG从现在起,一直到这局结束,总共能拿多少

其中最容易混的是最后两个,所以先把它们钉死:

  • 奖励是当场的,回报是一辈子的。吃一颗糖,奖励 +1;但如果这颗糖让你蛀牙,回报可能是负的。
  • agent 要最大化的是回报,不是奖励。这一个字的差别,撑起了整个卷 II。

自己走一局

下面这个世界你会在这本书里见到很多次。它来自 Russell & Norvig《人工智能:一种现代方法》第 17 章,是强化学习教材里最经典的那个玩具世界:4 列 3 行,中间一堵墙,右上角 +1,它下面一格 −1,起点在左下角。

▶ 动手 · 你来当 agent

用四个按钮走。走个七八步,注意三件事

① 每走一步都会付 −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 的 API

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 种组合(或者更常见的:四个连续的力矩值)
  • 奖励:这一帧往前挪了多少米,减去一点点能量消耗,摔倒扣一大笔
  • 策略:一个小神经网络,十几个实数进去,四个数出来
  • 回报:这一局总共跑了多远

你现在能看懂它的全部输入和全部输出了。中间那个「怎么改进」,是接下来二十二章的事。

这一章的一句话

状态、动作、奖励、策略、回报——五个词描述完整个领域。而其中只有一个是你亲手写的:奖励。

下一章:我们把这个循环砍到最小——去掉状态,去掉转移,只剩下「选哪个」。剩下的东西叫多臂老虎机,它只有一个矛盾,但那个矛盾贯穿整门学科:你该去试试新的,还是守着已知最好的?