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
代码实现:
python
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):
python
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):
python
class LinearWarmupCosineLRScheduler:
def step(self, cur_epoch, cur_step):
if cur_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):
python
def _train_inner_loop(self, epoch, iters_per_epoch, model, data_loader,
optimizer, lr_scheduler, scaler=None, accum_grad_iters=1):
for i in range(iters_per_epoch):
samples = next(data_loader) # 获取训练样本
lr_scheduler.step(cur_epoch=inner_epoch, cur_step=i) # 更新学习率
with torch.cuda.amp.autocast(enabled=use_amp):
loss, loss_dict = self.train_step(model=model, samples=samples)
loss /= accum_grad_iters # 梯度累积
if use_amp:
scaler.scale(loss).backward() # 混合精度反向传播
else:
loss.backward()
if (i + 1) % accum_grad_iters == 0: # 梯度累积更新
if use_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):
python
@property
def scaler(self):
amp = self.config.run_cfg.get("amp", False)
if amp:
if self._scaler is None:
self._scaler = torch.cuda.amp.GradScaler()
return self._scaler
优势:
- 显存占用减少约 50%
- 训练速度提升约 20-30%
- 不影响模型精度
1.6 分布式训练
算法原理:使用 PyTorch Distributed Data Parallel (DDP) 进行多卡训练。
配置 (runner_base.py:86-99):
python
@property
def model(self):
if self._model.device != self.device:
self._model = self._model.to(self.device)
if self.use_distributed:
self._wrapped_model = DDP(
self._model,
device_ids=[self.config.run_cfg.gpu],
find_unused_parameters=False
)
return self._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):
xml
<routes>
<route id="0" town="Town01">
<waypoint x="-2.96" y="233.65" yaw="90.0" /> <!-- 起点 -->
<waypoint x="33.55" y="330.46" yaw="0.0" /> <!-- 终点 -->
<weather id="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行):
xml
<route id="0" town="Town01">
<waypoint pitch="0.0" roll="0.0" x="-2.96" y="233.65" yaw="90.000374" z="0.0" />
<waypoint pitch="0.0" roll="0.0" x="33.55" y="330.46" yaw="0.0" z="0.0" />
<weather cloudiness="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):
python
def control_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_speed or (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])) / 90
steer = 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)
return steer, 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):
python
def run_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]
if end_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.8
control.throttle = float(throttle)
control.brake = float(brake)
return control
2.8 评测执行方式
使用 Carla Leaderboard 框架:
bash
# 启动 Carla 模拟器
CarlaUE4.exe
# 运行评测
python leaderboard/leaderboard/evaluate.py \
--scenario_runner leaderboard/scenario_runner \
--agent leaderboard/team_code/lmdriver_agent.py \
--routes langauto/benchmark_tiny.xml \
--checkpoint lmdrive_llava.pth \
--port 2000
关键组件:
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 模型不断优化语言指令理解和驾驶决策能力。