mmdet train

Published by onesixx on

W&B (Weight and Biases)

DataSet

Data 수집

기존 데이터셋 : 다운로드

신규 데이터셋 : 구성

1. Image 수집

  • 직접수집
  • 동영상에서 이미지 추출 (ffmpeg 사용)
    ffmpeg -i example.mp4 -vf fps=Afolder/ex_detect_%4d.jpg
  • google에서 수집
  • Unity를 통해 가상데이터 생성

2. Annotation (CVAT 사용)

  • Bbox
  • Polygon : segmentation
  • Key-point (top-down, down-top)

3. 데이터셋 만들기 (Image와 Annotation을 연결)

  • CoCo 데이터셋 포멧으로 CVAT에서 Export
    (keypoint에 경우, coco형식으로 export가 되지 않아, CVAT(xml)포멧으로 내보내기 한후, datumaru를 통해 coco 데이터셋으로 변환
  • Custom 데이터셋
    mmdetection에서 custom dataset 등록후 사용

DataSet 구성 (train / valid & test)

train / valid & test 데이터셋 준비 : 이미지는 그대로 두고, 각 DataSet별로 Annotation파일 분리하여 준비
(coco데이터셋은 새로 annotation후 채번을 다시 해야함)

Config에서, 소스의 trn, val, tst 의 디렉토리 구조 결정

커스텀 데이터셋의 경우

MyCustomDataset을 등록 (load_annotations 잘 수정해서)

dataset 생성

  • datasets = [build_dataset(cfg.data.train)] # /tools/train.py에서

cocoset으로 변환

웬만하면 Coco로 변환

Model

모델 선정

open-mmlab/mmdetection 의 model-zoo

Model-zoo 에서

ex) faster_rcrnn

https://comlini8-8.tistory.com/86

MMDet 모델을 5가지 요소로 구분

Backbone피처맵을 추출하기 위한 FCN 네트워크(ex. ResNet, MobileNet)
neckbackbone과 head 사이를 연결하는 요소(ex. FPN, PAFPN)
head구체적인 태스크를 위한 요소(ex. bbox prediction, mask prediction)
roi extractor피처맵으로부터 RoI 특징을 추출하는 부분(ex. RoI Align)
lossloss를 계산하기 위한 head의 구성 요소(ex. FocalLoss, L1Loss, GHMLoss)


checkpoints 파일 준비

mmdet 에서 ConvNeXt (CVPR’2022).

Model Zoo에서 pretrained Model의 네트웍을 받아옴.

w g e t -O checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth  http://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth

configuration – Config

기존 Config 가져오기

sixxconfigs/makeConfig.py 를 통해 초기 Config 생성

import os 
from mmcv import Config

os.chdir('/home/oschung_skcc/my/git/mmdetection')

config_file = 'configs/convnext/cascade_mask_rcnn_convnext-s_p4_w7_fpn_giou_4conv1f_fp16_ms-crop_3x_coco.py'
out_config =  'sixxconfigs/cascade_mask_rcnn_convnext-s_p4_w7_fpn_giou_4conv1f_fp16_ms-crop_3x_coco_sixx.py'

cfg = Config.fromfile(config_file)
#print(cfg.pretty_text)

try:
    with open(out_config, 'w') as f:
        f.write(cfg.pretty_text)
except FileNotFoundError:
    print("The 'docs' directory does not exist")
import argparse
import logging
import os 

from mmcv import Config

parser = argparse.ArgumentParser(description="")
parser.add_argument("-i", "--fromconfig",  default='', type=str, metavar="PATH", help="path from getting config")
parser.add_argument("-o", "--toconfig",    default='', type=str, metavar="PATH", help="path to getting config")

def print_info(message: str):
    logging.info(message)

def main():
    print_info("Starting...")
    args = parser.parse_args()

    if not args.fromconfig  :
        print("Warning!", "Nothing to set.\
Please specify a path!")
        print_info("Exiting...")
        return
    else:
        config_file =  args.fromconfig
        
    if not args.toconfig:
        out_config = 'sixxconfigs/'+  os.path.basename(args.fromconfig)
        print(args.toconfig)
    else:
        out_config  =  args.toconfig

    os.chdir('/home/oschung_skcc/my/git/mmdetection')
    # config_file = 'configs/convnext/cascade_mask_rcnn_convnext-s_p4_w7_fpn_giou_4conv1f_fp16_ms-crop_3x_coco.py'
    # out_config =  'sixxconfigs/cascade_mask_rcnn_convnext-s_p4_w7_fpn_giou_4conv1f_fp16_ms-crop_3x_coco_sixx.py'

    cfg = Config.fromfile(config_file)
    #print(cfg.pretty_text)

    try:
        with open(out_config, 'w') as f:
            f.write(cfg.pretty_text)
    except FileNotFoundError:
        print("The 'docs' directory does not exist")
    
    print_info("... End")

