news 2026/9/29 1:31:01

强化学习入门:贝尔曼方程、DQN与经验回放实战拆解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
强化学习入门:贝尔曼方程、DQN与经验回放实战拆解

强化学习这四个字,这几年被提得太频繁了,从下棋到机械臂抓取,从推荐排序到水下航行器控制,到处都能看到它的影子。但真正把 Course3-Week3 这一周的内容从头到尾啃一遍,你会发现很多网上讲得玄乎的东西,内核其实就几个概念反复转:回报、折扣因子、策略、状态动作价值函数、贝尔曼方程,再加上一个把表格换成神经网络的工程技巧。这一篇我想干的事很简单,把这一周课程里的核心知识点拆开,配上我自己跑代码时踩过的坑,讲清楚强化学习到底在算什么、为什么这么算、以及落到 Python 里该怎么写。适合刚入门想建立框架的朋友,也适合学过一遍但总觉得“懂了又没完全懂”的朋友拿来对照。全程不堆公式吓人,能上代码的地方就上代码,能上表格的地方就上表格。

1. 强化学习到底在解决一个什么问题

1.1 从一个火星车例子说清楚 RL 的基本框架

课程里用一个火星车的例子开场,我觉得这个例子比任何定义都好用。想象有一台火星车停在一条线上,线上有若干个位置,车可以往左走也可以往右走。某些位置埋着有价值的矿石,走到那里就能拿到对应的奖励,然后这一轮任务结束。车不知道地图,它只能通过不断尝试,慢慢摸清楚“在哪个位置、往哪边走、最后能拿到多少好处”。

这个场景几乎包含了强化学习的全部要素。车当前所在的位置叫状态(state),往左或往右这个决定叫动作(action),走到矿石位置拿到的分数叫奖励(reward)。车每一次决策后,环境会把它带到新的状态,并给它一个即时反馈。整套“状态、动作、奖励、下一状态”的循环,就是强化学习和环境交互的基本节奏。

和我们熟悉的监督学习相比,最大的差别在于没有标准答案。监督学习里,每张图片都标好了“这是猫”,模型只要逼近标签就行。而强化学习里,没人告诉你“在位置 4 应该往左走”,你只知道最后拿到的总分。这个延迟奖励的特性,是强化学习所有难点和魅力的根源。你要在几十步甚至几百步之后才知道当初那个决定对不对,这种“credit assignment(信用分配)”问题,正是价值函数要解决的核心。

我个人的体会是,刚开始学的时候别急着上神经网络,先把这种“小格子、有限状态”的问题在纸上或者用几行 Python 跑通,把回报算明白、把策略迭代看明白,后面换深度网络时才不会一头雾水。

1.2 监督学习、无监督学习和强化学习的分工

很多朋友一上来就纠结“强化学习是不是比深度学习更高级”,这其实是个伪命题。它们解决的是不同层次的问题,我习惯用一张表来对照:

维度监督学习无监督学习强化学习
输入特征 + 标签只有特征状态 + 奖励
反馈每一步都有正确答案无反馈延迟、稀疏、可能有噪声
目标拟合映射找结构最大化长期累积回报
数据来源静态数据集静态数据集与环境交互产生
典型任务分类、回归聚类、降维控制、决策、博弈

关键在于数据是不是自己产生的。监督学习的数据集是别人给你的,而强化学习的数据是智能体自己“玩”出来的,你选的动作会改变你接下来看到的数据分布。这就带来一个很微妙的后果:如果你一开始策略很差,收集到的数据也差,模型就容易越学越偏。这也是后面要讲经验回放、探索策略的原因。

把这层关系理顺,你再看“深度强化学习”这个词就不会发怵了——它无非是“用深度网络去拟合强化学习里的某个函数”,两套东西是组合关系,不是替代关系。

1.3 这一周课程在整个学习路径里的位置

Course3-Week3 属于整门课的收尾部分,前面你已经有了回归、分类、神经网络的基础,这一周才正式把“决策”这条线补上。我建议的学习顺序是:先理解回报和折扣因子这类“算账”的概念,再理解策略和价值函数这类“表示”的概念,最后才是 DQN 这类“用网络去逼近”的工程手段。顺序反了,就容易出现“代码能跑但不知道在优化什么”的尴尬。

