5.5 KiB
5.5 KiB
Task-specific GCA - Checkpoint部分加载策略
🎯 加载策略说明
问题
epoch_5.pth (旧checkpoint):
✅ encoders.camera
✅ encoders.lidar
✅ fuser
✅ decoder.backbone
✅ decoder.neck
✅ heads.object
✅ heads.map
❌ task_gca (不存在)
新模型 (Task-specific GCA):
✅ encoders.camera
✅ encoders.lidar
✅ fuser
✅ decoder.backbone
✅ decoder.neck
✅ heads.object
✅ heads.map
✨ task_gca['object'] (新增)
✨ task_gca['map'] (新增)
解决方案: 部分加载 ✅
📊 两种加载方式对比
方式1: --resume-from (严格加载)
--resume-from epoch_5.pth
行为:
- ✅ 加载模型权重
- ✅ 加载optimizer状态
- ✅ 加载学习率调度器
- ✅ 恢复epoch和iteration
- ❌ 严格匹配:所有键必须完全一致
- ❌ 问题:checkpoint中没有task_gca,会报错或警告
结果: ❌ 不适用(模型结构已改变)
方式2: --load_from (部分加载) ✅ 推荐
--load_from epoch_5.pth
行为:
- ✅ 只加载模型权重
- ✅ 忽略不匹配的键
- ✅ checkpoint有但新模型没有的键:忽略
- ✅ 新模型有但checkpoint没有的键:随机初始化
- ⚪ 不加载optimizer(重新初始化)
- ⚪ 不加载epoch(从配置文件中的起始epoch开始)
结果: ✅ 适用于模型结构改变的情况
🔄 具体加载过程
Step 1: 加载已有权重
从epoch_5.pth加载:
✅ encoders.camera.backbone.* (Swin Transformer,~88M参数)
✅ encoders.camera.neck.* (FPN,~3M参数)
✅ encoders.camera.vtransform.* (LSSTransform,~2M参数)
✅ encoders.lidar.voxelize.* (Voxelization)
✅ encoders.lidar.backbone.* (Sparse Encoder,~8M参数)
✅ fuser.* (ConvFuser,~0.2M参数)
✅ decoder.backbone.* (SECOND,~5M参数)
✅ decoder.neck.* (SECONDFPN,~3M参数)
✅ heads.object.* (TransFusion,~15M参数)
✅ heads.map.* (EnhancedBEVSeg,~8M参数)
总计: ~132M参数从checkpoint加载
Step 2: 随机初始化新模块
新增模块(checkpoint中不存在):
✨ task_gca.object.avg_pool (AdaptiveAvgPool2d)
✨ task_gca.object.fc.0 (Conv2d: 512→128)
✨ task_gca.object.fc.2 (Conv2d: 128→512)
✨ task_gca.map.avg_pool (AdaptiveAvgPool2d)
✨ task_gca.map.fc.0 (Conv2d: 512→128)
✨ task_gca.map.fc.2 (Conv2d: 128→512)
总计: ~0.26M参数随机初始化
📝 日志验证
启动后应该看到
Loading checkpoint from /workspace/bevfusion/runs/run-326653dc-2334d461/epoch_5.pth
The following keys in checkpoint are not matched with model:
(可能会列出一些不需要的键,可以忽略)
The following keys in model are not found in checkpoint:
task_gca.object.fc.0.weight
task_gca.object.fc.2.weight
task_gca.map.fc.0.weight
task_gca.map.fc.2.weight
... (task_gca相关的所有参数)
✅ 这是正常的!这些参数会被随机初始化。
🎯 训练策略
Epoch和学习率
配置文件设置:
max_epochs: 20
加载checkpoint:
--load_from epoch_5.pth
实际行为:
✅ 从epoch 0开始(配置中的默认值)
✅ 学习率从初始值开始
✅ Optimizer重新初始化
如果想从epoch 6继续:
在配置中设置: start_epoch: 6
或命令行: --cfg-options runner.start_epoch=6
建议策略
方案A: 从epoch 0重新开始 (保守,推荐用于新架构) ✅
- 让task_gca模块充分学习
- 整个模型重新适应新架构
- max_epochs: 20 (epoch 0-19)
方案B: 从epoch 6继续 (激进)
- 节省已训练的5个epoch
- max_epochs: 20 (epoch 6-19,共14 epochs)
- 需要验证task_gca初始化是否影响训练稳定性
当前使用: 方案A (从epoch 0开始) ✅
🔍 权重匹配检查
成功加载的标志
# 检查日志中的权重加载信息
grep "load checkpoint" /data/runs/phase4a_stage1_task_gca/*.log
# 应该看到:
load checkpoint from local path: /workspace/bevfusion/runs/.../epoch_5.pth
验证task_gca是否正确初始化
# 检查模型初始化日志
grep "Task-specific GCA" /data/runs/phase4a_stage1_task_gca/*.log
# 应该看到:
[BEVFusion] ✨✨ Task-specific GCA mode enabled ✨✨
[object] GCA: params: 131,072
[map] GCA: params: 131,072
📊 参数统计
总参数: ~132.26M
从checkpoint加载: ~132.00M (99.8%)
├─ Encoders: ~93M
├─ Fuser: ~0.2M
├─ Decoder: ~8M
├─ Detection Head: ~15M
└─ Segmentation Head: ~8M
随机初始化: ~0.26M (0.2%)
├─ task_gca['object']: ~0.13M
└─ task_gca['map']: ~0.13M
✅ 优势
1. ✅ 最大化利用已训练权重
- 骨干、neck、heads都保留训练成果
- 只有262K参数需要重新学习
2. ✅ 避免加载冲突
- 不会因为结构不匹配报错
- 灵活处理新增模块
3. ✅ 训练稳定性
- 大部分参数已经收敛
- 只需微调task_gca模块
4. ✅ 快速收敛
- 预期3-5 epochs内task_gca收敛
- 整体性能提升明显
🚀 启动命令
# 在Docker容器内
cd /workspace/bevfusion
bash START_PHASE4A_TASK_GCA.sh
# 脚本会自动使用 --load_from 策略
🎯 部分加载策略完美解决了模型结构改变的问题!