强化学习(一):基础与核心概念

用骑自行车的类比把强化学习从零讲清楚:MDP、Bellman 方程、动态规划、蒙特卡洛、时序差分(TD),附带可直接运行的 Python 代码。

第一次坐上自行车的时候,没有人会塞给你一本说明书写着"如果倾角超过 7.4 度,请反向打方向 12%"。你只是不停地试:晃一下、过校一下、摔一跤、爬起来再试。试上几百次以后,身体就"自己知道"该怎么骑了,哪怕你说不出原因。

这个试错—反馈—改进的回路,不光是人学骑车的方式。AlphaGo 击败围棋世界冠军、波士顿动力的机器人学会走路、推荐系统在你每次点击之后悄悄变得更聪明,背后都是同一个数学框架,叫强化学习(Reinforcement Learning,RL)。

这篇文章会从零开始把 RL 的整个地基铺平。我们用"学骑自行车"贯穿全篇,把每一个直觉都翻译成现代 RL 算法所依赖的数学。

你将学到什么

  • 马尔可夫决策过程(MDP)——所有 RL 问题共同的骨架
  • Bellman 方程:把价值函数变得可计算的关键
  • 动态规划:环境规则已知时的精确解法
  • 蒙特卡洛方法:完全靠经验学习
  • 时序差分(TD)学习:连接 DP 与 MC 的桥梁,DQN/PPO 的根基
  • 每一种方法的可运行 Python 代码

前置知识:基本概率和一点 Python;有监督学习经验更佳,但不是必需。


自行车回路

智能体与环境构成一个闭合回路

想象你第一次坐上自行车。每一瞬间都有三件事在飞快地循环:

  1. 你观察:倾角、速度、马路边在哪里。
  2. 你动作:稍微歪一点、稍微转向一点、踩一下脚踏。
  3. 世界回应:车要么稳住、要么继续偏、要么把你摔在地上。

第三步给了你一个信号——稳住时一点小奖励,摔倒时一记重罚。试得多了,大脑就拼出一套策略:从"我现在感觉到什么"映射到"我下一步该做什么"。这套策略从来不写下来,它是被这个回路本身刻进了反射里。

强化学习就是给这个回路写出数学描述。图里的"你"叫做智能体(agent),自行车 + 路面叫做环境(environment),歪一歪、踩一脚叫做动作(action),倾角和速度的读数叫做状态(state),不要摔倒的那种感觉叫做奖励(reward)。文章后面所有的内容,都只是在这张图上认真做账。


马尔可夫决策过程:数学基础

三状态自行车 MDP 的小例子

形式化地,自行车回路是一个马尔可夫决策过程(MDP),写成五元组:

$$\langle \mathcal{S}, \mathcal{A}, P, R, \gamma \rangle.$$

上面的图刻意画得很小:只有三个状态(平衡摇晃摔倒)、几个动作,转移概率和奖励都直接标在边上。所有真实的 RL 问题——机器人控制、围棋、大模型微调——都是同一个结构的(更大的)实例。

五个组件

状态空间 $\mathcal{S}$:智能体可能处于的所有情况。对自行车来说就是倾角、角速度、车速、路面曲率。状态可以是离散的(棋盘格子)也可以是连续的(机器人各关节角度)。

动作空间 $\mathcal{A}$:智能体能做的所有事情。离散(“左倾 / 右倾 / 保持”)或连续(给把手施加 0.37 N·m 的扭矩)。