这一周内容看着不多,但它其实是整门课里概念密度最高的一周,几乎每一段都对应一个独立的知识点。我的建议是每读完一小节就停下来自己复述一遍,比如“折扣因子到底在调节什么”,能用自己的话说清楚,才算真的过了。

2. 回报、折扣因子与策略:强化学习的三块基石

2.1 回报与折扣因子,到底在算一笔什么账

强化学习里,智能体追求的不是某一步的即时奖励,而是从当前时刻开始的累积回报(return)。定义很朴素:把未来每一步拿到的奖励加起来,但越靠后的奖励要打个折。这个折扣的系数就是折扣因子 γ(gamma),通常取 0 到 1 之间,比如 0.9、0.99。

为什么一定要打折,不能直接全加起来?我总结下来有三个现实理由。第一,未来的不确定性:越远的事情越难预测,用一个小于 1 的系数衰减,能体现这种不确定性。第二,数学上的收敛性:如果每一步都有正奖励且无限进行下去,不打折的总和会发散到无穷大,优化就没法做了。第三,行为偏好:打折其实是在告诉智能体“能早拿的奖励尽量早拿”,这符合很多实际控制任务的需求。

拿火星车例子算一下你就明白了。假设折扣因子 0.9,车在某个位置面临往左还是往右的选择:往左走三步能到达一个奖励为 100 的矿石,往右走两步能到达一个奖励为 40 的矿石。往左的回报约等于 100 乘以 0.9 的三次方,大概是 72.9;往右的回报约等于 40 乘以 0.9 的平方,大概是 32.4。所以哪怕左边的矿石更远,靠折扣一算,仍然是往左更划算。这就是折扣因子在“远近”和“大小”之间做权衡的方式。

注意:折扣因子越小,智能体越短视;越接近 1,它越有耐心。同一个任务,γ 从 0.9 调到 0.99,学出来的策略可能完全不同。

2.2 策略:把状态映射到动作的那张表

策略(policy)是强化学习里真正要学的东西。它的定义简单到一句话:给定一个状态,输出该采取什么动作。用符号写就是 π(s) = a。如果状态是离散的、数量有限,策略可以就是一张查找表,每个状态对应一个动作。如果状态是连续的高维向量(比如机械臂的关节角度、摄像头的像素),策略就得用一个函数来近似,通常是神经网络。

这里有个容易被忽略的点:策略和价值函数是两个东西。策略是“怎么做”,价值函数是“这么做值多少”。很多算法是先把价值函数学准,再从价值函数里提取出策略,比如后面要讲的 Q-learning;也有算法直接学策略,跳过价值函数,比如策略梯度那一类。这一周的重点偏向前者,也就是先把“值多少钱”算清楚,动作自然就选出来了。

我在实际项目里发现,把这两个概念分开想,调试时思路会清晰很多。当模型表现不好时,先问自己:是价值估计不准,还是我根据价值选动作的方式有问题?这两个方向排查的手段完全不一样。

2.3 马尔可夫决策过程,用一句话概括核心假设

强化学习的问题通常被形式化成马尔可夫决策过程(MDP)。这个名字听着唬人,核心假设其实只有一条:当前状态包含了做决策所需的全部信息,未来只取决于现在,和更早的历史无关。这就是所谓的“马尔可夫性”。

为什么这个假设重要?因为它让我们可以只盯着当前状态来估值,不用把整条历史轨迹都记下来。假设不成立的时候(比如你只看到一帧画面,不知道球的速度方向),我们通常的做法是把最近几帧拼起来当作状态,人为地“造”出马尔可夫性。

一个完整的 MDP 由状态集合、动作集合、状态转移概率、奖励函数、折扣因子这几样东西组成。落到代码里,如果你做的是“有模型”的方法,就需要显式地知道状态转移概率;如果做的是“无模型”的方法,比如 Q-learning,那只需要能跟环境交互、拿到“下一状态和奖励”就行。大部分实际问题都属于后者,因为你根本拿不到精确的转移概率。

