2022. 1. 30. 18:46ㆍcomputervision/섹션 8. EfficientDet
저번 시간에는 단순히 AutoML EfficientDet 패키지를 inference 해보았다.
이번에는 Pascal voc dataset을 이용하여 AutoML efficientdet 패키지를 학습해보고 inference 까지 수행해보려 한다.
!git clone --depth 1 https://github.com/google/automl
!cd /content/automl/efficientdet; pip install -r requirements.txt
import os
import sys
import tensorflow.compat.v1 as tf
sys.path.append('/content/automl/efficientdet')
import hparams_config
from tf2 import anchors
from model_inspect import ModelInspector
이후 필요한 라이브러리를 import한 후 sys의 경로에 efficientdet 폴더가 있는 위치를 추가 시켜준다. 이 작업을 해야 efficientdet폴더의 위치에서 필요한 모듈을 import 해 올 수 있다.
!wget http://pjreddie.com/media/files/VOCtrainval_06-Nov-2007.tar
!tar -xvf VOCtrainval_06-Nov-2007.tar > /dev/null 2>&1
이후 pascal voc 2007 dataset을 version을 다운받는다.
!mkdir -p /content/tfrecord/train
!mkdir -p /content/tfrecord/val
!cd /content/automl/efficientdet; PYTHONPATH="/content/automl/efficientdet:$PYTHONPATH" python dataset/create_pascal_tfrecord.py \
--data_dir=/content/VOCdevkit --year=VOC2007 --set=train --output_path=/content/tfrecord/train/pascal
!cd /content/automl/efficientdet; PYTHONPATH="/content/automl/efficientdet:$PYTHONPATH" python dataset/create_pascal_tfrecord.py \
--data_dir=/content/VOCdevkit --year=VOC2007 --set=val --output_path=/content/tfrecord/val/pascal
이후 다운받은 train, validation 데이터 셋을 tfrecord 형태로 변환을 거쳐야 한다.
tfrecord로 변환하는 패키지가 처음에 다운받은 efficientdet 폴더에 있기 때문에 별도의 작업 필요없이 create_pascal_tfrecord.py 모듈을 사용하면된다.
각각 train과 val 폴더를 생성후 create_pascal_tfrecord.py모듈을 사용하여 pascal_voc 형태의 데이터를 tfrecord형태의 데이터셋으로 변환 후 각각의 저장위치에 다운로드 받는다.
import os, sys
from google.colab import drive
drive.mount('/content/gdrive')
!ln -s /content/gdrive/My\ Drive/ /mydrive
!ls /mydrive
!mkdir -p /mydrive/model_trained
모델이 학습이 될때의 checkpoint 파일을 다운받을 경로를 구글드라이브로 설정했다.
이후 학습을 진행하기 위해서 config파일을 설정해주어야 한다.
config = hparams_config.get_detection_config('efficientdet-d0')
모델은 efficientdet-d0로 사용하였다.
class TRAIN_CFG:
model_name = 'efficientdet-d0'
strategy = ''
model_dir = '/mydrive/model_trained'
pretrained_ckpt = '/content/efficientdet-d0'
hparams = 'num_classes=20,moving_average_decay=0,mixed_precision=true'
use_xla = False
use_fake_data = False
batch_size = 8
eval_samples = 5000
steps_per_execution = 1
num_examples_per_epoch = 2500
num_epochs = 15
train_file_pattern = '/content/tfrecord/train/pascal-*.tfrecord'
val_file_pattern = '/content/tfrecord/val/pascal-*.tfrecord'
val_json_file = None
mode = 'traineval'
num_cores = 2
tpu = None
gcp_project = None
tpu_zone = None
eval_master = ''
eval_name = None
tf_random_seed = 2021
profile = False
debug = False
먼저 config파일에서 수정해야될 parmeter들을 class형식으로 지정해준다.
기존의 config파일에서 수정해야될 사항들이 적혀있다.
efficientdet의 모델명, 학습된 모델이 저장될 위치, evaluation image 데이터의 수, epoch 횟수..
from tf2.train import setup_model
import hparams_config
import utils
from tf2 import tfmot
from tf2 import train_lib
from tf2 import util_keras
config = hparams_config.get_detection_config(TRAIN_CFG.model_name)
config.override(TRAIN_CFG.hparams)
steps_per_epoch = TRAIN_CFG.num_examples_per_epoch // TRAIN_CFG.batch_size
if tf.config.list_physical_devices('GPU'):
ds_strategy = tf.distribute.OneDeviceStrategy('device:GPU:0')
else:
ds_strategy = tf.distribute.OneDeviceStrategy('device:CPU:0')
print(ds_strategy)
params = dict(
profile=TRAIN_CFG.profile,
mode = TRAIN_CFG.mode,
model_name=TRAIN_CFG.model_name,
steps_per_execution=TRAIN_CFG.steps_per_execution,
num_epochs = TRAIN_CFG.num_epochs,
model_dir=TRAIN_CFG.model_dir,
steps_per_epoch=steps_per_epoch,
strategy=TRAIN_CFG.strategy,
batch_size=TRAIN_CFG.batch_size,
tf_random_seed=TRAIN_CFG.tf_random_seed,
debug=TRAIN_CFG.debug,
val_json_file=TRAIN_CFG.val_json_file,
eval_samples=TRAIN_CFG.eval_samples,
num_shards=ds_strategy.num_replicas_in_sync
)
config.override(params, True)
config.image_size = utils.parse_image_size(config.image_size)
필요한 라이브러리를 호출 후 위에서 class형태로 지정한 config설정들을 기존의 config파일에 override 시킨다.
이때 입력 image size를 tuple형태로 지정해 주어야 한다. tuple형태로 맞춰주기 위해 utils에 있는 parse_image_size함수를 이용하면 된다.
여기까지 진행하면 모델의 학습에 필요한 config설정이 완료되었다.
이제 모델을 생성후 train,val용 dataset을 생성하고 train을 진행하면 된다.
import utils
from tf2 import tfmot
from tf2 import train_lib
from tf2 import util_keras
MODEL = 'efficientdet-d0'
def download(m):
if m not in os.listdir():
!wget https://storage.googleapis.com/cloud-tpu-checkpoints/efficientdet/coco/{m}.tar.gz
!tar zxf {m}.tar.gz
ckpt_path = os.path.join(os.getcwd(), m)
return ckpt_path
ckpt_path = download(MODEL)
이후 학습에 사용할 coco dataset으로 pretrained된 efficientdet d0 checkpoint파일을 다운로드 받는다.
from tf2 import train_lib
from tf2 import train
model = train_lib.EfficientDetNetTrain(config=config)
model = train.setup_model(model, config)
if TRAIN_CFG.pretrained_ckpt:
ckpt_path = tf.train.latest_checkpoint(TRAIN_CFG.pretrained_ckpt)
util_keras.restore_ckpt(
model,
ckpt_path,
config.moving_average_decay,
exclude_layers=['class_net'])
train.init_experimental(config)
model.summary()
위에서 다운받은 pretrained된 model은 coco dataset으로 학습되어져 있다. coco dataset과 지금 학습하고자 하는 pascal voc dataset의 최종 output layer의 개수가 다르므로 다운받은 pretrained 된 모델의 classification layer를 제외 시켜야한다.
이제 train, val용 dataset을 생성해야한다.
import dataloader
def get_dataset(is_training, config):
file_pattern = (
TRAIN_CFG.train_file_pattern
if is_training else TRAIN_CFG.val_file_pattern)
if not file_pattern:
raise ValueError('No matching files.')
return dataloader.InputReader(
file_pattern,
is_training=is_training,
use_fake_data=TRAIN_CFG.use_fake_data,
max_instances_per_image=config.max_instances_per_image,
debug=TRAIN_CFG.debug)(
config.as_dict())
이제 모델의 모델의 학습에 필요한 모든 과정이 끝났다.
from tf2 import train
import numpy as np
tr_steps_per_epoch = train_images_num//config.batch_size
val_steps_per_epoch = val_images_num//config.batch_size
print('tr_steps_per_epoch:', tr_steps_per_epoch, 'val_steps_per_epoch:', val_steps_per_epoch)
val_dataset = get_dataset(False, config) if 'eval' in config.mode else None
model.fit(
get_dataset(True, config),
epochs=15,
steps_per_epoch=tr_steps_per_epoch ,
callbacks=train_lib.get_callbacks(config.as_dict(), val_dataset),
validation_data=val_dataset,
validation_steps=val_steps_per_epoch)
tf.keras.backend.clear_session()
위의 과정에서 설정한 steps_per_epoch, num_epochs를 무시하고 다시 생성한다.
위에서 steps_per_epoch, num_epochs를 설정하지 않으면 정상적으로 코드가 동작하지 않았기 때문에 위에서 설정했지만 이 코드에서 다시 생성한 steps_per_epoch, num_epochs을 이용하여 모델의 학습이 이루어지게 된다.
steps_per_epoch는 (전체 학습데이터의 수/batch_size)로 표현할 수 있다.
모델이 epochs 15 학습을 맞춘후 Iou 0.5:0.95는 0.465 Iou 0.5는 0.715의 성능을 보여주었다.
하지만 여전히 small object에 대해서는 0.106이라는 낮은 성능을 보여준다. 이는 입력되는 input_img_size의 크기를 좀 더 키우거나, epoch수를 더 늘리거나, efficientdet 모델의 버전을 높은 버전을 사용되면 성능향상을 이끌어 낼 수 있지 않을까 생각해본다.
이후 inference 시각화 과정은 저번시간에 실습했던 내용이랑 같은 내용이다.
수행시간은 tensorflow v1의 static graph모드(non eager mode)로 실행했을 때 30ms가 나왔다.
앞서 수행했던 efficientdet v0 모델을 학습 하지 않고 바로 inference을 했을 때와 비슷한 결과가 나왔다.
'computervision > 섹션 8. EfficientDet' 카테고리의 다른 글
tfrecord dataset esri_challenge 학습 (0) | 2022.01.31 |
---|---|
Google automl Efficientdet inference 실습 (0) | 2022.01.29 |
T.F hub efficientDet lite v0~v2실습 (0) | 2022.01.29 |
EfficientDet 개념 정리 (0) | 2022.01.29 |