317 lines
7.3 KiB
Markdown
317 lines
7.3 KiB
Markdown
# 问题解决记录
|
||
|
||
## 运行 `train_magail.py` 遇到的问题及解决方案
|
||
|
||
---
|
||
|
||
### ❌ 问题1: 模块导入错误
|
||
|
||
**错误信息:**
|
||
```python
|
||
ImportError: attempted relative import with no known parent package
|
||
```
|
||
|
||
**原因:**
|
||
- `Algorithm/` 文件夹中的文件使用了不一致的导入方式
|
||
- 有些文件使用相对导入(`.ppo`, `.utils`),有些使用绝对导入
|
||
|
||
**解决方案:**
|
||
1. 修改所有导入语句为兼容模式(try相对导入,except绝对导入)
|
||
2. 创建 `Algorithm/__init__.py` 和 `Env/__init__.py` 使其成为Python包
|
||
|
||
**修改的文件:**
|
||
- ✅ `Algorithm/ppo.py` - 添加try-except导入
|
||
- ✅ `Algorithm/policy.py` - 添加try-except导入
|
||
- ✅ `Algorithm/disc.py` - 添加try-except导入
|
||
- ✅ `Algorithm/magail.py` - 添加try-except导入
|
||
- ✅ `Algorithm/__init__.py` - 新建包初始化文件
|
||
- ✅ `Env/__init__.py` - 新建包初始化文件
|
||
|
||
---
|
||
|
||
### ❌ 问题2: `action_shape` 参数缺失
|
||
|
||
**错误信息:**
|
||
```python
|
||
TypeError: MAGAIL.__init__() got an unexpected keyword argument 'action_shape'
|
||
```
|
||
|
||
**原因:**
|
||
- `MAGAIL` 类的 `__init__()` 方法没有定义 `action_shape` 参数
|
||
- 但训练脚本传递了这个参数
|
||
|
||
**解决方案:**
|
||
在 `MAGAIL.__init__()` 中添加 `action_shape` 参数并传递给父类
|
||
|
||
**修改代码:**
|
||
```python
|
||
# 修改前
|
||
class MAGAIL(PPO):
|
||
def __init__(self, buffer_exp, input_dim, device, ...):
|
||
super().__init__(state_shape=input_dim, device=device)
|
||
|
||
# 修改后
|
||
class MAGAIL(PPO):
|
||
def __init__(self, buffer_exp, input_dim, device, action_shape=(2,), **kwargs):
|
||
super().__init__(state_shape=input_dim, device=device,
|
||
action_shape=action_shape, **kwargs)
|
||
```
|
||
|
||
---
|
||
|
||
### ❌ 问题3: 维度类型不匹配
|
||
|
||
**错误信息:**
|
||
```python
|
||
TypeError: empty(): argument 'size' must be tuple of ints,
|
||
but found element of type tuple at pos 2
|
||
```
|
||
|
||
**原因:**
|
||
- `input_dim` 传入时是元组 `(108,)`
|
||
- 但 `Bert` 的 `nn.Linear(input_dim, embed_dim)` 期望 `input_dim` 是整数
|
||
|
||
**根本原因:**
|
||
```python
|
||
# 训练脚本中
|
||
magail = MAGAIL(
|
||
input_dim=(108,), # 传入的是元组
|
||
...
|
||
)
|
||
|
||
# 在 PPO.__init__ 中
|
||
self.critic = Bert(
|
||
input_dim=state_shape, # state_shape = (108,) 仍是元组
|
||
output_dim=1
|
||
)
|
||
|
||
# 在 Bert.__init__ 中
|
||
self.projection = nn.Linear(input_dim, embed_dim) # 期望 input_dim=108
|
||
```
|
||
|
||
**解决方案:**
|
||
在使用 `state_shape` 或 `input_dim` 创建 `Bert` 时,提取整数值
|
||
|
||
**修改代码:**
|
||
|
||
1. **在 `Algorithm/ppo.py` 中:**
|
||
```python
|
||
# 修改前
|
||
self.critic = Bert(
|
||
input_dim=state_shape,
|
||
output_dim=1
|
||
).to(device)
|
||
|
||
# 修改后
|
||
state_dim = state_shape[0] if isinstance(state_shape, tuple) else state_shape
|
||
self.critic = Bert(
|
||
input_dim=state_dim,
|
||
output_dim=1
|
||
).to(device)
|
||
```
|
||
|
||
2. **在 `Algorithm/magail.py` 中:**
|
||
```python
|
||
# 修改前
|
||
self.disc = GAILDiscrim(input_dim=input_dim)
|
||
|
||
# 修改后
|
||
state_dim = input_dim[0] if isinstance(input_dim, tuple) else input_dim
|
||
self.disc = GAILDiscrim(input_dim=state_dim)
|
||
```
|
||
|
||
3. **在 `Algorithm/magail.py` 的Normalizer中:**
|
||
```python
|
||
# 修改前
|
||
self.normalizer = Normalizer(self.state_shape[0]*2)
|
||
|
||
# 修改后
|
||
state_dim = self.state_shape[0] if isinstance(self.state_shape, tuple) else self.state_shape
|
||
self.normalizer = Normalizer(state_dim*2)
|
||
```
|
||
|
||
---
|
||
|
||
## 所有修改总结
|
||
|
||
### 修改的文件列表
|
||
|
||
| 文件 | 修改内容 |
|
||
|------|----------|
|
||
| `Algorithm/ppo.py` | 1. 添加try-except导入<br>2. 添加action_shape参数<br>3. 修复state_shape元组问题 |
|
||
| `Algorithm/magail.py` | 1. 添加try-except导入<br>2. 添加action_shape参数<br>3. 修复input_dim元组问题 |
|
||
| `Algorithm/policy.py` | 添加try-except导入 |
|
||
| `Algorithm/disc.py` | 添加try-except导入 |
|
||
| `Algorithm/__init__.py` | 新建包初始化文件 |
|
||
| `Env/__init__.py` | 新建包初始化文件 |
|
||
|
||
### 新增的文件
|
||
|
||
| 文件 | 用途 |
|
||
|------|------|
|
||
| `train_magail.py` | 完整的MAGAIL训练脚本 |
|
||
| `MAGAIL算法应用指南.md` | 详细的使用文档 |
|
||
| `快速测试.sh` | 快速测试脚本 |
|
||
| `问题解决记录.md` | 本文件 |
|
||
|
||
---
|
||
|
||
## 如何运行
|
||
|
||
### 方法1: 直接运行(推荐)
|
||
|
||
```bash
|
||
# 确保在conda环境中
|
||
conda activate metadrive
|
||
|
||
# 运行训练(少量episode测试)
|
||
python train_magail.py --episodes 5 --horizon 100
|
||
|
||
# 带可视化
|
||
python train_magail.py --episodes 5 --render
|
||
|
||
# 完整训练
|
||
python train_magail.py --episodes 1000 --horizon 300
|
||
```
|
||
|
||
### 方法2: 使用测试脚本
|
||
|
||
```bash
|
||
conda activate metadrive
|
||
bash 快速测试.sh
|
||
```
|
||
|
||
### 方法3: 查看帮助
|
||
|
||
```bash
|
||
python train_magail.py --help
|
||
```
|
||
|
||
---
|
||
|
||
## 验证是否修复成功
|
||
|
||
运行以下命令测试:
|
||
|
||
```bash
|
||
# 测试1: 验证导入
|
||
python -c "from Algorithm.magail import MAGAIL; print('✅ 导入成功!')"
|
||
|
||
# 测试2: 验证初始化
|
||
python -c "
|
||
from Algorithm.magail import MAGAIL
|
||
import torch
|
||
|
||
class DummyBuffer:
|
||
def __init__(self, device):
|
||
self.device = device
|
||
def sample(self, batch_size):
|
||
return torch.randn(batch_size, 108, device=self.device), \
|
||
torch.randn(batch_size, 108, device=self.device)
|
||
|
||
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
||
buffer = DummyBuffer(device)
|
||
magail = MAGAIL(
|
||
buffer_exp=buffer,
|
||
input_dim=(108,),
|
||
device=device,
|
||
action_shape=(2,)
|
||
)
|
||
print('✅ MAGAIL初始化成功!')
|
||
"
|
||
|
||
# 测试3: 运行1个episode
|
||
python train_magail.py --episodes 1 --horizon 50
|
||
```
|
||
|
||
---
|
||
|
||
### ❌ 问题4: 保存模型时目录不存在
|
||
|
||
**错误信息:**
|
||
```python
|
||
FileNotFoundError: [Errno 2] 没有那个文件或目录: './outputs/magail_xxx/models/best_model/model.pth'
|
||
```
|
||
|
||
**原因:**
|
||
- `save_models()` 方法直接保存文件,但没有创建目录
|
||
|
||
**解决方案:**
|
||
在保存前使用 `os.makedirs(path, exist_ok=True)` 创建目录
|
||
|
||
**修改代码:**
|
||
```python
|
||
# 修改前
|
||
def save_models(self, path):
|
||
torch.save({...}, os.path.join(path, 'model.pth'))
|
||
|
||
# 修改后
|
||
def save_models(self, path):
|
||
os.makedirs(path, exist_ok=True) # 确保目录存在
|
||
torch.save({...}, os.path.join(path, 'model.pth'))
|
||
```
|
||
|
||
---
|
||
|
||
## 剩余的已知问题
|
||
|
||
### 1. 专家数据加载未实现
|
||
|
||
**现象:**
|
||
```
|
||
⚠️ 警告: 未找到专家数据
|
||
```
|
||
|
||
**原因:**
|
||
`ExpertBuffer._extract_trajectories()` 方法是空的,需要根据实际Waymo数据格式实现
|
||
|
||
**TODO:**
|
||
- 分析Waymo pkl文件的实际结构
|
||
- 实现轨迹提取逻辑
|
||
|
||
### 2. 多智能体buffer存储
|
||
|
||
**现象:**
|
||
当前buffer是为单智能体设计的
|
||
|
||
**TODO:**
|
||
- 实现多智能体经验存储逻辑
|
||
- 或者修改为将所有智能体作为一个batch处理
|
||
|
||
### 3. 环境奖励为0
|
||
|
||
**现象:**
|
||
环境返回的奖励全是0
|
||
|
||
**TODO:**
|
||
- 设计合理的任务奖励函数
|
||
- 或者完全依赖GAIL的内在奖励
|
||
|
||
---
|
||
|
||
## 下一步计划
|
||
|
||
1. ✅ **已完成**: 修复导入问题
|
||
2. ✅ **已完成**: 修复参数问题
|
||
3. ✅ **已完成**: 修复维度问题
|
||
4. ✅ **已完成**: 修复保存模型目录问题
|
||
5. ✅ **已完成**: 测试完整训练流程 - **训练脚本可以正常运行!**
|
||
5. 📝 **待办**: 实现专家数据加载
|
||
6. 📝 **待办**: 完善多智能体buffer
|
||
7. 📝 **待办**: 设计奖励函数
|
||
8. 📝 **待办**: 超参数调优
|
||
|
||
---
|
||
|
||
## 参考文档
|
||
|
||
- `技术说明文档.md` - 完整的技术实现细节
|
||
- `MAGAIL算法应用指南.md` - 使用指南和示例
|
||
- `README.md` - 项目概述
|
||
|
||
---
|
||
|
||
**最后更新**: 2024
|
||
**状态**: ✅ 主要问题已解决,可以开始训练
|
||
|