我把这三块基石的关系理成一句话:策略决定怎么走,回报和折扣因子定义什么算走得好,MDP 规定了你在什么样的世界里走。这三者搭起来,剩下的就都是算法层面的工程活了。

3. 状态动作价值函数与贝尔曼方程,强化学习的心脏

3.1 状态动作价值函数 Q(s,a) 到底是什么

上一节说策略是 π(s)=a,但你有没有想过,凭什么在状态 s 就选这个 a?要回答这个问题,我们需要一个能对“某个状态下做某个动作”打分的东西,这就是状态动作价值函数,记作 Q(s,a)。它的含义是:在状态 s 采取动作 a,并且之后都按最优方式行动,能拿到的期望累积回报。

注意这里有两个关键限定词。一是“之后都按最优方式行动”,也就是说 Q 值衡量的是这一步动作的潜力,而不是随便乱走的结果。二是“期望”,因为环境可能有随机性,同样的动作不一定每次都给一样的结果,所以取的是平均意义下的回报。

这里顺带把一个常被问到的概念讲透:状态价值函数 V(s) 的作用是什么。V(s) 衡量的是“我就待在状态 s,按当前策略走下去能拿多少”。它和 Q(s,a) 的关系非常直接——V(s) 等于在这个状态下,对所有可能动作的 Q(s,a) 按当前策略的概率加权求和。如果你用的是贪心策略,那 V(s) 就等于 max 的 Q(s,a)。

那为什么实际算法里更常用 Q 而不是 V?因为光有 V 选不出动作。V 只告诉你这个状态好不好,却没告诉你是哪个动作让它变好的。而 Q 每个动作一个值,直接比较大小就能选出最优动作,这对无模型的算法太方便了。这是我看课程时印象最深的一个设计动机。

3.2 贝尔曼方程:把“未来”折叠进“现在”

Q 函数的定义里含有“未来所有步的回报之和”,看起来要算到天荒地老。贝尔曼方程的漂亮之处,就是把这个无限求和递归地折叠成一步:

Q(s,a) = R(s) + γ · max Q(s', a')

用人话翻译一遍:在状态 s 做动作 a 的价值,等于当下拿到的奖励,加上折扣后的、下一状态 s' 里最优动作的价值。你看,无穷远的未来被“下一状态的最优价值”这一项代表了,因为它本身又递归地包含了再下一步。

这个等式是几乎所有价值类强化学习算法的地基。它的直觉其实很符合生活:一件事值不值得做,等于立刻得到的好处,加上它把你带到的那个新处境本身的价值。我常常拿它类比“下棋”,一步棋的价值,等于吃子得分加上走完之后局面的优劣评估。

贝尔曼方程给了我们一个迭代求解的思路:先随便初始化所有 Q 值,然后反复用这个等式去更新,直到数值不再大幅变化,就收敛到了真实 Q 值。这就是所谓的价值迭代。理解了这一步,后面 DQN 里那个“目标值 = 奖励 + γ·max Q(下一状态)”的损失函数,就完全不用死记硬背了,它就是贝尔曼方程的工程版本。

3.3 用一个手算的例子把贝尔曼方程走一遍

光看公式容易飘,我们拿一个三状态的小例子走一遍。假设有状态 A、B、C,从 A 出发有两个动作:去 B 或去 C。去 B 的即时奖励是 0,到了 B 之后还能继续拿奖励;去 C 的即时奖励是 5,但 C 是终点,到了就结束。折扣因子取 0.5。再假设 B 状态下最优的 Q 值是 10。

那么从 A 去 B 的 Q 值等于 0 加上 0.5 乘以 10,等于 5。从 A 去 C 的 Q 值等于 5 加上 0.5 乘以 0(终点没有后续),等于 5。两个动作打平。如果我们把折扣因子改成 0.9,去 B 的 Q 值变成 0 加 0.9 乘 10 等于 9,此时去 B 明显更好。

这个手算过程揭示了一个非常重要的现象:折扣因子会改变最优动作的选择。所以调 γ 绝不是随便填个 0.99 就完事,它直接决定了智能体是“稳吃眼前小利”还是“冒险博取长远大利”。我在做控制类任务时,通常先从 0.9 起步,观察策略是否过于短视,再逐步上调。

