想象你是一个从没下过厨的小白,第一天进厨房要学做番茄炒蛋。你面前有四个“旋钮”可以调:番茄要不要去皮(两个选择)、鸡蛋打散还是整颗下锅(两个选择)、油温高还是低(两个选择)、先炒蛋还是先炒番茄(两个选择),一共16种组合。你每做一次,尝一口,记下“这个组合好吃/难吃”——第一天你只知道这几盘菜的好坏,并不知道没试过的组合会怎样。 但你很聪明,你会做一件关键的事:每做完一盘菜,你会琢磨——“如果我在这个步骤上换个做法,以后能多好吃?”。你说不清什么“长期价值”,但你心里大概有个数:现在这一步的选择,和未来整盘菜好不好吃,是绑在一起的。 这正是强化学习中智能体在做的事。它不断试错、记录、反思,最终学会一套“在什么状态做什么动作最划算”的攻略。这份攻略,我们叫它 Q表,而让这攻略逐步变准确的那条“更新规则”,就叫做 贝尔曼方程。这篇内容会带你彻底弄懂这条公式是怎么炼成的,从数学直觉到代码落地,一步一步来。

岗位关联

对AI从业者而言,Q-Learning是理解深度强化学习(如DQN、AlphaGo)的基石;弄懂贝尔曼方程更新规则,等于拿到了强化学习所有核心算法的“命脉”,无论是做推荐系统、自动驾驶还是游戏AI,你都拥有了最根本的设计语言。

目录
  1. 可视化演示
  2. 问题建模
  3. 奖励与回报
  4. 贝尔曼方程
  5. 时序差分TD
  6. 探索与利用
  7. 折扣因子
  8. 异策略本质
  9. 算法流程
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示Q表热力图、网格世界智能体路径和TD目标更新过程。交互切换Q表、网格和TD公式视图。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Q表热力图 每格存4个动作Q值 高Q值=最优动作 迭代更新收敛 Q(s,a)←Q(s,a)+αδ Q表存储状态-动作价值,迭代更新

问题建模

回到厨房。你要把“做番茄炒蛋”这件事变成一套可记录的攻略,首先得把“做菜”拆成一个个具体的问题:现在是什么状态(番茄切好了没?鸡蛋打了没?油热了没?),在这个状态下你有哪些动作可选(去皮?打散?大火?)。每一个“状态+动作”的组合,都会通向一个新的状态——这就是“状态-动作对”。

在强化学习的语言里,“状态”用 $s$ 表示,“动作”用 $a$ 表示。智能体每到一个状态 $s$,就从可选动作集合里挑一个 $a$ 执行,然后环境会反馈一个奖励 $r$,并推着它到达下一个状态 $s'$。这里的关键是:我们不能只关心“这一步吃到嘴里的味道”,还要考虑“这一步会把整道菜引向什么结局”。

为了记住每个“状态-动作对”的长期好坏,我们维护一张表格,叫 Q表。每一行是一个状态,每一列是一个动作,单元格里存的就是“在这个状态做这个动作能带来的长期总收益”——即 Q值。当智能体面对一个新状态时,它会查表,从中挑出Q值最大的动作来执行,这就是“策略查询”。

你一开始的账本全是空的,Q值全是0。没关系,接下来你会让这个账本在一次次的试做中,慢慢写满靠谱的数字。

Q:S×A→RQ: S \times A \rightarrow \mathbb{R}
通俗说:Q表是一本“菜谱账本”,记录着每个厨房场景下每个操作手法的“划算程度”,值越高越值得做。
  1. 理解符号 $QS \times A \rightarrow \mathbb{R}$:左边的 $S$ 是所有状态的集合,$A$ 是所有动作的集合,$\times$ 表示“两两组合”,$\mathbb{R}$ 表示“实数”。整句话的意思是:对于任意一个“状态+动作”,Q函数都能给出一个实数值。
    Q:S×A→R\displaystyle Q: S \times A \rightarrow \mathbb{R}
  2. 理解 $S$(状态空间)它代表厨房里所有可能出现的“局面”,比如“番茄切好块、蛋液已打散、油温七成热”是其中一个元素,$s$ 是它的具体代称。
    s∈S\displaystyle s \in S
  3. 理解 $A$(动作空间)它代表在每个状态下你所有可能做的动手选择,$a$ 是其中某一个动作。
    a∈A(s)\displaystyle a \in A(s)
  4. 理解 $\rightarrow \mathbb{R}$(输出实数)$Q(s, a)$ 的最终输出是一个实数,比如 8.5 分。这个分数不是“这道菜这一口好不好吃”,而是“在这个局面下做这个动作,到整道菜做完为止,预期能积累的总美味值”。
    Q(s,a)∈R\displaystyle Q(s, a) \in \mathbb{R}

奖励与回报

