object detection을 위한 api로는 대표적인게 Detectron, MMDetection, YOLOv5, 이 3가지 인 것 같습니다.
사실 제가 그냥 아는 api가 3개 밖에 없네요..ㅋㅋ
요즘 보면 Detectron보단 MMDetection이 훨씬 더 많은 모델들을 지원하고, 또 자주 업데이트 하는 것 같네요.
뭐 여하튼 본 글은 Detectron2에 대한 설명 글입니다.
0. 설치
linux, macOS 는 공식 문서에 나와있는 절차대로 따라하시면 쉽게 설치가 됩니다.
(https://detectron2.readthedocs.io/en/latest/tutorials/install.html)
문제는 windows인데요, windows는 공식적으로 지원하고 있진 않습니다.
windows는 아래 순서대로 해주세요.
# 가상환경 생성(python = 3.7)
conda create -n detectron_env python=3.7
conda activate detectron_env
# pytorch 및 cudatoolkit 설치 (cuda version 맞춰서 잘 설치하기)
# 참조 : https://pytorch.org/get-started/previous-versions/
# CUDA 11.1
pip install torch==1.9.0+cu111 torchvision==0.10.0+cu111 torchaudio==0.9.0 -f https://download.pytorch.org/whl/torch_stable.html
# 필요 패키지 설치
conda install -c anaconda pywin32
conda install -c anaconda cython
pip install opencv-python
pip install git+https://github.com/facebookresearch/fvcore
pip install git+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI
pip install av
conda install -c anaconda scipy
conda install -c anaconda ninja
# Detectron 설치
git clone https://github.com/facebookresearch/detectron2.git detectron_repo
pip install -q -e detectron_repo
cd detectron_repo
python setup.py build develop
1. 학습
tutorial : https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5#scrollTo=7unkuuiqLdqd
tutorial code에 custom dataset을 적용하는 방법은 나와있습니다.
저는 coco dataset 기준으로 하겠습니다.
0) dataset 등록
먼저 dataset을 detectron에 등록해야 합니다.
coco dataset 형식은 등록하는 함수가 따로 정의되어 있어서 편하게 등록할 수 있습니다.
(https://detectron2.readthedocs.io/en/latest/tutorials/datasets.html#register-a-dataset)
from detectron2.utils.logger import setup_logger
setup_logger() # Setup detectron2 logger
from detectron2 import model_zoo
from detectron2.config import get_cfg
from detectron2.data.datasets import register_coco_instances
from detectron2.engine import DefaultTrainer
# detectron에 dataset 등록 (학습할 때 등록된 데이터셋을 불러올 수 있습니다.)
register_coco_instances("train(데이터셋 이름)", {}, "train json 파일", "train images 폴더")
register_coco_instances("test(데이터셋 이름)", {}, "test json 파일", "test images 폴더")
1) model load, configure load
그 다음 학습에 쓰일 인자들을 넣어줄 겁니다..
detectron에 있는 get_cfg 함수를 사용하면 기본값들이 다 채워져 있는 configure를 얻을 수 있습니다.
그 다음 사용할 모델을 입력합니다.
### set detectron configure
cfg = get_cfg()
cfg.merge_from_file(
model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml"))
# training initialize from model zoo (pretrained model path를 넣어도 됨)
cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(
"COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml")
cfg.DATASETS.TRAIN = ("train",) # dataset 등록할 때의 이름
cfg.DATASETS.TEST = ("test",) # dataset 등록할 때의 이름
cfg.DATALOADER.NUM_WORKERS = 4 # 사용할 core 개수
model_zoo.get_config_file("모델이름") 에서 yaml파일들은 detectron2/detectron2/model_zoo/model_zoo.py 에서 골라와서 뒤에 .yaml 붙이면 됩니다.
(model zoo source : https://github.com/facebookresearch/detectron2/tree/main/detectron2/model_zoo)
그리고 pretrained 된 weights를 불러올 수도 있습니다.
직접 학습한 모델의 경로를 넣어도 되구요.
그 다음 위에서 등록했던 dataset 이름들을 통해 dataset을 등록합니다.
겨우 이것만으로도 기본적인 틀은 완성이 되었습니다.
2) hyperparameters
이제 hyperparameter들을 조정해야겠죠?
cfg.SOLVER.IMS_PER_BATCH = 4 # batch size
cfg.SOLVER.BASE_LR = 0.005
cfg.SOLVER.BASE_LR_END = 1e-6 # use with WarmupCosineLr
cfg.SOLVER.GAMMA = 0.5 # use with WarmupMultiStepLR
cfg.SOLVER.STEPS = [10, 50, 80] # use with WarmupMultiStepLR
cfg.SOLVER.LR_SCHEDULER_NAME = "WarmupMultiStepLR" # 또는 WarmupCosineLR
cfg.SOLVER.MAX_ITER = 1000 # epoch 단위가 아니라 iteration 단위입니다.
cfg.SOLVER.CHECKPOINT_PERIOD = 100 # model checkpoint (save period)
cfg.TEST.EVAL_PERIOD = 100 # validation period
cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 512 # box 개수
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 80 # detectron에선 배경 때문에 class개수 +1 할 필요 없습니다.
cfg.OUTPUT_DIR = "결과폴더"
# resize default func : resize shortest edge
cfg.INPUT.MIN_SIZE_TRAIN = [640, 672, 704, 720] # default : 뭐였더라..
cfg.INPUT.MAX_SIZE_TRAIN = 1280 # default : 1333
cfg.INPUT.MIN_SIZE_TEST = 720 # default : 800
cfg.INPUT.MAX_SIZE_TEST = 1280 # default : 1333
딱히 설명할 게 없네요..
이름 그대로 이해하시면 됩니다.
학습이 epoch위로 도는게 아니라 iteration 단위로 돈다는 점은 조금 특이하구요.
중요한건 num_classes 에 +1 하면 안됩니다.
그냥 클래스 개수 그대로 넣으세요. (coco는 80개)
resize는 기본이 ResizeShortestEdge 로 되어 있습니다.
이건 응용편에서 바꾸는 법을 또 올리겠습니다.
(선택) wandb 사용법
## wandb
import wandb, yaml
cfg.wandb_project = "프로젝트"
cfg.wandb_name = "이름"
cfg_wandb = yaml.safe_load(cfg.dump())
wandb.init(project=cfg.wandb_project, name=str(cfg.wandb_name), config=cfg_wandb)
wandb_id = wandb.run.id
training 파일 실행 전에 wandb login 미리 해주시면 됩니다.
아니면 안에 login 하는 코드 넣으셔도 되구요.
detectron config를 넣으면 편하게 wandb를 사용할 수 있습니다.
3) train
# default_setup(cfg, args)
trainer = DefaultTrainer(cfg)
trainer.resume_or_load(resume=False) # 중단된 학습을 재개할 것인지.
trainer.train() # 학습 시작
마지막으로 Trainer 선언하고, trainer.train()하면 학습 시작됩니다.
(종합)
최종적으로 합치면 다음과 같은 코드가 됩니다.
# Setup detectron2 logger
from detectron2.utils.logger import setup_logger
setup_logger()
from detectron2 import model_zoo
from detectron2.config import get_cfg
from detectron2.data.datasets import register_coco_instances
from detectron2.engine import DefaultTrainer
### detectron에 dataset 등록 (학습할 때 등록된 데이터셋을 불러올 수 있습니다.)
register_coco_instances("train(데이터셋 이름)", {}, "train json 파일", "train images 폴더")
register_coco_instances("test(데이터셋 이름)", {}, "test json 파일", "test images 폴더")
### set detectron configure
cfg = get_cfg()
cfg.merge_from_file(
model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml"))
# training initialize from model zoo (pretrained model path를 넣어도 됨)
cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(
"COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml")
cfg.DATASETS.TRAIN = ("train",) # dataset 등록할 때의 이름
cfg.DATASETS.TEST = ("test",) # dataset 등록할 때의 이름
cfg.DATALOADER.NUM_WORKERS = 4 # 사용할 core 개수
### Hyperparameters
cfg.SOLVER.IMS_PER_BATCH = 4 # batch size
cfg.SOLVER.BASE_LR = 0.005
cfg.SOLVER.BASE_LR_END = 1e-6 # use with WarmupCosineLr
cfg.SOLVER.GAMMA = 0.5 # use with WarmupMultiStepLR
cfg.SOLVER.STEPS = [10, 50, 80] # use with WarmupMultiStepLR
cfg.SOLVER.LR_SCHEDULER_NAME = "WarmupMultiStepLR" # WarmupCosineLR
cfg.SOLVER.MAX_ITER = 1000 # epoch 단위가 아니라 iteration 단위입니다.
cfg.SOLVER.CHECKPOINT_PERIOD = 100 # model checkpoint (save period)
cfg.TEST.EVAL_PERIOD = 100 # validation period
cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 512 # box 개수
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 80 # detectron에선 배경 때문에 class개수 +1 할 필요 없습니다.
cfg.OUTPUT_DIR = "결과폴더"
# resize default func : resize shortest edge (default는 (800, 1333))
cfg.INPUT.MIN_SIZE_TRAIN = [640, 672, 704, 720] # default : 뭐였더라..
cfg.INPUT.MAX_SIZE_TRAIN = 1280 # default : 1333
cfg.INPUT.MIN_SIZE_TEST = 720 # default : 800
cfg.INPUT.MAX_SIZE_TEST = 1280 # default : 1333
### wandb (선택)
# import wandb, yaml
# cfg.wandb_project = "프로젝트"
# cfg.wandb_name = "이름"
# cfg_wandb = yaml.safe_load(cfg.dump())
# wandb.init(project=cfg.wandb_project, name=str(cfg.wandb_name), config=cfg_wandb)
# wandb_id = wandb.run.id
### Train
trainer = DefaultTrainer(cfg)
trainer.resume_or_load(resume=False) # 중단된 학습을 재개할 것인지.
trainer.train() # 학습 시작
음... 끝입니다.
조금 응용한 버전도 또 올리겠습니다.
'Detection' 카테고리의 다른 글
Detectron2 - Training 응용 (0) | 2022.02.08 |
---|---|
Mask RCNN (Faster RCNN + segmentation) (0) | 2022.02.06 |