再补一个实操经验:手算这种小例子对理解收敛现象特别有用。你可以自己写个几行的循环,把 Q 值反复套用贝尔曼方程更新,然后把每一轮的数值打印出来,看着它从乱七八糟慢慢稳定到某个值,那种“哦原来收敛是这样”的感觉,比看十页推导都管用。

4. 从表格到神经网络:Deep Q-Learning 实战

4.1 为什么状态一多,表格法就撑不住了

前面几节说的都可以用一张表来存 Q 值,状态做行、动作做列。状态少的时候完全没问题,火星车就六个格子,随便存。但真实问题的状态是连续的高维向量:机械臂的状态可能包含七八个关节角度和角速度,游戏画面更是几十万维的像素。这时候表格的规模会爆炸,而且很多状态压根没被访问过,表里全是空的。

解决办法和图像识别里用神经网络代替查表是同一个思路:不去记每个状态的 Q 值,而是学一个函数 Q(s,a; θ),输入状态和动作,输出一个 Q 值,θ 是网络参数。这样即使遇到训练时没见过的新状态,网络也能根据相似性给出合理估计。这就是深度 Q 网络(DQN)的核心动机。

不过在工程细节上,把 Q 学习直接套上神经网络会非常不稳定,甚至发散。课程里专门花篇幅讲了两个关键的稳定化技巧,下面分别说。

4.2 目标网络与经验回放,两个救命的工程技巧

第一个技巧是目标网络(target network)。回忆贝尔曼方程构造的损失:我们让网络的输出 Q(s,a) 去逼近“即时奖励 + γ·max Q(s',a')”。问题是等式右边也用到了同一个 Q,这就好比你在追一个自己也在动的靶子,训练很容易震荡。

做法是再复制一个结构相同、参数暂时冻结的网络,专门用来算右边的目标值。主网络每更新若干步,才把参数“软更新”或者定期硬拷贝给目标网络。这样右边的靶子在短时间内是固定的,训练就稳了。所谓软更新,是每次只挪一小步,比如新目标网络参数等于 0.995 乘旧参数加 0.005 乘主网络参数,让目标缓慢跟随主网络,避免突变。

第二个技巧是经验回放(experience replay)。智能体在环境里连续跑,产生的样本之间高度相关,而神经网络的训练假设样本独立同分布。直接拿连续样本来训练,网络会顺着一个方向连续更新,容易过拟合最近的经历。

做法是准备一个回放缓冲区,把每一步的“状态、动作、奖励、下一状态”存进去,训练时从里面随机抽一小批。这样既打破了样本相关性,又能让同一份数据被反复利用,样本效率大幅提升。我在实际项目里,缓冲区的容量一般设到几万到几十万条,太小了容易遗忘早期经验,太大了又会拖慢单步训练速度,需要一个权衡。

4.3 探索与利用:epsilon-greedy 的取舍

还有一个绕不开的问题:智能体是根据当前 Q 值选动作的,可如果一开始 Q 值都是垃圾,它就会一直选那个“碰巧看起来最好”的动作,永远不去探索其他可能,最后困在局部最优里。这就是探索与利用(exploration vs exploitation)的矛盾。

最常用的解法是epsilon-greedy 策略:以 ε 的概率随机选一个动作去探索,以 1-ε 的概率选当前 Q 值最大的动作去利用。ε 通常从一个较大的值(比如 1.0,纯随机)开始,随着训练推进逐渐衰减到一个很小的值(比如 0.05 或 0.1)。前期多探索把地图摸清,后期多利用把已经学到的好策略稳定下来。

我踩过的一个坑是 ε 衰减得太快。刚跑几百步就把它降到 0.01,结果智能体还没探索明白就“锁定”了一条烂路,后面怎么训都上不去。经验是让 ε 的衰减和总训练步数挂钩,保证探索阶段有足够长的持续时间;也可以设一个下限,别让它降到 0,保留一点点随机性应对环境的微妙变化。

5. 一个可复现的 DQN 代码骨架