你试做了一盘番茄炒蛋,尝了一口——“嗯,有点咸,不过蛋很嫩,总体6分。”这个6分就是 即时奖励 $r$,它只评价“这一口”的味道。但人生不是只有这一口,一盘菜做到一半,后面还有好几个步骤,每一步都会带来新的味道体验。所有步骤里的奖励加在一起,才是这盘菜的 累计回报。

在强化学习里,智能体从某个状态 $s_t$ 开始,执行动作 $a_t$,拿到奖励 $r_{t+1}$,然后到达 $s_{t+1}$;再执行 $a_{t+1}$,拿 $r_{t+2}$,以此类推。从时间 $t$ 开始往后拿到的所有奖励之和,叫 回报,记作 $G_t$。但要注意:未来的奖励通常比现在的“缩水”,所以我们要给未来的奖励打一个折扣系数 $\gamma$(gamma),这个系数小于1。

一条从起点到终点的完整“状态-动作-奖励”链条,叫做 轨迹。比如你做一盘菜,从备料到出锅,中间经历了“切番茄 → 打蛋 → 热油 → 下蛋 → 下番茄 → 调味 → 出锅”。每一步吃到嘴里的味道,都是这条轨迹上的一个节点奖励。

现在你手头有了“这口味道”和“未来所有折扣过的味道”,下一步的Q值更新就会把这两者巧妙结合起来。

Gt=rt+1+γrt+2+γ2rt+3+⋯=∑k=0∞γkrt+k+1G_t = r_{t+1} + \gamma r_{t+2} + \gamma^2 r_{t+3} + \cdots = \sum_{k=0}^{\infty} \gamma^k r_{t+k+1}
通俗说:回报不是“这一口的快乐”,而是“从这步开始往后的每一口快乐,按折扣加一块的总和”。
  1. 理解 $G_t$(回报)$G_t$ 代表从时间 $t$ 开始直到终点的所有奖励总和,这是整道菜剩下的全部体验值。
    Gt=rt+1+γrt+2+γ2rt+3+⋯\displaystyle G_t = r_{t+1} + \gamma r_{t+2} + \gamma^2 r_{t+3} + \cdots
  2. 理解 $r_{t+1}$(第一步奖励)在状态 $s_t$ 执行动作 $a_t$ 后立即拿到的奖励,它就是“这一口”的即时味道,不用打折扣。
    rt+1\displaystyle r_{t+1}
  3. 理解 $\gamma r_{t+2}$(下一步的折扣)第二步的奖励要被乘一个小于1的系数 $\gamma$。比如 $\gamma=0.9$,那么下一步的1分美味,折算到现在只值0.9分。
    γrt+2\displaystyle \gamma r_{t+2}
  4. 理解 $\gamma^2 r_{t+3}$(再下一步的折扣)第三步的奖励要乘 $\gamma$ 的平方,也就是被折两次。距离现在越远的味道,折算到当前就越不值钱。
    γ2rt+3\displaystyle \gamma^2 r_{t+3}
  5. 理解 $\sum_{k=0}^{\infty} \gamma^k r_{t+k+1}$(通式)把从 $k=0$ 开始的每一项都加起来。$k$ 每加1,时间向后推一步,折扣也多乘一次 $\gamma$。
    ∑k=0∞γkrt+k+1\displaystyle \sum_{k=0}^{\infty} \gamma^k r_{t+k+1}

贝尔曼方程

你的直觉告诉自己:“这盘菜在第3步做得好不好,要看第3步的即时味道 + 第4步及以后的味道。”这个“当下的 + 未来的”结构,正是贝尔曼方程的核心思想。

贝尔曼方程说的是:一个状态-动作对的Q值,等于执行这个动作后获得的即时奖励,加上到达下一状态后、按最优策略继续走所能获得的折扣后的最大Q值。这里的“最大”是个关键,它假设从下一个状态开始,你会走得非常聪明,总是选择Q值最大的那个动作。

这意味着我们不是一步到位算出正确答案,而是用 旧Q值 算出 新Q值,反复迭代。就像你做菜,这次试验的经验(即时奖励 + 对未来最好情况的估计)会小幅修正你脑子里的菜谱;下次再做,你会带着这个修正后的菜谱重新试,再修正一次。随着次数增加,Q值会不断逼近最优值。

这个方程给了我们一个“自我更新”的公式:用旧Q值算出一个新目标,再往目标迈一小步,如此反复,Q表就会逐渐收敛到最优的 $Q^*$。