转移概率 $P(s' \mid s, a)$:在状态 $s$ 执行动作 $a$ 后落到 $s'$ 的概率,也就是环境的"物理规律":

$$P(s' \mid s, a) = \Pr(S_{t+1} = s' \mid S_t = s, A_t = a),\qquad \sum_{s'} P(s' \mid s, a) = 1.$$

实际世界并不确定:一阵风、一颗石子、踩脚踏时一点点不均匀,都可能让你落到完全不同的下一状态。转移概率把所有这些不确定性都打包进去了。

奖励函数 $R(s, a, s')$:完成 $s \xrightarrow{a} s'$ 这步转移之后立即拿到的回报。奖励是智能体唯一的学习信号。设错了,智能体会一丝不苟地优化错误的目标——也就是常说的"奖励漏洞"(reward hacking)。

折扣因子 $\gamma \in [0, 1)$:智能体对未来奖励相对于当下奖励的重视程度。后面会看到,这远不只是个让公式收敛的小技巧。

马尔可夫性质

MDP 的定义性假设非常优雅:未来只取决于现在,与你怎么走到现在无关。

$$P(S_{t+1} \mid S_t, A_t, S_{t-1}, A_{t-1}, \ldots) = P(S_{t+1} \mid S_t, A_t).$$

对自行车来说这看上去有点可疑——上一刻在往哪边偏难道不重要吗?当然重要,但解决办法是把历史折叠进状态本身。如果把状态从单纯的"倾角"扩展为"(倾角,角速度,车速)",马尔可夫性就重新成立了。当年 DeepMind 在 Atari 上把最近 4 帧画面堆成状态,就是出于完全相同的考量。

策略:从状态到动作

策略 $\pi$ 就是智能体的行动准则——把观测映射成决策的函数:

  • 确定性策略:$a = \pi(s)$。同一状态总是给出同一动作。
  • 随机性策略:$\pi(a \mid s) = \Pr(A_t = a \mid S_t = s)$。给出动作上的概率分布。

随机性策略在两个层面上很关键:它让智能体能探索新的行为;它也是神经网络最自然的输出形式(动作上的 softmax)。

回报与价值函数

智能体追求的不是"下一步"的奖励,而是从时刻 $t$ 起的累积折扣回报

$$G_t = r_t + \gamma r_{t+1} + \gamma^2 r_{t+2} + \cdots = \sum_{k=0}^{\infty} \gamma^k r_{t+k}.$$

为什么要折扣?三个独立的理由都指向同一个方向:

  • 数学层面:当 $|r| \le R_{\max}$ 时,几何级数有界 $|G_t| \le R_{\max} / (1 - \gamma)$,无穷视界任务才不会爆掉。
  • 认知层面:今天的奖励比明天的同等奖励更值钱——明天本身有不确定性。
  • 工程层面:没有折扣,一个智能体可以永远什么都不做仍然宣称自己拿到了无穷回报。折扣因子逼它赶紧动起来

由此定义两个价值函数,一个对状态,一个对状态-动作对:

$$V^\pi(s) = \mathbb{E}_\pi[G_t \mid S_t = s], \qquad Q^\pi(s, a) = \mathbb{E}_\pi[G_t \mid S_t = s, A_t = a].$$

口语化解释:$V^\pi(s)$ 回答"按 $\pi$ 走的话,待在这儿有多好?",$Q^\pi(s, a)$ 回答"在这儿先做这个动作、再按 $\pi$ 走,有多好?"。它们之间的关系是:

$$V^\pi(s) = \sum_a \pi(a \mid s) \, Q^\pi(s, a),\qquad Q^\pi(s, a) = \sum_{s'} P(s' \mid s, a)\!\left[R(s, a, s') + \gamma V^\pi(s')\right].$$

Bellman 方程:RL 的递归心脏

Bellman 备份树:今天的价值由明天的价值递推

价值函数有一个非常漂亮的递归结构。这是整个 RL 理论里最重要的一个想法——一旦理解了它,本系列后面所有算法都会像同一主题的变奏。

Bellman 期望方程(对任意策略 $\pi$):

$$V^\pi(s) = \sum_a \pi(a \mid s) \sum_{s'} P(s' \mid s, a)\!\left[R(s, a, s') + \gamma V^\pi(s')\right].$$

把它念出来:待在这里的价值 = 即时奖励的期望 + 下一个状态价值的折扣期望。上图把这个方程画成了一棵备份树——根是当前状态,中间一层是按 $\pi$ 加权的动作,叶子是按 $P$ 加权的下一状态,奖励就标在边上。

Bellman 最优方程(对最优策略 $\pi^*$):

$$V^*(s) = \max_a \sum_{s'} P(s' \mid s, a)\!\left[R(s, a, s') + \gamma V^*(s')\right],$$$$Q^*(s, a) = \sum_{s'} P(s' \mid s, a)\!\left[R(s, a, s') + \gamma \max_{a'} Q^*(s', a')\right].$$

差别看似很小,意义却天壤之别:把对 $\pi$ 的期望换成了 $\max$。一旦得到 $Q^*$,最优策略就唾手可得:

$$\pi^*(s) = \arg\max_{a} Q^*(s, a).$$

数值例子

来一个两状态的小 MDP,$\{s_1, s_2\}$,只有一个动作 $a_1$ 永远被选中,$\gamma = 0.9$。

状态动作下一状态概率奖励
$s_1$$a_1$$s_1$0.55
$s_1$$a_1$$s_2$0.510
$s_2$$a_1$$s_1$0.72
$s_2$$a_1$$s_2$0.38

代入 Bellman:

$$V(s_1) = 0.5\,[5 + 0.9 V(s_1)] + 0.5\,[10 + 0.9 V(s_2)],$$$$V(s_2) = 0.7\,[2 + 0.9 V(s_1)] + 0.3\,[8 + 0.9 V(s_2)].$$

整理后得到线性方程组

$$0.55\,V(s_1) - 0.45\,V(s_2) = 7.5,\qquad -0.63\,V(s_1) + 0.73\,V(s_2) = 3.8,$$

解得 $V(s_1) \approx 52.3$、$V(s_2) \approx 50.4$。数值这么大,是因为奖励永远会持续累加而 $\gamma$ 接近 1——这正是几何级数效应。


动态规划:环境规则已知

当环境模型 $P$、$R$ 完全已知时,动态规划(DP) 可以精确求出最优策略。没有采样,也没有噪声,只有对 Bellman 方程的确定性迭代。

策略评估

固定策略 $\pi$,反复应用 Bellman 期望算子:

$$V_{k+1}(s) = \sum_a \pi(a \mid s) \sum_{s'} P(s' \mid s, a)\!\left[R(s, a, s') + \gamma V_k(s')\right].$$

从 $V_0 \equiv 0$ 出发不停迭代。Bellman 算子在 sup-norm 下是 $\gamma$-压缩映射,所以 $V_k$ 以指数速度收敛到 $V^\pi$。

策略改进

有了 $V^\pi$,构造一个更贪心的策略:

$$\pi'(s) = \arg\max_{a} \sum_{s'} P(s' \mid s, a)\!\left[R(s, a, s') + \gamma V^\pi(s')\right].$$

策略改进定理保证 $V^{\pi'}(s) \ge V^\pi(s)$ 对每个状态都成立。也就是说,只要价值函数算对了,“更贪心"永远不会让你变差。

策略迭代

把上面两步交替进行:

  1. 任意初始化 $\pi_0$。
  2. 评估:算出 $V^{\pi_k}$。
  3. 改进:得到贪心策略 $\pi_{k+1}$。
  4. 若 $\pi_{k+1} = \pi_k$,停止——已经到不动点,就是最优策略。

价值迭代

何必先把策略评估到收敛?跳过它,直接迭代最优方程:

$$V_{k+1}(s) = \max_a \sum_{s'} P(s' \mid s, a)\!\left[R(s, a, s') + \gamma V_k(s')\right].$$

每扫一轮就把误差压缩 $\gamma$ 倍。下图展示了在一个小网格世界上收敛后的价值函数与对应的贪心策略。

网格世界上的价值热力图与贪心策略

两幅图是同一个答案不可分割的两半:热力图回答"待在这里有多好?",箭头回答"下一步该往哪走?"。箭头永远指向热力图上更亮的方向,这正是"对 $V$ 贪心"的几何含义。

代码:价值迭代解 GridWorld

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import numpy as np


class GridWorld:
    """智能体从起点走到终点;障碍格不可通过。"""

    def __init__(self, grid_size=(5, 5), start=(0, 0),
                 goal=(4, 4), obstacles=None):
        self.height, self.width = grid_size
        self.start = start
        self.goal = goal
        self.obstacles = set(obstacles or [])
        self.actions = [0, 1, 2, 3]                        # 上下左右
        self.action_names = ['U', 'D', 'L', 'R']
        self.action_deltas = {0: (-1, 0), 1: (1, 0),
                              2: (0, -1), 3: (0, 1)}
        self.reset()

    def reset(self):
        self.state = self.start
        return self.state

    def step(self, action):
        dr, dc = self.action_deltas[action]
        nr, nc = self.state[0] + dr, self.state[1] + dc
        if (0 <= nr < self.height and 0 <= nc < self.width
                and (nr, nc) not in self.obstacles):
            self.state = (nr, nc)
        if self.state == self.goal:
            return self.state, 10.0, True
        return self.state, -1.0, False

    def get_transitions(self, state, action):
        """确定性转移,返回 [(下一状态, 概率, 奖励)]。"""
        old = self.state
        self.state = state
        ns, r, _ = self.step(action)
        self.state = old
        return [(ns, 1.0, r)]


def value_iteration(env, gamma=0.9, theta=1e-6):
    """通过反复 max 备份求解 Bellman 最优方程。"""
    V = np.zeros((env.height, env.width))
    for iteration in range(1000):
        delta = 0
        for r in range(env.height):
            for c in range(env.width):
                s = (r, c)
                if s == env.goal or s in env.obstacles:
                    continue
                old_v = V[r, c]
                V[r, c] = max(
                    sum(p * (rew + gamma * V[ns])
                        for ns, p, rew in env.get_transitions(s, a))
                    for a in env.actions
                )
                delta = max(delta, abs(old_v - V[r, c]))
        if delta < theta:
            print(f"在第 {iteration + 1} 次扫描后收敛")
            break

    policy = np.zeros((env.height, env.width), dtype=int)
    for r in range(env.height):
        for c in range(env.width):
            s = (r, c)
            if s == env.goal or s in env.obstacles:
                continue
            q = [sum(p * (rew + gamma * V[ns])
                     for ns, p, rew in env.get_transitions(s, a))
                 for a in env.actions]
            policy[r, c] = int(np.argmax(q))
    return V, policy


env = GridWorld(grid_size=(5, 5), start=(0, 0), goal=(4, 4),
                obstacles=[(1, 1), (2, 2), (3, 1)])
V, policy = value_iteration(env)
print(np.round(V, 1))

DP 既精确又优雅,但有两个致命短板。一是它需要环境模型——现实里我们极少能拿到 $P$、$R$ 的解析形式。二是每次迭代都要遍历整个状态空间——当状态是 Atari 的 $84 \times 84$ 像素帧时,根本无法承受。下面两节分别解决这两件事。


蒙特卡洛方法:没有模型时怎么学

不知道 $P$ 和 $R$ 的时候,只能从经验里学。最直接的办法也是统计学里最古老的招式:多采样、求平均

核心思想

价值函数本质上就是一个期望回报。把期望换成样本均值即可:

$$V(s) \approx \frac{1}{N} \sum_{i=1}^{N} G_t^{(i)},$$

其中 $G_t^{(i)}$ 是第 $i$ 次途经 $s$ 的回合中观测到的回报。当 $N \to \infty$ 时这个估计无偏且一致。

操作流程粗暴而清晰:

  1. 从起点跑到终止状态,记录 $s_0, a_0, r_0, s_1, a_1, r_1, \ldots, s_T$。
  2. 对回合中每个被访问的状态,反向算出从那一点起的回报:$G_t = \sum_{k=0}^{T-t-1} \gamma^k r_{t+k}$。
  3. 用滑动平均更新估计。

首次访问 vs 每次访问

同一个回合里,同一个状态可能出现多次。两种处理方式:

  • 首次访问 MC:只用第一次出现时算出的回报。
  • 每次访问 MC:每次出现都用。

随着回合数增加,两种方法都收敛到 $V^\pi$。首次访问更容易证明无偏,是教科书里的默认选择。

MC 控制:寻找更好的策略

要做控制(即寻找最优策略),就估计 $Q(s, a)$ 而不是 $V(s)$,然后贪心改进。为了保证每个状态-动作对都被访问到,用 $\varepsilon$-贪心策略:

$$\pi(a \mid s) = \begin{cases} 1 - \varepsilon + \varepsilon / |\mathcal{A}|, & a = \arg\max_{a'} Q(s, a'), \\ \varepsilon / |\mathcal{A}|, & \text{其他}. \end{cases}$$

那个小小的 $\varepsilon$ 就是探索的引擎——没有它,智能体可能会锁定在某个平庸动作上,永远发现不了更好的。

代码:MC 评估与控制

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import numpy as np
from collections import defaultdict


def mc_policy_evaluation(env, policy_fn, num_episodes=10000, gamma=0.9):
    """首次访问 MC 策略评估。"""
    returns = defaultdict(list)
    V = defaultdict(float)
    for _ in range(num_episodes):
        trajectory, state, done = [], env.reset(), False
        while not done:
            action = policy_fn(state)
            next_state, reward, done = env.step(action)
            trajectory.append((state, action, reward))
            state = next_state
        G, visited = 0.0, set()
        for state, _, reward in reversed(trajectory):
            G = reward + gamma * G
            if state not in visited:
                visited.add(state)
                returns[state].append(G)
                V[state] = float(np.mean(returns[state]))
    return V


def mc_control(env, num_episodes=10000, gamma=0.9, epsilon=0.1):
    """带 epsilon-贪心探索的同策略 MC 控制。"""
    Q = defaultdict(lambda: np.zeros(len(env.actions)))
    returns = defaultdict(list)
    for _ in range(num_episodes):
        trajectory, state, done = [], env.reset(), False
        while not done:
            if np.random.random() < epsilon:
                action = int(np.random.choice(env.actions))
            else:
                action = int(np.argmax(Q[state]))
            next_state, reward, done = env.step(action)
            trajectory.append((state, action, reward))
            state = next_state
        G, visited = 0.0, set()
        for state, action, reward in reversed(trajectory):
            G = reward + gamma * G
            if (state, action) not in visited:
                visited.add((state, action))
                returns[(state, action)].append(G)
                Q[state][action] = float(np.mean(returns[(state, action)]))
    return Q

优点:无需模型,思想透明,无偏。

缺点:必须等回合结束(非终止任务直接出局);整段回报来自一条很长的噪声轨迹,方差很高;无法在线更新。


时序差分:两全其美

三种折扣因子下的回合回报曲线

时序差分(TD) 学习是现代 RL 的概念中枢。它把 MC 的"无需模型"和 DP 的"自举"用一行代码合并起来——DQN、A3C、PPO、SAC 全都建立在它之上。

TD(0):单步更新

更新规则:

$$V(S_t) \leftarrow V(S_t) + \alpha\,\big[\,r_t + \gamma V(S_{t+1}) - V(S_t)\,\big].$$

方括号里的量叫做 TD 误差

$$\delta_t = r_t + \gamma V(S_{t+1}) - V(S_t).$$

它衡量"刚刚发生的事”($r_t + \gamma V(S_{t+1})$)和"我之前的预期"($V(S_t)$)之间的差距。智能体把估计往现实方向轻轻一推,推多少由学习率 $\alpha$ 控制。

这条规则有三件事很特别:

方法更新目标偏差 / 方差在线?
蒙特卡洛$G_t$(实际回报)无偏 / 高方差
TD(0)$r_t + \gamma V(S_{t+1})$初期有偏 / 低方差
DP 备份$\mathbb{E}[r_t + \gamma V(S_{t+1})]$无噪声、需模型

上图显示了在一个小网格任务上,仅仅是 $\gamma$ 的不同就足以重塑 Q-Learning(一种 TD 方法)从早期泥沼里爬出来的速度。$\gamma$ 较小时信用分派更"局部",前期学得快;$\gamma$ 较大时收敛更慢,但更看重长期收益。

Sarsa:同策略 TD 控制

Sarsa 用智能体实际选取的下一动作来更新 $Q$:

$$Q(S_t, A_t) \leftarrow Q(S_t, A_t) + \alpha\,\big[\,r_t + \gamma Q(S_{t+1}, A_{t+1}) - Q(S_t, A_t)\,\big].$$

名字本身就拼出了它依赖的五元组:$(S_t, A_t, R_t, S_{t+1}, A_{t+1})$。

Q-Learning:离策略 TD 控制

Q-Learning(Watkins, 1989)把"实际下一动作"换成"最佳下一动作":

$$Q(S_t, A_t) \leftarrow Q(S_t, A_t) + \alpha\,\big[\,r_t + \gamma \max_{a'} Q(S_{t+1}, a') - Q(S_t, A_t)\,\big].$$

仅仅一个字符的差别——$A_{t+1}$ 还是 $\max_{a'}$——决定了一切。Sarsa 评估的是它实际执行的策略(同策略);Q-Learning 评估的是贪心策略,无论它实际怎么走(离策略)。所以 Q-Learning 可以一边随机探索,一边学最优策略

Sarsa vs Q-Learning:悬崖行走

经典对照实验是 cliff walking

S . . . . . . G
C C C C C C C C

智能体从 S 出发到 G,只要踩进下方的悬崖 C 就掉下去。

  • Sarsa 把"探索时不小心踏空"的风险纳入考虑,最终学出贴着上沿走的安全路线。
  • Q-Learning 评估的是从不探索的贪心策略,所以它学到的是紧贴悬崖的最短路径——但训练过程中它掉下悬崖的次数会多得多。

这是同策略 / 离策略权衡最清爽的一张例图:Sarsa 保守,Q-Learning 渐近最优但训练时更鲁莽。

TD($\lambda$) 与资格迹

TD(0) 只往前看一步。TD($\lambda$) 把多步回报混合起来:

$$G_t^\lambda = (1 - \lambda) \sum_{n=1}^{\infty} \lambda^{n-1} G_t^{(n)},$$

其中 $G_t^{(n)}$ 是 $n$ 步回报。插值参数 $\lambda \in [0, 1]$ 让我们在 TD(0)($\lambda = 0$)和蒙特卡洛($\lambda = 1$)之间平滑过渡。

资格迹通过维护一个指数衰减的"信用记忆" $e_t(s)$ 来高效实现这一点:

$$e_t(s) = \gamma \lambda \, e_{t-1}(s) + \mathbf{1}[S_t = s], \qquad V(s) \leftarrow V(s) + \alpha \, \delta_t \, e_t(s)\quad\text{对所有 } s.$$

最近被访问的状态在奖励到来时会获得更多信用——一次性把信息沿整条轨迹反向传播。

代码:Sarsa 与 Q-Learning

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import numpy as np


def _eps_greedy(Q, state, actions, epsilon):
    if np.random.random() < epsilon:
        return int(np.random.choice(actions))
    return int(np.argmax(Q[state]))


def sarsa(env, num_episodes=1000, alpha=0.1, gamma=0.9, epsilon=0.1):
    """Sarsa:同策略 TD 控制。"""
    Q = {(r, c): np.zeros(len(env.actions))
         for r in range(env.height) for c in range(env.width)}
    for _ in range(num_episodes):
        state = env.reset()
        action = _eps_greedy(Q, state, env.actions, epsilon)
        done = False
        while not done:
            next_state, reward, done = env.step(action)
            next_action = _eps_greedy(Q, next_state, env.actions, epsilon)
            target = reward + gamma * Q[next_state][next_action]
            Q[state][action] += alpha * (target - Q[state][action])
            state, action = next_state, next_action
    return Q


def q_learning(env, num_episodes=1000, alpha=0.1, gamma=0.9, epsilon=0.1):
    """Q-Learning:离策略 TD 控制。"""
    Q = {(r, c): np.zeros(len(env.actions))
         for r in range(env.height) for c in range(env.width)}
    for _ in range(num_episodes):
        state, done = env.reset(), False
        while not done:
            action = _eps_greedy(Q, state, env.actions, epsilon)
            next_state, reward, done = env.step(action)
            target = reward + gamma * np.max(Q[next_state])
            Q[state][action] += alpha * (target - Q[state][action])
            state = next_state
    return Q

贯穿始终的两个主题

上面所有算法里反复出现两个核心概念。提前把它们拎出来,后续系列里再看到时就能一眼认出来。

探索 vs 利用

10 臂老虎机上不同 epsilon 的累积遗憾

每个学习智能体都被同一个永恒难题困扰:用我已经知道的,还是去试我还不知道的? 永远只挑当前最看好的动作,可能永远发现不了更好的;不停乱试,学得多但赚得少。

上图是经典的 10 臂老虎机:每根"摇臂"是一台未知期望收益的老虎机,智能体有 1000 次拉的机会。累积遗憾是最优摇臂的收益和实际拿到的收益之间的差距。

  • $\varepsilon = 0$(纯贪心)很容易锁死在前几次"看上去不错"但其实不是最优的摇臂上——遗憾线性增长,停不下来。
  • $\varepsilon = 0.3$ 不停地把机会浪费在差的摇臂上。
  • $\varepsilon \in [0.01, 0.1]$ 才是甜区。

这个权衡贯穿整个系列:DQN 里的 $\varepsilon$-贪心、PPO 里的熵正则、第 4 篇的内在动机、贝叶斯 RL 里的 Thompson 采样……名字一直在变,问题始终一样。

折扣因子作为规划视野

折扣因子如何控制智能体的规划视野

折扣因子 $\gamma$ 远不只是数值上的旋钮。它悄悄定义了智能体能往多远的未来思考。两种角度:

  • 奖励权重(左图):$k$ 步以后的奖励折成现在只值 $\gamma^k$。$\gamma = 0.5$ 时,10 步后的奖励连 0.1% 都不到;$\gamma = 0.99$ 时仍有约 90%。
  • 有效视野(右图):对 $G_t$ 有显著贡献的未来步数大约是 $1 / (1 - \gamma)$。所以 $\gamma = 0.9$ 大致"想 10 步",$\gamma = 0.99$ “想 100 步”,$\gamma = 0.999$ “想 1000 步”。注意纵轴是对数刻度——把 $\gamma$ 从 0.99 调到 0.999,规划视野是 10 倍 扩张,而不是 1% 微调。

实际意义:$\gamma$ 应该匹配任务的时间尺度。游戏智能体常用 $\gamma \approx 0.99$;推荐系统看重十年级别的用户终身价值,可能需要更高;而机器人反射控制器可能只用 $\gamma = 0.9$ 甚至更小,因为再远的事根本无关紧要。


怎么选方法

一张速查表:

场景推荐方法原因
模型已知动态规划精确,无需采样
短回合、模型未知蒙特卡洛无偏,思想简单
长回合或持续任务TD(Q-Learning / Sarsa)在线,方差低
需要最优策略Q-Learning离策略,收敛到 $Q^*$
安全性优先Sarsa把探索风险纳入学习
长信用分派链TD($\lambda$) / Sarsa($\lambda$)资格迹快速传播信息

三句话记住

价值 = 即时奖励 + 折扣后的未来价值。

策略改进 = 贪心地偏好高价值动作。

学习 = 用经验修正价值估计。


总结

本章铺好了整个系列后续要用的地基:

  • MDP 把智能体-环境回路形式化为:状态、动作、转移、奖励、折扣。
  • Bellman 方程给价值函数一个递归结构,把长视野规划压缩成局部算术。
  • 动态规划在模型已知时给出精确解。
  • 蒙特卡洛通过完整回合在无模型下学习。
  • 时序差分把无模型与在线两个优点合二为一。
  • 探索 vs 利用折扣因子 是后续每个算法里都隐藏着的两个旋钮。

以上方法都假设状态、动作空间小且离散,可以为每个状态在表格里存一个数。一旦状态空间爆炸——想想 $256^{84 \times 84}$ 种 Atari 帧——表格法彻底失效。

下一篇第二篇 介绍 深度 Q 网络(DQN):用神经网络近似 $Q$,配合经验回放和目标网络稳住训练。这就是从教科书 RL 走到能打败人类玩 Atari 算法的桥梁。


参考资料

  • Sutton, R. S., & Barto, A. G. (2018). Reinforcement Learning: An Introduction (2nd ed.). MIT Press.
  • Watkins, C. J., & Dayan, P. (1992). Q-learning. Machine Learning, 8(3-4), 279-292.
  • Sutton, R. S. (1988). Learning to predict by the methods of temporal differences. Machine Learning, 3(1), 9-44.
  • Bellman, R. (1957). Dynamic Programming. Princeton University Press.
  • Silver, D. (2015). UCL Course on Reinforcement Learning.

系列导航

部分主题链接
1基础与核心概念(本文)
2Q-Learning 与深度 Q 网络下一篇 –>
3Policy Gradient 与 Actor-Critic阅读 –>

Liked this piece?

Follow on GitHub for the next one — usually one a week.

GitHub