
把强化学习单独放在一门课的第三周来讲第一次接触的人多半会有点措手不及——前两周还在跟监督学习的损失函数、正则化项较劲思路是给定输入预测标签错了就调参数突然画风一转变成了智能体在环境里反复试错、拿奖励、改策略。这个跳跃感是真实的也正因如此这一周的内容往往是整门课里最容易被反复回看的一节。强化学强化学习这件事说到底不是背下几个公式就完事而是要建立一套用试错来逼近最优决策的思维方式这个思维方式和之前所有学过的内容都不一样。这篇东西是把我自己啃这一周内容的过程完整摊开从这一周到底想讲什么开始把马尔可夫决策过程、状态价值函数、动作价值函数、贝尔曼方程这几个概念逐个拆开再落到能直接跑起来的 Q-learning 代码最后补上深度强化学习和离线强化学习的延伸方向以及我在调试过程中踩过的那些坑。适合两类人看一类是刚学完监督学习、准备跨进强化学习大门的新手另一类是学完一遍但感觉概念还是一团浆糊、想重新理顺逻辑的人。代码部分用的都是 Python 加 NumPy没有任何重型依赖复制粘贴就能跑。1. 从监督学习跨到试错学习这一周到底想教会你什么1.1 为什么强化学习被安排在第三周很多课程体系把强化学习放在比较靠后的位置是有讲究的。前面几周铺垫的东西——梯度下降、损失函数、过拟合与正则化、模型评估——本质上都在解决给定一批带标签的数据怎么把映射关系学准这个问题。这套思路的前提是有标准答案你算出来的预测值和真实标签一减误差就出来了剩下的就是优化。强化学习没有这个前提。智能体在环境里走一步得到的反馈不是一个正确答案而是一个标量奖励甚至这个奖励可能延迟到几十步之后才出现。你根本不知道当前这一步走得对不对只知道最后结果好不好。这种信用分配的难题才是强化学习真正区别于前面所有内容的地方。把它放在第三周我觉得意图是让你在已经熟悉用数值优化驱动模型改进这套逻辑之后再去看一种完全不同的驱动方式不靠标签靠奖励不靠一次前向传播就得到反馈靠和环境交互一整个回合才拿到反馈。理解了这个差异后面价值迭代、Q-learning 那些公式才不会显得像天书。1.2 五个基本要素搭起一个闭环不管教材怎么写强化学习的骨架始终是五个东西在转圈智能体、环境、状态、动作、奖励。智能体是决策者环境是它面对的世界状态是它此刻看到的信息动作是它能做的选择奖励是环境给它的反馈信号。这五者组成的闭环是这样的智能体观察到当前状态选一个动作丢给环境环境根据内部规则转移到新状态同时吐出一个奖励智能体拿到新状态和奖励后继续决策如此往复直到某个终止条件触发。整个过程叫一个 episode。这个闭环听起来简单但真正写代码时会立刻遇到几个绕不开的问题状态怎么表示动作空间是离散的还是连续的奖励什么时候给、给多少终止条件怎么定义这四件事定不下来后面的算法全是空中楼阁。我在做机械臂相关的练习时最深的一个体会就是环境建模花掉的时间远远超过调算法的时间而环境建模里最耗神的又恰恰是奖励设计。提示不要一上来就冲着算法去。先把环境的状态、动作、奖励、终止条件四件事写清楚写在纸上都行这一小时的投入能省掉后面十小时的调试。1.3 和另外两类学习范式的边界监督学习、无监督学习、强化学习这三者的边界很多人背得出概念但说不清区别我换个角度讲会更直观。监督学习是有老师批改作业每道题都有标准答案无监督学习是没有老师自己找规律比如把一堆数据分成几堆强化学习是没有标准答案只有一个期末总评你每一步怎么走没人管最后考砸了得自己倒推是哪一步出了问题。边界清晰之后适用场景也就清晰了。有大量标注数据、任务边界明确、每次预测都是独立的问题用监督学习。数据没有标签但需要发现内部结构用无监督学习。决策序列之间有强依赖、当前动作会影响未来状态、反馈延迟且稀疏那才是强化学习的地盘。游戏 AI、机器人控制、资源调度、推荐系统的长期收益优化都属于这一类。这里有个常见的误用有人拿强化学习去做本来用监督学习就能解决得很好的分类任务结果训练又慢又不稳定。原因很简单强化学习的样本效率天生就低它需要大量交互才能学到东西如果你有现成的标签用它纯属自找麻烦。搞清楚边界比多背几个算法有用得多。2. 马尔可夫决策过程把边走边决策翻译成可计算的数学结构2.1 五元组里的每一项对应现实中的什么马尔可夫决策过程通常写成五元组 (S, A, P, R, γ)也就是状态集合、动作集合、状态转移概率、奖励函数、折扣因子。这五个符号第一次看会觉得抽象我把它们一一对到现实场景里就好理解了。假设你在做一个仓储机器人调度系统S 是所有可能的位置组合与任务状态A 是前进、后退、转弯、抓取这些动作P 是从当前状态执行某动作后转移到各新状态的概率R 是每完成一个任务给的奖励γ 是衡量你多看重未来收益的一个系数。P 这个符号最容易被忽略但它其实是 MDP 的核心。它表达的是不确定性——同样的动作在不同情况下可能通向不同结果。真实系统里几乎不存在完全确定的转移地面打滑、传感器噪声、其他机器人抢道都会让 P 变成一个概率分布而不是一个确定值。也正因为有 P我们才需要讨论期望回报而不是确定回报。马尔可夫性这个前提值得单独说一句它假设下一个状态只取决于当前状态和当前动作跟更早的历史无关。这个假设在现实中当然不总是成立但它极大地简化了问题让价值函数可以写成只关于当前状态的函数。绝大多数入门内容都建立在这个假设上真要处理部分可观测的情况那是 POMDP 的范畴属于进阶话题。2.2 回报、折扣因子与眼前的奖励要不要贪从某一时刻开始往后所有奖励的累加就是回报。但直接累加有个问题如果任务是持续进行的奖励序列无限长总和会发散。所以引入了折扣因子 γ把未来的奖励按 γ 的幂次打折。回报的定义是 G_t R_{t1} γR_{t2} γ²R_{t3} …γ 取 0 到 1 之间。γ 的取值直接决定智能体的性格。γ 接近 0它极度短视只看眼前这一步的奖励γ 接近 1它愿意为了远期收益牺牲当下。我在做一个路径规划的小实验时对比过 γ 0.5 和 γ 0.99 的区别前者学出来的策略会在终点附近绕圈因为它看不到远处的目标奖励后者才会老老实实走最短路径。这个参数的物理含义其实是未来一步奖励在当前时刻值多少钱γ 0.9 意味着十步之后的奖励大约值当前的 0.35 倍。至于为什么用几何衰减而不是线性衰减如果认真推导一遍会有个漂亮的结论只有当折扣是几何形式时回报的递归关系 G_t R_{t1} γG_{t1} 才能成立。而这个递归关系正是后面贝尔曼方程的基础。换句话说γ 这个设计不是为了方便而是为了让整个数学框架自洽。2.3 策略的两种表示方式策略就是智能体的行为规则记作 π。它有两种常见形式搞清这两种形式是理解后面算法分歧的钥匙。第一种是确定性策略写作 a π(s)给定状态直接输出唯一动作。第二种是随机性策略写作 π(a|s)给定状态输出一个动作上的概率分布。听起来确定性策略更简洁但为什么很多算法偏偏用随机策略两个原因。一是探索需要随机性能让智能体在训练阶段尝试不同动作避免一开始就锁死在某个次优路径上。二是有些场景下最优策略本身就是随机的比如石头剪刀布这类博弈问题确定性策略一定会被对手针对。这里有个容易被忽略的细节策略是我们要优化的对象但绝大多数算法并不直接优化策略而是先算出价值函数再从价值函数里反推出策略。这个绕一圈的做法就是所谓的基于价值的方法Q-learning 属于这一派。另有一派直接对策略参数做梯度上升叫策略梯度方法。两条路线的分歧根源就在策略的表示形式上。2.4 贝尔曼方程用一个等式把无限未来折叠起来贝尔曼方程是这一周最核心的一个式子也是很多人第一次看会卡住的地方。它的思想其实很朴素一个状态的价值等于立刻拿到的奖励加上折扣后的下一个状态的价值。写成期望形式就是 V(s) 等于在策略 π 下对动作求期望、再对下一状态求期望得到 r 加上 γ 倍的 V(s)。这个式子的威力在于它把从现在到无限远的累加折叠成了一步加下一个状态的价值无限问题变成了递归问题。递归意味着可以用迭代法求解这才是后面价值迭代、时序差分这些算法能成立的根本原因。我第一次看这个推导时的疑惑是这不是循环定义吗V(s) 用 V(s) 定义V(s) 又用 V(s) 定义怎么解答案在于终止状态。总有些状态的价值是已知的比如终点的价值就是最终奖励从这个锚点出发往回一层层传整个价值表就能收敛。这也解释了为什么强化学习的问题必须要有明确的终止条件——没有终点这个递归就没有落脚点。3. 状态价值函数的作用这一周最容易被追问的考点3.1 V(s) 衡量的到底是什么状态价值函数 V(s) 的定义是从状态 s 出发按照某个策略 π 继续走下去能获得的期望回报。注意三个关键词——从 s 出发按照 π期望。第一个词说明它只跟当前状态有关跟你怎么到达这个状态无关第二个词说明它依赖于策略同一个状态在不同策略下价值不同第三个词说明它是个期望值因为转移和策略都可能是随机的。它解决的问题是这个局面好不好。举个下棋的例子棋盘上某个局面对你有利还是不利这就是状态价值的直观含义。有了它你甚至不需要预先知道每一步怎么走只要在每个状态看一眼四个方向里哪个下一状态价值最高往那边走就行了。V(s) 在实际中的用途比想象中广。除了用来做决策它还能用来做信用分配——如果一个状态的价值很高说明从这里往后大概率能拿到好结果这个状态就值得被保护。另外在优势演员评论家这类算法里V(s) 被当作基准线来降低梯度的方差这是它一个非常实用但入门时很少被强调的作用。3.2 Q(s,a) 与 V(s) 的互相推导动作价值函数 Q(s,a) 的定义是在状态 s 下先执行动作 a之后再按照策略 π 走能获得的期望回报。它比 V 多了一个维度多出来的就是当前这一步选了什么。两者的关系可以这样理解V(s) 是对所有可能动作的加权平均权重就是策略在该状态下选择每个动作的概率即 V(s) Σ π(a|s) Q(s,a)。反过来如果你知道所有动作的 Q 值那最优策略就是直接选 Q 最大的那个动作所以 V*(s) max_a Q*(s,a)。为什么要有 Q 而不只用 V关键在于光有 V(s) 你还没法直接选动作你得知道环境的转移概率 P 才能算出每个动作之后的期望价值。而在很多真实问题里P 是未知的你只能通过实际尝试来估计。这就是无模型方法存在的理由Q 值可以直接通过试错估计出来V 值在不知道 P 的情况下反而不好用。所以我个人的经验是只要环境模型未知就从 Q 入手如果模型完全已知动态规划用 V 会更省内存。3.3 优势函数与这个动作比平均水平好多少优势函数是 A(s,a) Q(s,a) − V(s)含义是在这个状态下选这个动作比按当前策略的平均表现好多少。它是个相对量正值表示这个动作优于平均负值表示劣于平均。这个量为什么重要因为它把绝对好坏变成了相对好坏。同一个 Q 值在一个整体价值很低的局面里可能是很好的选择在一个整体价值很高的局面里却可能是拖后腿的。用优势函数做策略更新梯度信号的方差会小很多训练也稳定得多。入门阶段不一定会重点讲优势函数但它是连接基于价值方法和策略梯度方法的桥梁。理解它之后再去看那些评论家网络、广义优势估计的内容就不会觉得突兀。我建议在学完 V 和 Q 之后立刻把优势函数补上它的思维成本很低但收益很大。3.4 手算一个四格世界的价值迭代光看公式容易飘我用手算一个极简例子把它落地。假设一条四个格子的直线通道位置记作 1、2、3、44 是终点。每一步可以往左或往右走出边界就停在原地并得到 −1 的惩罚。到达终点得 10并且游戏结束。折扣因子 γ 取 0.9所有状态初始价值设为 0。第一轮迭代我们从终点反推。位置 4 是终止状态价值直接是 10。位置 3 的策略是往右走价值是 10 × 0.9 9。位置 2 往右走到 3价值是 9 × 0.9 8.1。位置 1 同理是 8.1 × 0.9 7.29。这是一次完整的价值回传。第二轮再检查一遍位置 2 如果往左走到 1 再走回来得到的期望价值更低所以最优动作仍然是往右。整个过程重复几轮价值表就稳定了。这个手算过程能让你直观看到奖励从终点向起点一层层传播的机制而这个机制正是后面所有迭代算法的内核。你可以把这个例子推广到带惩罚的版本比如每走一步扣 0.1看看价值分布怎么变——会发现离终点越远价值越低而且这个衰减是指数的。提示手算这一步千万别跳过。我在带新人时发现能自己把四格世界的价值迭代算一遍的人后面理解时序差分几乎没有障碍跳过这步的人往往卡在为什么更新目标是 r γV(s)上很久。4. 从动态规划到 Q-learning能跑起来的完整实现4.1 动态规划两条路线策略迭代与价值迭代在环境模型已知的前提下求解最优策略有两条经典路线。第一条叫策略迭代分两步走先做策略评估把当前策略的价值函数算准再做策略改进对每个状态贪心地选当前看起来最好的动作。这两步交替进行直到策略不再变化。第二条叫价值迭代把评估和改进揉在一起每轮只做一次更新更新式是 V(s) 取所有动作里立刻奖励加折扣后下个状态价值的最大值。它相当于把多次策略评估压缩成了一次收敛速度往往更快代码也更短。两者怎么选如果动作空间大、每次评估都很贵价值迭代更划算如果希望每一步都有明确的策略含义策略迭代更直观。实测下来小规模问题上两者的差距可以忽略直接用价值迭代省事。价值迭代的伪代码只有几行初始化价值表循环每个状态用最大值更新反复直到变化量小于阈值。4.2 蒙特卡洛与时序差分的取舍当环境模型未知时动态规划用不了因为它需要 P。这时候有两类替代方案。蒙特卡洛方法是等一整个 episode 跑完用实际拿到的回报来更新价值。它无偏但方差很大而且必须等到回合结束才能更新不适合连续任务。时序差分方法则是走一步就更新用立刻奖励加上下一个状态的估计价值来近似真实回报。它引入了偏差但方差小得多也能在线学习。这个取舍在实践中的表现是蒙特卡洛收敛慢但目标稳定时序差分快但前期估计不准容易震荡。绝大多数现代算法都站在时序差分这一边因为在线学习的能力太重要了。我做过一个对比实验同样的迷宫环境时序差分大约用三分之一的回合数就能达到相同的成功率。4.3 Q-learning 更新公式逐项拆解Q-learning 的更新式是Q(s,a) 增加 α 乘以r 加上 γ 乘以下一状态所有动作里最大的 Q 值再减去当前的 Q(s,a)。逐项看。α 是学习率控制每次更新迈多大步子。r 是这一步实际拿到的奖励。γ 是折扣因子。max Q(s,a) 是对下一个状态所有可能动作取最大值这个最大是 Q-learning 最标志性的地方它意味着它学的是最优策略的价值跟你当前实际采用的行为策略无关。括号里那一整块叫时序差分误差可以理解成我原来以为值多少和实际观测加上后续估计告诉我值多少之间的差距。乘以学习率就是按这个差距的一部分去修正。这个结构和梯度下降的更新形式几乎一样只不过梯度换成了 TD 误差。这个最大也带来一个问题Q-learning 是离策略算法它敢用贪心的目标来更新而如果行为策略长期探索不到某些动作这些动作的 Q 值可能被高估。这就是著名的最大化偏差问题后面发展的双 Q 学习就是为了缓解它。入门时不用急着处理但心里要有这个数。4.4 一段可以直接跑的 Q-table 迷宫代码下面这段代码是一个完整的 Q-learning 实现五乘五的网格起点左上角终点右下角中间有几个障碍格。每一步撞墙或者走到普通格子扣少量分到达终点给正奖励。整个流程不依赖任何强化学习库只要 NumPy。import random import numpy as np GRID 5 START (0, 0) GOAL (4, 4) BLOCKS {(1, 1), (1, 2), (2, 2), (3, 3)} ACTIONS [(-1, 0), (1, 0), (0, -1), (0, 1)] # 上 下 左 右 N_ACTIONS len(ACTIONS) def is_valid(r, c): return 0 r GRID and 0 c GRID and (r, c) not in BLOCKS def step(state, action): 返回 (下一状态, 奖励, 是否终止) r, c state dr, dc ACTIONS[action] nr, nc r dr, c dc if not is_valid(nr, nc): return state, -1.0, False # 撞墙或撞障碍原地不动 if (nr, nc) GOAL: return (nr, nc), 10.0, True # 到达终点 return (nr, nc), -0.1, False # 普通移动给小惩罚 def q_learning(episodes3000, alpha0.1, gamma0.95, eps_start1.0, eps_end0.05): Q np.zeros((GRID, GRID, N_ACTIONS)) eps eps_start decay (eps_start - eps_end) / (episodes * 0.8) for ep in range(episodes): state START for _ in range(200): # 单回合步数上限 # epsilon-贪心选动作 if random.random() eps: action random.randrange(N_ACTIONS) else: action int(np.argmax(Q[state[0], state[1]])) next_state, reward, done step(state, action) # 终止状态未来价值为 0 future 0.0 if done else gamma * np.max(Q[next_state[0], next_state[1]]) td_target reward future td_error td_target - Q[state[0], state[1], action] Q[state[0], state[1], action] alpha * td_error state next_state if done: break eps max(eps_end, eps - decay) # 探索率逐渐衰减 return Q if __name__ __main__: Q q_learning() # 从起点出发按贪心策略走一遍打印路径 state, path START, [START] for _ in range(50): action int(np.argmax(Q[state[0], state[1]])) state, reward, done step(state, action) path.append(state) if done: break print(学到的路径:, path)跑完之后打印出来的路径应该是一条避开障碍、尽量短的路线。如果跑出来还在原地打转或者撞墙先检查 epsilon 衰减是不是太快或者单回合步数上限设得太小导致走不到终点。代码里有两个细节值得说。一是终止状态的处理done为真时未来价值取 0这不是偷懒而是因为终点之后没有未来了如果这里还去查 Q 表会把终点后面的估计值错误地算进来。二是 epsilon 的衰减速度我用的是线性衰减到 0.05 为止保留一点探索是为了防止策略完全锁死。4.5 三个核心参数怎么定学习率 α、折扣因子 γ、探索率 ε 是三个必须调的旋钮它们各自的作用和常见取值我用一张表对比一下。参数作用常见取值调大了会怎样调小了会怎样α 学习率每次修正的步长0.05 ~ 0.2更新快但震荡难收敛收敛稳但极慢γ 折扣因子对远期奖励的重视程度0.9 ~ 0.99看得远但方差大、易过估计短视学不到长期策略ε 探索率随机尝试的概率从 1.0 衰减到 0.05一直乱走学不会早早锁死次优路径这三者的联动很有意思。γ 调大之后回报的方差会显著上升这时候如果 α 还开得很大训练曲线会剧烈抖动解决办法是把 α 降下来同时多跑一些回合。反过来如果 α 很小而 γ 也小智能体会学得非常慢而且短视看起来像是什么都没学到。我自己的经验速记迷宫这类离散小问题α 从 0.1 起、γ 从 0.95 起、ε 从 1.0 线性衰减到 0.05基本不用怎么改就能跑通。遇到连续控制或者状态空间大的问题再针对性调整。5. 表格装不下状态之后深度强化学习与离线强化学习5.1 函数逼近为什么是必然选择Q-table 的方式有个硬伤它要求每个状态单独占一行。状态数量少的时候没问题一旦状态变成图像、连续坐标、高维传感器读数表格就彻底装不下了这就是维度灾难。而且表格方式没有泛化能力见过状态 A 学到的东西对相邻的状态 B 一点用都没有。解决办法是用一个参数化函数来近似 Q 值输入状态输出各动作的价值函数的形式可以是线性模型也可以是神经网络。用了神经网络就是深度强化学习。它的好处是相邻状态会得到相似的输出学到的经验能自动泛化而且参数量不随状态数指数增长。代价也很明显不再有任何收敛保证。表格方法在合适条件下能证明收敛换成神经网络之后训练稳定性成了主要难题各种技巧基本都是围绕这一点发展出来的。5.2 DQN 稳住训练的两个关键设计深度 Q 网络把 Q 学习和神经网络结合起来但直接拼起来会失败原因有两个。一是样本之间高度相关相邻时刻的样本几乎是同一场景的变体用它做梯度下降会破坏独立同分布假设。二是目标值和预测值同时更新相当于追着自己的尾巴跑。对应的两个设计是经验回放和目标网络。经验回放把交互产生的转移存进一个大缓冲区训练时从中随机采样一批这样样本之间的相关性被打散了而且一条经验可以被反复利用样本效率提升明显。目标网络是另外复制一个结构相同但参数更新缓慢的网络专门用来算更新目标隔一段时间才把主网络的参数同步过去这样目标不会每一步都变。这两个技巧的组合效果非常显著可以说是深度强化学习能落地的基石。实现上有几个细节要注意缓冲区容量通常在十万量级太小起不到打散作用目标网络的同步周期一般是几百到几千步训练时先让缓冲区积累一定数量的数据再开始学不然一开始样本太少没意义。5.3 奖励设计与稀疏奖励的破解思路奖励设计是实战中最容易翻车的地方也是书本上很少讲透的部分。稀疏奖励指的是只有达成目标才有奖励中间过程没有任何反馈智能体相当于在一个巨大的空间里盲找几乎学不到东西。破解思路有几条。第一是奖励塑形在中间过程加一些引导性奖励比如离目标更近就给一点正反馈、每消耗一步给一点负反馈。这个做法要注意尺度如果引导奖励给得太大智能体可能学会拿奖励但不完成任务比如原地打转刷分。第二是分层思想把大任务拆成若干子目标每个子目标单独给奖励。第三是用内在好奇心类的方法鼓励智能体探索状态空间中新奇的区域。我在做机械臂抓取练习时遇到过典型症状机械臂在原地抖动不抓取原因是每步惩罚设得比抓取奖励还重它干脆选择不动来少扣分。后来把步惩罚调小同时给爪子靠近物体一个小的中间奖励训练立刻就有起色。这个坑很典型如果你发现智能体学会了什么都不做先去检查奖励的量级关系。5.4 离线强化学习适合什么场景前面讲的都是在线方法智能体一边交互一边学。但有些场景根本不允许你随便试比如医疗决策、工业生产参数调整、真实机器人操作试错成本太高甚至不可逆。离线强化学习解决的就是这个问题只给你一批已经采集好的历史数据要求从中学会策略全程不再和环境交互。难点在于分布偏移。历史数据是用某个行为策略采集的学出来的策略会倾向于选择数据里出现很少的动作而这些动作的价值估计极不可靠容易被高估最后策略跑偏到数据分布之外。常见的应对方法是给更新目标加约束限制新策略偏离行为策略太远。如果你的场景是仿真环境、可以随时重置、试错成本为零那就老老实实在线学。只有当真机操作代价高、数据只能靠历史积累的时候离线方法才是必须的。判断标准很简单你能不能承受一万次失败能就在线不能就离线。6. 实操踩坑实录与问题速查6.1 训练不收敛时的排查顺序遇到训练不收敛不要急着改算法按固定顺序排查效率最高。先看环境。奖励函数有没有量级失衡终止条件能不能被触发动作执行之后状态有没有真的变化这三个问题里任何一个出问题再强的算法也救不回来。我遇到过最离谱的一次是碰撞检测写错了一个坐标导致智能体永远撞不到障碍自然学不会避障。再看数据流。Q 值有没有在更新打印几个状态下的 Q 值看看如果全是零或者全是 NaN说明更新逻辑有问题。NaN 通常来自学习率过大或者除以零。然后看超参数。α 是不是太大导致震荡γ 是不是太小导致短视ε 衰减是不是太快导致没探索够最后才看算法本身是不是适合当前问题。虽然理论上 Q-learning 能处理任意离散 MDP但状态空间大的时候它确实力不从心这时候要换函数逼近方法而不是继续调参数。6.2 常见现象与成因对照表下面这些症状我在调试过程中基本都遇到过整理成表方便对号入座。现象可能的成因处理办法智能体原地不动步惩罚大于动作收益调小每步惩罚增加中间引导奖励前期学到策略后期崩掉学习率过大或探索率衰减过快降低 α放缓 ε 衰减Q 值持续膨胀不收敛未处理终止状态γ 接近 1终止状态未来价值置 0适度降低 γ回合长度越来越长却总失败陷入绕圈循环增加步上限加入每步负奖励训练几百轮毫无起色奖励过于稀疏做奖励塑形或引入中间目标学习曲线剧烈抖动样本相关性过强引入经验回放增大批量表现远好于实际测试时仍在探索评估阶段关闭探索用贪心策略这张表不是万能的但能覆盖大部分入门阶段的问题。我建议每次遇到异常先在这张表里找找有没有对应项往往比盲目改参数高效得多。6.3 几条我自己总结的经验第一条先跑通再优化。不要一上来就追求 SOTA 效果先用最小环境加最小算法跑出能动的策略确认整条链路通了再去处理性能问题。很多新手的卡点其实在于环境代码本身有 bug而不是算法不行。第二条把可视化做在前面。训练过程中的 Q 值分布、平均回报曲线、智能体的行动轨迹这三样东西能解决八成的调试问题。纯看数字打日志效率太低我在关键实验里都会顺手把轨迹画出来。提示在评估阶段一定要把探索关掉。开着 ε 去评估测出来的成功率会明显偏低你会误以为算法没学好白白折腾半天。第三条学会用极端参数定位问题。想确认某段逻辑有没有生效就把相关参数设成极端值看行为有没有明显变化。比如把 γ 设成 0.01如果策略毫无变化说明你的折扣因子根本没进到更新式里。这个技巧能快速排除改了但没生效这类隐蔽 bug。第四条把随机种子固定下来。强化学习方差天然就大不固定种子的话两次跑出来的结果差异可能比改算法的差异还大导致你无法判断改动到底有没有用。固定种子之后再刻意用多个种子做对比看均值而不是看单次结果。第五条也是我个人体会最深的一条强化学习的门槛不在算法在环境。把环境设计清楚了奖励给对了剩下的算法部分其实是整个流程里最标准化的环节。我见过太多人花两周调算法最后发现问题出在奖励函数的一个符号上。回过头看这一周的内容V 函数、Q 函数、贝尔曼方程这三样东西是贯穿全场的骨架其余内容基本都是从它们派生出来的。真正学透的标志不是能背下更新公式而是看到一个新问题时能条件反射地想清楚状态怎么定义、动作空间长什么样、奖励该在哪里给、折扣因子取多少。这四个问题回答好了选什么算法反而是水到渠成的事。这套框架用在游戏、机器人、调度系统上是同一套差别只在细节。