5.1 网络结构与关键超参数

理论说再多,不如直接看代码怎么搭。下面是一个简化的 DQN 骨架,用 PyTorch 写的,结构上做了精简,方便你理解主流程,真正跑任务时再按需加深加宽。

import random import numpy as np import torch import torch.nn as nn import torch.optim as optim from collections import deque class QNet(nn.Module): def __init__(self, state_dim, action_dim, hidden=128): super().__init__() self.net = nn.Sequential( nn.Linear(state_dim, hidden), nn.ReLU(), nn.Linear(hidden, hidden), nn.ReLU(), nn.Linear(hidden, action_dim) ) def forward(self, x): return self.net(x) class ReplayBuffer: def __init__(self, capacity=100000): self.buffer = deque(maxlen=capacity) def push(self, s, a, r, s_next, done): self.buffer.append((s, a, r, s_next, done)) def sample(self, batch_size): batch = random.sample(self.buffer, batch_size) s, a, r, s_next, done = zip(*batch) return (np.array(s), np.array(a), np.array(r), np.array(s_next), np.array(done)) def __len__(self): return len(self.buffer)

网络部分我没用卷积,是因为大多数入门任务的输入本身就是低维向量。真到了玩像素游戏那种场合,前面再加几层卷积把图像压成特征向量,思路是一样的。隐藏层 128 是一个起步值,任务简单可以缩到 64,复杂就往 256 加。

超参数方面,我一般这么起步:折扣因子 0.99,学习率 1e-3 到 5e-4 之间,回放缓冲区容量 10 万,每步之后从缓冲区抽 64 或 128 条训练,目标网络每几百步同步一次。这些数不是金科玉律,但作为起点很稳,能省掉很多盲调的时间。

5.2 训练循环与损失函数

训练循环是整个算法的主干,贴出来对照着看会清楚很多:

def train(env, num_episodes=1000, gamma=0.99, lr=1e-3, batch_size=64, buffer_size=100000, eps_start=1.0, eps_end=0.05, eps_decay=0.995, target_update=10): state_dim = env.observation_space.shape[0] action_dim = env.action_space.n policy_net = QNet(state_dim, action_dim) target_net = QNet(state_dim, action_dim) target_net.load_state_dict(policy_net.state_dict()) target_net.eval() optimizer = optim.Adam(policy_net.parameters(), lr=lr) buffer = ReplayBuffer(buffer_size) eps = eps_start for episode in range(num_episodes): s, _ = env.reset() done = False while not done: if random.random() < eps: a = env.action_space.sample() else: with torch.no_grad(): q = policy_net(torch.tensor(s, dtype=torch.float32)) a = int(q.argmax().item()) s_next, r, terminated, truncated, _ = env.step(a) done = terminated or truncated buffer.push(s, a, r, s_next, done) s = s_next if len(buffer) >= batch_size: bs, ba, br, bsn, bd = buffer.sample(batch_size) bs = torch.tensor(bs, dtype=torch.float32) ba = torch.tensor(ba, dtype=torch.long).unsqueeze(1) br = torch.tensor(br, dtype=torch.float32).unsqueeze(1) bsn = torch.tensor(bsn, dtype=torch.float32) bd = torch.tensor(bd, dtype=torch.float32).unsqueeze(1) q_values = policy_net(bs).gather(1, ba) with torch.no_grad(): next_q = target_net(bsn).max(1, keepdim=True)[0] target = br + gamma * next_q * (1 - bd) loss = nn.functional.mse_loss(q_values, target) optimizer.zero_grad() loss.backward() optimizer.step() eps = max(eps_end, eps * eps_decay) if episode % target_update == 0: target_net.load_state_dict(policy_net.state_dict())

这段代码里有几个地方值得单独拎出来讲。一是 (1 - bd) 这一项,它保证当这一步是终止状态时,目标值只等于即时奖励,不再往后叠加未来价值,否则会错误地把“下一局的开始”当成当前局面的延续。二是用 target_net 算 next_q,这就是前面说的目标网络稳定化。三是 gather 操作,它的作用是只取实际执行的那个动作对应的 Q 值,其他动作的值不参与这次损失,这是 Q 学习的标准做法。

