Skip to content

路线一:Q(s,a)——给每个动作打分

本节导读

核心内容

  • 掌握动作价值函数 Qπ(s,a)Q^\pi(s,a):在状态 ss 先做动作 aa,之后按策略行动的期望回报。
  • 理解 V(s)V(s)Q(s,a)Q(s,a) 的关系,以及为什么 QQ 能直接用于动作选择。
  • 学会用 Q 的贝尔曼方程推出最优动作价值 QQ^* 和最优策略。

核心公式

Qπ(s,a)=Eπ[Gtst=s,at=a](动作价值函数定义:评估先做动作 a 的回报)Q^\pi(s,a) = \mathbb{E}_\pi[G_t\mid s_t=s,a_t=a] \quad \text{(动作价值函数定义:评估先做动作 }a\text{ 的回报)}

动作价值函数 (Action-Value Function):

  • Qπ(s,a)Q^\pi(s,a):动作价值(Action-Value),即在状态 ss先强制执行动作 aa,之后一直按策略 π\pi 行动能拿到的平均总分。
  • st=s,at=as_t=s, a_t=a:这是期望的已知条件,表示当前时刻 tt 必须在状态 ss 并且做动作 aa

Vπ(s)=aπ(as)Qπ(s,a)(V-Q 关系式:用动作价值求状态价值)V^\pi(s) = \sum_a \pi(a\mid s)Q^\pi(s,a) \quad \text{(V-Q 关系式:用动作价值求状态价值)}

V-Q 关系式 (V-Q Relationship):

  • Vπ(s)V^\pi(s):状态 ss 的整体价值。
  • π(as)\pi(a\mid s):在状态 ss 选动作 aa 的概率。这个公式说明,整体局面的价值等于所有可选动作价值的概率加权平均。