if __name__ == "__main__":
    main()

쉬운 수정을 위해 풀어진 config 만들기

$ python sixxtools/makeConfig_sixx.py \\
--fromconfig configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py \\
--toconfig sixxconfigs/faster_rcnn_r50_fpn_1x_coco_001.py
$ python sixxtools/misc/print_config.py \\
configs/convnext/cascade_mask_rcnn_convnext-s_p4_w7_fpn_giou_4conv1f_fp16_ms-crop_3x_coco.py

config 대분류 및 주요설정내역

config
대분류
설명
dataset dataset의 type(customdataset, cocodataset 등),
train/val/test dataset 유형,
data_root,
train/val/test dataset의 주요 파라미터 설정(type, ann_file, img_prefix, pipeline 등)
modelobject detection model의 backbone, neck, dense head, roi extractor, roi head(num_classes=4)
주요 영역별로 세부 설정
scheduler optimizer 유형 설정 (sgd, adam, rmsprop 등),
최초 learning 설정
학습중 동적 learning rate 적용 정책 설정(step, cyclic, cosine annealing 등)
train 시 epochs 횟수 : learning rate scheduler
runtime주로 hook(callback)관련 설정
학습 중 checkpoint 파일,
log 파일 생성을 위한 interval epochs 수

config 수정

기존 config가져와서, training에 사용할 config 파일생성
sixxconfigs/faster_rcnn_r50_fpn_1x_coco_sixx.py 그리고 수정

  • num_classes=4, 수정(model아래)
  • dataset_type = ‘CocoDataset’ 확인
  • data_root = ‘data/msc_pilot2/’ 수정
  • classes = [‘TRAY_A_1’, ‘TRAY_A_2’, ‘TRAY_A_3’, ‘TRAY_B_1’] 추가

gpu

  • samples_per_gpu
  • workers_per_gpu

data

  • train / val / test
    – ann_file 수정
    – classes 추가

config 수정 예

