주뇽's 저장소

YOLO_NAS_커스텀 데이터 (포켓몬 도감 만들기) 본문

ComputerVision/YOLO

YOLO_NAS_커스텀 데이터 (포켓몬 도감 만들기)

뎁쭌 2023. 7. 1. 09:23
728x90
반응형

프로젝트 시작(커스텀 데이터)


커스텀 데이터(Pokemon)

Step0. 데이터 준비 및 라벨링을 위한 Roboflow 회원가입

Images.zip
16.75MB

Step1. 데이터 라벨링- 

2345678910

 

이미지 하나씩 라벨링 시작 smart 기능을 이용하면 더욱 정교하게 라벨링 가능(신세계 경험)

  • 만약 라벨링을 실수한경우 손바닥 모양을 클릭하면 쉽게 수정 가능!!

1112

위처럼 하면 안됨 아래처럼 !! 사각형(바운딩 박스)으로 라벨링 해야함

13

라벨링이 모두 끝나면 add 버튼 클릭

14

원하는 비율로 데이터셋을 나누고 버튼 클릭(수정 가능)

15

데이터셋에서 이미지 증폭등 다양한 변환 가능

16

  • 이미지 레벨과 바운딩박스 레벨에서 90도 변환 증폭을 적용해봤음17

YOLOv5 format 으로 내보내기

1819

 

Colab 환경에서 학습을 해야 하므로 주피터 포맷을 선택하고 해당 코드 복사

20

Step2. Colab에서 커스텀 데이터 학습

Step0. 필요 라이브러리 설치

  • 아래 라이브러리 설치 후 런타임 재시작
%%capture
#-- 현재 파이썬 3.10 버전부터는 생기는 에러가 있으므로 아래 3.1.1으로 다운받아야 에러가 안남
#-- 현재는 그냥 버전을 지워버려야 함
!pip install super-gradients
!pip install imutils
!pip install roboflow
!pip install pytube --upgrade

Step1. 필요 라이브러리 import & GPU 설정

import cv2
import torch
from IPython.display import clear_output
from super_gradients.training.losses import PPYoloELoss
from super_gradients.training.metrics import DetectionMetrics_050
from super_gradients.training.models.detection_models.pp_yolo_e import PPYoloEPostPredictionCallback
from super_gradients.training import models
from super_gradients.training import Trainer
from super_gradients.training import dataloaders
from super_gradients.training.dataloaders.dataloaders import coco_detection_yolo_format_train, coco_detection_yolo_format_val
#-- GPU 설정
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)
use_cuda = torch.cuda.is_available()
print(use_cuda)
if use_cuda:
  print(torch.cuda.get_device_name(0))

Step2. 체크포인트 설정

CHECKPOINT_DIR = 'checkpoints'
trainer = Trainer(experiment_name='Pokémon_yolonas_run', ckpt_root_dir=CHECKPOINT_DIR)

Step3. roboflow 데이터를 코랩으로 가져오기

  • roboflow에서 복사해뒀던 코드를 붙여넣기

21

!pip install roboflow

from roboflow import Roboflow
rf = Roboflow(api_key="3NnsrtodD4CdBVrs1VJk")
project = rf.workspace("pokmon").project("pokemon-abicz")
dataset = project.version(1).download("yolov5")

위 코드를 실행하면 로컬에 해당 데이터셋 폴더가 생성 된다 해당 폴더 경로 복사

22

Step4. 디렉토리로 데이터셋 로드

  • data_dir은 위에서 복사한 경로를 넣어줌
  • classes에는 클래스들을 넣어주면 된다.
dataset_params = {
    'data_dir':'/content/pokemon-1',
    'train_images_dir':'train/images',
    'train_labels_dir':'train/labels',
    'val_images_dir':'valid/images',
    'val_labels_dir':'valid/labels',
    'test_images_dir':'test/images',
    'test_labels_dir':'test/labels',
    'classes': ['Bulbasaur', 'Charmander', 'Squirtle']
}

Step5. 데이터 parmas를 데이터셋 parmas 인자로 삽입

from super_gradients.training import dataloaders
from super_gradients.training.dataloaders.dataloaders import coco_detection_yolo_format_train, coco_detection_yolo_format_val

train_data = coco_detection_yolo_format_train(
    dataset_params={
        'data_dir': dataset_params['data_dir'],
        'images_dir': dataset_params['train_images_dir'],
        'labels_dir': dataset_params['train_labels_dir'],
        'classes': dataset_params['classes']
        # 'show_all_warnings': True
    },
    dataloader_params={
        'batch_size':16,
        'num_workers':2
    }
)

val_data = coco_detection_yolo_format_val(
    dataset_params={
        'data_dir': dataset_params['data_dir'],
        'images_dir': dataset_params['val_images_dir'],
        'labels_dir': dataset_params['val_labels_dir'],
        'classes': dataset_params['classes']
    },
    dataloader_params={
        'batch_size':16,
        'num_workers':2
    }
)

test_data = coco_detection_yolo_format_val(
    dataset_params={
        'data_dir': dataset_params['data_dir'],
        'images_dir': dataset_params['test_images_dir'],
        'labels_dir': dataset_params['test_labels_dir'],
        'classes': dataset_params['classes']
    },
    dataloader_params={
        'batch_size':16,
        'num_workers':2
    }
)

clear_output()

Step6. 앞에서 정의한 데이터 세트 검사

train_data.dataset.transforms
train_data.dataset.dataset_params['transforms'][1]
train_data.dataset.dataset_params['transforms'][1]['DetectionRandomAffine']['degrees'] = 10.42

