智能体在车联网中的应用:第49天 为信号灯智能体设计MARL问题,目标协同降低区域总旅行时间
本文探讨了从单智能体到多智能体强化学习(MARL)在交通信号控制中的范式转变。通过将交通路网建模为部分可观测的马尔可夫博弈(POMG),提出了多智能体协同优化的框架。文章详细定义了智能体集合、状态空间、观察空间、动作空间等关键组件,并重点讨论了奖励函数设计的挑战与方案,包括局部指标奖励、全局共享奖励、差异奖励和基于价值的分解方法。研究表明,MARL能够突破基于规则系统的局限性,通过智能体间的交互学
引言:从单智能体到多智能体强化学习的范式跃迁
在D71-73的实践中,我们成功在SUMO中构建了多智能体信号控制的基础框架,并采用了基于规则的决策逻辑。然而,规则系统存在明显的天花板:其性能严重依赖专家经验,难以适应动态变化的交通流,更无法实现真正意义上的“协同优化”。要突破这一瓶颈,我们必须引入多智能体强化学习(Multi-Agent Reinforcement Learning, MARL),让信号灯智能体通过与环境持续交互、试错学习,自发地发现降低区域总旅行时间或排队长度的协同策略。
第一部分:问题形式化——定义多智能体交通博弈
在MARL框架下,我们的交通路网被建模为一个部分可观测的马尔可夫博弈(Partially Observable Markov Game, POMG)。这是马尔可夫决策过程(MDP)在多智能体场景下的扩展。
1.1 智能体集合与环境
- 智能体集合 (Agents): ( \mathcal{N} = {1, 2, …, N} ),其中 ( N ) 是信号灯的数量(例如,我们路网中的4个交叉口)。每个智能体 ( i ) 控制一个交通信号灯。
- 环境 (Environment): 即SUMO仿真的动态交通流路网,包括车辆生成、移动、排队等所有物理过程。
1.2 关键组件定义
一个标准的POMG由以下元组定义:( \langle \mathcal{N}, \mathcal{S}, \mathcal{O}, \mathcal{A}, \mathcal{P}, \mathcal{R}, \gamma \rangle )。我们需要为交通信号控制问题具体化每一个元素。
1.2.1 状态空间 (State Space, ( \mathcal{S} ))
状态 ( s_t \in \mathcal{S} ) 是环境在时刻 ( t ) 的完整描述。在理想的全知视角下,它可以包含:
- 路网中每一辆车的精确位置、速度、加速度。
- 每一个车道段的车辆排队长度、密度、平均速度。
- 所有信号灯的当前相位和持续时间。
然而,这个全局状态 ( s_t ) 维度极高,且通常对单个智能体是不可见的。
1.2.2 观察空间 (Observation Space, ( \mathcal{O}^i ))
每个智能体 ( i ) 只能获取到全局状态的一部分,即其局部观察 ( o_t^i \in \mathcal{O}^i )。这是“部分可观测性”的体现。对于信号灯智能体 ( i ),其观察通常设计为:
- 自身控制区域的状态:
- 各进口车道排队车辆数(
lane.getLastStepHaltingNumber)。 - 各进口车道车辆等待总时间(
lane.getWaitingTime)。 - 各进口车道车辆密度(
lane.getLastStepVehicleNumber / laneLength)。 - 当前相位索引及已持续时间。
- 各进口车道排队车辆数(
- 有限范围的邻近信息(用以促进协同):
- 上游相邻车道(即将驶入本交叉口的车道)的车辆排队或速度。
- 下游相邻车道(车辆离开本交叉口后进入的车道)的空闲程度(防止“溢出”)。
- 相邻交叉口信号灯的当前相位(可选,需通信)。
技术实现示例:
def get_observation(self):
obs_vec = []
# 1. 自身进口车道信息
for lane_id in self.incoming_lanes:
obs_vec.append(traci.lane.getLastStepHaltingNumber(lane_id))
obs_vec.append(traci.lane.getLastStepMeanSpeed(lane_id) / 13.89) # 归一化
obs_vec.append(traci.lane.getLastStepVehicleNumber(lane_id) / self.lane_max_capacity[lane_id])
# 2. 相位信息
obs_vec.append(self.current_phase)
obs_vec.append((traci.simulation.getTime() - self.last_phase_change) / self.max_green) # 归一化持续时间
# 3. 简单邻近信息:上游路段末尾的排队长度
for upstream_lane in self.upstream_lanes:
obs_vec.append(traci.lane.getLastStepHaltingNumber(upstream_lane))
return np.array(obs_vec, dtype=np.float32)
1.2.3 动作空间 (Action Space, ( \mathcal{A}^i ))
动作 ( a_t^i \in \mathcal{A}^i ) 是智能体 ( i ) 在每个决策时刻可以执行的操作。常见设计有两种:
- 离散动作空间:最常用。动作定义为“切换到下一个预设相位”或“保持当前相位”。对于N相位的信号灯,动作空间可以是 {0, 1, …, N-1} 直接选择相位,但更常见的是 {0: 保持, 1: 切换},相位切换顺序是预设循环。
- 连续/离散化动作空间:动作可以是对当前各相位绿灯时长的调整量(连续),或从一组预定时长方案(如“延长10秒”、“缩短5秒”、“切换”)中选择(离散)。
示例(离散切换动作):
class DiscreteActionSpace:
def __init__(self):
self.actions = {0: "KEEP", 1: "CHANGE"}
def execute(self, agent_id, action):
if action == 1:
current_phase = traci.trafficlight.getPhase(agent_id)
next_phase = (current_phase + 1) % phase_count
traci.trafficlight.setPhase(agent_id, next_phase)
# 注意:在SUMO中直接切换相位可能导致黄灯或全红缺失,需使用setPhaseDuration或完整逻辑程序
1.2.4 状态转移函数 (Transition Function, ( \mathcal{P} ))
( \mathcal{P}(s_{t+1} | s_t, a_t^1, …, a_t^N) ) 描述了在联合动作 ( \mathbf{a}t = (a_t^1, …, a_t^N) ) 下,环境从状态 ( s_t ) 转移到 ( s{t+1} ) 的概率。这个函数由SUMO仿真器的底层物理模型(车辆跟驰、换道、路口冲突解析等)隐式定义,对于我们来说是黑箱,但正是强化学习智能体需要学习和适应的对象。
1.2.5 奖励函数 (Reward Function, ( \mathcal{R}^i ))
奖励 ( r_t^i = \mathcal{R}^i(s_t, \mathbf{a}t, s{t+1}) ) 是驱动智能体学习的信号。设计奖励函数是MARL成功与否的最关键环节。我们的全局目标是降低区域总旅行时间(或总排队长度)。如何将这个全局目标分解到每个智能体的局部奖励 ( r^i ) 上,是核心挑战。
1. 基于局部指标的奖励(独立学习,简单但易导致次优):
- 负的排队长度:( r_t^i = -\sum_{l \in L_i} \text{queue}_length(l) )
- 负的等待时间:( r_t^i = -\sum_{l \in L_i} \text{waiting_time}(l) )
缺点:智能体自私地最小化自身交叉口排队,可能将车辆快速“推给”下游邻居,导致拥堵转移,而非全局消除。
2. 基于全局指标的共享奖励(团队奖励):
- ( r_t^i = r_t^{\text{global}} = -(\text{TotalTravelTime}_t / \text{NumVehicles}) ) 或 ( -\text{TotalQueueLength}_t )
优点:所有智能体为同一目标努力,理论上可导向全局最优。
缺点:信用分配问题 严重。当全局奖励变好或变差时,很难区分每个智能体的贡献,导致学习缓慢、不稳定。
3. 差异奖励(Difference Rewards):一种巧妙的折中,旨在评估单个智能体对全局的边际贡献。
- ( D^i = R(s) - R(s_{-i}) )
- 其中 ( R(s) ) 是全局奖励(如负的总排队长度),( R(s_{-i}) ) 是假设智能体 ( i ) 采取一个默认“空动作”(如保持红灯)时的全局奖励。计算 ( R(s_{-i}) ) 需要做反事实模拟,在实践中通常用智能体 ( i ) 的局部影响来近似。
- 近似示例:( r_t^i = -[\text{QueueAtIntersection}_i + \alpha \cdot \text{QueueDownstreamAffectedBy}_i] ),其中第二项试图捕捉智能体i对下游的影响。
4. 基于价值的奖励分解(如VDN, QMIX):在训练时,学习一个将全局Q值 ( Q_{tot} ) 分解为个体Q值 ( Q^i ) 的函数,使得 ( Q_{tot}(\mathbf{o}, \mathbf{a}) \approx \sum_i Qi(oi, a^i) )。个体的奖励隐式地包含在个体Q值的学习中。这属于CTDE(Centralized Training with Decentralized Execution) 架构,是我们后续实现的重点。
技术实现示例(局部奖励+邻近惩罚):
def compute_local_reward(self):
# 自身交叉口排队负奖励
self_queue = sum([traci.lane.getLastStepHaltingNumber(l) for l in self.incoming_lanes])
reward = -self_queue
# 惩罚:如果我的动作导致上游(我下游的邻居)排队急剧增加
for up_lane in self.upstream_lanes_of_neighbor:
neighbor_queue = traci.lane.getLastStepHaltingNumber(up_lane)
if neighbor_queue > 20: # 阈值
reward -= 2.0 # 附加惩罚
return reward
1.2.6 折扣因子 ( ( \gamma ) )
( \gamma \in [0, 1] ) 用于权衡即时奖励和未来奖励的重要性。在交通控制中,一个动作(如切换绿灯)的效果(车辆开始移动、排队消散)会持续多个时间步,因此通常设置较高的 ( \gamma )(如0.95-0.99),以鼓励智能体考虑其决策的较长期影响。
第二部分:MARL算法架构选择与训练框架设计
定义了问题之后,我们需要选择一个合适的MARL算法架构来训练智能体。
2.1 独立Q学习(IQL)及其局限性
最简单的方法是让每个智能体独立运行一个DQN算法,将自己的经验视为一个非平稳的MDP。每个智能体学习自己的Q函数 ( Qi(oi, a^i) )。
# 伪代码示意
for each agent i:
obs_i = env.get_observation(i)
action_i = epsilon_greedy(Q_network_i, obs_i)
# 执行联合动作,得到下一个观察和奖励
next_obs_i, reward_i, done = env.step([action_1, ..., action_N])
# 独立存储和更新
replay_buffer_i.store(obs_i, action_i, reward_i, next_obs_i, done)
train(Q_network_i, replay_buffer_i)
问题:环境对每个独立学习的智能体而言是非平稳的,因为其他智能体的策略也在不断变化,这违反了传统RL收敛所需的环境平稳性假设,极易导致训练不稳定。
2.2 集中式训练与分布式执行(CTDE)范式
这是目前解决多智能体协同问题的主流范式。其核心思想是:
- 训练时:允许算法利用全局信息(如全局状态 ( s )、所有智能体的动作和观察)来学习更好的策略,并解决信用分配问题。
- 执行时:每个智能体仅依据自己的局部观察 ( o^i ) 做出决策,实现分布式部署。
我们将基于此范式,采用 QMIX 算法或其变种作为我们的核心算法。QMIX的优势在于:
- 它通过学习一个混合网络来保证个体Q值与全局Q值的单调关系:( \frac{\partial Q_{tot}}{\partial Q^i} \geq 0 )。这意味著提升任何一个体的Q值都能保证提升全局Q值,从而将全局优化目标与个体策略更新联系起来。
- 它能够处理智能体异构的动作观察空间。
- 它在StarCraft等复杂环境中取得了巨大成功,其思想适用于交通协同控制。
2.3 基于PyMARL/EPyMARL的SUMO集成训练框架设计
我们需要构建一个连接SUMO仿真环境和MARL算法库(如PyMARL)的训练框架。
框架组件:
-
多智能体交通环境封装类 (MultiAgentSumoEnv):
- 继承自
gym.Env或类似接口。 reset(): 重置SUMO仿真,获取所有智能体的初始观察。step(actions): 接受一个所有智能体动作的字典,在SUMO中执行多步(如10秒,对应一个决策周期),然后收集所有智能体的下一个观察、奖励、完成标志。- 提供
get_global_state()方法(可选),为CTDE算法提供额外的全局信息(如路网关键链路的车流密度矩阵)。
- 继承自
-
QMIX智能体模型:
- 个体RNN (DRQN): 每个智能体一个,输入自己的观察和动作历史,输出Q值 ( Qi(oi_t, h^i_{t-1}, a^i) )。
- 混合网络 (Mixing Network): 输入所有个体Q值,以及全局状态 ( s_t )(如路网负载矩阵),输出全局动作值 ( Q_{tot} )。
-
训练循环:
# 伪代码,基于简化逻辑
env = MultiAgentSumoEnv(config)
qmix_agents = QMIXAgentNetwork(num_agents, obs_spaces, act_spaces)
replay_buffer = MultiAgentReplayBuffer()
for episode in range(total_episodes):
obs_dict = env.reset()
episodic_reward = 0
while not done:
# 分布式执行:每个智能体根据局部观察选择动作
actions = {}
for agent_id in env.agents:
action = qmix_agents.sample_action(obs_dict[agent_id], agent_id)
actions[agent_id] = action
# 环境步进
next_obs_dict, reward_dict, done_dict, global_info = env.step(actions)
global_reward = calculate_global_reward(global_info) # 如总排队长度负值
# 为CTDE存储经验。注意:存储全局奖励和全局状态。
replay_buffer.push(obs_dict, actions, global_reward, next_obs_dict, done_dict, global_state)
obs_dict = next_obs_dict
episodic_reward += global_reward
# 定期从缓冲区采样,进行集中式训练
if replay_buffer.size() > batch_size:
batch = replay_buffer.sample(batch_size)
# QMIX损失计算:基于全局Q值和时间差分误差
loss = qmix_agents.compute_loss(batch)
optimizer.zero_grad()
loss.backward()
optimizer.step()
关键点:经验回放缓冲区中存储的是 (全局状态, 联合观察, 联合动作, 全局奖励, 下一全局状态) 的元组。训练时,混合网络利用全局状态信息来学习如何正确地组合个体Q值,以逼近真实的全局Q值。
第三部分:挑战、评估与前瞻
3.1 核心挑战与应对策略
- 非平稳性:通过CTDE架构和基于全局状态的训练来缓解。
- 信用分配:通过QMIX等值分解方法显式解决。
- 部分可观测性:为个体智能体引入RNN(如GRU/LSTM)来记忆历史观察序列,学习隐含状态。
- 探索-利用困境:在高维连续动作空间中尤为突出。可使用参数化噪音(如NoisyNet)、内在好奇心激励或课程学习来改善探索。
- 仿真与现实的差距:在SUMO中训练的模型需考虑泛化能力。应使用多样化的交通流场景(平日/周末、高峰/平峰、偶发事故)进行训练和验证。
3.2 性能评估
除了监控训练过程中的全局平均旅行时间和总排队长度的下降趋势,还应评估:
- 学习稳定性:奖励曲线是否平滑收敛。
- 协同有效性:对比独立学习(IQL)、固定时长方案、感应控制等方法。
- 策略可解释性:可视化学习到的策略,例如在特定交通模式下,智能体之间是否形成了“绿波带”等协同模式。
3.3 未来拓展方向
- 分层MARL:将路网划分为区域,高层智能体协调区域间的流量分配,低层智能体负责区域内信号控制。
- 图神经网络(GNN)集成:用GNN对路网拓扑结构进行编码,作为智能体观察或全局状态的增强,使模型能更好地理解空间关联。
- 离线强化学习与迁移学习:利用历史交通数据或不同路网的预训练模型进行微调,加速在新场景下的部署。
更多推荐


所有评论(0)