路线一:Q(s,a)——给每个动作打分
本节导读
核心内容
- 掌握动作价值函数 :在状态 先做动作 ,之后按策略行动的期望回报。
- 理解 与 的关系,以及为什么 能直接用于动作选择。
- 学会用 Q 的贝尔曼方程推出最优动作价值 和最优策略。
核心公式
动作价值函数 (Action-Value Function):
- :动作价值(Action-Value),即在状态 下先强制执行动作 ,之后一直按策略 行动能拿到的平均总分。
- :这是期望的已知条件,表示当前时刻 必须在状态 并且做动作 。
V-Q 关系式 (V-Q Relationship):
- :状态 的整体价值。
- :在状态 选动作 的概率。这个公式说明,整体局面的价值等于所有可选动作价值的概率加权平均。
Q 的贝尔曼最优方程 (Bellman Optimality Equation for Q):
- :最优动作价值,即在所有可能策略中能拿到的最高分数。
- :假设到了下一个状态 后,我们能完美地选出那个最高分的动作 。
贪心最优策略 (Greedy Optimal Policy):
- :最优策略,直接告诉你在这个状态下该选哪个动作。
- :一个数学算子,意思是“去把那个能让后面式子取到最大值的 给我找出来”。
为什么需要这些公式
前面学 时,我们终于能判断"这个局面好不好"了。但真正做决策时,光知道局面好不好还不够,还要知道"往左走好,还是往右走好"。这就是 出场的原因:它把问题从"这个位置值多少分"推进到"在这个位置做这个动作值多少分"。- 关系告诉我们,局面的价值其实是动作价值按策略加权后的结果; 再告诉我们,如果每个动作都有分数,直接选最高分就行。这里应该有一个很自然的"哦":原来 Q-Learning 和 DQN 的底层想法,就是先给每个动作贴分数牌,再按分数选动作。
上一节我们认识了状态价值函数 :它告诉你一个局面到底值多少分。但 有一个根本性的局限——它评估的是“状态”,而不是“动作”。
考虑上一节那个只有一条直路的 1×5 走廊寻宝游戏:
┌───┬───┬───┬───┬───┐
│ S │ │ │ │ 🏆 │
└───┴───┴───┴───┴───┘
-4 -3 -2 -1 0在这个走廊里,每个格子你只能被迫做一个动作(往右走),所以知道 就足够了。但如果走廊有岔路呢?
┌───┬───┐
│ │ 🏆│ 上方路线
┌───┼───┘ │
┌───┤ ? │ │
│ S │ │ │ 下方路线
└───┴───┴───────┘假设你现在站在 ? 处。 会告诉你:“这个岔路口整体值个 50 分”。 但这就尴尬了,作为一个需要做决定的智能体,你无法回答那个最关键的问题:我到底是该往上走,还是往下走?
你需要的是一块更精细的“路牌”——它不仅告诉你每条路通向哪里,还得直接标出“如果你选了这条路,预计能拿多少分”。这块带方向的路牌,就是动作价值函数 。
Q(s,a) 的定义
的定义是:在状态 下先强制执行动作 ,然后从下一步开始,老老实实遵循策略 行动,所能获得的期望累积回报:
和 相比, 在条件里多加了一个 。我们用迷宫来类比这俩的区别:
- :站在这个岔路口,你闭着眼睛按现在的习惯走,整体胜率是多少?(它把所有可能走的路混在一起算平均)
- :如果你现在立刻决定向上走,并且之后按习惯走,胜率是多少?
- :如果你现在立刻决定向下走,并且之后按习惯走,胜率是多少?
你看,只要你能把每个动作的 值算出来,做决定就变成了一件小学生都会的事——比较大小,选 值最高的那个动作。
用格子世界建立直觉
为了把 的直觉变得可触摸,我们构造一个更具体的 3×3 格子世界:
┌─────┬─────┬─────┐
│ s0 │ s1 │ s2 │
├─────┼─────┼─────┤
│ s3 │ s4 │ s5 │
├─────┼─────┼─────┤
│ s6 │ s7 │ s8 │
│ ⭐ │ │ 🏆 │
└─────┴─────┴─────┘规则很简单:
- 从 ⭐(s6)出发,目标是到达 🏆(s8)
- 每步可以往上、下、左、右走
- 走出边界留在原地,扣 2 分
- 每走一步扣 1 分(体力消耗)
- 到达宝藏处游戏结束,奖励 0
- 折扣因子 (先不考虑折扣,简化计算)
站在 s7(宝藏左边那格),所有动作的 值是多少?
- 向右:走到 s8(宝藏),扣 1 分,然后游戏结束。
- 向左:回到 s6,扣 1 分。(还要继续走)
- 向上:走到 s4,扣 1 分。
- 向下:撞墙,留在 s7,扣 2 分。
在 s7,向右的 值是 ,一目了然——"走一步就到宝藏了,只扣 1 分"。其他方向都绕远了, 值更低。如果你知道每个格子的每个方向的 值,只需比较大小,就知道该往哪走。
V 和 Q 的关系:整体与局部的加权
既然 衡量的是整体, 衡量的是局部(某条特定的路),它们之间肯定有个换算关系:
这个公式其实非常直白:一个路口的整体价值 ,等于所有分岔路价值 的“概率加权平均”。
用我们上面的 1×3 走廊来验证一下。假设你现在站在 s1,你的习惯(策略)是“50% 概率向右走,50% 概率向左走”:
- 查一查向右的牌子:(走一步到终点,扣 1 分)
- 查一查向左的牌子:(走回起点,再走回来,还要继续走)
- 算一算整体的平均分:
验算无误。这说明了什么? 本质上是在所有动作上“和稀泥”——好的坏的混在一起。而 把每个动作的贡献单独拎了出来,清清楚楚地告诉你“做这个动作到底值多少”。正因如此, 携带了比 更细粒度的信息,天然适合做决策。
从 Q 到最优策略:只需一步 argmax
既然 已经把“在这个局面下做这个动作值多少分”标得清清楚楚了,那么什么是最优策略?
简单粗暴:选分数最高的那个。
不需要复杂的逻辑推理,不需要写 if-else 规则树,比较数字大小就够了。
回到刚刚的 3×3 格子世界。假设经过一番学习,我们已经知道了 s7 的这块“最优动作价值路牌” :
| 动作 | 牌子上写的分数 |
|---|---|
| 向右 | |
| 向左 | |
| 向上 | |
| 向下 |
看到这块牌子,连闭着眼睛都知道该怎么走——向右(-1 分是扣得最少的,也就是价值最大的)。
这就是**路线一(Value-Based)**的核心思路。你可以用一个生动的类比来记住它:
想象你在走一个巨大的迷宫,每到一个岔路口,你都能看到路边立着一块牌子。 牌子上写着:“往左走预计总共能拿 80 分,往右走预计总共能拿 30 分。” 你当然毫不犹豫地选往左。
这块“牌子”就是 。它不直接命令你该走哪条路,它只是客观地告诉你每条路的预期回报,由你自己去选那个最高的。这就是所谓的“给动作打分,选最高分”。
用 Python 验证格子世界的 Q 值
我们用一个简化的 1×3 直线走廊来验证 值的计算和 决策:
import numpy as np
# 1×3 走廊:s0 -> s1 -> s2(宝藏)
n_states = 3
n_actions = 2 # 0=左, 1=右
gamma = 1.0
step_cost = -1
# 转移:s2 是终点,到达后游戏结束
def step(s, a):
if s == 2: # 终点
return s, 0
if a == 1: # 向右
s_next = min(s + 1, 2)
else: # 向左
s_next = max(s - 1, 0)
reward = step_cost if s_next != s else -2 # 撞墙扣 2
return s_next, reward
# 用贝尔曼最优方程迭代求解 Q*
Q = np.zeros((n_states, n_actions))
for _ in range(50):
Q_new = Q.copy()
for s in range(n_states):
for a in range(n_actions):
s_next, r = step(s, a)
Q_new[s, a] = r + gamma * np.max(Q[s_next])
Q = Q_new
print("Q* 表格(行=状态, 列=动作[左, 右]):")
print(Q)
print()
# 在每个状态用 argmax 选最优动作
for s in range(n_states):
best_a = np.argmax(Q[s])
direction = "右" if best_a == 1 else "左"
print(f"s{s}: Q*=[左={Q[s,0]:.1f}, 右={Q[s,1]:.1f}] → 选{direction}")运行结果
Q* 表格(行=状态, 列=动作[左, 右]): [[-3. -2.] [ -2. -1.] [ 0. 0.]]
s0: Q*=[左=-3.0, 右=-2.0] → 选右 s1: Q*=[左=-2.0, 右=-1.0] → 选右 s2: Q*=[左=0.0, 右=0.0] → 选右
手动验证 s1:向右走到 s2(终点),扣 1 分,;向左走到 s0,,所以 。代码结果吻合。在每个状态, 都选了向右——走向宝藏的方向。
Q 的贝尔曼方程
和 一样, 也满足贝尔曼方程。先用格子世界建立直觉,再看公式。
站在 s7, 是多少?你已经知道了:。它是怎么算出来的?
站在 s4(s7 的上方), 是多少?
关键发现: 的值 = 这一步的即时奖励 + 下一状态的价值。和 的贝尔曼方程一样的递归结构,只不过第一步的动作被固定了。
贝尔曼期望方程 for Q
与 的贝尔曼方程对比: 需要对所有动作取策略加权平均(外层 ),而 已经固定了第一步动作,所以直接用 开始,不需要对第一个动作求和。但在下一步 处,仍然需要对所有 取策略加权平均。
贝尔曼最优方程 for Q
贝尔曼最优方程把策略加权平均替换为 max:
注意 出现在 自身的更新中——这意味着只要知道了 ,最优策略就直接确定了:
不需要知道环境的转移概率 。这就是 Q-Learning 的理论基础——通过学习 来隐式地找到最优策略。
点击展开:用格子世界验证贝尔曼最优方程
回到 1×3 走廊,从终点往回推 :
s2(终点):游戏结束,任何动作的 。
s1:
向右明显更好,。
s0:
向左撞墙留在 s0,形成自环方程——实际 。每个状态,贝尔曼最优方程通过 自动选出最好的下一步,递归地给出当前步骤的最优 值。
这条路线的算法演进
沿着“学 Q 挑出最大 Q 得到最优策略”这条路,诞生了强化学习历史上最经典的一系列算法:
| 算法 | 核心思路 | 解决了什么问题 |
|---|---|---|
| Q-Learning | 拿个表格,把所有 的 Q 值记下来 | 最经典的入门方法,但只能处理格子迷宫这种小问题 |
| DQN | 把表格换成神经网络 | 从“小表格”走向“看像素打游戏”,深度强化学习的开山鼻祖 |
| Double DQN | 修正 DQN 的“盲目乐观” | 解决 DQN 既当裁判又当运动员导致 Q 值偏高的问题 |
| Dueling DQN | 分别给“整体局面”和“具体动作”打分 | 在那些“做什么动作都差不多”的状态下,学习效率更高 |
值得一提的是,这条路线有一个非常强大的武器:离策略(Off-policy)学习。
你看, 定义的是“最完美的打分表”。这就意味着,不管你现在是一个像没头苍蝇一样乱撞的菜鸟,还是一个按特定策略行事的普通玩家,你都可以把你试错的经历(状态、动作、拿到的奖励、下一个状态)记录在小本本上。然后,你可以对着这个小本本,去反复推敲那张“完美的打分表”该怎么写。
这就好比,就算是你瞎走出来的一段经验,你也可以把它存进一个**经验回放池(Replay Buffer)**里,拿出来反复学习。这就是为什么 DQN 对数据的利用率非常高。作为对比,我们在下一节要学的路线二(比如 REINFORCE 算法),只能用当前的策略去跑数据,跑完一次就得扔掉(On-policy),非常费数据。
这条区别会在第 4 章和第 5 章的实战中给你留下深刻的印象。
本节总结
本节的核心收获可以归纳为以下几点:
- 比 多了一个维度——动作。 只会说"这个局面值多少分", 会说"这个局面下做某个动作值多少分"。多出来的这一维信息,正是做决策所需要的。
- 从 Q 到策略只需一步:argmax。 知道了 ,最优策略就是选 值最高的动作。不需要知道环境的转移概率 ,不需要复杂的推理——比较数字大小就够了。
- Q 的贝尔曼方程和 V 共享同样的递归结构。 当前步骤的动作价值 = 这一步的即时奖励 + 接下来按最优策略行动的下一状态价值。区别只在于第一步的动作被固定了,后续步骤仍然取 。
- Off-policy 学习的基础。 因为 描述的是“最优情况”下的价值,我们可以用任何策略(比如随机探索)去收集数据,同时利用这些数据来逼近 ,这也是 Q-Learning 能使用经验回放池的原因。
局限性与后续引申
路线一(Value-Based)的优势是打分准确、样本效率高(可以复用旧数据)。但这条路线有一个硬伤:当动作空间变成连续的时(比如机器人各个关节的连续力矩,或自动驾驶的连续转向角度), 彻底失灵——你无法给无穷多个动作逐一打分并挑出最大值。此外,它也不擅长探索(需要 -贪婪等人工补丁来强制探索)。
既然没法给每一个动作打分,那我们能不能换个思路,不给动作打分,而是直接学"遇到这个局面该做什么动作"?
这就引出了我们的第二条路线:Policy-Based 方法。
← 上一节:经典方法速览 | 下一节:路线二:J(θ)——直接优化策略