基于CARLA和TD3算法的深度强化学习实战:从仿真到策略优化

1次阅读
没有评论

共计 3973 个字符,预计需要花费 10 分钟才能阅读完成。

image.webp

背景痛点

自动驾驶仿真训练中,传统方法面临两个主要问题:稀疏奖励和样本效率低下。稀疏奖励意味着智能体在训练初期很难获得正向反馈,导致学习速度缓慢;样本效率低下则是指算法需要大量交互数据才能学到有效的策略。DDPG(Deep Deterministic Policy Gradient)算法虽然在一些连续控制任务中表现不错,但也存在几个明显的局限性:

基于 CARLA 和 TD3 算法的深度强化学习实战:从仿真到策略优化

  • 对超参数敏感:DDPG 的性能高度依赖于超参数的选择,尤其是学习率和探索噪声的设置。
  • 过估计偏差:DDPG 的 Q 值估计容易偏高,导致策略更新不稳定。
  • 探索不足:DDPG 的动作空间是连续的,但缺乏有效的探索机制,容易陷入局部最优。

这些问题使得 DDPG 在复杂的自动驾驶任务中表现不佳,尤其是在 CARLA 这种高保真仿真环境中。

技术选型

针对 DDPG 的不足,TD3(Twin Delayed DDPG)算法通过三个关键技术改进解决了这些问题:

  1. 双 Critic 网络 :TD3 使用两个独立的 Critic 网络,取两者中的较小值作为 Q 值估计,有效减少了过估计偏差。
  2. 延迟更新 :TD3 的策略网络(Actor)更新频率低于 Critic 网络,避免了因 Q 值估计不稳定导致的策略震荡。
  3. 目标策略平滑 :TD3 在目标动作上添加噪声,进一步减少了 Q 值估计的方差。

与 PPO(Proximal Policy Optimization)相比,TD3 更适合连续动作空间的任务,尤其是在需要精细控制(如方向盘和油门)的自动驾驶场景中。PPO 虽然更稳定,但在高维动作空间中的表现往往不如 TD3。

实现细节

CARLA 环境搭建与 Python API 交互

CARLA 是一个开源的自动驾驶仿真平台,支持高保真的传感器模拟和物理引擎。搭建 CARLA 环境的主要步骤包括:

  1. 从 CARLA 官网下载预编译的二进制包。
  2. 启动 CARLA 服务器:./CarlaUE4.sh -world-port=2000
  3. 使用 Python API 连接服务器:
    import carla
    client = carla.Client("localhost", 2000)
    world = client.get_world()

状态空间设计

自动驾驶任务的状态空间通常包括:

  • 车辆状态:位置、速度、加速度、航向角等。
  • 传感器数据:摄像头图像、激光雷达点云、雷达测距等。
  • 环境信息:车道线、交通标志、其他车辆位置等。

为了提高训练效率,建议对原始传感器数据进行预处理,例如将图像降采样或提取特征向量。

动作空间离散化处理

虽然 TD3 支持连续动作空间,但在实际应用中,可以对动作空间进行离散化以简化问题。例如,方向盘角度可以离散化为 [-1, -0.5, 0, 0.5, 1],油门和刹车也可以类似处理。这种离散化可以减少动作空间的维度,加快训练速度。

奖励函数工程

奖励函数的设计是强化学习成功的关键。自动驾驶任务的奖励函数通常包括:

  • 正向奖励:车辆沿车道中心线行驶、保持合理速度、到达目标点。
  • 负向奖励:碰撞、偏离车道、急刹车或急加速。

一个示例奖励函数:

def calculate_reward(state, action):
    reward = 0
    # 正向奖励:速度接近目标速度
    reward += max(0, 1 - abs(state["speed"] - target_speed) / target_speed)
    # 负向奖励:偏离车道中心
    reward -= abs(state["lane_offset"]) * 0.1
    # 安全惩罚:碰撞或危险行为
    if state["collision"]:
        reward -= 10
    return reward

代码示例

Actor-Critic 网络结构

TD3 的 Actor 和 Critic 网络通常采用全连接层,中间加入 LayerNorm 以稳定训练:

import torch
import torch.nn as nn
import torch.nn.functional as F

