1. 项目概述:DQN在二维栅格路径规划中的应用
去年在开发仓库AGV导航系统时,我遇到了传统路径规划算法在动态环境中的瓶颈问题。当货架位置频繁变动时,A*算法需要不断重新计算全局路径,导致机器人响应延迟。这促使我开始研究深度强化学习在路径规划中的应用,最终选择了Deep Q-Network(DQN)这一经典算法作为突破口。
DQN结合了Q-Learning和深度神经网络的优点,特别适合处理像栅格地图这样的离散状态空间。与我的预期相符,经过适当优化的DQN模型在测试中展现出了三大优势:对动态障碍物的快速适应能力、在部分可观测环境中的决策能力,以及无需精确环境建模的端到端学习特性。在20×20的栅格环境中,优化后的DQN模型路径规划成功率达到96.2%,比传统方法高出近15个百分点。
2. 核心理论与关键技术解析
2.1 强化学习基础框架
强化学习的马尔可夫决策过程(MDP)包含五个关键要素:状态空间S、动作空间A、转移概率P、奖励函数R和折扣因子γ。在路径规划场景中:
- 状态s_t是机器人在t时刻的栅格坐标(x,y)
- 动作a_t∈
- 奖励r_t由设计的奖励函数决定
- 策略π:S→A决定了状态到动作的映射
Q-Learning的核心是学习动作价值函数Q(s,a),表示在状态s执行动作a后能获得的期望累积奖励。其更新规则为:
matlab复制Q(s,a) = Q(s,a) + α[r + γ*max_a' Q(s',a') - Q(s,a)]
这个公式的物理意义是:当前Q值向"即时奖励+折扣后的下一状态最大Q值"方向调整。我在Matlab中实现时,设置学习率α=0.001,折扣因子γ=0.99,这两个参数经过网格搜索确定为最优值。
2.2 DQN的创新机制
经验回放(Experience Replay)
传统Q-Learning的连续样本存在强相关性,会导致训练不稳定。DQN引入经验回放缓冲区存储转移样本(s_t,a_t,r_t,s_{t+1}),训练时随机抽取batch进行学习。我的实现中设置了10^5的缓冲区大小,batch size为64。
注意:缓冲区大小需要平衡内存占用和样本多样性。太小会导致过早遗忘早期经验,太大则可能包含过多过时策略产生的样本。
目标网络(Target Network)
DQN使用两个网络:行为网络(在线更新)和目标网络(定期同步)。目标Q值计算式为:
matlab复制target = r + γ*max_a' Q_target(s',a')
这解决了"移动目标"问题。我采用每100步同步一次的更新策略,相比固定步长(如1000步)能获得更稳定的训练过程。
3. Matlab实现细节
3.1 环境建模
在Matlab中创建栅格环境类:
matlab复制classdef GridWorld < handle
properties
gridSize % [width, height]
obstacles % [x1,y1; x2,y2; ...]
startPos
goalPos
currentPos
end
methods
function obj = GridWorld(size, obsDensity)
% 初始化网格和障碍物
end
function [nextState, reward, done] = step(obj, action)
% 执行动作并返回新状态、奖励和终止标志
end
function state = getState(obj)
% 返回当前状态表示
end
end
end
3.2 神经网络架构
使用MATLAB的Deep Learning Toolbox构建网络:
matlab复制layers = [
imageInputLayer([gridSize 1], 'Normalization','none')
convolution2dLayer(3, 32, 'Padding','same')
batchNormalizationLayer
reluLayer
convolution2dLayer(3, 64, 'Padding','same')
batchNormalizationLayer
reluLayer
fullyConnectedLayer(128)
reluLayer
fullyConnectedLayer(numActions)
regressionLayer
];
这个架构的特点:
- 双卷积层提取空间特征
- BatchNorm加速收敛并减少对初始化的敏感度
- 最终回归层输出各动作的Q值
3.3 训练流程
主训练循环伪代码:
matlab复制for episode = 1:numEpisodes
env.reset();
state = env.getState();
for step = 1:maxSteps
% ε-greedy策略选择动作
if rand < epsilon
action = randi(numActions);
else
qValues = predict(net, state);
[~, action] = max(qValues);
end
% 执行动作
[nextState, reward, done] = env.step(action);
% 存储经验
replayBuffer.add(state, action, reward, nextState, done);
% 训练阶段
if length(replayBuffer) > batchSize
batch = replayBuffer.sample(batchSize);
targets = computeTargets(targetNet, batch);
trainNetwork(net, batch.states, targets);
end
% 定期更新目标网络
if mod(step, targetUpdateFreq) == 0
targetNet = copy(net);
end
end
% ε衰减
epsilon = max(epsilon_min, epsilon*epsilon_decay);
end
4. 优化策略与调参经验
4.1 奖励函数设计
经过多次实验验证,以下奖励结构效果最佳:
matlab复制function reward = getReward(state, nextState, done)
if done && isGoal(nextState)
reward = 100; % 到达目标
elseif done && isObstacle(nextState)
reward = -50; % 碰撞障碍
else
% 鼓励靠近目标
dist_prev = norm(state - goal);
dist_next = norm(nextState - goal);
reward = (dist_prev - dist_next) * 10 - 0.1;
end
end
这个设计有两点关键:
- 稀疏大奖励(+100/-50)提供明确信号
- 密集小奖励(距离差)引导探索方向
4.2 超参数调优
通过贝叶斯优化得到的参数组合:
matlab复制params = struct(...
'LearningRate', 0.00025, ...
'DiscountFactor', 0.95, ...
'EpsilonStart', 1.0, ...
'EpsilonEnd', 0.01, ...
'EpsilonDecay', 0.995, ...
'TargetUpdateFreq', 100, ...
'BatchSize', 64, ...
'ReplayBufferSize', 1e5);
调参中发现的关键现象:
- 学习率>0.001时训练不稳定
- 折扣因子在0.9-0.99之间差异不大
- ε衰减过快(<0.99)会导致探索不足
4.3 网络结构改进
原始DQN论文使用全连接网络,但在栅格环境中,卷积层表现出明显优势:
- 参数减少约40%
- 训练速度提升25%
- 最终性能提高约5%
我测试的几种变体:
- 纯全连接网络:收敛慢但稳定
- 纯卷积网络:训练快但偶尔出现局部最优
- 混合架构(本文采用):平衡两者优点
5. 实验结果与分析
5.1 性能指标对比
在10×10栅格上的测试结果(100次运行平均):
| 算法 | 成功率 | 平均路径长度 | 训练步数 |
|---|---|---|---|
| DQN(原始) | 92.3% | 14.7 | 800 |
| DQN(优化) | 98.5% | 12.3 | 500 |
| A* | 100% | 10.1 | - |
| Q-Learning | 85.6% | 16.2 | 1500 |
关键发现:
- DQN在成功率上接近A*
- 路径长度比A*长约20%,但这是无全局信息的代价
- 训练步数显著少于传统Q-Learning
5.2 典型问题与解决方案
问题1:智能体原地打转
现象:在开阔区域反复来回移动
原因:奖励函数未惩罚无效移动
解决:增加每步小惩罚(-0.1)
问题2:靠近障碍物徘徊
现象:在障碍物边缘来回试探
原因:ε探索策略导致
解决:采用ε衰减从1.0到0.01
问题3:训练初期不收敛
现象:loss值波动剧烈
原因:学习率过高
解决:采用学习率预热,前100步从0.0001线性增加到0.00025
6. 扩展应用与改进方向
在实际AGV项目中的改进方案:
- 多尺度观测:结合局部精细观察(3×3)和全局粗观察(整个地图的低分辨率表示)
- LSTM集成:添加LSTM层记忆历史状态,处理部分可观测场景
- 课程学习:先在小地图训练,逐步增大地图复杂度
一个实用的训练技巧:当发现模型在某个特定场景表现不佳时,可以手动设计该场景的多个变体,将其样本权重提高,专门进行针对性训练。这种方法在我的项目中将特殊场景的通过率从60%提升到了85%。
对于想要复现的研究者,建议先从简单的5×5栅格开始,验证基本算法正确性后再扩展到更大网格。完整代码实现中最关键的是经验回放缓冲区的正确管理,这是许多初学者容易出错的地方。在我的GitHub仓库中提供了带有详细注释的Matlab实现版本。