ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

MATLAB实现Q-Learning迷宫路径规划:从Q表到Dijkstra基线对比

MATLAB实现Q-Learning迷宫路径规划:从Q表到Dijkstra基线对比 简介一份基于MATLAB的强化学习Q-Learning算法迷宫路径规划资源面向强化学习初学者、研究人员及路径规划相关领域从业者系统展示了智能体通过Q表试错更新在迷宫中寻找最优路径的完整流程。压缩包共593个文件、7.32MB以481个.m源码文件为核心覆盖Q-Learning核心逻辑、环境仿真与主控脚本同时包含26个.mat数据文件、20个.fig结果图像、10个.txt说明及pdf文档等可结合文档理解参数配置与实验输出。已有314人学习下载资料不仅对Q-Learning原理、迷宫环境建模、Q表初始化与更新规则、MATLAB编码步骤进行了细致拆解还给出实验结果分析和未来优化方向如算法改进、与其他方法融合、多智能体协作及真实场景迁移。借助这些脚本、数据和图示可快速复现迷宫逃脱实验并在此基础上开展二次开发深入掌握基于价值迭代的路径规划思路同时加深对强化学习机制的理解。1. 迷宫路径规划为什么我先把钱花在Q-Learning上做迷宫路径规划很多同学第一反应是 A* 或 Dijkstra但这类算法要求环境模型完整摆在面前地图一变就要重新跑一遍图搜索。Q-Learning 则不需要预知全局地图智能体靠试错更新 Q 表就能逐步逼近最优策略这正好切中“动态环境 奖励可调”的诉求。这篇文章用 MATLAB 写一个可复现的迷宫逃脱 demo10×10 网格地图、四个动作、终点给正奖赏训练出 Q 表后按贪心策略走路径。适合有基础 MATLAB 语法的开发者和刚接触强化学习的研究者新手能照步骤跑通熟手可以从中拆奖励设计和超参调优的边界。源码包里的dijkstra.cpp等 MEX 文件也正好拿来当对比基线量化 Q-Learning 学到的东西离“最优”还差多远。2. Q-Learning 原理与迷宫环境建模2.1 从马尔可夫决策过程到 Q 表强化学习把迷宫问题建模成马尔可夫决策过程典型五元组是S, A, P, R, γ。在迷宫里状态 S 是智能体所在网格坐标动作 A 是上、下、左、右四个移动方向转移概率 P 在静态地图中接近确定性R 是每步获得的奖励γ 是折扣因子控制未来奖励对当前决策的影响程度。Q-Learning 是离策略、无模型的时序差分算法核心更新公式是Q(s,a) ← Q(s,a) α · (r γ · max_{a} Q(s,a) − Q(s,a))这个公式的直观理解是执行动作 a 到状态 s′ 后用“真实奖励 r 下一状态里最大 Q 值的折现”作为目标值减去当前 Q 值得到误差再乘以学习率 α 更新。因为它取的是max_{a}所以学习目标是最优策略的期望回报而实际采集中使用 ε-greedy 产生动作属于典型的 off-policy 方式。迷宫场景下状态空间不大用一张二维表格存 Q 值完全够用不需要引入神经网络这也是表格型 Q-Learning 最适合入门的原因。常见参数配置如下参数推荐范围说明α 学习率0.1 ~ 0.5越大更新越快但太大会震荡γ 折扣因子0.9 ~ 0.99小则短视大则更重视远期奖励ε 初始值1.0训练初期保证充分探索ε 衰减率0.99 ~ 0.999每 episode 乘一次后期转入利用episode 数500 ~ 200010×10 地图一般 800 轮足够2.2 迷宫网格与奖励函数设计先说地图设计。这里用一个 10×10 矩阵表示迷宫1 是墙0 是通道起点在左上角(1,1)终点在右下角(10,10)。MATLAB 实现时我习惯直接用矩阵画迷宫map zeros(10, 10); map(2, 3:9) 1; % 第二行一堵横墙 map(5, 1:4) 1; % 第五行左侧墙 map(8, 6:10) 1; % 第八行右侧墙 map(4, 7) 1; % 独立障碍 map(7, 3) 1; % 独立障碍 nrow size(map, 1); ncol size(map, 2); N nrow * ncol; % 状态总数实际可访问状态要排除墙 start_idx sub2ind([nrow, ncol], 1, 1); goal_idx sub2ind([nrow, ncol], 10, 10); reward -0.04 * ones(nrow, ncol); % 每走一步的小额成本 reward(10, 10) 10; % 终点给正奖励 Q zeros(N, 4); % 4 个动作1上、2下、3左、4右这段代码里reward -0.04是老玩家常说的“步成本”它让智能体学会走路时少绕弯。如果不加步成本只给终点正奖励Q-Learning 很可能学出“走空地绕圈子”的奇怪行为因为中途所有状态价值看起来都一样。撞墙或越界不能在奖励函数里一视同仁我一般给 −1否则智能体会贴着墙试错很久。终点的 10 需要盖过整条路径的负累积10×10 地图最长路径不会超过几十步−0.04×20 大约是 −0.8差距足够明显。3. MATLAB 实现学习率、折扣因子和贪心系数怎么控制训练主循环3.1 训练主循环结构与完整实现训练主循环是 Q-Learning 的核心。每一 episode 从起点出发按 ε-greedy 选动作执行动作得到奖励和下一状态然后更新 Q 表直到走到终点或超过最大步数。完整代码如下alpha 0.1; % 学习率 gamma 0.95; % 折扣因子 epsilon 1.0; % 探索率 epsilon_min 0.01; % 最小探索率 decay 0.995; % 每 episode 衰减因子 max_episodes 800; max_steps 300; actions [-1 0; 1 0; 0 -1; 0 1]; % 上、下、左、右 episode_rewards zeros(max_episodes, 1); for ep 1:max_episodes s start_idx; total_reward 0; for step 1:max_steps % epsilon-greedy 选择动作 if rand epsilon a randi(4); else [~, a] max(Q(s, :)); end % 执行动作计算新位置 r ceil(s / ncol); c mod(s - 1, ncol) 1; nr r actions(a, 1); nc c actions(a, 2); % 越界或撞墙留在原地给惩罚 if nr 1 || nr nrow || nc 1 || nc ncol || map(nr, nc) 1 next_s s; r_step -1; else next_s sub2ind([nrow, ncol], nr, nc); r_step reward(nr, nc); end % Q 表更新 Q(s, a) Q(s, a) alpha * (r_step gamma * max(Q(next_s, :)) - Q(s, a)); total_reward total_reward r_step; s next_s; % 到达终点后结束本 episode if nr 10 nc 10 break; end end episode_rewards(ep) total_reward; epsilon max(epsilon_min, epsilon * decay); end这段代码有几个容易踩的细节r_step和终点奖励的关系如果nr 10 nc 10reward(10,10)取到的是 10更新后立刻 break不再用终点的next_s继续往后算。撞墙时next_s等于s更新公式里会出现max(Q(s,:))和旧状态发生耦合这是合理的表示原地惩罚。rand epsilon是标准的 ε-greedy 写法均匀随机数小于 epsilon 就随机探索否则取 Q 值最大的动作。很多人在训练后段发现路径不稳定往往是因为 epsilon 没有衰减到 0.1 以下。3.2 探索与利用的平衡epsilon-greedy 细节探索与利用的平衡是 Q-Learning 能不能收敛的关键。训练初期 Q 表全是零如果直接取max(Q(s,:))智能体会一直选前几个动作比如总是向上走导致永远到不了终点。所以初始 epsilon 要足够大常见做法是 1.0 开始让前几十轮完全随机。衰减速度也要控制。我的经验是10×10 迷宫decay0.995大约在 300 个 episode 后 epsilon 降到 0.22之后慢慢进入利用期如果decay0.9580 轮后 epsilon 已经低于 0.02地图还没探索完就变成纯贪心最后 Q 表会收敛到局部次优解。更稳妥的做法是记录走过的步数超过阈值再默认从起点重新开始但这对入门代码反而复杂不如直接用衰减。超参数的影响可以做一张速查表现象可能原因调整方向训练后路径过长探索不足或 α 过大调大epsilon_min调低 α路径频繁贴墙步成本过小把reward中普通步设为 −0.1后期奖励曲线震荡γ 过大或 ε 衰减过快γ 保持 0.95decay 调到 0.998前期一直撞墙ε 下降太快提高epsilon_min延长探索期3.3 收敛判断与 Q 表检查不能只看某一次运行结果是好的就说算法收敛。我一般会保存每个 episode 的累计奖励然后画移动平均线观察曲线前 100 轮快速升高、中段平稳、后段无明显下降趋势。累计奖励通常是负的因为步成本会一路累积直到最后拿到 10 之后才可能整体转正因此看负值的走势并不可怕关键是不要一直停留在同一个低水平。也可以直接检查 Q 表max(Q, [], 2)得到每个状态的最大价值打印起点附近的值看是否呈现从起点向终点递增的梯度。如果起点价值反而是全图最高说明奖励设置或导数项计算有代码问题。4. 运行、可视化与迷宫逃脱调试4.1 项目文件结构与 dijkstra.cpp 的作用资源包内除了主 MATLAB 脚本还包含dijkstra.cpp、find_nn.c、kernel_function.c、mexCCACollectData.c等文件。这些是 C 编写的 MEX 辅助源文件并不是全部需要编译。dijkstra.cpp的作用很清晰提供标准最短路径计算用来和 Q-Learning 的结果做对比。find_nn.c通常是最近邻搜索工具和迷宫主流程关系不大可以暂时忽略。使用dijkstra.cpp前需要在 MATLAB 中编译mex dijkstra.cpp编译成功后当前目录会出现.mexw64或.mexa64后缀的二进制文件。如果你的机器没装配置好的 C 编译器mex会报错常见解决办法是安装 MinGW-w64 工具箱或用mex -setup检查当前编译器。主训练脚本不依赖这些 MEX 文件纯 MATLAB 也能跑通所以排错时先把.cpp放一边专注主脚本。4.2 复现路径与绘制收敛曲线训练完成后最好写一个函数把学习到的路径画出来直观确认迷宫逃脱的效果function q_steps plot_q_path(map, Q, start_idx, goal_idx, nrow, ncol) map_show 1 - map; imagesc(map_show); colormap(gray); axis xy; axis equal; hold on; s start_idx; q_steps 0; actions [-1 0; 1 0; 0 -1; 0 1]; while s ~ goal_idx q_steps 300 [r, c] ind2sub([nrow, ncol], s); plot(c, r, ro, MarkerSize, 6, MarkerFaceColor, r); [~, a] max(Q(s, :)); r r actions(a, 1); c c actions(a, 2); s sub2ind([nrow, ncol], r, c); q_steps q_steps 1; end end这段代码把可通行区域显示成白色、墙显示成黑色走过的路径用红点标出。imagesc后加axis xy是为了让纵坐标从下往上增加和矩阵行列的自然顺序一致否则路径会上下翻转。绘制红点时用ro加MarkerFaceColor输出更清楚。再画累计奖励曲线figure; plot(movmean(episode_rewards, 50), LineWidth, 1.5); xlabel(Episode); ylabel(Smoothed Total Reward); grid on;movmean的第二个参数 50 表示取前后 50 个 episode 的均值可以过滤掉单次 episode 的随机波动。如果曲线整体缓慢上升并趋于平稳说明学习过程正常如果出现断崖式下跌大概率是 epsilon 衰减太快导致提前进入利用期。4.3 常见失败模式与排查思路根据我调试这类迷宫代码的经验失败大多是这几类现象根因排查/解决办法智能体永远在起点附近转Q 表没更新成功奖励没有进入状态检查reward(10,10)是否真的为 10打印每一步的r_step到达终点前反复绕圈步成本太弱绕远路和近路价值差不大把步成本从 −0.04 调到 −0.1路径撞到墙后卡住撞墙惩罚过大智能体不敢离开当前状态撞墙惩罚从 −1 降到 −0.1训练时间很长但路径时好时坏ε 没有衰减到较小值一直在随机动作确认epsilon max(epsilon_min, epsilon * decay)在 episode 外层执行运行报错说数组索引超出维度状态索引写成了二维数组Q(s,:)的 s 不是线性索引统一用sub2ind/ind2sub做转换还有一个排查技巧在训练循环里定期输出“当前 episode 是否到达终点”如果 500 轮仍然从未到达过终点优先检查奖励矩阵和终点判定逻辑而不是着急调超参数。MATLAB 的disp开销不大每 50 轮打印一次命中终点的计数能比看累计奖励更快定位问题。5. 用 Dijkstra 基线校准 Q-Learning 策略质量训练结束只说明“智能体能到达终点”但没法直接回答“路径是否接近最优”。这时候上面提到的dijkstra.cpp就该上场了。Dijkstra 在静态图上计算从每个可通行格子到终点的最短步数是标准的最优解用来做评估基线非常合适。mex dijkstra.cpp; D dijkstra(map, goal_idx); % 返回与地图同尺寸的最短距离矩阵 baseline_steps D(1, 1); q_steps plot_q_path(map, Q, start_idx, goal_idx, nrow, ncol); ratio q_steps / baseline_steps; fprintf(Q-Learning 步数: %d, Dijkstra 最优步数: %d, 比值: %.2f\n, ... q_steps, baseline_steps, ratio);ratio是衡量策略质量的核心指标。等于 1 说明学到的就是最优路径在 1 ~ 1.2 之间说明策略可用但仍有绕路超过 1.5 基本可以断定奖励设计或超参数有问题。注意dijkstra的输入输出格式要以包内源码注释为准我这边用的是D dijkstra(map, goal_idx)的约定具体 MEX 返回值可能是矩阵也可能是索引数组先size(D)确认一下。在此基础上还能做更细的验证把终点奖励从 10 改成 20看ratio是否变化或者把步成本从 −0.04 改为 −0.2观察 Q-Learning 是否更接近 Dijkstra。另一个实用技巧是把地图中某个障碍随机移动让智能体重新训练 20 次统计平均ratio和到达率。能稳定维持在 1.2 以内的模型才说明不是碰运气跑通而是真正学到了可泛化的策略。最后把Q、episode_rewards、ratio一并存到results.mat里每次调参后都用同一组评估代码做对比这样后续调优才有依据。本文还有配套的精品资源点击获取
返回列表