class Actor(nn.Module):
    def __init__(self, state_dim, action_dim):
        super(Actor, self).__init__()
        self.fc1 = nn.Linear(state_dim, 256)
        self.ln1 = nn.LayerNorm(256)
        self.fc2 = nn.Linear(256, 256)
        self.ln2 = nn.LayerNorm(256)
        self.fc3 = nn.Linear(256, action_dim)

    def forward(self, x):
        x = F.relu(self.ln1(self.fc1(x)))
        x = F.relu(self.ln2(self.fc2(x)))
        return torch.tanh(self.fc3(x))

经验回放缓冲区优化

经验回放缓冲区(Replay Buffer)是 off-policy 算法的核心组件。为了提高样本利用率,可以优先存储重要的转移(如碰撞或高奖励的样本):

class PrioritizedReplayBuffer:
    def __init__(self, capacity, alpha=0.6):
        self.capacity = capacity
        self.alpha = alpha
        self.buffer = []
        self.priorities = np.zeros(capacity)
        self.pos = 0

    def add(self, state, action, reward, next_state, done):
        max_prio = self.priorities.max() if self.buffer else 1.0
        if len(self.buffer) < self.capacity:
            self.buffer.append((state, action, reward, next_state, done))
        else:
            self.buffer[self.pos] = (state, action, reward, next_state, done)
        self.priorities[self.pos] = max_prio
        self.pos = (self.pos + 1) % self.capacity

目标网络软更新

目标网络的软更新(soft update)是 TD3 稳定训练的关键:

def soft_update(target, source, tau):
    for target_param, param in zip(target.parameters(), source.parameters()):
        target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data)

训练循环中的策略延迟更新

TD3 的策略网络(Actor)更新频率低于 Critic 网络,通常每 2 次 Critic 更新才更新一次 Actor:

for t in range(total_timesteps):
    # 采样并存储转移
    state, action, reward, next_state, done = env.step(...)
    replay_buffer.add(state, action, reward, next_state, done)

    if t % 2 == 0:  # 延迟更新
        # 更新 Critic
        ...
        # 更新 Actor
        actor_loss = -critic1(state, actor(state)).mean()
        actor_optimizer.zero_grad()
        actor_loss.backward()
        actor_optimizer.step()
        # 软更新目标网络
        soft_update(target_actor, actor, tau)
        soft_update(target_critic1, critic1, tau)
        soft_update(target_critic2, critic2, tau)

避坑指南

CARLA 同步模式下的性能调优

CARLA 默认运行在异步模式下,可能导致仿真时间与真实时间不同步。为了确保训练的一致性,建议启用同步模式:

settings = world.get_settings()
settings.synchronous_mode = True
world.apply_settings(settings)

梯度裁剪阈值选择

梯度裁剪(Gradient Clipping)可以防止梯度爆炸,但阈值的选择需要谨慎。对于 TD3,Critic 网络的梯度裁剪阈值通常设置为 1.0,Actor 网络可以稍大一些(如 5.0)。

探索噪声衰减策略

探索噪声(Exploration Noise)在训练初期应较大,随着训练的进行逐渐衰减。常用的衰减策略是线性衰减或指数衰减:

exploration_noise = max(min_noise, initial_noise * (1 - t / total_timesteps))

分布式训练注意事项

分布式训练可以显著加快 TD3 的训练速度,但需要注意:

  • 确保不同进程的环境随机种子不同,以增加样本多样性。
  • 使用共享的经验回放缓冲区时,注意同步问题。
  • 定期同步各进程的模型参数,避免策略差异过大。

验证指标

训练完成后,可以通过以下指标评估模型性能:

  • 训练曲线 :观察平均奖励和 Q 值估计的变化趋势,确保其稳定上升。
  • 成功率 :在测试环境中运行多个 episode,统计成功到达目标点的比例。
  • 平均奖励 :计算测试 episode 的平均奖励,反映策略的整体性能。

结论与开放性问题

TD3 在 CARLA 仿真环境中表现出色,但仍有一些开放性问题值得探索:

  • 多智能体场景 :如何将 TD3 扩展到多车协作或竞争的场景?
  • 异构传感器融合 :如何更好地融合摄像头、激光雷达和雷达的异构数据?
  • 实时性要求 :在计算资源有限的情况下,如何进一步优化 TD3 的推理速度?

希望本文能够帮助开发者在自动驾驶仿真任务中快速上手 TD3 算法。更多细节可以参考原版 TD3 论文(Fujimoto et al., 2018)。

正文完
 0
评论(没有评论)