Nuscenes数据集只下载了1/10?手把手教你修改代码适配子集训练(附避坑指南)

张开发
2026/4/10 3:58:27 15 分钟阅读

分享文章

Nuscenes数据集只下载了1/10?手把手教你修改代码适配子集训练(附避坑指南)
Nuscenes数据集子集训练实战从数据加载到评估的全流程适配指南当你兴冲冲地下载了Nuscenes的mini版或部分子集准备开始3D目标检测实验时是否遇到过这样的场景代码明明指向了子集路径控制台却显示加载了完整数据集的所有scene数量训练时一切正常但评估阶段突然抛出Samples in split doesnt match samples in predictions的致命错误这就像准备做一道小份试吃装料理厨房却给你送来了满汉全席的食材——不仅浪费资源更会打乱整个实验节奏。1. 理解Nuscenes数据集的结构特点Nuscenes作为自动驾驶领域标杆级的3D感知数据集其结构设计比传统2D数据集复杂得多。官方提供的v1.0-trainval版本包含850个场景scene34,149个样本sample263万个传感器数据sample_data关键层级关系场景(scene) └─ 首样本(first_sample_token) └─ 多模态传感器数据(LIDAR_TOP, CAM_FRONT等) └─ 标注信息(sample_annotation)当使用子集时常见陷阱是代码仍然尝试加载完整数据集的索引结构。比如即使你只下载了part6约1/10数据运行官方转换脚本时仍会看到Loading NuScenes tables for version v1.0-trainval... total scene num: 850 # 这里显示的是完整数据集的场景数 exist scene num: 85 # 这才是实际下载的子集场景数2. 数据加载层的深度改造2.1 动态检测可用场景首先需要建立真实数据存在性检查机制。以下代码可以准确识别实际下载的场景from nuscenes.nuscenes import NuScenes import os nusc NuScenes(versionv1.0-mini, dataroot./data/nuscenes, verboseTrue) available_scenes [] for scene in nusc.scene: sample_token scene[first_sample_token] lidar_token nusc.get(sample, sample_token)[data][LIDAR_TOP] lidar_path nusc.get(sample_data, lidar_token)[filename] if os.path.exists(os.path.join(nusc.dataroot, lidar_path)): available_scenes.append(scene[token]) print(f实际可用场景数: {len(available_scenes)})2.2 修改数据转换脚本在mmdetection3d等框架中关键修改点在nuscenes_converter.py的get_available_scenes函数def get_available_scenes(nusc): # 原始代码直接返回所有scene # return [s[name] for s in nusc.scene] # 修改为只返回有实际数据的scene available_scenes [] for scene in nusc.scene: sample_token scene[first_sample_token] lidar_path nusc.get_sample_data_path(sample_token, LIDAR_TOP) if os.path.exists(lidar_path): available_scenes.append(scene[name]) return available_scenes对应的_fill_trainval_infos函数也需要调整样本过滤逻辑for sample in mmcv.track_iter_progress(nusc.sample): # 增加样本存在性检查 lidar_token sample[data][LIDAR_TOP] lidar_path nusc.get_sample_data_path(lidar_token) if not os.path.exists(lidar_path): continue # 后续处理逻辑...3. 训练评估环节的精准适配3.1 数据分片策略调整Nuscenes官方将完整数据集分为10个part每个part的样本范围如下Part编号起始样本索引结束样本索引样本数量part1033753376part2337667423367............part1030729341483420当使用part6子集时需要在数据加载器中添加范围限制# 在build_dataloader时添加样本过滤 def filter_samples(samples): return samples[16975:20418] # part6的范围3.2 评估模块的深度修改评估报错Samples in split doesnt match的根源在于GT加载逻辑。需要修改loaders.py中的核心函数# 原始代码加载全部样本 # sample_tokens [s[token] for s in nusc.sample] # 修改为只加载子集样本 sample_tokens [nusc.sample[i][token] for i in range(16975, 20418)]对于评估速度优化可以重写NuScenesEval类的evaluate方法def evaluate(self): # 只处理子集对应的sample_tokens subset_tokens self.get_subset_tokens() self.pred_boxes filter_boxes(self.pred_boxes, subset_tokens) self.gt_boxes filter_boxes(self.gt_boxes, subset_tokens) # 后续评估逻辑...4. 工程实践中的性能优化技巧4.1 内存占用控制使用子集训练时可以通过以下配置降低内存消耗# configs/_base_/datasets/nuscenes-3d.py data dict( samples_per_gpu2, # 减少batch_size workers_per_gpu2, # 减少数据加载线程 traindict( datasetdict( load_interval5 # 间隔采样 ) ) )4.2 分布式训练适配当在多卡环境下使用子集时需要特别注意数据分片均衡# 修改distributed sampler if is_subset: self.num_samples int(math.ceil(len(self.dataset) * 1.0 / self.total_replicas)) self.total_size self.num_samples * self.total_replicas4.3 实验管理建议建立子集训练的标准化命名规范exp_subset_{part_num}_{model}_lr{lr}_bs{bs} 例如exp_subset_part6_centerpoint_lr0.001_bs4在代码库中维护子集配置的独立分支避免与完整数据集训练的配置混淆。

更多文章