Step7. 증폭 기능이 적용된 훈련 데이터 시각화

train_data.dataset.plot()

23

Step8. 모델 인스턴스화

  • 다음은 미세 조정을 위해 모델을 인스턴스화하는 방법이다 여기에 num_classes 인수를 추가해야 한다는 점에 유의해야 한다.
  • 이 튜토리얼에서는 yolo_nas_s를 사용하지만, 슈퍼 그레이디언트에는 두 가지 다른 종류의 yolo_nas_myolo_nas_l`를 사용할 수 있다.
model = models.get('yolo_nas_s',
                   num_classes=len(dataset_params['classes']),
                   pretrained_weights="coco"
                   )

Step9. 모델 하이퍼 파라미터 설정

  • max_epochs - 최대 훈련 에포크 수
  • loss - 사용하려는 손실 함수
  • optimizer - 사용하려는 손실 함수
  • train_metrics_list - 트레이닝 중에 기록할 메트릭
  • valid_metrics_list - 트레이닝 중에 기록할 메트릭
  • metric_to_watch - 모델 체크포인트가 저장될 지표

다음과 같은 다양한 옵티마이저 중에서 선택할 수 있다: Adam, AdamW, SGD, Lion 또는 RMSProps. 이러한 옵티마이저의 잘못된 파라미터를 변경하려면 해당 파라미터를 optimizer_params에 전달한다.

train_params = {
    # ENABLING SILENT MODE
    'silent_mode': True,
    "average_best_models":True,
    "warmup_mode": "linear_epoch_step",
    "warmup_initial_lr": 1e-6,
    "lr_warmup_epochs": 3,
    "initial_lr": 5e-4,
    "lr_mode": "cosine",
    "cosine_final_lr_ratio": 0.1,
    "optimizer": "Adam",
    "optimizer_params": {"weight_decay": 0.0001},
    "zero_weight_decay_on_bias_and_bn": True,
    "ema": True,
    "ema_params": {"decay": 0.9, "decay_type": "threshold"},
    # 이 예제의 경우 15개의 에포크만 교육한다.
    "max_epochs": 15,
    "mixed_precision": True,
    "loss": PPYoloELoss(
        use_static_assigner=False,
        # 참고: num_classes는 여기에 정의되어야 한다.
        num_classes=len(dataset_params['classes']),
        reg_max=16
    ),
    "valid_metrics_list": [
        DetectionMetrics_050(
            score_thres=0.1,
            top_k_predictions=300,
            # 참고: num_classes는 여기에 정의되어야 한다.
            num_cls=len(dataset_params['classes']),
            normalize_targets=True,
            post_prediction_callback=PPYoloEPostPredictionCallback(
                score_threshold=0.01,
                nms_top_k=1000,
                max_predictions=300,
                nms_threshold=0.7
            )
        )
    ],
    "metric_to_watch": 'mAP@0.50'
}

Step10. 모델 학습

trainer.train(model=model,
              training_params=train_params,
              train_loader=train_data,
              valid_loader=val_data)

Step11. 최고의 모델 얻기

best_model = models.get('yolo_nas_s',
                        num_classes=len(dataset_params['classes']),
                        checkpoint_path="checkpoints/Pokemon_yolonas_run/ckpt_best.pth")

Step12. 모델 평가

trainer.test(model=best_model,
            test_loader=test_data,
            test_metrics_list=DetectionMetrics_050(score_thres=0.1,
                                                   top_k_predictions=300,
                                                   num_cls=len(dataset_params['classes']),
                                                   normalize_targets=True,
                                                   post_prediction_callback=PPYoloEPostPredictionCallback(score_threshold=0.01,
                                                                                                          nms_top_k=1000,
                                                                                                          max_predictions=300,
                                                                                                          nms_threshold=0.7)
                                                  ))

Step13. 모델 예측

#-- 테스트 동영상 다운로드
import locale
def getpreferredencoding(do_setlocale = True):
    return "UTF-8"
locale.getpreferredencoding = getpreferredencoding

!gdown "https://drive.google.com/uc?id=1HsCBy8HU0Rqs-nb_mScRXVmLwrY1G3UQ"
input_video_path = f"/content/pokemon.mp4"
output_video_path = "detections.mp4"

best_model.to(device)
best_model.predict(input_video_path, conf = 0.4).save(output_video_path)
from IPython.display import HTML
from base64 import b64encode
import os

# Input video path
save_path = '/content/detections.mp4'

# Compressed video path
compressed_path = "/content/result_compressed.mp4"

os.system(f"ffmpeg -i {save_path} -vcodec libx264 {compressed_path}")

# Show video
mp4 = open(compressed_path,'rb').read()
data_url = "data:video/mp4;base64," + b64encode(mp4).decode()
HTML("""
<video width=400 controls>
      <source src="%s" type="video/mp4">
</video>
""" % data_url)

24

small 모델과 적은 학습으로 인해 높은 결과는 나오지는 않는다. 파라메터 수정 후 테스트 해보면 좋을듯

 

Large + 100번 반복 후 84퍼 정확도 모델 결과

확실하게 이전 모델보다는 잘 인식한다. 더 많은 데이터셋과 파라메터 수정을 하면 좋은 결과 가능할듯

 

25

 

 

[확인용] 실행했던 YOLO-NAS-CUSTOM 파일 

YOLO_NAS_custom.ipynb
4.33MB

 

'ComputerVision > YOLO' 카테고리의 다른 글

YOLO_NAS_SORT 이용하여 people counting  (0) 2023.07.03
YOLO_NAS Tutorial  (0) 2023.07.01
YOLO-NAS  (0) 2023.07.01