LMDrive 双损失函数训练模块与 LangAuto 基准评测框架
1. 双损失函数训练模块
1.1 损失函数设计
核心思想:同时优化轨迹点回归和终点分类两个任务,通过加权联合损失实现多任务学习。
损失函数定义(drive.py:166-167, 506-514):
| 损失类型 | 任务目标 | 损失函数 | 权重 |
|---|---|---|---|
| Waypoints Loss | 回归5个未来轨迹点坐标 | L1Loss | 1.0 |
| End Loss | 二分类判断轨迹终点 | CrossEntropyLoss | 0.2 |
联合损失公式:
loss = waypoints_loss + end_loss * 0.2代码实现:
self.waypoints_loss=torch.nn.L1Loss()# L1损失:对异常值更鲁棒self.end_loss=torch.nn.CrossEntropyLoss()# 交叉熵:分类任务标准损失waypoints_loss=self.waypoints_loss(predicted_waypoints,gt_waypoints)end_loss=self.end_loss(predicted_end_prob,gt_end_flags)loss=waypoints_loss+end_loss*0.2权重设计原因:
- Waypoints 回归是核心任务,权重设为 1.0
- End 分类是辅助任务,权重设为 0.2 防止过度拟合
- 终点判断对安全至关重要但样本可能不平衡
1.2 优化器配置
算法原理:使用 AdamW 优化器,支持梯度裁剪和权重衰减。
配置参数(runner_base.py:105-123):
self._optimizer=torch.optim.AdamW(optim_params,lr=float(self.config.run_cfg.init_lr),# 初始学习率betas=(0.9,beta2),# 动量系数weight_decay=weight_decay,# 权重衰减)关键参数:
| 参数 | 典型值 | 说明 |
|---|---|---|
| lr | 1e-4 | 初始学习率 |
| betas | (0.9, 0.999) | Adam 动量系数 |
| weight_decay | 0.05 | 权重衰减(正则化) |
| lr_layer_decay | 1 | 层学习率衰减因子 |
1.3 学习率调度器
算法原理:采用线性预热 + 余弦退火策略,初期缓慢提升学习率,后期平滑下降。
代码实现(optims.py:56-94):
classLinearWarmupCosineLRScheduler:defstep(self,cur_epoch,cur_step):ifcur_epoch==0:# 线性预热阶段warmup_lr_schedule(step=cur_step,max_step=self.warmup_steps,init_lr=self.warmup_start_lr,max_lr=self.init_lr,)else:# 余弦退火阶段cosine_lr_schedule(epoch=cur_epoch,max_epoch=self.max_epoch,init_lr=self.init_lr,min_lr=self.min_lr,)学习率曲线:
学习率 ^ | /\ | / \ | / \ | / \ | / \ |/__________\ +-------------> 迭代次数 预热期 余弦退火期余弦退火公式:
lr = min_lr + 0.5 * (init_lr - min_lr) * (1 + cos(π * epoch / max_epoch))1.4 训练循环流程
核心训练循环(drive.py:185-287):
def_train_inner_loop(self,epoch,iters_per_epoch,model,data_loader,optimizer,lr_scheduler,scaler=None,accum_grad_iters=1):foriinrange(iters_per_epoch):samples=next(data_loader)# 获取训练样本lr_scheduler.step(cur_epoch=inner_epoch,cur_step=i)# 更新学习率withtorch.cuda.amp.autocast(enabled=use_amp):loss,loss_dict=self.train_step(model=model,samples=samples)loss/=accum_grad_iters# 梯度累积ifuse_amp:scaler.scale(loss).backward()# 混合精度反向传播else:loss.backward()if(i+1)%accum_grad_iters==0:# 梯度累积更新ifuse_amp:scaler.step(optimizer)scaler.update()else:optimizer.step()optimizer.zero_grad()训练流程详解:
| 阶段 | 操作 | 说明 |
|---|---|---|
| 数据加载 | next(data_loader) | 加载批次训练数据 |
| 学习率更新 | lr_scheduler.step() | 根据当前 epoch/step 更新学习率 |
| 前向传播 | model(samples) | 计算损失 |
| 梯度累积 | loss /= accum_grad_iters | 模拟更大批次训练 |
| 反向传播 | loss.backward() | 计算梯度 |
| 参数更新 | optimizer.step() | 更新模型参数 |
| 梯度清零 | optimizer.zero_grad() | 准备下一轮 |
1.5 AMP 混合精度训练
算法原理:使用 FP16 进行前向传播,FP32 进行梯度累积,减少显存占用并加速训练。
配置(runner_base.py:126-133):
@propertydefscaler(self):amp=self.config.run_cfg.get("amp",False)ifamp:ifself._scalerisNone:self._scaler=torch.cuda.amp.GradScaler()returnself._scaler优势:
- 显存占用减少约 50%
- 训练速度提升约 20-30%
- 不影响模型精度
1.6 分布式训练
算法原理:使用 PyTorch Distributed Data Parallel (DDP) 进行多卡训练。
配置(runner_base.py:86-99):
@propertydefmodel(self):ifself._model.device!=self.device:self._model=self._model.to(self.device)ifself.use_distributed:self._wrapped_model=DDP(self._model,device_ids=[self.config.run_cfg.gpu],find_unused_parameters=False)returnself._wrapped_model关键特性:
- 每张卡独立计算,梯度同步通过 all-reduce
- 支持多节点训练
find_unused_parameters=False优化性能
2. LangAuto 基准评测框架
2.1 框架概述
LangAuto是 LMDrive 项目的自动驾驶基准评测框架,基于 Carla 模拟器构建,用于评估语言指令驱动的自动驾驶模型性能。
核心设计理念:
- 多城镇覆盖:Town01-Town10HD
- 多天气场景:晴天、雨天、雾天、夜晚等
- 多路线长度:tiny(短)、short(中)、long(长)
2.2 基准配置文件
三个基准级别:
| 基准名称 | 路线数量 | waypoint数 | 用途 |
|---|---|---|---|
| benchmark_tiny.xml | 16 | 2 | 快速验证、调试 |
| benchmark_short.xml | 16 | 2 | 常规评测 |
| benchmark_long.xml | 32 | 2-4 | 全面评估 |
路线特征:
- Tiny/Short:每条路线仅包含起点和终点两个 waypoint
- Long:每条路线包含 2-4 个 waypoint,路线更长、更复杂
文件结构(langauto/benchmark_tiny.xml):
<routes><routeid="0"town="Town01"><waypointx="-2.96"y="233.65"yaw="90.0"/><!-- 起点 --><waypointx="33.55"y="330.46"yaw="0.0"/><!-- 终点 --><weatherid="SoftRainNoon"precipitation="30.0".../><!-- 天气 --></route>...</routes>2.3 评测城镇覆盖
基准覆盖 8 个城镇:
| 城镇 | 特点 |
|---|---|
| Town01 | 小型城镇,简单道路 |
| Town02 | 中型城镇,多交叉路口 |
| Town03 | 丘陵地形,坡道 |
| Town04 | 大型城镇,高速公路 |
| Town05 | 密集城区,复杂交通 |
| Town06 | 大型城市,立交桥 |
| Town07 | 乡村道路,自然景观 |
| Town10HD | 高清城镇,复杂建筑 |
2.4 天气条件配置
支持多种天气场景:
| 天气 ID | 描述 | 关键参数 |
|---|---|---|
| ClearNoon | 晴朗正午 | cloudiness=5 |
| CloudyNight | 多云夜晚 | sun_altitude_angle=-90 |
| SoftRainNoon | 小雨正午 | precipitation=30 |
| HardRainNoon | 大雨正午 | precipitation=100 |
| WetCloudyNight | 湿滑多云夜 | wetness=60 |
| MidRainyNight | 中雨夜晚 | precipitation=60 |
| ClearSunset | 晴朗日落 | sun_altitude_angle=15 |
| CloudySunset | 多云日落 | cloudiness=60 |
天气参数说明:
| 参数 | 范围 | 说明 |
|---|---|---|
| cloudiness | 0-100 | 云量百分比 |
| precipitation | 0-100 | 降水量 |
| precipitation_deposits | 0-100 | 地面积水 |
| fog_density | 0-100 | 雾密度 |
| wetness | 0-100 | 地面湿润度 |
| sun_altitude_angle | -90~90 | 太阳高度角(-90为夜晚) |
2.5 路线定义格式
每个 route 包含:
- route id:路线唯一标识
- town:城镇名称
- waypoint(起点):包含 x, y, z 坐标和 yaw 方向
- waypoint(终点):目标位置
- weather:天气配置
示例(benchmark_tiny.xml第2-5行):
<routeid="0"town="Town01"><waypointpitch="0.0"roll="0.0"x="-2.96"y="233.65"yaw="90.000374"z="0.0"/><waypointpitch="0.0"roll="0.0"x="33.55"y="330.46"yaw="0.0"z="0.0"/><weathercloudiness="20.0"fog_density="3.0"precipitation="30.0"sun_altitude_angle="45.0"id="SoftRainNoon"/></route>waypoint 参数:
x,y,z:世界坐标位置yaw:朝向角度(0-360度)pitch,roll:俯仰角和滚转角
2.6 Waypoint-to-Control 转换
算法原理:模型预测的 waypoints 需转换为车辆控制指令(转向、油门、刹车),采用 PID 控制器实现。
代码实现(lmdriver_agent.py:581-623):
defcontrol_pid(self,waypoints,velocity):waypoints=waypoints.data.cpu().numpy()waypoints[:,1]*=-1# 坐标系转换# 计算期望速度desired_speed=np.linalg.norm(waypoints[0]-waypoints[1])*2.0# 判断是否需要刹车brake=desired_speed<self.config.brake_speedor(speed/desired_speed)>self.config.brake_ratio# 计算转向角度aim=(waypoints[1]+waypoints[0])/2.0# 取前两个waypoint的中点angle=np.degrees(np.pi/2-np.arctan2(aim[1],aim[0]))/90steer=self.turn_controller.step(angle)steer=np.clip(steer,-1.0,1.0)# 计算油门delta=np.clip(desired_speed-speed,0.0,self.config.clip_delta)throttle=self.speed_controller.step(delta)throttle=np.clip(throttle,0.0,self.config.max_throttle)returnsteer,throttle,brake,metadata控制流程:
预测 waypoints [5, 2] → 取前2个点计算目标方向 → PID转向控制 → 计算期望速度 → PID速度控制 → 输出控制指令PID 控制器参数(lmdriver_config.py):
- 转向控制:
turn_KP,turn_KI,turn_KD - 速度控制:
speed_KP,speed_KI,speed_KD
2.7 评测指标
核心评测指标:
| 指标 | 类型 | 说明 |
|---|---|---|
| 路线完成率 | 百分比 | 成功到达终点的路线比例 |
| 平均轨迹误差 | 米 | 预测轨迹与真实轨迹的平均距离 |
| 碰撞次数 | 计数 | 与障碍物/车辆的碰撞次数 |
| 违规次数 | 计数 | 闯红灯、逆行等违规行为 |
| 行驶速度 | km/h | 平均行驶速度 |
| 任务成功率 | 百分比 | 正确执行语言指令的比例 |
评估流程:
1. 加载基准配置文件 (langauto/benchmark_xxx.xml) 2. 在 Carla 中生成路线和天气 3. LMDriveAgent 运行模型执行驾驶任务 4. 记录车辆状态和行为(速度、位置、控制指令) 5. Carla Leaderboard 计算评测指标 6. 输出评估报告评测执行流程(lmdriver_agent.py:415-569):
defrun_step(self,input_data,timestamp):tick_data=self.tick(input_data)# 预处理传感器数据# 提取特征image_embeds=self.net.visual_encoder(input_data)image_embeds=self.update_and_collect(image_embeds)# 模型推理waypoints,is_end=self.net(input_data,inference_mode=True,image_embeds=image_embeds)waypoints=waypoints[-1].view(5,2)# 终点判断end_prob=self.softmax(is_end)[-1][1]ifend_prob>0.75:self.visual_feature_buffer=[]# waypoint → 控制指令steer,throttle,brake,metadata=self.control_pid(waypoints,velocity)# 返回控制指令control=carla.VehicleControl()control.steer=float(steer)*0.8control.throttle=float(throttle)control.brake=float(brake)returncontrol2.8 评测执行方式
使用 Carla Leaderboard 框架:
# 启动 Carla 模拟器CarlaUE4.exe# 运行评测python leaderboard/leaderboard/evaluate.py\--scenario_runnerleaderboard/scenario_runner\--agentleaderboard/team_code/lmdriver_agent.py\--routeslangauto/benchmark_tiny.xml\--checkpointlmdrive_llava.pth\--port2000关键组件:
lmdriver_agent.py:LMDrive 智能体实现evaluate.py:评测执行入口routes:基准路线配置文件
3. 训练与评测协同架构
┌─────────────────────────────────────────────────────────────────────────┐ │ 训练与评测协同架构 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────┐ │ │ │ 训练数据加载 │ │ │ │ (WebDataset) │ │ │ └────────┬─────────┘ │ │ │ 多视角图像 + LiDAR + 文本指令 + 轨迹标注 │ │ ▼ │ │ ┌──────────────────┐ │ │ │ 双损失函数训练 │ │ │ │ ┌─────────────┐ │ │ │ │ │ Waypoints │ │ L1Loss → 轨迹回归 │ │ │ │ Loss (1.0) │ │ │ │ │ └─────────────┘ │ │ │ │ ┌─────────────┐ │ │ │ │ │ End Loss │ │ CrossEntropyLoss → 终点分类 │ │ │ │ (0.2) │ │ │ │ │ └─────────────┘ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ loss = L1 + 0.2×CE │ │ │ │ │ │ │ │ ▼ │ │ │ │ AdamW + CosineLR + AMP │ │ └────────┬─────────┘ │ │ │ 模型权重 │ │ ▼ │ │ ┌──────────────────┐ ┌──────────────────┐ │ │ │ LangAuto 评测 │ │ 训练验证循环 │ │ │ │ 基准测试集 │ │ val_step 评估 │ │ │ │ 8城镇×多天气 │ │ after_evaluation │ │ │ │ benchmark_tiny │ │ TensorBoard记录 │ │ │ │ benchmark_short │ │ │ │ │ │ benchmark_long │ │ │ │ │ └────────┬─────────┘ └────────┬─────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────────────────────────────────┐ │ │ │ 性能指标反馈 │ │ │ │ 路线完成率 / 轨迹误差 / 碰撞次数 / 成功率 │ │ │ └─────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘4. 关键技术参数总结
4.1 训练参数
| 参数 | 默认值 | 说明 |
|---|---|---|
| init_lr | 1e-4 | 初始学习率 |
| min_lr | 1e-5 | 最小学习率 |
| max_epoch | 10 | 训练轮数 |
| warmup_steps | 1000 | 预热步数 |
| weight_decay | 0.05 | 权重衰减 |
| beta2 | 0.999 | AdamW beta2 |
| accum_grad_iters | 1 | 梯度累积步数 |
| amp | True | 混合精度训练 |
4.2 损失参数
| 参数 | 值 | 说明 |
|---|---|---|
| waypoints_loss_type | L1Loss | 轨迹回归损失 |
| end_loss_type | CrossEntropyLoss | 终点分类损失 |
| end_loss_weight | 0.2 | 终点损失权重 |
4.3 评测参数
| 参数 | 值 | 说明 |
|---|---|---|
| 城镇数量 | 8 | Town01-Town10HD |
| 路线数量(tiny) | 16 | 快速验证 |
| 路线数量(short) | 16 | 常规评测 |
| 路线数量(long) | 32 | 全面评估 |
| waypoint数(tiny/short) | 2 | 起点+终点 |
| waypoint数(long) | 2-4 | 多途经点 |
| 天气类型 | 10+ | 晴/雨/雾/夜等 |
| 传感器 | 5摄像头+LiDAR+GPS+IMU | 多模态感知 |
5. 总结
双损失函数训练模块
LMDrive 的训练模块采用多任务学习策略,通过加权联合损失同时优化:
- Waypoints Loss(L1Loss):回归 5 个未来轨迹点,权重 1.0
- End Loss(CrossEntropyLoss):分类判断轨迹终点,权重 0.2
训练过程使用:
- AdamW 优化器 + 余弦退火学习率调度
- AMP 混合精度训练减少显存占用
- DDP 分布式训练支持多卡加速
- 梯度累积模拟大批次训练
LangAuto 基准评测框架
LangAuto 提供标准化的自动驾驶评测环境:
- 覆盖 8 个不同地形城镇(小型→大型,简单→复杂)
- 支持 10+ 种天气条件(晴天、雨天、雾天、夜晚等)
- 提供三个基准级别(tiny/short/long)适应不同评测需求
- 基于 Carla 模拟器,可复现性强
通过训练与评测的闭环迭代,LMDrive 模型不断优化语言指令理解和驾驶决策能力。