我第一次写这些代码时,最常犯的错就是忘了乘 (1 - bd),导致智能体在任务结束后还傻乎乎地估值,训练目标总是偏高,表现就是怎么都学不好。这种 bug 不报错,但会让结果诡异,排查起来很费劲。

5.3 训练过程中的观察与判断

代码能跑不等于学得对,你得会看训练曲线。我通常盯三个指标:每回合的总回报、损失值、以及回合长度。健康的情况是总回报整体上升、损失先降后在一个区间波动、回合长度按照任务性质变化(比如控制任务希望它越走越稳,游戏任务希望它存活越久)。

如果回报一直贴着地板不动,先别急着调网络,回头看看奖励设计和 ε 衰减。如果是损失剧烈震荡,八成是学习率太高或者目标网络同步太频繁。我总结了一个粗线条的排查顺序:奖励信号是否合理 → 探索是否充分 → 目标网络是否稳定 → 网络容量和学习率。按这个顺序查,基本能定位到八成的问题。

提示:训练几百回合没起色很正常,DQN 的方差本来就大。建议同一套配置至少跑三次取平均,别被单次运气好的结果骗了。

6. 常见问题与排查技巧实录

6.1 训练不收敛、震荡、卡在低分的排查

这一节基本是我自己踩坑的合集。先上一张速查表,出问题时对着看:

现象可能原因排查/解决方向
回报长期不上升奖励太稀疏、探索不足检查奖励设计,调大初始 ε 或放缓衰减
损失剧烈震荡学习率过高、目标网络更新太频繁降学习率,拉长目标同步间隔或用软更新
回报先升后崩灾难性遗忘、经验回放比例失衡增大缓冲区,检查样本采样是否偏最新
Q 值爆炸到很大缺少终止处理、折扣因子接近 1确认终止状态不叠加未来值,检查 γ
策略来回抖动ε 太低导致探索不足、环境噪声大保留 eps 下限,平滑决策或多次评估

一个特别隐蔽的坑是奖励尺度。如果你一个任务里奖励有的给 1,有的给 1000,网络就会被大数值的奖励牵着走,忽略掉那些小但有意义的信号。稳妥的做法是做奖励归一化,或者把奖励都缩放到一个相近的量级。我做过一个任务,就是因为在某个少见状态下给了个异常大的奖励,结果智能体一心想着复现那个场景,其他有用的行为全被压下去了。

另一个经验是先跑通一个极简环境。在 CartPole 这种小任务上调通,确认你的代码框架、损失、目标网络都没问题,再搬到复杂任务上。直接在复杂环境里 debug,你会分不清到底是框架有 bug 还是任务本身难,那才叫折磨。

6.2 奖励设计:一个被严重低估的环节

强化学习里有一句话叫“你奖励什么,就会得到什么”,这话一点不夸张。奖励设计得好,任务轻松学;设计得烂,智能体总能找到你想不到的歪路。我见过智能体为了刷分,宁可停在原地不停触发小奖励,也不去完成真正的目标,俗称“奖励黑客”。

设计奖励我的几条原则:让最终目标有明确的正奖励,中间步骤可以给稀疏的引导奖励,但别让引导奖励盖过最终目标;惩罚要克制,惩罚太狠会让智能体干脆不动,因为不动就不会被罚;考虑时间尺度,如果任务本身奖励很稀疏,可以加一点基于进展的塑形奖励,但要小心别把最优解带偏。

说实话,奖励设计更像是一门手艺而不是科学,得多试。我的笨办法是每次只改一个地方,跑一小批实验记录对比,慢慢就能养出对“什么奖励会引出什么行为”的直觉。

6.3 一句话讲清离线强化学习为什么火

进阶方向里,这几年讨论度很高的是离线强化学习,代表算法之一是IQL(Implicit Q-Learning)。它解决的是一个很现实的痛点:在很多领域(医疗、自动驾驶)你没法让智能体随便去环境里试错,风险太大,你只有一批历史数据,想知道在这批数据上能学到多好的策略。

