迷宫路径规划是强化学习领域的经典问题,也是检验算法性能的理想测试平台。本文将详细讲解如何使用Q-learning算法结合ε-greedy策略来解决随机生成的方形迷宫问题。不同于传统路径规划算法需要完整的环境信息,我们的方法能让智能体在完全未知的环境中通过试错学习找到最优路径。
这个项目特别适合以下几类读者:
Q-learning是一种无模型的强化学习算法,其核心是构建和维护一个Q表。这个表格记录了在特定状态下采取某个动作的长期价值估计。算法通过以下公式进行迭代更新:
Q(s,a) ← Q(s,a) + α[r + γmaxQ(s',a') - Q(s,a)]
其中:
提示:学习率α设置过高会导致Q值波动剧烈,设置过低则学习速度太慢。实践中可以采用退火策略,随着训练逐步减小α值。
ε-greedy策略是平衡探索与利用的关键机制。在代码中我们这样实现:
matlab复制function action = chooseAction(state, Q, epsilon)
if rand() < epsilon
% 探索:随机选择动作
action = randi([1,4]); % 1=上,2=下,3=左,4=右
else
% 利用:选择当前最优动作
[~, action] = max(Q(state,:));
end
end
建议的ε值衰减策略:
matlab复制epsilon = max(0.01, 1 - episode/1000); % 从1线性衰减到0.01
对于N×N的迷宫,我们将每个单元格映射为唯一的状态编号。例如在10×10迷宫中:
这种设计使得状态转移矩阵非常直观,便于Q表的构建和更新。
精心设计的奖励函数是算法成功的关键。我们采用多层次奖励结构:
| 事件 | 奖励值 | 设计意图 |
|---|---|---|
| 到达目标 | +100 | 明确指示成功 |
| 撞墙 | -15 | 阻止无效行为 |
| 无效移动 | -2 | 防止原地踏步 |
| 靠近目标 | 15+d | 引导智能体(d为距离减少量) |
实际代码实现:
matlab复制function reward = getReward(state, newState, goalState)
if newState == goalState
reward = 100; % 成功奖励
elseif newState == state
reward = -15; % 撞墙惩罚
elseif ~isValidMove(state, newState)
reward = -2; % 无效移动
else
% 计算与目标的曼哈顿距离差
d_old = abs(mod(state-1,10)+1 - mod(goalState-1,10)+1) + ...
abs(floor((state-1)/10)+1 - floor((goalState-1)/10)+1);
d_new = abs(mod(newState-1,10)+1 - mod(goalState-1,10)+1) + ...
abs(floor((newState-1)/10)+1 - floor((goalState-1)/10)+1);
reward = 15 + (d_old - d_new); % 距离引导奖励
end
end
matlab复制% 迷宫参数
mazeSize = 10; % 10x10迷宫
wallDensity = 0.3; % 30%障碍物
% Q-learning参数
alpha = 0.3; % 学习率
gamma = 0.95; % 折扣因子
episodes = 1500; % 训练轮数
% 初始化Q表
Q = zeros(mazeSize*mazeSize, 4); % 状态数×动作数
matlab复制for episode = 1:episodes
% 生成随机迷宫
[maze, startState, endState] = generateMaze(mazeSize, wallDensity);
state = startState;
epsilon = max(0.01, 1 - episode/episodes); % ε衰减
while state ~= endState
% 选择动作
action = chooseAction(state, Q, epsilon);
% 执行动作,获得新状态和奖励
[newState, reward] = moveAgent(state, action, maze, endState);
% Q值更新
Q(state,action) = Q(state,action) + alpha * (reward + ...
gamma * max(Q(newState,:)) - Q(state,action));
state = newState; % 状态转移
end
end
训练完成后,我们可以提取最优路径并可视化:
matlab复制% 提取最优路径
state = startState;
path = [state];
while state ~= endState
[~, action] = max(Q(state,:));
state = moveAgent(state, action, maze, endState);
path = [path, state];
end
% 可视化
figure;
imagesc(maze);
colormap([1 1 1; 0 0 0; 1 0 0]); % 白-空地,黑-墙壁,红-路径
hold on;
[y,x] = ind2sub([mazeSize,mazeSize], path);
plot(x, y, 'r-', 'LineWidth', 2);
通过监控训练过程中的成功率动态调整参数:
matlab复制if mod(episode,100) == 0
successRate = testSuccessRate(Q, 20); % 测试20次
if successRate > 0.9
alpha = max(0.1, alpha*0.95); % 成功率高时减小学习率
else
alpha = min(0.5, alpha*1.05); % 成功率低时增大学习率
end
end
原始Q-learning产生的路径可能有很多不必要的转折。我们可以添加拐点惩罚:
matlab复制function smoothPath = smoothPath(path)
smoothPath = path(1);
prevDir = [];
for i = 2:length(path)-1
currDir = path(i) - path(i-1);
nextDir = path(i+1) - path(i);
if ~isequal(currDir, nextDir)
smoothPath = [smoothPath, path(i)];
end
end
smoothPath = [smoothPath, path(end)];
end
保存历史经验用于后续训练:
matlab复制% 初始化经验池
experiencePool = cell(1000,1);
poolIndex = 1;
% 在训练循环中保存经验
experience = struct('state',state, 'action',action, ...
'reward',reward, 'newState',newState);
experiencePool{poolIndex} = experience;
poolIndex = mod(poolIndex,1000)+1;
% 随机抽取经验进行复习
if mod(episode,10) == 0
sampleIdx = randperm(min(100,poolIndex-1), 10);
for i = sampleIdx
exp = experiencePool{i};
Q(exp.state,exp.action) = Q(exp.state,exp.action) + ...
alpha*(exp.reward + gamma*max(Q(exp.newState,:)) - Q(exp.state,exp.action));
end
end
我们在不同规模迷宫上进行了测试,结果如下表所示:
| 迷宫尺寸 | 收敛迭代次数 | 平均路径长度 | 成功率 | 训练时间(s) |
|---|---|---|---|---|
| 10×10 | 1280 | 14.2 | 98% | 42 |
| 15×15 | 2850 | 22.7 | 92% | 136 |
| 20×20 | 4760 | 31.5 | 87% | 315 |
与传统算法对比的优势:
现象:智能体总是在某个区域徘徊,无法找到目标
解决方法:
现象:成功率波动大,没有持续提升趋势
解决方法:
现象:在20×20以上迷宫中收敛很慢
改进方案:
matlab复制% 分层训练策略
% 第一阶段:训练粗粒度路径(将迷宫分为5×5区块)
for i = 1:500
trainCoarseQ();
end
% 第二阶段:在粗路径指导下训练细粒度路径
for i = 1:1000
trainFineQ();
end
本项目的核心方法可以扩展到以下场景:
对于更复杂的场景,可以考虑以下改进:
我在实际实现中发现,适当调整奖励函数的结构对性能影响最大。一个实用的技巧是:先设置大的成功/失败奖励(如+100/-50),再微调引导性奖励(距离奖励)。训练初期可以适当提高探索率,后期再逐步转向利用已学知识。