半监督目标检测
- 准备和拆分数据集
- K则交叉验证的解释
- 完整的半监督配置文件代码
- 修改继承的数据流文件代码
- 多GPU训练示范
参考 MMDetection半监督目标检测,半监督目标检测同时利用标签数据和无标签数据进行训练,一方面可以减少模型对检测框数量的依赖,另一方面也可以利用大量的未标记数据进一步提高模型。
准备和拆分数据集
我们提供了数据集下载脚本,默认下载 coco2017 数据集,并且自动解压。
python tools/misc/download_dataset.py
在该代码这一块修改半监督数据集具体生成路径和k则交叉验证默认参数
def parse_args():parser = argparse.ArgumentParser()parser.add_argument('--data-root',type=str,help='The data root of coco dataset.',default='/data/miqi/coco/')parser.add_argument('--out-dir',type=str,help='The output directory of coco semi-supervised annotations.',default='/data/miqi/coco/semi_anns/')parser.add_argument('--labeled-percent',type=float,nargs='+',help='The percentage of labeled data in the training set.',default=[1, 2, 5, 10])parser.add_argument('--fold',type=int,help='K-fold cross validation for semi-supervised object detection.',default=5)args = parser.parse_args()return args
解压后的数据集目录如下:
mmdetection
├── data
│ ├── coco
│ │ ├── annotations
│ │ │ ├── image_info_unlabeled2017.json
│ │ │ ├── instances_train2017.json
│ │ │ ├── instances_val2017.json
│ │ ├── test2017
│ │ ├── train2017
│ │ ├── unlabeled2017
│ │ ├── val2017
半监督目标检测在 coco 数据集上有两种比较通用的实验设置:
(1)将 train2017
按照固定百分比(1%,2%,5% 和 10%)划分出一部分数据作为标签数据集,剩余的训练集数据作为无标签数据集,同时考虑划分不同的训练集数据作为标签数据集对半监督训练的结果影响较大,所以采用五折交叉验证来评估算法性能。我们提供了数据集划分脚本:
python tools/misc/split_coco.py
倘若不是指定的coco2017数据集,需要检查annotations
的.json
文件字段是否含有'info'
,'licenses'
等。
def save_anns(name, images, annotations):sub_anns = dict()sub_anns['images'] = imagessub_anns['annotations'] = annotationssub_anns['licenses'] = anns['licenses']sub_anns['categories'] = anns['categories']# sub_anns['info'] = anns['info'] # 没有就注释掉mkdir_or_exist(out_dir)dump(sub_anns, f'{out_dir}/{name}.json')
该脚本默认会按照 1%,2%,5% 和 10% 的标签数据占比划分 train2017
,每一种划分会随机重复 5 次,用于交叉验证。生成的半监督标注文件名称格式如下:
- 标签数据集标注名称格式:
instances_train2017.{fold}@{percent}.json
- 无标签数据集名称标注:
instances_train2017.{fold}@{percent}-unlabeled.json
其中,fold
用于交叉验证,percent
表示标签数据的占比。 划分后的数据集目录结构如下:
mmdetection
├── data
│ ├── coco
│ │ ├── annotations
│ │ │ ├── image_info_unlabeled2017.json
│ │ │ ├── instances_train2017.json
│ │ │ ├── instances_val2017.json
│ │ ├── semi_anns
│ │ │ ├── instances_train2017.1@1.json
│ │ │ ├── instances_train2017.1@1-unlabeled.json
│ │ │ ├── instances_train2017.1@2.json
│ │ │ ├── instances_train2017.1@2-unlabeled.json
│ │ │ ├── instances_train2017.1@5.json
│ │ │ ├── instances_train2017.1@5-unlabeled.json
│ │ │ ├── instances_train2017.1@10.json
│ │ │ ├── instances_train2017.1@10-unlabeled.json
│ │ │ ├── instances_train2017.2@1.json
│ │ │ ├── instances_train2017.2@1-unlabeled.json
│ │ ├── test2017
│ │ ├── train2017
│ │ ├── unlabeled2017
│ │ ├── val2017
K则交叉验证的解释
在半监督学习的目标检测任务中,COCO数据集通过特定的划分方法被分为有标签数据集和无标签数据集,以供模型训练使用。这种划分是为了评估不同量级的有标签数据对模型性能的影响,以及验证模型在有限标注数据下的泛化能力。以下是详细的解释:
-
数据集划分:
- 有标签数据集:从原始的train2017数据集中,按照1%,2%,5%,和10%的比例选取部分样本作为有标签数据集。这些数据带有完整的标注信息,包括物体类别、边界框等,用于直接训练模型。
- 无标签数据集:剩下的train2017数据则构成无标签数据集。这部分数据虽然没有标注信息,但在半监督学习场景下,可以用来提升模型的性能,例如通过自训练、一致性正则化等策略。
-
交叉验证:
- 由于数据集划分的不同可能会影响最终模型的性能,为了减少偏差并提高评估的可靠性,采用了五折交叉验证的方法。这意味着原始数据会被分成五个不同的子集,每个子集轮流作为验证集,其余四份作为训练集的一部分,这样可以得到更稳定的性能估计。
-
数据集文件命名与存储:
- 命名格式:有标签数据集和无标签数据集的标注文件遵循特定的命名规则。例如,
instances_train2017.{fold}@{percent}.json
表示第{fold}折的有标签数据集,占总数据的{percent}%。而instances_train2017.{fold}@{percent}-unlabeled.json
则是对应的无标签数据集。 - 目录结构:数据集被组织在
mmdetection/data/coco/semi_anns
目录下,这里存放了所有不同比例、不同折数的有标签和无标签数据集的标注文件。
- 命名格式:有标签数据集和无标签数据集的标注文件遵循特定的命名规则。例如,
-
数据集划分脚本:
- 提供的
split_coco.py
脚本用于自动化地完成上述数据集划分过程。通过运行此脚本,可以自动按照设定的比例生成所需的有标签和无标签数据集,以及对应的标注文件。
- 提供的
通过这样的数据集划分和组织方式,研究者能够系统地探索不同规模的标注数据对模型性能的影响,以及评估半监督学习方法的有效性。
(2)将 train2017
作为标签数据集,unlabeled2017
作为无标签数据集。由于 image_info_unlabeled2017.json
没有 categories
信息,无法初始化 CocoDataset
,所以需要将 instances_train2017.json
的 categories
写入 image_info_unlabeled2017.json
,另存为 instances_unlabeled2017.json
,相关脚本如下:
from mmengine.fileio import load, dumpanns_train = load('/data/miqi/coco/annotations/instances_train2017.json')
anns_unlabeled = load('/data/miqi/coco/annotations/image_info_unlabeled2017.json')
anns_unlabeled['categories'] = anns_train['categories']
dump(anns_unlabeled, '/data/miqi/coco/annotations/instances_unlabeled2017.json')
完整的半监督配置文件代码
新建配置文件mmdetection/configs/_base_/models/semi-supervised/faster-rcnn_r50_fpn_semi.py
_base_ = ['/home/miqi/mmdetection/configs/_base_/models/faster-rcnn_r50_fpn.py', '/home/miqi/mmdetection/configs/_base_/default_runtime.py','/home/miqi/mmdetection/configs/_base_/schedules/schedule_1x.py', '/home/miqi/mmdetection/configs/_base_/datasets/semi_coco_detection.py'
]detector = _base_.model
detector.data_preprocessor = dict(type='DetDataPreprocessor',mean=[103.530, 116.280, 123.675],std=[1.0, 1.0, 1.0],bgr_to_rgb=False,pad_size_divisor=32)
detector.backbone = dict(type='ResNet',depth=50,num_stages=4,out_indices=(0, 1, 2, 3),frozen_stages=1,norm_cfg=dict(type='BN', requires_grad=False),norm_eval=True,style='caffe',init_cfg=dict(type='Pretrained',checkpoint='open-mmlab://detectron2/resnet50_caffe'))model = dict(_delete_=True,type='SoftTeacher',detector=detector,data_preprocessor=dict(type='MultiBranchDataPreprocessor',data_preprocessor=detector.data_preprocessor),semi_train_cfg=dict(freeze_teacher=True,sup_weight=1.0,unsup_weight=4.0,pseudo_label_initial_score_thr=0.5,rpn_pseudo_thr=0.9,cls_pseudo_thr=0.9,reg_pseudo_thr=0.02,jitter_times=10,jitter_scale=0.06,min_pseudo_bbox_wh=(1e-2, 1e-2)),semi_test_cfg=dict(predict_on='teacher'))custom_hooks = [dict(type='MeanTeacherHook')]
val_cfg = dict(type='TeacherStudentValLoop')load_from = 'checkpoints/faster_rcnn_r50_fpn_mstrain_3x_coco_20210524_110822-e10bd31c.pth'
修改继承的数据流文件代码
文件位于mmdetection/configs/_base_/datasets/semi_coco_detection.py
# dataset settings
dataset_type = 'CocoDataset'
data_root = '/data/miqi/coco/' # 自己的数据集根路径
batch_size = 5 # GPU空闲内存相关
num_workers = 5 # CPU数据加载子进程数量相关
在PyTorch的数据加载器(DataLoader
)配置中,num_workers
参数用于指定在数据加载过程中使用的子线程或进程的数量。这个参数对于优化数据加载速度和并行处理能力至关重要。
当num_workers
设置为大于0的值时,PyTorch会使用多个工作进程来预加载和处理数据,这可以显著提高数据加载的速度,特别是在数据处理较为复杂或者数据集较大的情况下。每个工作进程都会独立地从磁盘读取数据、应用数据转换,并将数据发送到主进程中供模型训练使用。
例如,如果你的计算机有足够多的CPU核心,你可以将num_workers
设为一个较大的值,比如4或8,这样可以充分利用多核处理器的优势,加快数据加载速度。但需要注意的是,过多的工作进程可能会消耗大量系统资源,导致其他操作变慢,因此需要根据你的硬件配置合理设置这个参数。
多GPU训练示范
CUDA_VISIBLE_DEVICES=0, 4, 5, 9 ./tools/dist_train.sh \configs/_base_/models/semi-supervised/faster-rcnn_r50_fpn_semi.py \4 \--work-dir work_dirs/faster-rcnn_r50_fpn_semi