Files
MAGAIL4AutoDrive/MAGAIL算法应用指南.md

544 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# MAGAIL算法应用指南
## 目录
1. [Algorithm模块概览](#algorithm模块概览)
2. [如何应用到环境](#如何应用到环境)
3. [完整训练流程](#完整训练流程)
4. [当前实现状态](#当前实现状态)
5. [需要完善的部分](#需要完善的部分)
---
## Algorithm模块概览
### 📁 模块文件说明
```
Algorithm/
├── bert.py # BERT判别器/价值网络
├── disc.py # GAIL判别器继承BERT
├── policy.py # 策略网络Actor
├── ppo.py # PPO算法基类
├── magail.py # MAGAIL主算法继承PPO
├── buffer.py # 经验回放缓冲区
└── utils.py # 工具函数(标准化等)
```
### 🔗 模块依赖关系
```
MAGAIL (magail.py)
├─ 继承 PPO (ppo.py)
│ ├─ 使用 RolloutBuffer (buffer.py)
│ ├─ 使用 StateIndependentPolicy (policy.py)
│ └─ 使用 Bert作为Critic (bert.py)
├─ 使用 GAILDiscrim (disc.py)
│ └─ 继承 Bert (bert.py)
└─ 使用 Normalizer (utils.py)
```
---
## 如何应用到环境
### ✅ 已完成的准备工作
我已经为您:
1. **修复了PPO代码bug**:添加了缺失的`action_shape`参数
2. **创建了训练脚本**`train_magail.py`
3. **提供了完整框架**:包含环境初始化、训练循环、模型保存等
### 🚀 快速开始
#### 方法1使用训练脚本推荐
```bash
# 基本训练(使用默认参数)
python train_magail.py
# 自定义参数
python train_magail.py \
--data-dir /path/to/waymo/data \
--episodes 1000 \
--horizon 300 \
--batch-size 256 \
--lr-actor 3e-4 \
--render # 可视化
# 查看所有参数
python train_magail.py --help
```
#### 方法2在Jupyter Notebook中使用
```python
import sys
sys.path.append('Algorithm')
sys.path.append('Env')
from Algorithm.magail import MAGAIL
from Env.scenario_env import MultiAgentScenarioEnv
# 初始化环境
env = MultiAgentScenarioEnv(config={...})
# 初始化MAGAIL
magail = MAGAIL(
buffer_exp=expert_buffer,
input_dim=(108,), # 观测维度
device="cuda"
)
# 训练循环
for episode in range(1000):
obs = env.reset()
for step in range(300):
actions, log_pis = magail.explore(obs)
next_obs, rewards, dones, infos = env.step(actions)
# ... 更新逻辑
```
---
## 完整训练流程
### 📊 数据流程图
```
┌─────────────────────────────────────────────────────────────┐
│ MAGAIL训练流程 │
└─────────────────────────────────────────────────────────────┘
第1步: 初始化
├─ 加载Waymo专家数据 → ExpertBuffer
├─ 创建MAGAIL算法实例
│ ├─ Actor (policy.py)
│ ├─ Critic (bert.py)
│ ├─ Discriminator (disc.py)
│ └─ Buffers (buffer.py)
└─ 创建多智能体环境
第2步: 训练循环
for episode in range(episodes):
├─ env.reset() → 重置环境,生成车辆
for step in range(horizon):
├─ obs = env._get_all_obs() # 收集观测
├─ actions = magail.explore(obs) # 策略采样
├─ next_obs, rewards, dones = env.step(actions)
├─ buffer.append(obs, actions, rewards, ...) # 存储经验
└─ if step % rollout_length == 0:
├─ 更新判别器
│ ├─ 采样策略数据: buffer.sample()
│ ├─ 采样专家数据: expert_buffer.sample()
│ └─ update_disc(policy_data, expert_data)
├─ 计算GAIL奖励
│ └─ reward = -log(1 - D(s, s'))
└─ 更新PPO
├─ 计算GAE优势
├─ update_actor()
└─ update_critic()
第3步: 评估与保存
└─ 保存模型、记录指标
```
### 🔑 关键代码段
#### 1. 初始化MAGAIL
```python
from Algorithm.magail import MAGAIL
magail = MAGAIL(
buffer_exp=expert_buffer, # 专家数据缓冲区
input_dim=(obs_dim,), # 观测维度 (108,)
device=device, # cuda/cpu
action_shape=(2,), # 动作维度 [转向, 油门]
# 判别器参数
disc_coef=20.0, # 判别器损失系数
disc_grad_penalty=0.1, # 梯度惩罚系数
disc_logit_reg=0.25, # Logit正则化
disc_weight_decay=0.0005, # 权重衰减
lr_disc=3e-4, # 判别器学习率
epoch_disc=5, # 判别器更新轮数
# PPO参数
rollout_length=2048, # 更新间隔
lr_actor=3e-4, # Actor学习率
lr_critic=3e-4, # Critic学习率
epoch_ppo=10, # PPO更新轮数
batch_size=256, # 批次大小
gamma=0.995, # 折扣因子
lambd=0.97, # GAE lambda
# 其他
use_gail_norm=True, # 使用数据标准化
)
```
#### 2. 环境交互
```python
# 重置环境
obs_list = env.reset(episode)
# 收集观测(所有车辆)
obs_array = np.array(env.obs_list) # shape: (n_agents, 108)
# 策略采样
actions, log_pis = magail.explore(obs_array)
# actions: list of [转向, 油门] for each agent
# log_pis: list of log probabilities
# 构建动作字典
action_dict = {
agent_id: actions[i]
for i, agent_id in enumerate(env.controlled_agents.keys())
}
# 环境步进
next_obs, rewards, dones, infos = env.step(action_dict)
```
#### 3. 模型更新
```python
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter('logs')
# 更新判别器和策略
if total_steps % rollout_length == 0:
# MAGAIL会自动
# 1. 从buffer采样策略数据
# 2. 从expert_buffer采样专家数据
# 3. 更新判别器
# 4. 计算GAIL奖励
# 5. 更新PPOActor + Critic
reward = magail.update(writer, total_steps)
print(f"Step {total_steps}, Reward: {reward:.4f}")
```
#### 4. 保存和加载模型
```python
# 保存
magail.save_models('outputs/models/checkpoint_100')
# 加载
magail.load_models('outputs/models/checkpoint_100/model.pth')
```
---
## 当前实现状态
### ✅ 已实现功能
| 模块 | 状态 | 说明 |
|------|------|------|
| BERT判别器 | ✅ 完整 | 支持动态车辆数量 |
| GAIL判别器 | ✅ 完整 | 包含梯度惩罚、正则化 |
| 策略网络 | ✅ 完整 | 高斯策略,重参数化 |
| PPO算法 | ✅ 完整 | GAE、裁剪目标、自适应LR |
| MAGAIL | ✅ 完整 | 判别器+PPO整合 |
| 缓冲区 | ✅ 完整 | 经验存储和采样 |
| 数据标准化 | ✅ 完整 | 运行时统计量 |
| 环境接口 | ✅ 完整 | 多智能体场景环境 |
### ⚠️ 需要注意的问题
#### 1. 多智能体适配问题
**当前状态:** Algorithm模块设计为单智能体但环境是多智能体
**影响:**
- `buffer.append()` 接受单个状态-动作对
- 但环境返回多个智能体的数据
**解决方案A** 将所有智能体视为一个整体
```python
# 拼接所有智能体的观测
all_obs = np.concatenate([obs for obs in obs_list])
all_actions = np.concatenate([actions for actions in action_list])
```
**解决方案B** 为每个智能体独立存储
```python
for i, agent_id in enumerate(env.controlled_agents):
buffer.append(obs_list[i], actions[i], rewards[i], ...)
```
**推荐:** 解决方案B因为MAGAIL的设计就是处理多智能体的
#### 2. 专家数据加载
**当前状态:** `ExpertBuffer` 类只有框架,未实现实际加载
**需要完善:**
```python
def _extract_trajectories(self, scenario_data):
"""
需要根据Waymo数据格式实现
示例结构:
scenario_data = {
'tracks': {
'vehicle_id': {
'states': [...], # 状态序列
'actions': [...], # 动作序列(如果有)
}
}
}
"""
# TODO: 提取state和next_state对
for track_id, track_data in scenario_data['tracks'].items():
states = track_data['states']
for i in range(len(states) - 1):
self.states.append(states[i])
self.next_states.append(states[i+1])
```
#### 3. 观测维度对齐
**当前假设:** 观测维度为108
- 位置(2) + 速度(2) + 朝向(1) + 激光雷达(80) + 侧向(10) + 车道线(10) + 红绿灯(1) + 目标点(2) = 108
**需要验证:** 实际运行时打印观测shape
```python
obs = env.reset()
print(f"观测维度: {len(obs[0]) if obs else 0}")
```
---
## 需要完善的部分
### 🔨 短期TODO
#### 1. 修复多智能体buffer问题
**创建文件:** `Algorithm/multi_agent_buffer.py`
```python
class MultiAgentRolloutBuffer:
"""
多智能体经验缓冲区
支持动态数量的智能体
"""
def __init__(self, buffer_size, state_shape, action_shape, device):
self.buffer_size = buffer_size
self.state_shape = state_shape
self.action_shape = action_shape
self.device = device
# 使用列表存储,支持动态智能体数量
self.episodes = []
self.current_episode = {
'states': [],
'actions': [],
'rewards': [],
'dones': [],
'log_pis': [],
'next_states': [],
}
def append(self, state, action, reward, done, log_pi, next_state):
"""添加单步经验"""
self.current_episode['states'].append(state)
self.current_episode['actions'].append(action)
self.current_episode['rewards'].append(reward)
self.current_episode['dones'].append(done)
self.current_episode['log_pis'].append(log_pi)
self.current_episode['next_states'].append(next_state)
def finish_episode(self):
"""完成一个episode"""
self.episodes.append(self.current_episode)
self.current_episode = {
'states': [],
'actions': [],
'rewards': [],
'dones': [],
'log_pis': [],
'next_states': [],
}
def sample(self, batch_size):
"""采样批次"""
# 从所有episode中随机采样
all_states = []
all_next_states = []
for episode in self.episodes:
all_states.extend(episode['states'])
all_next_states.extend(episode['next_states'])
indices = np.random.choice(len(all_states), batch_size, replace=False)
states = torch.tensor([all_states[i] for i in indices], device=self.device)
next_states = torch.tensor([all_next_states[i] for i in indices], device=self.device)
return states, next_states
```
#### 2. 实现专家数据加载
**需要了解:** Waymo数据的实际格式
```python
# 示例读取一个pkl文件并打印结构
import pickle
with open('Env/exp_converted/exp_converted_0/sd_waymo_*.pkl', 'rb') as f:
data = pickle.load(f)
print(type(data))
print(data.keys() if isinstance(data, dict) else len(data))
# 根据实际结构调整加载代码
```
#### 3. 完善训练循环
**在 `train_magail.py` 中添加:**
```python
# 完整的buffer存储逻辑
for i, agent_id in enumerate(env.controlled_agents.keys()):
if i < len(obs_array) and i < len(actions):
magail.buffer.append(
state=obs_array[i],
action=actions[i],
reward=rewards.get(agent_id, 0.0),
done=dones.get(agent_id, False),
tm_done=dones.get(agent_id, False),
log_pi=log_pis[i],
next_state=next_obs_array[i] if i < len(next_obs_array) else obs_array[i],
next_state_gail=next_obs_array[i] if i < len(next_obs_array) else obs_array[i],
means=magail.actor.means[i].detach().cpu().numpy(),
stds=magail.actor.log_stds.exp()[0].detach().cpu().numpy()
)
```
### 🎯 中期TODO
1. **实现多智能体BERT**当前BERT接受(batch, N, obs_dim),需要确保正确处理
2. **奖励设计**当前环境奖励为0需要设计合理的任务奖励
3. **评估脚本**:创建评估脚本,可视化训练好的策略
4. **超参数调优**使用wandb或tensorboard进行超参数搜索
---
## 使用示例
### 示例1简单训练
```bash
# 1. 确保环境正常
python Env/run_multiagent_env.py
# 2. 开始训练(不渲染,快速训练)
python train_magail.py \
--episodes 100 \
--horizon 200 \
--rollout-length 1024 \
--batch-size 128
# 3. 查看训练日志
tensorboard --logdir outputs/magail_*/logs
```
### 示例2调试模式
```bash
# 少量episode启用渲染
python train_magail.py \
--episodes 5 \
--horizon 100 \
--render
```
### 示例3在代码中使用
```python
# test_algorithm.py
import sys
sys.path.append('Algorithm')
from Algorithm.magail import MAGAIL
import torch
# 创建虚拟数据测试
class DummyExpertBuffer:
def __init__(self, device):
self.device = device
def sample(self, batch_size):
states = torch.randn(batch_size, 108, device=self.device)
next_states = torch.randn(batch_size, 108, device=self.device)
return states, next_states
# 初始化
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
expert_buffer = DummyExpertBuffer(device)
magail = MAGAIL(
buffer_exp=expert_buffer,
input_dim=(108,),
device=device,
action_shape=(2,),
)
# 测试前向传播
test_obs = torch.randn(5, 108, device=device) # 5个智能体
actions, log_pis = magail.explore(test_obs)
print(f"观测形状: {test_obs.shape}")
print(f"动作数量: {len(actions)}")
print(f"单个动作形状: {actions[0].shape}")
print(f"测试成功!✅")
```
---
## 总结
### ✅ 现在可以做什么
1. **运行环境测试**`run_multiagent_env.py` 已经可以正常运行
2. **测试算法模块**Algorithm中的所有模块都已实现
3. **开始初步训练**:使用 `train_magail.py`但需要完善buffer逻辑
### ⚠️ 需要您完成的
1. **调试多智能体buffer**:确保经验正确存储
2. **实现专家数据加载**:根据实际数据格式调整
3. **验证观测维度**确认实际观测是否为108维
4. **调整训练参数**:根据训练效果调优
### 🎯 最终目标
```
环境 (Env/) + 算法 (Algorithm/) = 完整的MAGAIL训练系统
训练出能够模仿专家行为的
多智能体自动驾驶策略
```
祝训练顺利!🚀