难点在于分布偏移——数据里出现过的好动作和你策略想选的动作可能对不上,直接用普通的 Q 学习会高估那些没见过的动作,越学越离谱。IQL 的巧思在于用“期望回归”去估计数据分布内的最优价值,而不用去查询数据分布外的动作,从而绕开了这个高估问题。理解它的前提,还是前面那套 Q 函数和贝尔曼方程,只不过在“能从数据里学多少”这件事上做了严格约束。想深入这一块,先把这一周的表格方法吃透,再看 IQL 会觉得顺很多。

7. 强化学习还能往哪些方向延展

7.1 机械臂控制与经典控制的结合

一个很落地的方向是机械臂控制。传统机械臂大多用 PID 那套经典控制方法,调参靠经验,遇到负载变化、摩擦干扰时需要重新调。有研究把 Q-learning 这类自适应方法和 PID 结合,让控制器能根据实时反馈自动调整参数,在水下航行器(AUV)这类环境多变的场景里表现更稳。思路上,智能体学的不是直接输出力矩,而是学“在当前状态下 PID 参数该往哪个方向调”,把强化学习当成了上层调参器。这种“经典控制打底 + 强化学习微调”的混合方案,我觉得比纯端到端更靠谱,也更容易在实际工程里落地。

对刚入门的朋友,我建议拿一个带连续控制的仿真环境练手,先把离散动作的 DQN 跑熟,再去看需要处理连续动作的算法,会顺很多。

7.2 从图强化学习到多智能体与联邦训练

随着任务越来越复杂,出现了一批有意思的延展方向。图强化学习是把状态或智能体之间的关系用图结构表示,再配合图神经网络去抽取关系特征,适合交通路网、社交网络这类天然带结构的问题。深度强化学习则是前面一直在讲的主线,用深网络拟合价值或策略。联邦式的多智能体训练关注的是多个智能体在各自本地数据上学习、又需要协作的场景,核心难点在于如何在不集中数据的前提下让整体策略收敛。

这些方向的共同点是,它们都没有绕开这一周的基础概念,价值函数、贝尔曼方程、探索与利用,全都还在。区别只在于“状态怎么表示”“多个智能体怎么协调”这些工程层面的问题。所以别急着追新名词,地基打牢了,上层建筑换得再快你也接得住。

8. 我个人的一些收尾体会

把这一周啃下来,我觉得强化学习最反直觉、也最需要反复咀嚼的,就是那个延迟奖励带来的信用分配问题。监督学习每步都有答案,你错了立刻知道;强化学习里,一个糟糕的决定可能几十步之后才显出后果,而一个局部的坏结果背后未必是坏决定。理解了这点,你就能明白为什么价值函数这么重要——它本质上是在给每个“状态动作对”一个长远视角的评分,把模糊的、延迟的反馈拆解到每一步上。

再一个体会是,工程细节的重要性远超标配的公式。目标网络、经验回放、epsilon 衰减、(1-done) 的处理,这些看起来琐碎的技巧,恰恰是决定你能不能跑出结果的关键。公式告诉你要往哪走,而这些技巧决定你能不能走到。我经常跟人开玩笑说,写 DQN 就像熬汤,原料就那么几样,但火候和放料的顺序才见功夫。

如果让我给正在学这一块的朋友一条建议,那就是:别贪多,把一个小环境从随机乱撞训到稳定拿高分,比把十个环境的示例代码都跑一遍收获大得多。你在那个从零到一的过程中踩的坑、调的参、看的曲线,才是真正长在你身上的东西。等哪天你看着回报曲线从一条平线慢慢抬头、又稳定在高位,你会真切地感受到强化学习是怎么回事——那种感觉,比任何定义都实在。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 1:30:40

J-Link调试器从安装到量产烧录:嵌入式开发核心工具实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:30:38

Windows内存映射:大文件处理与进程共享的底层实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:30:33

SPEED2000时域电源噪声分析:PDN瞬态响应建模与根因定位

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:30:33

ST22实战:ABAP运行时错误分析与系统排查指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:30:32

旅游景点数据分析实战:从数据清洗到客流预测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:30:16

C51单片机PWM舵机控制:无硬件PWM的精准角度实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华