model = dict(
    roi_head=dict(
        bbox_head=dict(
            num_classes=4,

dataset_type = 'CocoDataset'
#data_root = 'data/coco/'
data_root = 'data/msc_pilot2/'   
classes=('Car', 'Truck', 'Pedestrian', 'Cyclist')

data = dict(
    train=dict(
        type='CocoDataset',
        ann_file='data/kitti_tiny/anno_cc.json', 
        #img_prefix='data/kitti_tiny/training/image_2', 
        classes=classes,

    val=dict(
        type='CocoDataset',
        ann_file='data/kitti_tiny/anno_cc_val.json',
        #img_prefix='data/kitti_tiny/training/image_2',
        classes=classes,

    test=dict(
        type='CocoDataset',
        ann_file='data/kitti_tiny/anno_cc_val.json',
        #img_prefix='data/kitti_tiny/training/image_2',
        classes=classes,
)

W&B설정 예

https://onesixx.com/wandb/

#log_config = dict(interval=1, hooks=[dict(type='TextLoggerHook')])

log_config = dict(
    interval=10, #500
    hooks=[
        dict(type='TextLoggerHook',  interval=500),  
        dict(type='WandbLoggerHook', interval=1000,
            init_kwargs=dict(
                project='faster_rcnn_r50_fpn_1x',
                #entity = 'ENTITY 이름',
                name='sixx_tray')
        )
    ]
)

# workflow = [('train', 1)]
# 1 epoch에 train과 validation을 모두 하고 싶으면 
workflow = [('train', 1), ('val', 1)]

transfer learning

load_from = 'checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
# 200epoch 학습하는 동안 50번 마다 pth파일 만들고, 100번마다 로그 찍음
# 평가는 200번 돌고 함. 
evaluation = dict(interval=200, metric='mIoU') #'mAP')
runner = dict(type='EpochBasedRunner', max_epochs=400)
checkpoint_config = dict(interval=50)
log_config = dict(interval=100, hooks=[dict(type='TextLoggerHook')])



# 학습율 변경 환경 파라미터 설정. 
optimizer = dict(type='SGD', lr=0.02/8, momentum=0.9, weight_decay=0.0001)
lr_config = dict(
    policy='step',
    warmup=None,
    warmup_iters=500,
    warmup_ratio=0.001,
    step=[8, 11])


# 가장 최근꺼 부터 이어서 학습
resume_from = 'work_dirs/sixx_faster_rcnn_r50_fpn_1x_coco/latest.pth'

예시2>

model = dict(
    roi_head=dict(
        bbox_head=dict(
            num_classes=4,
\t\t\t\t  dict(
            num_classes=4,
\t\t\t      dict(
            num_classes=4,
            ...
    mask_head=dict(
            num_classes=4,    
        
    
dataset_type = 'CocoDataset'
data_root = 'data/kitti_tiny/'
classes=('Car', 'Truck', 'Pedestrian', 'Cyclist'),
        
data = dict(
    
    samples_per_gpu=4,
    workers_per_gpu=4,
    
    train=dict(
        type='CocoDataset',
        ann_file='data/kitti_tiny/anno_cc.json', 
        img_prefix='data/kitti_tiny/training/image_2', 
        classes=classes,

    val=dict(
        type='CocoDataset',
        ann_file='data/kitti_tiny/anno_cc_val.json',
        img_prefix='data/kitti_tiny/training/image_2',
        classes=classes,

    test=dict(
        type='CocoDataset',
        ann_file='data/kitti_tiny/anno_cc_val.json',
        img_prefix='data/kitti_tiny/training/image_2',
        classes=classes,
)
        
evaluation = dict(metric=['bbox', 'segm'], save_best='auto', interval=50)
runner = dict(type='EpochBasedRunner',     max_epochs=10000)
checkpoint_config = dict(interval=500)        

        
# workflow = [('train', 1)]
# 1 epoch에 train과 validation을 모두 하고 싶으면 
workflow = [('train', 1), ('val', 1)]

#load_from = 'checkpoints/cascade_mask_rcnn_convnext-s_p4_w7_fpn_giou_4conv1f_fp16_ms-crop_3x_coco_20220510_201004-3d24f5a4.pth'
load_from = 'https://download.openmmlab.com/mmclassification/v0/convnext/downstream/convnext-small_3rdparty_32xb128-noema_in1k_20220301-303e75e3.pth'

runner 의 max_epochs 가 원하는 epoch 46

Batch_size

step 1473/ 46 약 32 …= iteration..

평가 (evaluation, 50번에 한번)

checkpoint 1번에 한번

log_config 1번

CUDA_VISIBLE_DEVICES=2,3 port=29506 sixxtools/dist_train.sh "sixxconfigs/cascade_mask_rcnn_convnext-s_p4_w7_fpn_giou_4conv1f_fp16_ms-crop_3x_coco_sixx.py" 2
       
work_dir = './work_dirs/cascade_mask_rcnn_convnext-s_p4_w7_fpn_giou_4conv1f_fp16_ms-crop_3x_coco_sixx'
auto_resume = False
gpu_ids = range(0, 2)

model

  • num_class

dataset_type

data_root

classes

data

  • samples_per_gpu
  • workers_per_gpu
  • train / val / test
    – ann_file
    – classes

load_from


evaluation

  • save_best=’auto’, interval=50

checkpoint_config


optimizer의 lr 줄임

lr_config = dict(
    policy='step',      # 어떤 scheduler 를 쓸건지
    warmup='linear',    # warmup을 할건지
    warmup_iters=500,   # warmup iteration 얼마나 줄건지
    warmup_ratio=0.001, 
    step=[8, 11])        # step은 얼마마다 밟은 건지

runner (_1x는 epoch 12번, _2x는 epoch 24번, _20e는 epoch 20번을 의미)

  • max_epochs=10000


auto_resume

gpu_ids

https://onesixx.com/mmdet-log/

# 평가는 200번 돌고 함. 
evaluation        = dict(interval=200, metric='mIoU') #'mAP')

# 200 epoch 학습하는 동안 50번 마다 pth파일 만들고, 100번마다 로그 찍음
runner            = dict(type='EpochBasedRunner', max_epochs=400)
checkpoint_config = dict(interval=50)
log_config        = dict(interval=100, hooks=[dict(type='TextLoggerHook')])

# 학습율 변경 환경 파라미터 설정. 
optimizer = dict(type='SGD', lr=0.02/8, momentum=0.9, weight_decay=0.0001)
lr_config = dict(
    policy='step',
    warmup=None,
    warmup_iters=500,
    warmup_ratio=0.001,
    step=[8, 11])

# 가장 최근꺼 부터 이어서 학습
resume_from = 'work_dirs/sixx_faster_rcnn_r50_fpn_1x_coco/latest.pth'

GPU사용량 모니터링 (nvidia-smi, nvitop, gpustat)

watch -d -n 0.5 nvidia-smi

$ conda update -n base -c defaults conda

# https://anaconda.org/conda-forge/nvitop
# https://github.com/XuehaiPan/nvitop

$ conda install -c conda-forge nvitop
$ nvitop


# https://anaconda.org/conda-forge/gpustat
$ conda install -c conda-forge gpustat
$ gpustat

Training 실행

$ python sixxtools/train.py "sixxconfigs/faster_rcnn_r50_fpn_1x_coco_sixx.py"

~/my/git/mmdetection/tools ==> sixxtools

$ python sixxtools/train.py \\
  "sixxconfigs/cascade_rcnn_r50_fpn_1x_coco.py" \\
  --work-dir "work_dirs/ttt"

work_dirs에 작업할 폴더를 만들어짐

수정된 cfg 확인

epoch_69.pth (PyTorch Model)이 생성된다.

모델 실험을 위한 config 수정

https://pebpung.github.io/wandb/2021/10/06/WandB-1.html

직관적으로 수정하는 방법은 비효율적이다..

여러 GPU 사용

$ CUDA_VISIBLE_DEVICES=2,3 port=29506 sixxtools/dist_train.sh work_dirs/sixx_faster_rcnn_r50_fpn_1x_coco.py 2
$ CUDA_VISIBLE_DEVICES=2,3,4,5,6,7 port=29506 sixxtools/dist_train.sh sixxconfigs/faster_rcnn_r50_fpn_1x_coco_sixx.py 6

CUDA_VISIBLE_DEVICES로 사용할 GPU를 한정해주고,

Port를 분리한 후,

실행

CUDA_VISIBLE_DEVICES=2,3 python train.py

CUDA_VISIBLE_DEVICES=2,3 python train.py

CUDA_VISIBLE_DEVICES=2,3 python train.py

참고

#!/usr/bin/env bash

CONFIG=$1
GPUS=$2
NNODES=${NNODES:-1}
NODE_RANK=${NODE_RANK:-0}
PORT=${PORT:-29501}
MASTER_ADDR=${MASTER_ADDR:-"127.0.0.1"}

PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \\
python -m torch.distributed.launch \\
    --nnodes=$NNODES \\
    --node_rank=$NODE_RANK \\
    --master_addr=$MASTER_ADDR \\
    --nproc_per_node=$GPUS \\
    --master_port=$PORT \\
    $(dirname "$0")/train.py \\
    $CONFIG \\
    --seed 0 \\
    --launcher pytorch ${@:3}
gpu_ids = range(1,3)
$ watch -d -n0.5 nvidia-smi

~/my/git/mmdetection$ bash sixx/dist_train.sh work_dirs/sixx_faster_rcnn_r50_fpn_1x_coco/sixx_faster_rcnn_r50_fpn_1x_coco.py  3

다시 Training work_dirs

sixx/dist_train.sh: line 2: $’\r’: command not found

이런 에러가 날 경우, 전체 줄바꿈(Carriage return과 New Line \r )을 newline( )으로 바꿔준다.

sed -i -e ‘s/\r$//’ ./sixx/dist_train.sh

https://github.com/open-mmlab/mmdetection/issues/334

$ bash tools/dist_train.sh configs/skeleton/posec3d/slowonly_r50_u48_240e_ntu120_xsub_keypoints.py 
1 
--work-dir work_dirs/slowonly_r50_u48_240e_ntu120_xsub_keypoints 
--validate 
--test-best 
--seed 0 
--deterministic

https://github.com/facebookresearch/maskrcnn-benchmark

export NGPUS=2
CUDA_VISIBLE_DEVICES=2,3 python -m torch.distributed.launch --nproc_per_node=$NGPUS tools/train.py configs/faster_rcnn_r101_fpn_1x.py --gpus 2

https://artiiicy.tistory.com/61

 “CUDA_VISIBLE_DEVICES”를 통해 cuda가 볼 수 있는 GPU 제한하기

항상 cuda는 GPU 0번(torch.cuda.current_device())부터 사용을 하게 되고, CUDA_VISBLE_DEVICES= 2,3 이라면, cuda는 2,3번째만 볼수 있기때문에 GPU 0을 할당하는다는 것이 2를 사용하는것과 같다.

단, multi인 경우, nn.DataParallel()을 작성해주어야 한다.

1-2) Jupyter notebook 등의 python script “~.ipynb” file 내에서 돌리는 경우

“~.ipynb” 와 같이 python script 내에서 돌리는 경우에는 다음과 같이 os.environ[ ] code를 활용하여 environment를 설정하여 실행할 수 있다.

os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"  # Arrange GPU devices starting from 0
os.environ["CUDA_VISIBLE_DEVICES"]= "2,3"     # Set the GPUs 2 and 3 to use
$ python sixx/train.py work_dirs/sixx_faster_rcnn_r50_fpn_1x_coco.py

$ python sixxtools/train.py sixxconfigs/cascade_rcnn_r50_fpn_1x_coco.py

Categories: vision

onesixx

Blog Owner

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x