ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Dueling-DQN与双经验池优先采样在MATLAB栅格路径规划中的实战解析

Dueling-DQN与双经验池优先采样在MATLAB栅格路径规划中的实战解析 前阵子做移动机器人路线规划仿真把Dueling-DQN和双经验池优先采样组合起来在MATLAB里搭了一套完整的强化学习训练流程。老实说这个组合不是拍脑袋选的而是被传统DQN在栅格地图里的表现一步步“逼”出来的。最开始用普通DQN20x20的地图跑了几百回合路径绕远、收敛慢、偶尔还撞墙后来换掉网络结构和采样策略同一张地图训练效率提升非常明显。这篇就把这套基于双经验池优先采样和Dueling-DQN的路线规划MATLAB仿真完整拆一遍从网络结构到采样机制从超参配置到训练调试包括那些文档里不会写的踩坑记录都整理出来。适合正在做强化学习入门、深度强化学习实战或者想在MATLAB里跑路线规划仿真的人参考可以直接抄作业。1. 为什么选 Dueling-DQN 做路线规划从传统DQN的三个痛点说起1.1 DQN家族在路线规划里的定位强化学习做路线规划市面上常见方案有基于策略梯度的PPO、基于值函数的DQN系列、以及基于Model-Based的算法。在栅格地图这类离散动作空间场景里DQN系列是最容易落地的一支因为动作空间天然有限——无非就是上下左右四个方向或者加对角线一共八个方向不需要像连续控制那样做复杂的策略约束。传统DQN的核心是用一个深度神经网络去逼近Q值函数也就是在某一状态s下采取动作a以后期望能获得的累积奖励。训练时通过经验回放打破样本之间的相关性配合目标网络稳定训练目标这就是2015年Nature那篇DQN的基本框架。DQN在Atari游戏上表现惊艳但搬到路线规划里就会出现一系列问题。我在仿真里调试时发现普通DQN的问题不是不收敛而是收敛得很“粗糙”具体表现就是路径次优、训练后期Q值震荡、对障碍物边缘状态判断不够稳定。1.2 传统DQN的三个明显短板第一个痛点是Q值估计结构不够合理。传统DQN的最后一层直接输出每个动作的Q值网络需要同时学会“当前状态本身有多好”和“当前状态下每个动作相对有多好”这两件事。但在路线规划里大量状态其实是“无论选哪个方向都差不多”的——比如离目标点还远的时候往左往右对结果影响不大而真正需要区分的是靠近障碍物或者靠近目标时那几步的决策。如果强行让网络同时拟合这两类信息训练负担很大也容易把有限的学习能力浪费在大同小异的评估上。第二个痛点是经验采样效率太低。普通经验回放是从一个巨大的经验池里均匀随机抽取样本。问题是不同样本对网络的学习价值差异极大。一次“差点撞墙后成功绕开”的经验和一次“在空旷区域漫无目的地走”的经验信息量完全不同。均匀采样相当于把高价值样本和低价值样本一视同仁导致那些罕见的、关键的决策点始终得不到充分学习。第三个痛点是奖励稀疏时探索效率直线下降。路线规划任务里起点到终点距离可能跨越几十个栅格中间没有中途奖励的话前期大部分尝试都是零回报加上均匀采样回放缓冲区里充斥着大量无意义的“僵尸样本”网络反复从中学不到东西。1.3 Dueling结构的核心思路Dueling-DQN针对第一个痛点做了网络结构上的手术。它把Q值函数拆成两项之和Q(s, a) V(s) A(s, a)其中V(s)是状态价值函数表示到达状态s本身能带来的期望回报A(s, a)是优势函数表示在该状态下选择动作a相对于平均水平的优势程度。网络共享底层的特征提取层到末端分成两条支路分别输出V(s)和A(s, a)最后再合并成每个动作的Q值。这样分解之后网络不再需要每个动作都去拟合完整的Q值对于“状态价值占主导、动作差异不大”的情况可以由V(s)支路直接把握大局A(s, a)支路只需要学习微小修正。放到路线规划里空旷区域导航时状态价值主导网络快速推进靠近障碍物或终点时优势支路集中火力学习动作差异决策精度明显提升。需要留意的是A(s, a)存在一个可加常数的不确定性也就是同一个Q(s, a)可以拆出无数种V(s)和A(s, a)的组合。为了让分解唯一Dueling-DQN的做法是在合并时让优势函数减去该状态下所有动作优势的均值Q(s, a) V(s) A(s, a) - mean(A(s, a))这样既保证了分解稳定性也加快了训练收敛。我在仿真里对比过去掉这个均值约束后网络输出的Q值和真实回报之间的偏差明显增大路径规划结果也波动得更厉害。2. 双经验池优先采样到底在解决什么问题2.1 优先经验回放PER的基本逻辑DQN系列算法里经验回放缓冲区的样本来源是智能体不断与环境交互产生的轨迹。优先经验回放Prioritized Experience Replay的核心观点非常朴素样本的重要程度不一样学的时候理应区别对待。衡量样本重要程度的天然指标是TD误差。TD误差的定义为δ r γ * max_a Q(s, a; θ⁻) - Q(s, a; θ)其中r是即时奖励γ是折扣因子θ⁻是目标网络参数θ是当前网络参数。TD误差的绝对值越大说明当前网络的预测和真实目标之间的差距越大这个样本越“出乎意料”越值得反复学习。PER的经典做法就是按每个样本的TD误差大小来计算采样概率P(i) p_i^α / Σ_j p_j^α其中p_i是样本i的优先级通常取|δ_i| εε是为了防止概率为0α控制优先程度。为了让引入的采样偏差不破坏学习的无偏性还要配套重要性采样权重修正w_i (N * P(i))^(-β)β在训练过程中从0逐渐增加到1修正梯度估计的偏差。2.2 单经验池的“贪心”陷阱采用了优先采样之后等于是把“均匀吸收经验”改成了“挑重点反复学”。理论上效率会提升但实践里单经验池优先采样会引入一个隐蔽的问题高TD误差样本会持续获得更高的采样概率网络反复学习这些样本TD误差逐步下降然后它们又会被其他新样本取代——听起来很自洽但实际操作中网络很容易被少量极端样本绑架。路线规划里最典型的情况是地图上某个区域障碍物分布复杂智能体在这里连续产生高TD误差的样本比如贴着障碍物边缘反复试探。这些样本占据了高优先级位次采样时大量命中网络频繁更新之后对整个地图其他区域的泛化能力被挤占。最终表现就是那一小片区域学得还不错但路线整体绕来绕去甚至在某些开阔区域走出很奇怪的折线。还有一个问题是样本覆盖度。单池优先采样本质上是在“吞吐效率”和“样本多样性”之间做权衡一旦α设置偏高比如0.7以上整个采样过程几乎盯着头部少数样本反复抽经验池容量再大也形同虚设。2.3 双经验池怎么划分、怎么配合采样双经验池的设计思路简单说就是把“高优先级样本”和“普通样本”从物理上分开存放按比例从两个池子里分别采样再混合成一个小批次去更新网络。我实现时采用的具体方案是计算每个新样本的TD误差绝对值|δ|设定一个动态阈值threshold。如果一个样本的|δ|高于当前批次平均TD误差的某个倍数比如1.2倍就放入高优先级池否则放入普通池。两个池子分别维护独立的优先级排序采样时按比例混合高优先级池采样占比η我常用0.5到0.7普通池采样占比1-η。这样做的好处在于极端样本被集中管理不用担心它们淹没普通样本普通池里那些|δ|不大但状态覆盖广泛的样本始终稳定地提供基础学习信号两个池子的采样概率都各自归一化偶发的高TD误差突变不会影响整体采样分布。阈值不是固定死的。训练早期所有样本的TD误差普遍较大阈值较高后期整体误差下降阈值也自动跟着降低。我实际用下来这个动态阈值方案比固定阈值更省心不用隔几百步就手动调一次。需要说明的是双经验池并不改变PER的权重修正逻辑从两个池子里采出的样本仍然要按各自的采样概率计算重要性采样权重w然后再参与梯度更新。修正公式里那个N是整个经验池的总样本数而不是某个池子的样本数这一点在实现时非常容易写错。3. MATLAB仿真环境搭建与网络结构实现3.1 栅格地图与强化学习环境建模MATLAB里做路线规划仿真第一步是把环境定义清楚。我用的是经典栅格地图法地图大小20x200表示可行区域1表示障碍物。起点固定在地图左上角终点在右下角。智能体每个时间步可以从当前栅格向上下左右四个方向移动一步撞到边界或障碍物时不移动并收到负奖励。环境交互用函数封装reset函数把智能体放回起点step函数接收动作返回新状态、奖励、是否结束getState函数生成当前状态的特征表示状态表示是这类仿真里最影响效果的设计点之一。最初我试过直接用智能体坐标(x, y)做状态训练结果不太好因为纯坐标看不出周围障碍物分布。后来改用特征拼接智能体自身坐标、终点相对坐标、以及以智能体为中心3x3视野范围内的障碍物编码。这样一个状态的维度是2 2 9 13维信息量足够又不至于让网络过于臃肿。奖励函数的设计我调了好几版最终版本如下到达终点20撞障碍物-5每走一步-0.1每步距离终点的欧氏距离若比上一步小0.02这样设计的好处是终点的正奖励引导最终目标障碍物的负惩罚避免碰撞步数惩罚促使路径尽量短距离奖励解决稀疏奖励问题让智能体即使在早期也能感知到“接近终点”这个方向信号。注意奖励值范围要控制住。我第一版把到达终点的奖励设成100结果梯度爆炸Q值直接发散调了很多轮才定位到奖励尺度过大的问题。强化学习里奖励幅度一般控制在-1到1区间附近比较稳妥正负奖励的绝对值差距也不要太大。3.2 Dueling-Q网络的MATLAB实现MATLAB里实现Dueling-DQN网络我用的是深度学习工具箱的dlnetwork。网络结构分三段输入层、共享层、双支路。共享层用三层全连接加ReLU激活sharedLayers [ featureInputLayer(13, Normalization, none) fullyConnectedLayer(128) reluLayer fullyConnectedLayer(128) reluLayer ];状态价值支路和优势支路共享前面的特征层末端分出两路valueBranch [ fullyConnectedLayer(64) reluLayer fullyConnectedLayer(1) ]; advantageBranch [ fullyConnectedLayer(64) reluLayer fullyConnectedLayer(4) % 动作空间是4个方向 ];前向传播时合并两条支路减去优势均值function q duelingQ(net, state) % 共享层前向 shared forward(net.shared, state); % 双支路前向 v forward(net.value, shared); a forward(net.advantage, shared); % 合并 Q V A - mean(A) q v a - mean(a, 2); end这里有一个容易踩的坑直接用MATLAB的sum或mean函数时要明确聚合维度。状态输入是按列组成的批量数据每个样本占一列所以动作维度是行方向减均值时应该按行方向做mean(a, 1)或者根据实际数据布局确认维度的顺序。我写代码时就因为维度方向搞反导致Q值计算错误但仿真仍能“跑起来”只是结果一直不对排查了很久。3.3 双经验池与训练主循环的实现双经验池的数据结构我用两个MATLAB结构体数组实现每个元素包含状态、动作、奖励、下一状态、结束标志、TD误差优先级。核心逻辑是每次step之后用当前网络计算新样本的TD误差然后决定放入哪个池子。训练主循环的流程如下for episode 1:maxEpisodes state env.reset(); done false; while ~done action epsilonGreedy(net, state, epsilon); [nextState, reward, done] env.step(action); td reward gamma * max(duelingQ(netTarget, nextState)) - duelingQ(net, state, action); if abs(td) threshold push(highPriorityPool, state, action, reward, nextState, done, abs(td)); else push(normalPool, state, action, reward, nextState, done, abs(td)); end state nextState; if poolSize batchSize % 分别采样并混合 highBatch sample(highPriorityPool, round(batchSize * eta)); normalBatch sample(normalPool, batchSize - round(batchSize * eta)); batch [highBatch, normalBatch]; % 计算重要性采样权重 w computeISWeights(batch, highPriorityPool.num, normalPool.num); % 更新网络参数 trainStep(net, batch, w); end end % 目标网络定期同步 if mod(episode, targetUpdateFreq) 0 netTarget updateTargetNetwork(net); end endepsilon贪心探索策略采用线性衰减从一个较大的值逐渐降到小值保证前期充分探索、后期充分利用。目标网络采用硬拷贝方式每隔固定回合数直接把当前网络参数复制过去。训练过程中的梯度更新使用了MATLAB的dlgradient和dlupdate每次采样完一个batch就做一次参数更新没有用多个batch累积再更新的方式。实测下来单步更新收敛更稳定时间开销也在可接受范围内。4. 训练参数设置与仿真结果分析4.1 关键超参数怎么定强化学习训练的参数之间相互牵制网上表格里的默认值并不是万能配方。我最终在20x20栅格地图上稳定收敛的一组参数如下参数取值说明经验池容量高优先池4000普通池16000总容量20000batch大小64高优先池采样占比0.6学习率5e-4使用Adam优化器折扣因子γ0.95步数惩罚下太大会导致长期绕路ε贪心起始值1.0初始阶段全随机探索ε终值0.05训练后期基本利用为主ε衰减步数50000线性衰减目标网络更新频率每200回合硬拷贝方式优先级指数α0.6控制优先级影响强度重要性采样指数β0.4到1.0随训练进程线性增长这里说几个调整经验。学习率方面5e-4对这条网络规模比较合适再大一些训练后半程Q值开始抖动再小的话收敛到最优路径要明显更久的回合。折扣因子0.95配合每步-0.1的惩罚恰好能平衡“尽快到达终点”和“避免绕路”两个目标如果把γ调到0.99智能体变得很“短视”前的远视反而会多绕路因为远程奖励经过扣减后影响力过大。双经验池的采样比例η我试过0.5、0.6、0.7三档。0.5时训练平稳但高价值样本学习速度偏慢0.7时收敛速度最快但偶尔会出现某个局部区域反复振荡0.6是一个性能和稳定性的折中。如果你在自己的场景里发现训练震荡优先降低η值而不是调小学习率。4.2 收敛曲线怎么观察训练过程中我实时绘制三条曲线每个回合的总奖励每个回合的步数每1000步的平均TD误差绝对值总奖励曲线是最直观的但它的波动也最大。回合总奖励从初始的-20左右开始随着训练的推进逐步上升最终稳定在0到5之间。注意总奖励为负不代表训练失败因为每步有-0.1的步数惩罚一条40步的路径仅步数惩罚就是-4加上探索过程中的碰撞惩罚负值很正常。关键看曲线是否单调上升并趋于平稳。平均TD误差绝对值是一个早期的监控信号。训练刚开始时这个值通常较大因为网络预测完全不准随着学习推进应该快速下降。如果它下降得很慢或者反复横跳说明经验池样本分布有问题或者网络结构、超参设置有误。步数曲线则是路径质量的直接反映。最优路径的步数在起点到终点曼哈顿距离的基础上还要加上绕开障碍物的额外步数。20x20地图从左上到右下无障碍物时最优路径38步左右实际由于障碍物分布训练收敛后智能体一般能走出45到55步的路径。如果步数长期在100步以上徘徊大概率是探索策略出了问题或者奖励函数引导不够。4.3 路线规划效果对比我在同一张地图上做了三组对比实验普通DQN、单经验池优先采样的Dueling-DQN、双经验池优先采样的Dueling-DQN。每组都跑500回合记录收敛后的平均路径长度和成功率。算法组合收敛回合数平均路径长度成功率普通DQN大约35072步82%Dueling-DQN 单池PER大约22058步90%Dueling-DQN 双池PER大约15049步96%这里“成功率”指训练结束后用epsilon0纯贪心策略评估10次成功从起点到达终点的比例。双经验池版本在收敛速度和路径质量上都是最优的这个结果也正好验证了前面关于样本多样性保护的分析——单池PER在优先学习高价值样本时不自觉地牺牲了全局覆盖路线偶尔会陷入局部绕路。5. 训练调试踩坑记录四个高频问题与排查思路5.1 训练不收敛损失曲线反复横跳这个问题在换用Dueling-DQN初期非常常见。现象是总奖励曲线一直在低位震荡平均TD误差不下降怎么调学习率都没用。排查思路按优先级排序先看奖励函数各分量是不是量级不匹配比如碰撞惩罚和终点奖励差太多再看epsilon衰减是否太慢导致训练后阶段还在大量随机探索最后检查目标网络更新频率太频繁会让训练目标一直在变。我遇到的情况是碰撞惩罚给得太重-10的碰撞惩罚让智能体变得过度保守宁可在空旷区域反复绕圈子也不敢靠近障碍物。调整到-5之后智能体开始愿意尝试贴着障碍物穿过窄通道训练很快就有起色。5.2 TD误差普遍相同优先采样失去效力一个隐蔽的坑是网络初始化的时候所有输出Q值几乎都在0附近导致初期所有样本的TD误差都约等于reward而且数值差异不大。此时如果直接用TD误差绝对值当优先级等于退化成均匀采样。解决方法是给每个新样本进入经验池时的初始优先级设置一个正数下限比如1.0而不是直接用计算出的TD误差。这样即使某一步网络预测很准、TD误差接近0样本也不会立即变成“零优先级”被完全忽略。样本在后续被采样更新后再根据实际的TD误差重新赋值优先级。5.3 双经验池样本数量严重失衡动态阈值方案下训练初期几乎所有样本都进高优先级池普通池里几乎没有样本训练后期反过来高优先级池变得冷清。两种极端都不利于采样混合。我的处理办法是对阈值加上一个范围约束计算当前批次平均TD误差的1.2倍作为基准阈值但同时限制阈值必须落在[0.1, 2.0]区间内。另外在训练前200回合强制把所有样本按比例随机分配到两个池子等样本积累到一定数量后再启用TD误差判定。这样两个池子在冷启动阶段就都有了足够的底子。5.4 收敛到局部最优路径绕着大圈到达终点智能体有时候会学会一条“虽然绕远但稳定得分”的路径因为路径长意味着每步小惩罚多但全程稳定不撞墙总奖励比老是撞墙失败要高。如果步数惩罚设置太小比如-0.01绕远路和走最优路之间的总奖励差异非常小网络很难分辨出更优策略。把这个步数惩罚适度调大或者增加每步的“距离减少”正奖励就能有效拉开最优路径和次优路径的得分差距。我最终选的-0.1步数惩罚在这个地图上效果最好。5.5 常见问题速查表现象可能原因处理办法训练完全无法起步奖励过于稀疏加入距离引导式中间奖励后期频繁撞障碍物epsilon衰减过快探索不足放慢衰减速度增大终值Q值输出数值异常大奖励幅度过大或学习率过高归一化奖励降低学习率路径绕大圈不贴边步数惩罚过小调大步数惩罚或距离奖励权重双池中一个池接近空阈值范围不合理限制阈值区间冷启动随机分配目标网络同步后性能突变硬拷贝更新频率过高降低更新频率改为软更新6. 后续可以扩展的方向这套环境搭建和训练流程稳定之后扩展方向其实很多。一个很自然的尝试是把动作空间从四方向扩展到八方向路径会平滑不少但网络输出维度增加会带来训练难度的上升。另一个方向是换成连续状态空间把栅格地图换成矢量地图配合Dueling-DQN评估连续状态这样更贴近真实机器人导航场景。还有就是把网络结构稍微升级共享层改成一维卷积来处理局部视野可以更高效地提取周围障碍物特征训练收敛速度大概率还能再提升一截。这些改造都不需要推翻现有框架在已跑通的双经验池Dueling-DQN基础之上做增量调整就行。最后再分享一个个人经验调参过程中不要同时改多个参数。每改一个变量就完整跑一轮观察效果虽然慢但你能清楚地知道是哪一步改动带来了结果变化。强化学习仿真的变量太多串行调试看起来笨拙实际上是效率最高的路径。
返回列表