1. Set Virtual Environment
가상환경 세팅은 conda를 사용하였으며, 개발 환경은 ubuntu / i9-13900K CPU / GTX 4080 / 64GB Mem이다.
1-1) Git Clone
우선, 아래의 DINO 공식 Github 링크에 들어가서 해당 repo를 local에 clone 해준다.
git clone https://github.com/IDEA-Research/DINO.git
cd DINO
1-2) Setup Pytorch
그래픽 카드 버전에 맞는 pytorch를 install 해준다. 4080은 어떤 버전을 사용해야 하는지 잘 몰라서 가장 최신 버전인 11.7 버전을 가상환경에 설치해주었다.
torch.cuda.is_available()의 return값이 True이면 버전에 맞게 잘 설치된 것이다.
>>> import torch
>>> torch.cuda.is_available()
True
-
주의사항
만약, pytorch build가 cpu로 설치됐다면, 버전이 맞지 않는 것이므로 다른 버전을 찾아 설치해주면 된다. 버전이 맞지 않으면 cuda를 사용할 수 없으니 버전을 잘 맞추도록 하자
1-3) requirements 설치
1-3-1. install requirements.txt
pip install -r requirements.txt
1-3-2. Compiling CUDA operators
cd DINO/models/dino/ops
python setup.py build install
# unit test (should see all checking is True)
python test.py
cd ../../..
2. Prepare Dataset
Dataset은 다음과 같은 구조로 설치하면 된다.
COCODIR/
├── train2017/
├── val2017/
└── annotations/
├── instances_train2017.json
└── instances_val2017.json
터미널에 아래의 명령어를 차례차례 입력하면 된다. 해외 서버에서 wget으로 받아오다보니 시간이 오래 걸린다. 조금 더 빨리 받아올 수 있는 방법이 있는걸로 알고있는데 정확히 기억나지 않아서 그냥 기다렸다.
cd DINO
mkdir COCODIR
cd COCODIR
wget http://images.cocodataset.org/zips/train2017.zip
wget http://images.cocodataset.org/zips/val2017.zip
wget http://images.cocodataset.org/annotations/annotations_trainval2017.zip
unzip train2017.zip
unzip val2017.zip
unzip annotations_trainval2017.zip
rm train2017.zip
rm val2017.zip
rm annotations_trainval2017.zip
3. Pre-trained Model Inference
공식 github에서 Model Zoo를 제공하고 있어, 다양한 세팅에 대해 Inference 및 evaluation을 해볼 수 있었다. 현재는 간단한 inference만 해보면 되기 때문에, 4 scale feature로 12 epoch 학습(Resnet50 백본)한 모델의 체크 포인트를 사용하였다. ipynb 코드는 아래 링크를 참조하면 된다.
ckpts link : https://drive.google.com/file/d/1eeAHgu-fzp28PGdIjeLe-pzGPMG2r2G_/view?usp=sharing
code link : https://github.com/On-JungWoan/paper-review/blob/main/DINO/script/inference_and_visualization.ipynb
Inference 코드는 다음과 같다. DINO 폴더 최상위에 작성하면 된다.
import torch
import json
import datasets.transforms as T
from main import build_model_main
from datasets import build_dataset
from util.visualizer import COCOVisualizer
from util.slconfig import SLConfig
from PIL import Image
from util import box_ops
import numpy as np
#
model_config_path = "config/DINO/DINO_4scale.py"
model_checkpoint_path = "logs/DINO/train_test/checkpoint_best_regular.pth" # your ckp path
img_dir = "figs/idea.jpg" # your image path
#
args = SLConfig.fromfile(model_config_path)
args.device = 'cuda'
model, criterion, postprocessors = build_model_main(args)
checkpoint = torch.load(model_checkpoint_path, map_location='cpu')
model.load_state_dict(checkpoint['model'])
_ = model.eval()
# load coco names
with open('util/coco_id2name.json') as f:
id2name = json.load(f)
id2name = {int(k):v for k,v in id2name.items()}
#
image = Image.open(img_dir).convert("RGB")
transform = T.Compose([
T.RandomResize([800], max_size=1333),
T.ToTensor(),
T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
image, _ = transform(image, None)
#
output = model.cuda()(image[None].cuda())
output = postprocessors['bbox'](output, torch.Tensor([[1.0, 1.0]]).cuda())[0]
# visualize outputs
if output['scores'].max() > 0.3:
thershold = 0.3 # set a thershold
else:
thershold = float(sorted(output['scores'].cpu())[-6])
np.array(output['scores'].cpu())
vslzr = COCOVisualizer()
scores = output['scores']
labels = output['labels']
boxes = box_ops.box_xyxy_to_cxcywh(output['boxes'])
select_mask = scores > thershold
box_label = [id2name[int(item)] for item in labels[select_mask]]
pred_dict = {
'boxes': boxes[select_mask],
'size': torch.Tensor([image.shape[1], image.shape[2]]),
'box_label': box_label
}
vslzr.visualize(image, pred_dict, savedir=None, dpi=100)
3.1) 결과
기존 DETR 계열의 문제점이었던 작은 obj도 잘 감지하는 모습을 확인할 수 있다. 또한, obj가 겹쳐있는 경우도 문제없이 잘 추론하고 있다.
4. Train Model
COCO 데이터셋을 전부 사용하여 학습하기에는 시간이 다소 오래 걸릴 것 같아서 일부만 사용하였다. 다음은 예상 학습 시간을 계산한 테이블이다(rs50 backbone, 4scale 기준). 본인의 여건에 맞춰서 선택하면 된다. 해당 시간은 train 시간만 고려하였으므로 실제 train 시간은 아래 시간보다 더 오래 소요되며, 개발 환경에 따라 달라질 수 있다. 본 포스팅에서는 1만개 train dataset을 사용하여 12 epoch 학습하였다. 또한, 한 epoch 내에서의 loss 변화를 보기 위해 이미지 30장마다 loss를 기록해주었다.
. | full dataset | 25,000 | 10,000 | 5000 |
---|---|---|---|---|
1epoch | 3h | 1.5h | 36m | 18m |
12epoch | 36h | 18h | 7.2h | 3.6h |
이를 위해 간단한 코드 custom을 해주었다.
# $1 : COCO Dir.
# $2 : Num of train_dataset
# $3 : Num of val_dataset
# $4 : use custom logger
bash scripts/DINO_train_custom.sh COCODIR/ 10000 5000 --custom_logger
coco_path=$1
python main.py \
--num_train $2 --num_val $3 $4\
--output_dir logs/DINO/train_$2_$3_4scale_rs50_12epc \
-c config/DINO/DINO_4scale.py --coco_path $coco_path \
--options dn_scalar=100 embed_init_tgt=TRUE \
dn_label_coef=1.0 dn_bbox_coef=1.0 use_ema=False \
dn_box_noise_scale=1.0
...
parser.add_argument("--num_train", type=int)
parser.add_argument("--num_val", type=int)
parser.add_argument("--custom_logger", action='store_true')
...
...
if args.custom_logger:
if _cnt%30 == 0:
with open(args.output_dir + '/loss_only.txt', 'a') as f:
f.write(f'{_cnt} : {loss_value}\n')
...
자세한 코드는 아래를 참고.
link : https://github.com/On-JungWoan/paper-review/blob/main/DINO/script/result_visualization.ipynb
4-1) Effectiveness
4-1-1. Loss in Entire Epoch
우선, 한 epoch 내에서 loss가 어떻게 변하는지를 확인하기 위해, 30개의 이미지를 학습할 때마다 loss를 기록하였다. 아래 그래프는 결과의 일부를 발췌한 것이며, x축은 (학습한 이미지의 수 * 30), y축은 loss이다. epoch을 거듭할수록 전반적인 loss가 감소하는 것은 확인하였으나, 한 epoch 내에서(1 epoch 제외) loss의 감소는 관찰할 수 없었다.
-
For all epoch
-
Only 1, 6, 12 epoch
4-1-2. Loss (Mean of Epoch)
x축은 epoch, y축은 loss를 의미하며 최종 12epoch에서의 train loss는 11.87, test loss는 5.64(full-dataset : 4.6)를 기록하였다. train loss보다 test loss가 더 낮게 나오는 이유는 배움이 얕아 아직 파악하지 못했다.
4-1-3. AP
최종 AP은 38.1로, COCO dataset 5만개를 전부 사용하여 학습했을 때(49.0)에 비해 -10.9AP의 스코어 차이를 보였다. 하지만 12epoch 기준 약 30시간 정도의 시간을 절약할 수 있기 때문에, 빠르게 개요만 확인하고 싶은 경우 이 방법을 채택해도 좋을 것 같다.
4-1-4. Epoch Time
4-2) Performance
다음은 model의 각 epoch별 inference 결과를 시각화 한 것이다.
4-2-1. 1 Epoch model
threshold를 넘는 bbox가 존재하지 않아, confidence가 가장 높은 5개의 bbox를 image 위에 그려주었다. 아직은 제대로 된 inference를 하지 못하고 있다.
4-2-2. 6 Epoch model
전반적으로 detection 수준이 향상되었으나, 논문에서 언급된 duplicated prediction 문제가 일어나고 있다. CDN Training을 통해 해당 문제를 해결할 수 있을 것으로 기대된다.
4-2-3. 12 Epoch model
Duplicated Prediction 문제가 해결되었으며, 기존 DETR계열 모델이 small obj를 잘 탐지하지 못했던 문제를 해결한 것을 확인할 수 있다.
4-2-4. Full Dataset model
Full Dataset을 사용하여 학습한 모델과 비교하여 나쁘지 않은 performance를 보이고 있음을 확인할 수 있다.
댓글남기기