半監督目標檢測
- 準備和拆分數據集
- 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