1. Set Virtual Environment

가상환경 세팅은 conda를 사용하였으며, 개발 환경은 ubuntu / i9-13900K CPU / GTX 4080 / 64GB Mem이다.

image

1-1) Git Clone

우선, 아래의 DINO 공식 Github 링크에 들어가서 해당 repo를 local에 clone 해준다.

link : https://github.com/IDEA-Research/DINO

git clone https://github.com/IDEA-Research/DINO.git
cd DINO


1-2) Setup Pytorch

그래픽 카드 버전에 맞는 pytorch를 install 해준다. 4080은 어떤 버전을 사용해야 하는지 잘 몰라서 가장 최신 버전인 11.7 버전을 가상환경에 설치해주었다.

link : https://pytorch.org/get-started/locally

image

torch.cuda.is_available()의 return값이 True이면 버전에 맞게 잘 설치된 것이다.

>>> import torch
>>> torch.cuda.is_available()
True 
  • 주의사항

    만약, pytorch build가 cpu로 설치됐다면, 버전이 맞지 않는 것이므로 다른 버전을 찾아 설치해주면 된다. 버전이 맞지 않으면 cuda를 사용할 수 없으니 버전을 잘 맞추도록 하자

    image


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가 겹쳐있는 경우도 문제없이 잘 추론하고 있다.

output



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을 해주었다.

[Terminal]
# $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
[DINO_train_custom.sh]
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
[main.py]
...

parser.add_argument("--num_train", type=int)
parser.add_argument("--num_val", type=int)
parser.add_argument("--custom_logger", action='store_true')

...
[engine.py]
...

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

    image

  • Only 1, 6, 12 epoch

    image

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를 보이고 있음을 확인할 수 있다.

댓글남기기