Qπ(s,a)=E[rt+1+γmax⁡a′Qπ(st+1,a′)∣st=s,at=a]Q^{\pi}(s,a) = \mathbb{E}\left[ r_{t+1} + \gamma \max_{a'} Q^{\pi}(s_{t+1}, a') \mid s_t = s, a_t = a \right]
通俗说:这一步的“攻略分数” = 吃到嘴里的分数 + 折扣 × 下一步最好操作能带来的分数。
  1. 理解 $Q^{\pi}(s,a)$(当前状态-动作的Q值)在策略 $\pi$ 下,处于状态 $s$ 并执行动作 $a$ 的长期预期得分。
    Qπ(s,a)\displaystyle Q^{\pi}(s,a)
  2. 理解 $r_{t+1}$(即时奖励)执行 $a$ 后立刻收到的反馈,来自环境的味觉评分。
    rt+1\displaystyle r_{t+1}
  3. 理解 $\max_{a'} Q^{\pi}(s_{t+1}, a')$(未来的最大值)到达下一个状态 $s_{t+1}$ 后,在它所有可选动作 $a'$ 中,挑Q值最高的那个。这代表着“接下来每一步都走最划算的操作”。
    max⁡a′Qπ(st+1,a′)\displaystyle \max_{a'} Q^{\pi}(s_{t+1}, a')
  4. 理解 $\gamma \max_{a'} Q^{\pi}(s_{t+1}, a')$(折扣未来)未来的最大价值需要乘 $\gamma$,表示“未来的幸福要打点折扣”。$\gamma$ 越接近1,你越看重长远;$\gamma$ 越接近0,你越只看重眼前。
    γmax⁡a′Qπ(st+1,a′)\displaystyle \gamma \max_{a'} Q^{\pi}(s_{t+1}, a')
  5. 理解 $\mathbb{E}[\cdot]$(期望)环境有随机性,比如“这次蛋炒得嫩不嫩”不完全由你控制,所以要用期望表示“平均意义下的价值”。
    E[⋅]\displaystyle \mathbb{E}[\cdot]

时序差分TD

想象你学做菜,你不是等整盘菜做完、全家人吃完才评价“整盘菜值几分”。你在每一步出锅后,尝一口,立刻嘀咕一句:“嗯,这一步做得不错,下一步继续保持。”这种“走一步、看一步、立刻修正”的方法,就是 时序差分(Temporal Difference,简称 TD)。

TD的核心思想是:我们不必等到轨迹走完拿到真正的总回报 $G_t$,而是可以利用 当前奖励 + 对下一状态的估计值 作为“一个临时的目标”,这个临时目标叫做 TD目标。拿TD目标减去当前Q值,就得到 TD误差,误差越大,说明我们的估计越需要修正。

