简介面向交通仿真与强化学习研究者提供一套基于开源微观交通仿真平台、利用深度强化学习网络改进路口信号灯相位时长的完整工程包。内容覆盖从仿真路网搭建、车流定义到状态特征提取、相位动作设计、奖励设置与策略训练的全流程核心脚本包含多个用于训练与辅助的Python脚本文件可通过经验回放和迭代更新逼近最优控制策略适合智能交通课程设计、算法验证与实际路口信号优化研究。压缩包共32个文件以路网配置、地图数据、算法脚本、表格数据及说明文档为主其中XML文件用于定义路网与仿真参数OSM文件提供真实地图底图Python脚本实现Q学习及优先级优化Excel表格记录车道与配时信息整体大小仅532KB结构清晰便于快速加载和二次开发。已有497人学习下载对理解交通仿真与强化学习结合的接口设计、建模方法及性能评估具有直接参考价值。1. 利用SUMO和DQN优化交通信号灯一个值得下手的强化学习仿真项目交通信号灯配时优化是个典型的时序决策问题传统固定配时方案在高峰期经常出现单方向排队溢出、绿灯空放。用强化学习中的DQN做自适应信号控制核心思路是把路口状态当成观测值让智能体通过学习选择最优的相位持续时间。这个基于SUMO的仿真项目正好把整条技术链路打通了SUMO负责搭建路网和车辆流DQN算法负责决策相位时间两边通过TraCI接口实时交互。对于想入门强化学习落地、又不想纠结真实路测成本的从业者这个资源相当于给了你一套可复现的实验平台既能看算法效果又能对比训练曲线和通行效率指标。2. 为什么是SUMO和DQN选型逻辑与适用边界2.1 SUMO的仿真能力与TraCI接口价值SUMOSimulation of Urban MObility是个开源微观交通仿真平台能在没有真实道路数据的情况生成路网、车流和信号控制逻辑。选它做强化学习环境核心原因是TraCITraffic Control Interface提供了实时读取和操控仿真状态的通道。你可以在训练循环里获取每个路口的车辆数、等待时间、排队长度也可以动态修改信号灯相位。这种双向控制能力让外部Python代码能像操作真实基础设施一样驱动仿真。推荐流量下SUMO的单步仿真速度很快但这并不能说明它适合所有场景。SUMO的路网建模需要手动配置交叉口、车道、连接关系和信号灯组前期环境搭建工作量比使用虚拟仿真环境大得多这也是项目中值得认真拆解的部分。不过好处是建模粒度可控从单路口到多路口网络从固定车流到随机到达都能在SUMO里精确描述。2.2 DQN在信号控制问题中的适配性DQNDeep Q-Network擅长处理高维状态空间和离散动作空间的问题。交通信号控制正好满足这两个条件状态来自路口的连续数值排队长度、车辆数、当前相位动作则是可选相位方案或相位持续时间调整。传统Q表格在这个规模下会因状态组合爆炸而失效深度网络正好替代Q表格做值函数逼近。项目用DQN而不选策略梯度方法主要理由在于信号控制问题天然是离散决策要么延长当前相位要么切换下一个相位不存在连续动作的需求。虽然DDPG、PPO这类算法也能处理离散动作但DQN网络结构简单训练稳定调参成本低对刚接入SUMO的团队来说是最快能跑通整个闭环的算法。项目里使用经验回放和目标网络两个组件是为了打破样本相关性并稳定目标值计算这两个在后续代码解析里会看到具体落点。3. 环境搭建与项目文件结构从零跑通训练闭环3.1 安装配置三件套SUMO、Python环境和依赖库跑通这个项目的第一步是装好SUMO本体。常见做法是下载Windows安装包或Linux源码编译装完确认环境变量里能调用sumo-gui和sumo命令。Python版本建议3.8或3.9配合traci库做通信。依赖库主要集中在PyTorchDQN网络用、NumPy数据处理和Matplotlib画训练曲线这几个。bash创建虚拟环境并激活python -m venv sumo-rl-env source sumo-rl-env/bin/activate # Windows下为 sumo-rl-env\Scripts\activate安装依赖pip install traci numpy matplotlib torch验证SUMO安装sumo --version python -c import traci; print(traci.version)这里sumo --version用于确认命令行工具可用import traci验证Python能连接SUMO。如果traci版本与SUMO主程序版本不一致极容易在仿真中途报连接断开下面会专门说这个坑。3.2 项目文件的模块拆解项目压缩包内部大致包含三类内容路网文件、训练脚本、工具脚本。路网文件通常是.net.xml和.rou.xml后缀分别描述交叉口几何形态和车辆出行需求训练脚本是核心逻辑从环境封装到DQN智能体都在里面工具脚本负责画图、统计结果、生成对比报告。文件类型典型后缀作用关键参数路网描述文件.net.xml定义车道、节点、连接交叉口类型、车道数、限速车辆流文件.rou.xml定义车辆出发时间、路径流量密度、车辆类型比例仿真配置.sumocfg整合路网与车流仿真时长、步长、输出文件训练主脚本.pyDQN训练与评估循环学习率、batch size、epsilon训练脚本内部包含四个模块SUMO环境封装类负责启动仿真并返回状态DQN网络结构定义采用三层全连接网络经验回放缓冲区存储最近N条转移样本训练循环则控制探索率衰减和目标网络同步频率。初次看代码时建议按这个顺序读因为后面的网络更新逻辑依赖前面的接口定义。3.3 启动训练命令行参数与首次运行观察bashpython train_dqn.py--config config/single_intersection.sumocfg--episodes 500--max-steps 3600--learning-rate 0.001--batch-size 64--epsilon-start 1.0--epsilon-end 0.05--epsilon-decay 0.995--save-dir ./models这段命令的含义--config指向SUMO仿真的总配置文件--episodes 500表示训练500个回合每个回合对应一次完整的仿真运行--max-steps 3600限制单回合最大仿真步数防止个别回合因车辆堵死导致超时探索率从1.0线性衰减到0.05让智能体前期充分探索相位策略后期逐渐倾向利用已学策略。如果训练过程打开SUMO-GUI动态观察车辆运行状态建议将仿真步长调慢否则图像刷新跟不上训练速度。首次跑通训练后观察两个关键指标Loss曲线是否震荡下降平均回报是否逐步上升。如果训练过程显示Loss极低但路口的平均等待时间没有改善优先怀疑奖励函数设计出了问题而不是网络参数问题。这个判定逻辑在后面避坑章节会展开。4. DQN核心实现拆解网络结构、奖励设计与训练参数4.1 DQN网络结构与状态定义项目里的网络结构没什么花哨设计就是一个输入层、两个隐藏层、一个输出层的全连接网络。输入维度取决于状态特征数量这里的状态向量由当前相位索引、当前相位已持续时长、各车道排队车辆数、等待时间共四个部分组成经过标准化后送入网络。输出维度等于可选相位持续动作的数量动作空间上采用离散方式。pythonimport torch import torch.nn as nnclass DQN(nn.Module): definit(self, state_dim, action_dim, hidden_dim128): super(DQN, self).init() self.fc1 nn.Linear(state_dim, hidden_dim) self.fc2 nn.Linear(hidden_dim, hidden_dim) self.fc3 nn.Linear(hidden_dim, action_dim)def forward(self, x): x torch.relu(self.fc1(x)) x torch.relu(self.fc2(x)) return self.fc3(x)这里把两层隐藏层设为128维属于经验值。状态维度过小时网络容量过剩容易过拟合到早期训练数据发现训练后期回报上不去时可以先把隐藏层降到64维试试。动作维度与相位方案一一对应比如方案0表示维持当前相位不变方案1表示切换相位具体数量要和路网信号灯组配置匹配。4.2 奖励函数设计等待时间与排队长度的权衡奖励函数是这个项目里最值得研究的部分直接决定智能体学出来的是“真会”还是“假会”。如果只按路口总等待时间给负奖励智能体会倾向于让某一方向的车一直等因为整体等待时间可能并不会明显增加。实际项目采用的是加权组合奖励把等待时间变化量和排队长度同时纳入pythondef compute_reward(previous_wait, current_wait, queue_length): wait_delta current_wait - previous_wait reward -abs(wait_delta) - 0.5 * queue_length return rewardprevious_wait和current_wait分别表示上一仿真步和当前仿真步的路口总等待时间wait_delta取绝对值后惩罚等待时间剧烈波动目的是避免相位频繁切换带来的大量加减速损失queue_length乘以0.5的权重让智能体顾及到排队的公平性。参数权重需要根据路口规模调整单路口项目里0.5足够多路口网络建议把排队项权重下调到0.3左右防止个别路口被过度邯郸。等待时间统计在SUMO里通过traci.vehicle.getAccumulatedWaitingTime()获取这个API返回的是车辆累计等待时间的均值适合做单路口实验。多路口场景建议改用traci.lane.getWaitingTime()做分车道统计粒度更细也能更容易定位到异常相位。4.3 训练参数的经验取值与调试方向训练收敛速度和稳定性受多个参数影响。学习率设0.001是PyTorch默认配置下的稳妥选择太高容易让Loss震荡太低则收敛慢。批大小64、目标网络更新频率通常设为每200步同步一次这些参数在项目的默认配置里已经做了平衡。参数名称默认值调试方向失败表现learning-rate0.001调低范围Loss不降、回报不稳定batch-size64调高范围内存占用偏大、单步耗时增加gamma0.99调低范围短期决策过于激进频繁切换相位target-update-freq200调低目标值不稳定训练震荡gamma参数尤其值得注意它在DQN里决定智能体对远期回报的重视程度。调太低会让智能体只关注眼前几秒的等待时间变化训练结果就是信号灯疯狂切换、车辆不停启停调太高又会忽略近期拥堵。单路口场景设置在0.99附近比较合理如果是多路口联动场景建议下调到0.95因为交通流在路网上的传播延时远大于单路口。5. 避坑与常见问题跑SUMODQN最容易翻车的五个点5.1 仿真连接中断报“TraCI connection closed”或仿真卡住不动现象一训练跑了几百步后突然报连接关闭错误或者仿真窗口无响应。原因一SUMO版本与traci库版本不匹配常见于用pip安装的traci是最新版本而SUMO本体停在旧版。另外当仿真步长设得过小时网络通信频率太高Python主进程处理不过来也会触发连接断开。解决一先用pip show traci查库版本再去SUMO的安装目录下sumo --version查主程序版本。若不一致用pip install traci对应版本号锁定版本更稳妥。跑长训练时把仿真步长从0.1s改到0.5s或1s降低通信频率训练速度也会提上来。5.2 Loss掉得快但通行效率没改善奖励设计缺陷现象二训练Loss一路走低但路口的平均等待时间不降反升甚至出现某方向车辆白白等了一整个训练回合。原因二奖励函数只惩罚了等待时间而没有惩罚排队长度或者权重失衡。DQN优化的是奖励信号不是路口通行本身一个设计不当的奖励信号会让智能体学习到“钻空子”的行为。解决二把排队长度纳入负奖励并检查reward计算里用的是绝对值变化量还是差值本身。差值符号混乱会让智能体无法分辨动作好坏解决方法是统一奖励朝向通行效率越好奖励越大。5.3 训练后期探索不足陷入局部最优现象三训练到300回合以后回报曲线不再上升固定在一个较差水平震荡。原因三epsilon衰减过快智能体过早进入利用阶段没有机会再尝试更优的相位组合策略。这与epsilon-decay参数直接相关。解决三把epsilon衰减速度调慢或者改成阶段性重置探索率。常见做法是每隔100回合把epsilon回调到0.3再继续衰减相当于让智能体在学到的策略基础上重新审视一下有没有更好的可选动作。项目里如果不方便改这段逻辑也可以手动降低--epsilon-decay的数值让探索周期拉长。5.4 单回合训练时间异常长仿真步长和车流量设置不合理现象四一个回合训练跑了5分钟还没结束对比其他回合明显偏慢。原因四--max-steps设置过大或者车辆流文件里的车辆数太多导致单回合需要仿真很久。另一种情况是路网里存在死锁车辆全部堵在一个路口仿真卡住在循环里。解决四检查车辆流文件的begin和end标签确认总车辆数按经验把单回合仿真时长控制在60~90秒之间死锁问题要回netedit检查交叉口连接关系特别是T型路口和右转专用道的车道连接这一项纸面调试无法解决必须在GUI里可视化看。5.5 目标网络不更新导致训练崩溃忘记同步权重现象五训练Loss波动幅度越拉越大最后直接变成inf。原因五目标网络用于计算TD目标值其权重是定期从评估网络复制过来的。如果训练代码里漏掉了同步操作目标值会一直使用初始随机权重训练目标本身就是漂移的网络没法收敛这是强化学习里的经典问题。解决五检查训练循环里是否调用了target_net.load_state_dict(policy_net.state_dict())并确认调用时机是按步数而不是按回合。按回合同步会让目标Q值更新过于缓慢在SUMO这类环境变化较大的仿真里容易造成偏差累积。6. 进阶调优从单路口扩展到多路口与真实路网验证单路口跑通之后真正有价值的是把模型迁移到多路口场景。这里会遇到两个新问题状态维度和动作维度都变大以及路网耦合带来的信用分配难题。项目里单路口模型泛化到多路口时推荐直接改用参数共享的DQN变体所有路口共用一套网络权重但每个路口的观测独立编码。这样既避免了状态维度过高的计算开销又能让所有路口的学习经验互相补充。评估阶段建议做一次呼应性对比实验固定配时方案、固定相位切换方案、训练完成的DQN方案三种方案在同一组车流数据下对比平均等待时间、平均车速和排队长度三项指标。为了避免偶然性每种方案至少跑10个回合取平均值。绘制等待时间分布曲线时注意只看稳态区间的数据跳过仿真刚开始车辆逐渐进入路网的头几百步否则容易把启动阶段的空载数据混进来拉低平均值。多路口模型的难点在于一个路口的相位决策会通过上游来车直接影响到下游路口的状态分布此时单路口训练经验里学到的“当前路口状态足以决定最优动作”这个假设不再成立。如果迁移后出现上游绿灯放行、下游反而严重拥堵的现象可以在状态向量里额外增加上一路口的信号灯状态和排队信息也就是把状态从独立观测改成受邻接路口影响的联合观测。这是很多仿真项目实战中最后能真正提高路网吞吐量的关键一步。最后提醒一句有价值的经验调SUMODQN项目时每次训练前强制走一遍“清缓存、查版本、跑短回合验证环境连接”三连操作能省掉很多四分之一的调试时间。血泪教训是有次改了路网文件忘记重新生成net文件结果训练了三百回合才发现车流全部跑在旧路网上相当于白学了三个小时。从那以后每次环境变更都强制走一遍版本核对和短回合冒烟测试。希望帮到你。本文还有配套的精品资源点击获取