Q(s,a)=R(s,a)+γsSP(ss,a)maxaQ(s,a)(Q 的贝尔曼最优方程:递归定义最优动作价值)Q^*(s,a) = R(s,a)+\gamma\sum_{s'\in\mathcal{S}}P(s'\mid s,a)\max_{a'}Q^*(s',a') \quad \text{(Q 的贝尔曼最优方程:递归定义最优动作价值)}

Q 的贝尔曼最优方程 (Bellman Optimality Equation for Q):

  • Q(s,a)Q^*(s,a):最优动作价值,即在所有可能策略中能拿到的最高分数。
  • maxaQ(s,a)\max_{a'}Q^*(s',a'):假设到了下一个状态 ss' 后,我们能完美地选出那个最高分的动作 aa'

π(s)=argmaxaQ(s,a)(贪心最优策略:选择最高分动作)\pi^*(s) = \arg\max_a Q^*(s,a) \quad \text{(贪心最优策略:选择最高分动作)}

贪心最优策略 (Greedy Optimal Policy):

  • π(s)\pi^*(s):最优策略,直接告诉你在这个状态下该选哪个动作。
  • argmaxa\arg\max_a:一个数学算子,意思是“去把那个能让后面式子取到最大值的 aa 给我找出来”。

为什么需要这些公式

前面学 V(s)V(s) 时,我们终于能判断"这个局面好不好"了。但真正做决策时,光知道局面好不好还不够,还要知道"往左走好,还是往右走好"。这就是 Q(s,a)Q(s,a) 出场的原因:它把问题从"这个位置值多少分"推进到"在这个位置做这个动作值多少分"。VV-QQ 关系告诉我们,局面的价值其实是动作价值按策略加权后的结果;QQ^* 再告诉我们,如果每个动作都有分数,直接选最高分就行。这里应该有一个很自然的"哦":原来 Q-Learning 和 DQN 的底层想法,就是先给每个动作贴分数牌,再按分数选动作。

上一节我们认识了状态价值函数 V(s)V(s):它告诉你一个局面到底值多少分。但 V(s)V(s) 有一个根本性的局限——它评估的是“状态”,而不是“动作”。

考虑上一节那个只有一条直路的 1×5 走廊寻宝游戏:

┌───┬───┬───┬───┬───┐
│ S │   │   │   │ 🏆 │
└───┴───┴───┴───┴───┘
  -4  -3  -2  -1   0

在这个走廊里,每个格子你只能被迫做一个动作(往右走),所以知道 V(s)V(s) 就足够了。但如果走廊有岔路呢?

          ┌───┬───┐
          │   │ 🏆│  上方路线
      ┌───┼───┘   │
  ┌───┤ ? │       │
  │ S │   │       │  下方路线
  └───┴───┴───────┘

假设你现在站在 ? 处。V(?)V(?) 会告诉你:“这个岔路口整体值个 50 分”。 但这就尴尬了,作为一个需要做决定的智能体,你无法回答那个最关键的问题:我到底是该往上走,还是往下走?

你需要的是一块更精细的“路牌”——它不仅告诉你每条路通向哪里,还得直接标出“如果你选了这条路,预计能拿多少分”。这块带方向的路牌,就是动作价值函数 Q(s,a)Q(s,a)

Q(s,a) 的定义

Qπ(s,a)Q^\pi(s,a) 的定义是:在状态 ss先强制执行动作 aa,然后从下一步开始,老老实实遵循策略 π\pi 行动,所能获得的期望累积回报:

Qπ(s,a)=Eπ[Gtst=s,at=a]Q^\pi(s,a) = \mathbb{E}_\pi \left[ G_t \mid s_t = s, a_t = a \right]

V(s)V(s) 相比,Q(s,a)Q(s,a) 在条件里多加了一个 at=aa_t = a。我们用迷宫来类比这俩的区别:

  • V(s)V(s):站在这个岔路口,你闭着眼睛按现在的习惯走,整体胜率是多少?(它把所有可能走的路混在一起算平均)
  • Q(s,向上)Q(s, \text{向上}):如果你现在立刻决定向上走,并且之后按习惯走,胜率是多少?
  • Q(s,向下)Q(s, \text{向下}):如果你现在立刻决定向下走,并且之后按习惯走,胜率是多少?

你看,只要你能把每个动作的 QQ 值算出来,做决定就变成了一件小学生都会的事——比较大小,选 QQ 值最高的那个动作。

用格子世界建立直觉

为了把 Q(s,a)Q(s,a) 的直觉变得可触摸,我们构造一个更具体的 3×3 格子世界:

┌─────┬─────┬─────┐
│  s0 │  s1 │  s2 │
├─────┼─────┼─────┤
│  s3 │  s4 │  s5 │
├─────┼─────┼─────┤
│  s6 │  s7 │  s8 │
│  ⭐  │     │  🏆  │
└─────┴─────┴─────┘

规则很简单:

  • 从 ⭐(s6)出发,目标是到达 🏆(s8)
  • 每步可以往上、下、左、右走
  • 走出边界留在原地,扣 2 分
  • 每走一步扣 1 分(体力消耗)
  • 到达宝藏处游戏结束,奖励 0
  • 折扣因子 γ=1\gamma = 1(先不考虑折扣,简化计算)

站在 s7(宝藏左边那格),所有动作的 QQ 值是多少?

  • 向右:走到 s8(宝藏),扣 1 分,然后游戏结束。Q(s7,)=1+0=1Q(s7, \text{右}) = -1 + 0 = -1
  • 向左:回到 s6,扣 1 分。Q(s7,)=1+V(s6)Q(s7, \text{左}) = -1 + V(s6)(还要继续走)
  • 向上:走到 s4,扣 1 分。Q(s7,)=1+V(s4)Q(s7, \text{上}) = -1 + V(s4)
  • 向下:撞墙,留在 s7,扣 2 分。Q(s7,)=2+V(s7)Q(s7, \text{下}) = -2 + V(s7)

在 s7,向右的 QQ 值是 1-1,一目了然——"走一步就到宝藏了,只扣 1 分"。其他方向都绕远了,QQ 值更低。如果你知道每个格子的每个方向的 QQ 值,只需比较大小,就知道该往哪走。

V 和 Q 的关系:整体与局部的加权

既然 V(s)V(s) 衡量的是整体,Q(s,a)Q(s,a) 衡量的是局部(某条特定的路),它们之间肯定有个换算关系:

Vπ(s)=aπ(as)Qπ(s,a)V^\pi(s) = \sum_{a} \pi(a | s) \cdot Q^\pi(s, a)

这个公式其实非常直白:一个路口的整体价值 V(s)V(s),等于所有分岔路价值 Q(s,a)Q(s,a) 的“概率加权平均”。

用我们上面的 1×3 走廊来验证一下。假设你现在站在 s1,你的习惯(策略)是“50% 概率向右走,50% 概率向左走”:

  • 查一查向右的牌子:Q(s1,)=1Q(s1, \text{右}) = -1(走一步到终点,扣 1 分)
  • 查一查向左的牌子:Q(s1,)=3Q(s1, \text{左}) = -3(走回起点,再走回来,还要继续走)
  • 算一算整体的平均分:V(s1)=0.5×(1)+0.5×(3)=2V(s1) = 0.5 \times (-1) + 0.5 \times (-3) = -2

验算无误。这说明了什么?V(s)V(s) 本质上是在所有动作上“和稀泥”——好的坏的混在一起。而 Q(s,a)Q(s,a) 把每个动作的贡献单独拎了出来,清清楚楚地告诉你“做这个动作到底值多少”。正因如此,Q(s,a)Q(s,a) 携带了比 V(s)V(s) 更细粒度的信息,天然适合做决策。

从 Q 到最优策略:只需一步 argmax

既然 Q(s,a)Q(s,a) 已经把“在这个局面下做这个动作值多少分”标得清清楚楚了,那么什么是最优策略?

简单粗暴:选分数最高的那个。

π(s)=argmaxaQ(s,a)\pi^*(s) = \arg\max_a \, Q^*(s, a)

不需要复杂的逻辑推理,不需要写 if-else 规则树,比较数字大小就够了。

回到刚刚的 3×3 格子世界。假设经过一番学习,我们已经知道了 s7 的这块“最优动作价值路牌” QQ^*

动作牌子上写的分数 Q(s7,a)Q^*(s7, a)
向右1-1
向左3-3
向上3-3
向下4-4

看到这块牌子,连闭着眼睛都知道该怎么走——向右(-1 分是扣得最少的,也就是价值最大的)。

这就是**路线一(Value-Based)**的核心思路。你可以用一个生动的类比来记住它:

想象你在走一个巨大的迷宫,每到一个岔路口,你都能看到路边立着一块牌子。 牌子上写着:“往左走预计总共能拿 80 分,往右走预计总共能拿 30 分。” 你当然毫不犹豫地选往左。

这块“牌子”就是 Q(s,a)Q(s,a)。它不直接命令你该走哪条路,它只是客观地告诉你每条路的预期回报,由你自己去选那个最高的。这就是所谓的“给动作打分,选最高分”。

用 Python 验证格子世界的 Q 值

我们用一个简化的 1×3 直线走廊来验证 QQ 值的计算和 argmax\arg\max 决策:

python
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 分,Q(s1,)=1+0=1Q^*(s1, \text{右}) = -1 + 0 = -1;向左走到 s0,Q(s0,)=2Q^*(s0, \text{右}) = -2,所以 Q(s1,)=1+(2)=3Q^*(s1, \text{左}) = -1 + (-2) = -3。代码结果吻合。在每个状态,argmax\arg\max 都选了向右——走向宝藏的方向。

Q 的贝尔曼方程

V(s)V(s) 一样,Q(s,a)Q(s,a) 也满足贝尔曼方程。先用格子世界建立直觉,再看公式。

站在 s7,Q(s7,)Q(s7, \text{右}) 是多少?你已经知道了:1-1。它是怎么算出来的?

Q(s7,)=1这一步扣 1 分+γ×V(s8)=0(宝藏处,游戏结束)Q(s7, \text{右}) = \underbrace{-1}_{\text{这一步扣 1 分}} + \gamma \times \underbrace{V(s8)}_{= 0 \text{(宝藏处,游戏结束)}}

站在 s4(s7 的上方),Q(s4,)Q(s4, \text{下}) 是多少?

Q(s4,)=1走到 s7+γ×V(s7)s7 还要继续走Q(s4, \text{下}) = \underbrace{-1}_{\text{走到 s7}} + \gamma \times \underbrace{V(s7)}_{\text{s7 还要继续走}}

关键发现:Q(s,a)Q(s,a) 的值 = 这一步的即时奖励 + 下一状态的价值。和 V(s)V(s) 的贝尔曼方程一样的递归结构,只不过第一步的动作被固定了。

贝尔曼期望方程 for Q

Qπ(s,a)=R(s,a)+γsSP(ss,a)aAπ(as)Qπ(s,a)Q^\pi(s,a) = R(s,a) + \gamma \sum_{s' \in \mathcal{S}} P(s' | s, a) \sum_{a' \in \mathcal{A}} \pi(a' | s') \, Q^\pi(s', a')

VV 的贝尔曼方程对比:VV 需要对所有动作取策略加权平均(外层 aπ(as)\sum_a \pi(a|s)),而 QQ 已经固定了第一步动作,所以直接用 R(s,a)R(s,a) 开始,不需要对第一个动作求和。但在下一步 ss' 处,仍然需要对所有 aa' 取策略加权平均。

贝尔曼最优方程 for Q

贝尔曼最优方程把策略加权平均替换为 max:

Q(s,a)=R(s,a)+γsSP(ss,a)maxaQ(s,a)Q^*(s,a) = R(s,a) + \gamma \sum_{s' \in \mathcal{S}} P(s' | s, a) \max_{a'} Q^*(s', a')

注意 maxa\max_{a'} 出现在 QQ 自身的更新中——这意味着只要知道了 QQ^*,最优策略就直接确定了:

π(s)=argmaxaQ(s,a)\pi^*(s) = \arg\max_a Q^*(s, a)

不需要知道环境的转移概率 PP。这就是 Q-Learning 的理论基础——通过学习 QQ^* 来隐式地找到最优策略。

点击展开:用格子世界验证贝尔曼最优方程

回到 1×3 走廊,从终点往回推 QQ^*

s2(终点):游戏结束,任何动作的 Q=0Q = 0

s1

Q(s1,)=1+γmaxaQ(s2,a)=1+1×0=1Q^*(s1, \text{右}) = -1 + \gamma \cdot \max_a Q^*(s2, a) = -1 + 1 \times 0 = \mathbf{-1}

Q(s1,)=1+γmaxaQ(s0,a)=1+1×(2)=3Q^*(s1, \text{左}) = -1 + \gamma \cdot \max_a Q^*(s0, a) = -1 + 1 \times (-2) = \mathbf{-3}

向右明显更好,maxaQ(s1,a)=1\max_a Q^*(s1, a) = -1

s0

Q(s0,)=1+γmaxaQ(s1,a)=1+1×(1)=2Q^*(s0, \text{右}) = -1 + \gamma \cdot \max_a Q^*(s1, a) = -1 + 1 \times (-1) = \mathbf{-2}

Q(s0,)=2+γmaxaQ(s0,a)Q^*(s0, \text{左}) = -2 + \gamma \cdot \max_a Q^*(s0, a)

向左撞墙留在 s0,形成自环方程——实际 Q(s0,)=3Q^*(s0, \text{左}) = \mathbf{-3}。每个状态,贝尔曼最优方程通过 maxa\max_a 自动选出最好的下一步,递归地给出当前步骤的最优 QQ 值。

这条路线的算法演进

沿着“学 Q \rightarrow 挑出最大 Q \rightarrow 得到最优策略”这条路,诞生了强化学习历史上最经典的一系列算法:

算法核心思路解决了什么问题
Q-Learning拿个表格,把所有 (s,a)(s, a) 的 Q 值记下来最经典的入门方法,但只能处理格子迷宫这种小问题
DQN把表格换成神经网络从“小表格”走向“看像素打游戏”,深度强化学习的开山鼻祖
Double DQN修正 DQN 的“盲目乐观”解决 DQN 既当裁判又当运动员导致 Q 值偏高的问题
Dueling DQN分别给“整体局面”和“具体动作”打分在那些“做什么动作都差不多”的状态下,学习效率更高

值得一提的是,这条路线有一个非常强大的武器:离策略(Off-policy)学习

你看,QQ^* 定义的是“最完美的打分表”。这就意味着,不管你现在是一个像没头苍蝇一样乱撞的菜鸟,还是一个按特定策略行事的普通玩家,你都可以把你试错的经历(状态、动作、拿到的奖励、下一个状态)记录在小本本上。然后,你可以对着这个小本本,去反复推敲那张“完美的打分表”该怎么写。

这就好比,就算是你瞎走出来的一段经验,你也可以把它存进一个**经验回放池(Replay Buffer)**里,拿出来反复学习。这就是为什么 DQN 对数据的利用率非常高。作为对比,我们在下一节要学的路线二(比如 REINFORCE 算法),只能用当前的策略去跑数据,跑完一次就得扔掉(On-policy),非常费数据。

这条区别会在第 4 章和第 5 章的实战中给你留下深刻的印象。

本节总结

本节的核心收获可以归纳为以下几点:

  • Q(s,a)Q(s,a)V(s)V(s) 多了一个维度——动作。 V(s)V(s) 只会说"这个局面值多少分",Q(s,a)Q(s,a) 会说"这个局面下做某个动作值多少分"。多出来的这一维信息,正是做决策所需要的。
  • 从 Q 到策略只需一步:argmax。 知道了 QQ^*,最优策略就是选 QQ 值最高的动作。不需要知道环境的转移概率 PP,不需要复杂的推理——比较数字大小就够了。
  • Q 的贝尔曼方程和 V 共享同样的递归结构。 当前步骤的动作价值 = 这一步的即时奖励 + 接下来按最优策略行动的下一状态价值。区别只在于第一步的动作被固定了,后续步骤仍然取 max\max
  • Off-policy 学习的基础。 因为 QQ^* 描述的是“最优情况”下的价值,我们可以用任何策略(比如随机探索)去收集数据,同时利用这些数据来逼近 QQ^*,这也是 Q-Learning 能使用经验回放池的原因。

局限性与后续引申

路线一(Value-Based)的优势是打分准确、样本效率高(可以复用旧数据)。但这条路线有一个硬伤:当动作空间变成连续的时(比如机器人各个关节的连续力矩,或自动驾驶的连续转向角度),argmax\arg\max 彻底失灵——你无法给无穷多个动作逐一打分并挑出最大值。此外,它也不擅长探索(需要 ϵ\epsilon-贪婪等人工补丁来强制探索)。

既然没法给每一个动作打分,那我们能不能换个思路,不给动作打分,而是直接学"遇到这个局面该做什么动作"?

这就引出了我们的第二条路线:Policy-Based 方法。

← 上一节:经典方法速览 | 下一节:路线二:J(θ)——直接优化策略

Built for reusable bilingual course delivery