Q-Learning使用的更新方式是 单步TD:每执行一个动作,立即用这一条的 $(s, a, r, s')$ 四元组更新一次Q值。好处显而易见——一步一更新,不用傻傻等到终局,效率极高。

这种“走一步修一步”的机制,让智能体能在一次轨迹进行中不断积累经验,不用等到游戏结束才知道哪个动作好——这是TD方法独有的魅力。

Q(s,a)←Q(s,a)+α[r+γmax⁡a′Q(s′,a′)−Q(s,a)]Q(s,a) \leftarrow Q(s,a) + \alpha \left[ r + \gamma \max_{a'} Q(s',a') - Q(s,a) \right]
通俗说:每次做完一步,直接说“刚才那个预测偏了,往尝到味道 + 预估下一步的方向掰一点点”,每步都修,越修越准。
  1. 理解 $\leftarrow$(赋值更新)右边的计算结果覆盖掉左边的旧值,Q表单元格被刷新了一次。
    Q(s,a)←Q(s,a)+α[⋯ ]\displaystyle Q(s,a) \leftarrow Q(s,a) + \alpha[\cdots]
  2. 理解 $r + \gamma \max_{a'} Q(s',a')$(TD目标)这是“现实”给出的一个临时目标:这一口的真实反馈 + 折扣后的下一步最优估计。
    r+γmax⁡a′Q(s′,a′)\displaystyle r + \gamma \max_{a'} Q(s',a')
  3. 理解 $r + \gamma \max_{a'} Q(s',a') - Q(s,a)$(TD误差)现实目标与当前预测的差距。差距大,说明你的菜谱预测得离谱,需要大改;差距小,说明估计得差不多了。
    r+γmax⁡a′Q(s′,a′)−Q(s,a)\displaystyle r + \gamma \max_{a'} Q(s',a') - Q(s,a)
  4. 理解 $\alpha$(学习率)$0 < \alpha \leq 1$,它决定你每次修正的步子迈多大。$\alpha$ 大,学得快但容易振荡;$\alpha$ 小,学得稳但慢吞吞。
    α∈(0,1]\displaystyle \alpha \in (0, 1]

探索与利用

你学会番茄炒蛋后,天天做同一做法,确实稳定好吃,但你永远也不知道“加一点糖”会不会让味道更惊艳。如果只做自己最拿手的,就永远困在已知领域里——这叫 利用。而偶尔故意换个做法,哪怕可能会失败,却可能发现新的美味——这叫 探索。只会利用会止步不前,只会探索则浪费已有经验,两者需要平衡。

Q-Learning中最常用的平衡策略叫 ε-greedy(epsilon-greedy)。它规定:有 $\varepsilon$ 的概率(比如10%),随机选一个动作来试——这是探索;有 $1-\varepsilon$ 的概率,选择当前Q值最大的动作——这是利用。

注意一个细节:即使你在探索时选了“看起来很烂”的动作,Q-Learning的更新公式依然会用到“下一步的最优值”($\max_{a'} Q(s',a')$),而不是“下一步按探索策略实际做的动作”的值。这保证了你即使在乱试,学到的依然是“最优策略下”的价值。

这样一套机制,让智能体既能守住既有经验,又能持续探索新的可能性,最终学会更全面的攻略。

π(a∣s)={1−ε+ε∣A(s)∣if a=arg⁡max⁡a′Q(s,a′)ε∣A(s)∣otherwise\pi(a|s) = \begin{cases} 1-\varepsilon + \frac{\varepsilon}{|A(s)|} & \text{if } a = \arg\max_{a'} Q(s,a') \\ \frac{\varepsilon}{|A(s)|} & \text{otherwise} \end{cases}
通俗说:90%的精力做你最拿手的菜,10%的精力用来冒险新实验;实验的收获照样能总结出真本事。
  1. 理解 $\arg\max_{a'} Q(s,a')$(最优动作)在当前状态 $s$ 下,Q表里分数最高的那个动作,叫最有把握的手法。
    arg⁡max⁡a′Q(s,a′)\displaystyle \arg\max_{a'} Q(s,a')
  2. 理解 $1-\varepsilon + \frac{\varepsilon}{|A(s)|}$(最优动作的概率)$1-\varepsilon$ 的固定概率选最优动作,另外 $\frac{\varepsilon}{|A(s)|}$ 是它作为随机动作时也可能被选中的份额,所以总概率略高于 $1-\varepsilon$。
    1−ε+ε∣A(s)∣\displaystyle 1-\varepsilon + \frac{\varepsilon}{|A(s)|}
  3. 理解 $\frac{\varepsilon}{|A(s)|}$(其他动作的概率)$|A(s)|$ 是可选动作总数,所有非最优动作共享 $\varepsilon$ 的概率。
    ε∣A(s)∣\displaystyle \frac{\varepsilon}{|A(s)|}

折扣因子

现在思考一个更深的问题:为什么未来的奖励要打折?假设你学炒菜,今天的每一步操作,都会影响明天、后天做菜的水平。如果你只看今天这口好不好吃,就可能只追求“腌肉时多放糖”这种即时满足;但如果你把未来也想进去,你会选择“今天练习精准控火”这种眼前没好处但长期收益爆表的动作。

$\gamma$ 就是控制这种权重的旋钮。$\gamma = 0$ 时,智能体极度短视,只看即时奖励——“这口不入味就负分滚出”;$\gamma$ 接近1时,智能体深谋远虑,愿意为了长期大收益牺牲眼前小利——“现在练控火,未来才能做出米其林”。当 $\gamma = 1$ 且轨迹有限时,就是完全没折扣的累计回报。

这个“今天种因,未来得果”的结构,是Q-Learning能够进行长期规划的关键。它让一步棋的价值不仅取决于这步棋本身,还取决于它把局面引向何方。

在烹饪里,你现在愿意花30分钟熬一锅高汤,正因为它能让之后每一道菜都升华——这就是折扣因子在智能体身上注入的“大局观”。

γ∈[0,1]\gamma \in [0, 1]
通俗说:$\gamma$ 衡量你的“远视程度”——$\gamma$ 越大,你看得越远,现在的每一步都是在为未来铺路。
  1. 理解 $\gamma \in [0,1]$(取值范围)$\gamma$ 是一个从0到1之间的数,两头通常是开区间,即 $\gamma < 1$ 时才能保证无穷求和收敛。
    0≤γ<1\displaystyle 0 \leq \gamma < 1
  2. 理解 $\gamma$ 的指数效应第 $k$ 步未来的奖励要乘 $\gamma^k$,距离越远,折扣越大,影响越小。
    γk\displaystyle \gamma^k
  3. 理解 $\gamma$ 的收益权衡当 $\gamma$ 较大时,临近终点的动作(如“出锅装盘”)的Q值会被低估优先级,因为它的后续奖励很少;而启发阶段的动作(如“备料”)因为影响深远,Q值会被高估。当 $\gamma$ 较小时,则相反,智能体变得急功近利。
    γ 越大 ⇒ 策略越长远\displaystyle \gamma \text{ 越大 } \Rightarrow \text{ 策略越长远}

异策略本质

回到你学做菜的身份:你是一个“两条腿”的厨师。一条腿是 行为策略 ——它负责决定你“实际动手”怎么做:有时候用最拿手的手法,有时故意做点实验。另一条腿是 目标策略 ——它负责代表你“理想中”最优的稳定煮法:永远选择Q值最高的动作。

Q-Learning的独特之处在于:它用来更新Q值的“目标”(TD目标)里面,用的是 目标策略(下一步取 $\max$),而用来决定“下一步实际走哪个动作”的,却是 行为策略(ε-greedy)。学习和行动用的是两套策略——这就叫 off-policy(异策略)。

这与另一种叫 on-policy(同策略) 的算法(比如SARSA)形成对比。SARSA 用“下一步实际做出来的动作”来更新,学习路线跟着实际走;而Q-Learning 用的“下一步假想最优动作”来更新,它学的是一个大胆的幻想——“如果我从现在开始一直走最优,这条路值多少分值”,哪怕我现在走的是探索路线。

异策略的优点是巨大的:你可以在安全的环境里大胆实验(比如试遍所有奇怪的菜谱),同时学到一套最优的稳定菜谱,两者互不干扰——这就是Q-Learning能同时兼顾“探索”和“收敛”的根本原因。

Q-Learning 更新: r+γmax⁡a′Q(s′,a′)(目标策略)\text{Q-Learning 更新: } r + \gamma \max_{a'} Q(s',a') \quad \text{(目标策略)}
通俗说:你实际在厨房里乱试(行为策略),但记菜谱时按“最理想的手法”来记(目标策略),学到的是“如果我一直做得很好”的攻略。
  1. 理解行为策略决定智能体在环境中实际如何选择动作 $\mu$(如 ε-greedy),它控制的是智能体的“手脚”。
    at∼μ(⋅∣st)\displaystyle a_t \sim \mu(\cdot|s_t)
  2. 理解目标策略决定更新Q值时参照的最优动作 $\pi$(如 $\arg\max$),它控制的是智能体的“梦想”。
    π(s′)=arg⁡max⁡a′Q(s′,a′)\displaystyle \pi(s') = \arg\max_{a'} Q(s',a')
  3. 理解TD目标中的 $\max$$r + \gamma \max_{a'} Q(s',a')$ 中用的是目标策略的 $\max$,而非实际行为策略的动作,这正是 off-policy 的体现。
    r+γmax⁡a′Q(s′,a′)\displaystyle r + \gamma \max_{a'} Q(s',a')

算法流程

现在,把你学做菜的全过程整理成一套可执行的菜谱算法:

第一步,把Q表全部初始化为0(你什么都不知道);第二步,循环很多轮;每轮从起点开始,重复:观察状态 $s$,按ε-greedy选动作 $a$,执行并拿到奖励 $r$ 和下一个状态 $s'$,然后按贝尔曼更新公式刷新 $Q(s,a)$,之后把 $s'$ 当作新的 $s$,继续走;直到走到终点,一轮结束,重开下一轮。

关键点在“收敛”:随着不断重复,Q表里的每个值会越来越稳定,更新幅度越来越小(TD误差趋近于0)。当Q表稳定下来时,从每个状态看Q值最大的那个动作,就拼成了一张最终攻略—— 最优策略 $\pi^*(s) = \arg\max_a Q^*(s,a)$。

需要注意的是,Q-Learning是表格型的,它要求状态和动作都是离散的有限集合。现实中很多问题状态是连续的(比如车速、坐标),那就需要后续的DQN等方法来泛化Q函数了。

当这张表最终稳定时,你的“菜谱”就完成了。每一步该做什么,表中都有明确答案——一个从一无所知到成为大厨的完整历程。

π∗(s)=arg⁡max⁡aQ∗(s,a)\pi^*(s) = \arg\max_a Q^*(s,a)
通俗说:整个学做菜的过程可以总结为“初始化一张空的记分表 → 反复试做、每步修正分数 → 直到分数稳定 → 照着分数最高的手法做菜”。
  1. 理解 $\pi^*(s)$(最优策略)在每个状态 $s$,选择Q值最优的动作 $a$,就得出了最优策略。
    π∗(s)=arg⁡max⁡aQ∗(s,a)\displaystyle \pi^*(s) = \arg\max_a Q^*(s,a)
  2. 理解 $Q^*(s,a)$(最优Q值)经过反复迭代收敛后的Q表,里面的每个值都已经是“真实最优”的估计。
    Q∗(s,a)\displaystyle Q^*(s,a)
  3. 理解整个流程的循环算法是一个持续迭代的过程,直到 $\max_{s,a} |Q_{\text{new}}(s,a) - Q_{\text{old}}(s,a)| < \theta$(阈值θ极小)才停止。
    max⁡s,a∣Qnew−Qold∣<θ\displaystyle \max_{s,a} |Q_{\text{new}} - Q_{\text{old}}| < \theta

AI 应用场景

场景一:游戏AI自动通关

阶段:智能体训练与策略学习

解决的问题:传统游戏AI靠人工编写行为规则(比如“遇到敌人就开枪”),遇到复杂关卡就得写几千条if-else,而且无法应对玩家从没见过的局面。用Q-Learning,AI把游戏画面抽象成状态,把按键抽象成动作,通过海量自我对局,自动学会每个状态下最秀的操作。

具体案例:某游戏公司训练一个“超级马里奥”通关AI。状态是玩家坐标和周围地形,动作是“左/右/跳/加速”。AI在模拟器里以每秒几百次的速度玩,Q表记录每个地形下的最佳按键组合,几个小时后AI就能自主跳过所有陷阱通关。

场景二:推荐系统中的“冷启动”探索

阶段:采样式策略优化

解决的问题:新用户没有历史行为数据,推荐系统不知道该推什么。传统方法只能推热门内容,体验差。把用户状态建模成“浏览历史向量”(离散化),动作是“推送的品类”,奖励是“用户点击/购买”。Q-Learning的ε-greedy策略在这个场景下既会尝试新品类(探索),也会守住已知用户偏好(利用),逐步收敛到该用户的个性化最优策略。

具体案例:视频平台给新注册用户做冷启动。初始Q表全为0,前几轮随机推荐各类视频(探索),用户点击后立即更新Q值;几轮之后,Q表已能反映出该用户的偏好,推送精准度显著提升。

Python 演示

python66 行
import numpy as np class QLearningAgent:    def __init__(self, n_states, n_actions, alpha=0.1, gamma=0.9, epsilon=0.1):        self.n_states = n_states        self.n_actions = n_actions        self.alpha = alpha          # 学习率,控制每次修正幅度        self.gamma = gamma          # 折扣因子,控制长远眼光        self.epsilon = epsilon      # 探索率        self.Q_table = np.zeros((n_states, n_actions))  # 初始化Q表全为0     def choose_action(self, state):        if np.random.uniform(0, 1) < self.epsilon:      # ε概率随机探索            return np.random.choice(self.n_actions)        else:                                           # 1-ε概率利用最优            return np.argmax(self.Q_table[state])     def update(self, state, action, reward, next_state):        best_next = np.max(self.Q_table[next_state])    # 目标策略:取最大值        td_target = reward + self.gamma * best_next     # TD目标        td_error = td_target - self.Q_table[state, action]  # TD误差        self.Q_table[state, action] += self.alpha * td_error  # 贝尔曼更新     def train(self, env, episodes=500):        for ep in range(episodes):            state = env.reset()            done = False            while not done:                action = self.choose_action(state)                next_state, reward, done = env.step(action)                self.update(state, action, reward, next_state)                state = next_state  class SimpleGridWorld:    def __init__(self):        self.grid_size = 5          # 5x5网格        self.start = (0, 0)         # 起点左上角        self.goal = (4, 4)          # 终点右下角        self.state = self.start     def reset(self):        self.state = self.start        return self._state_to_idx(self.state)     def step(self, action):        x, y = self.state        moves = [(-1, 0), (1, 0), (0, -1), (0, 1)]  # 上下左右        dx, dy = moves[action]        nx, ny = x + dx, y + dy        if 0 <= nx < self.grid_size and 0 <= ny < self.grid_size:            self.state = (nx, ny)        done = (self.state == self.goal)        reward = 1.0 if done else 0.0        return self._state_to_idx(self.state), reward, done     def _state_to_idx(self, pos):        return pos[0] * self.grid_size + pos[1]  if __name__ == "__main__":    env = SimpleGridWorld()    agent = QLearningAgent(n_states=25, n_actions=4)    agent.train(env, episodes=300)    print("训练完成,最终Q表:")    print(agent.Q_table)
目的:这个Python脚本完整实现了Q-Learning算法,用5×5网格世界做小演示。智能体从左上角出发,要学到去右下角的最优路径。
  1. self.Q_table = np.zeros((n_states, n_actions))把Q表初始化为全0矩阵,就像空白的菜谱账本。
  2. if np.random.uniform(0, 1) < self.epsilon掷骰子决定是否探索,epsilon是一个0到1的随机数。
  3. return np.argmax(self.Q_table[state])这是“利用”路径:选当前Q值最大的动作,也就是“做最拿手的那道菜”。
  4. best_next = np.max(self.Q_table[next_state])目标策略:看下一步状态所有动作里Q值最大的那个。
  5. td_target = reward + self.gamma * best_next计算TD目标:现实奖励 + 折扣后的未来最优估计。
  6. td_error = td_target - self.Q_table[state, action]计算TD误差,衡量预测跟现实的差距。
  7. self.Q_table[state, action] += self.alpha * td_error按学习率修正旧Q值,这正是贝尔曼方程的最朴素落地。

常见误区

误区我一开始以为Q-Learning直接学习的是“现在该做什么动作”,所以算法每次迭代都在更新动作选择策略,像神经网络调权重那样直接调策略。

正解其实Q-Learning学的是“每个状态动作对的预期总回报”——Q值,而不是直接学策略。策略只是Q表的“副产品”:你看到Q值最大的动作,拿过来用,这构成了策略。策略本身不直接被参数化、不被“更新”,它只是查询Q表的结果。就像你学做菜,你学的是“每种做法好吃程度的分数表”,而不是直接列出“步骤一做什么步骤二做什么”的菜谱;菜谱是你每次照着分数表临时生成的。

为何常见:因为“做决策”是这个算法外在表现,大家容易误以为决策本身是被学习的对象;而实际上被学习的是背后的“价值观”。

误区我总觉得强化学习就是“跑完一整轮游戏,拿到完整的奖励列表,再回头改进”。我试过写代码时把更新放在一轮结束后才做,结果效率极低。

正解Q-Learning是单步TD算法,它每走一步就立即用 $(s, a, r, s')$ 更新一次Q值,根本不需要等一轮结束。单步更新的优势在于:你每尝一口菜,马上就把这一口的经验融入菜谱,不用等整桌菜上齐。这也是TD方法区别于蒙特卡洛方法(需要整轨结束)的关键。

为何常见:很多人先学了“回报=全程奖励求和”的定义,本能地以为必须有了全程奖励才能更新,忽略了TD目标“估计”的威力。

误区我觉得折扣因子 $\gamma$ 越小,未来的奖励打折越狠,这样智能体就越不会被遥远的、不确定的事情分心,应该学得更快更聪明。

正解$\gamma$ 恰恰是控制“远视”的旋钮,不是越大越聪明,也不是越小越聪明,而是看任务需求。如果任务里“前期选择决定后期生死”(比如下围棋),你需要大的 $\gamma$ 才能长远规划;如果任务是“眼下的操作直接影响当前得分”(比如即时反应游戏),小的 $\gamma$ 反而够用。它本质是“时间偏好”,不是“智能程度”。

为何常见:人们习惯性地认为“折扣”是贬义词,觉得打折扣就是“不重视长期”,想当然地认为不重视长期能让学习更专注。

误区我以为探索率 $\varepsilon$ 设成0.1就一直用0.1,这样既能保证探索又能保证利用,反正每个回合都用这个比例就行了。

正解工程实践中,$\varepsilon$ 通常需要随训练进度 衰减。训练初期,Q表全是0,你什么都不知道,所以要大胆探索($\varepsilon$ 大,比如1.0);训练后期,Q表已经很准了,再大量探索反而会破坏已学到的稳定策略,所以要慢慢减小到0.01甚至0。这叫 epsilon decay,是让Q-Learning收敛更快更稳的关键工程技巧。

为何常见:因为纸上定义的ε-greedy常被表述为“固定概率”,初学者容易忽略“参数要随训练动态调整”这一工程层面的设计。

误区我总想:既然实际走的时候用的是ε-greedy,那更新的时候也应该用同一个动作,不然“学”和“做”不就对不上了吗?

正解这恰恰是Q-Learning(off-policy)和SARSA(on-policy)的分水岭。Q-Learning用 $\max$(理想最优),就像你实际可以乱煮,但记笔记时永远写“如果按最理想手法做会怎样”——你学的是一个“理想的自己”的价值。SARSA用实际动作,学的是“实际会怎样”的价值。没有谁绝对好,但你如果写Q-Learning却用了实际动作,那代码就跑成了SARSA,两者行为完全不同。

为何常见:人类思维倾向于“你做了什么就学什么”,很难天然理解“做的”和“学的”可以分离——这违背直觉,但恰恰是异策略的强大之处。

面试题

Q1. 贝尔曼方程中,$Q(s,a)$ 的更新目标(TD目标)是下面哪个?

单选题 · easy

  • A.$r + \gamma \max_{a'} Q(s',a')$← 正确答案
  • B.$r + \gamma Q(s',a')$
  • C.$r + \max_{a'} Q(s',a')$
  • D.$\gamma r + \max_{a'} Q(s',a')$

答案:A。TD目标是即时奖励 + 折扣 × 下一步最优Q值,即 $r + \gamma \max_{a'} Q(s',a')$。B 少了“最优”,C 少了折扣 $\gamma$,D 把折扣加错位置了。记住“吃到嘴里的 + 打折扣的未来最好”,答案自然就是A。

Q2. 在Q-Learning中,学习率 $\alpha$ 的作用是什么?

单选题 · easy

  • A.控制每次Q值更新的步长大小← 正确答案
  • B.控制探索动作的随机比例
  • C.控制未来奖励的折扣程度
  • D.控制状态空间的离散化粒度

答案:A。$\alpha$ 是学习率,决定TD误差被吸收进Q值的比例,步长越大学得越快但易振荡。B是探索率 $\varepsilon$,C是折扣因子 $\gamma$,D是环境建模层面的事,跟 $\alpha$ 无关。

Q3. 当折扣因子 $\gamma = 0$ 时,智能体的Q值更新将表现为?

单选题 · mid

  • A.只看重即时奖励,不考虑任何未来收益← 正确答案
  • B.完全忽略即时奖励,只看重长远收益
  • C.Q值永远不更新
  • D.所有Q值趋于无穷大

答案:A。$\gamma=0$ 时,TD目标的未来项被完全抹除,只剩当前奖励 $r$,智能体变成“急功近利”型。B恰好说反了,C和D与 $\gamma$ 定义不符。

Q4. Q-Learning属于哪种策略类型?它使用什么动作进行更新?

单选题 · mid

  • A.on-policy;使用行为策略实际执行的动作
  • B.off-policy;使用目标策略下的最优动作← 正确答案
  • C.on-policy;使用目标策略下的最优动作
  • D.off-policy;使用上一个时间步的历史动作

答案:B。Q-Learning是off-policy(异策略),更新TD目标时用的是 $\max_{a'} Q(s',a')$,即目标策略下的最优动作,而非行为策略实际走的动作。这使它能在探索的同时学习最优策略。

Q5. 为什么要使用ε-greedy策略来平衡探索与利用?

单选题 · mid

  • A.为了完全杜绝随机性,保证训练稳定
  • B.因为最优策略本身只能通过随机探索才能求得
  • C.因为初始Q值不够准确,需要随机探索发现更优动作← 正确答案
  • D.因为ε-greedy能保证环境返回最大的奖励

答案:C。Q表初始值不准确甚至全为0,如果只做利用(选当前最大),一旦选中次优动作就永远无法发现更优解。ε-greedy通过小概率随机探索,保证所有动作被持续尝试,从而让Q值逼近真实最优。A说反了,B和D对不上ε-greedy的实际作用。

Q6. 在Q-Learning中,若 $\alpha=0$,则对Q表的影响是?

单选题 · hard

  • A.Q表会立刻收敛到最优值
  • B.Q表完全不再被更新← 正确答案
  • C.Q表每次更新到TD目标值
  • D.Q表只会被探索影响

答案:B。$\alpha=0$ 时,$Q \leftarrow Q + 0 \times TDerror$,无论TD误差多大,Q值都不变,智能体完全停止学习。A和C都误解了学习率的含义,D没有依据。

Q7. 以下哪些是TD方法相比蒙特卡洛方法的优势?

多选题 · mid

  • A.不需要等到一轮轨迹结束就能更新← 正确答案
  • B.天然支持在线学习和连续任务← 正确答案
  • C.每一步都能利用自举估计来修正← 正确答案
  • D.完全不需要折扣因子

答案:ABC。TD方法的核心优势就是“走一步更新一步”,天然适合在线学习(A),支持没有终止状态的连续任务(B)。它用 $r+\gamma\max Q$ 作为自举目标来修正当前估计(C)。D错误:TD目标里包含 $\gamma$,折扣因子是必需的。

Q8. 关于探索率 $\varepsilon$ 的衰减,以下做法最合理的是?

单选题 · mid

  • A.整个训练过程始终保持 $\varepsilon=0.1$
  • B.训练初期 $\varepsilon$ 大(如1.0),随着训练推进逐渐衰减到接近0← 正确答案
  • C.训练初期 $\varepsilon$ 小,后期增大
  • D.完全不用 $\varepsilon$,直接用最大Q值动作

答案:B。初期Q值不准,需要大探索;后期Q值可靠,应该增大利用、减小探索。这就是epsilon decay策略。A可能造成后期策略不稳定,C顺序颠倒,D失去了探索能力容易陷入局部最优。

Q9. 以下对“Q-Learning是off-policy算法”的理解正确的是?

多选题 · hard

  • A.行为策略和目标策略是同一个策略
  • B.更新TD目标时使用的是目标策略的 $\max$ 操作← 正确答案
  • C.行为策略可以大胆探索而不影响收敛← 正确答案
  • D.目标策略在训练过程中保持不变

答案:BC。off-policy的“异”体现在行为策略(ε-greedy探索)与目标策略(最优max)分离。B正确:TD目标用 $\max$。C正确:这正是能边探索边学最优的原因。A说反了,D错误:目标策略的Q值一直在更新,策略本身也在动态变化。

Q10. 在网格世界例子中,智能体每到达终点获得奖励+10,每踏进陷阱获得-5,折扣因子 $\gamma=0.9$。以下说法正确的是?

多选题 · hard

  • A.距离终点越近的状态,其最优Q值越高← 正确答案
  • B.陷阱相邻状态的Q值会被负奖励拉低← 正确答案
  • C.学习率 $\alpha=1$ 时,单次经验即可把Q值跳到TD目标← 正确答案
  • D.$\gamma=0.9$ 使智能体完全忽略陷阱的风险

答案:ABC。A正确,近距离高奖励通过折扣传导,使邻近状态Q值被抬高。B正确,邻近陷阱的状态因为执行某些动作会踩坑,对应Q值会被负TD误差拉低。C正确,$\alpha=1$ 时更新式变为 $Q=TDtarget$,一步到位。D错误:$\gamma=0.9$ 只是对远期收益打了小折扣,并不会忽略负奖励。