오늘은 시각지능_딥러닝의 마지막 날이였습니다.
YOLO의 특징이라 하면 One Stage Detector라는 특징을 가지고 있습니다. 해당 특징으로 말하자면 위치를 찾는 것과 클레스 구분을 동시에 진행해주는 것을 의미하면 YOLO의 버전이 높아질 수록 실시간 Detection하는 성능이 좋아집니다.
우리가 해결하고자 하는 문제에 맞는 이미지를 수집하고 데이터셋 위치, 클레스 수를 수정하고 학습과 Detection까지 같이 진행해보겠습니다.
이런 작업에 앞서 라벨링이 필요합니다. 라벨링이란 문제 맞는 이미지를 찾고 해당 이미지에 대한 x, y, w, h, Class를 직접 만들어주고 정의해야하기 때문에 시간이 오래 걸린다는 단점이 있습니다.
이번 실습은 어제와 보다 높은 버전인 YOLOv5를 사용하여 실습을 진행했습니다.
먼저 실습에 앞서 알아두어야할 사전 지식으러 yaml파일은 모델의 구조를 가지고 있는 파일입니다. 해당 구조를 가져와서 사용하고자 한다면 detected.py를 진행하는 과정에서 --cfg
옵션을 사용합니다. 즉, 구조에 맞는 가중치를 넣어서 학습을 진행하기 때문에 문제해결에 더 빠른 학습속도를 기대할 수 있습니다. 또 옵션으로 --patience
를 사용할 수 있는데 이를 통해 EarlyStopping이 자동으로 내장되어 있음을 알 수 있었습니다.
이제 우리는 Custom yaml을 직접 우리가 해결하고자 하는 문제에 맞게 만들어야합니다. yaml파일 설정과 데이터셋의 구조가 같아야하기 때문에 yaml파일을 만들때는 구조와 클레스 순서를 명시해줄 때 주의해주어야 합니다.
Annotation이란 이미지의 Detection 정보를 별도의 설명 파일로 제공하는 것을 의미합니다.
실습에 들어가기 앞서 먼저 제가 설정한 문제는 사람, 도넛, 커피를 Detection하는 모델을 만들고자함에 있었습니다.
라벨링을 위해 Annotaion Tool인 Ybet Master을 사용했습니다.
이런식으로 사람과 도넛 커피가 있는 사진들을 라벨링 작업을 진행해주었고 30장의 사진에 대해서 라벨링 작업을 했습니다.
앞서 말했듯이 yaml은 파일은 데이터의 구조를 알려줍니다. 먼저 yaml파일의 작성시 path, train, val과 클레스를 명시해주었습니다.
path: /content/drive/MyDrive/주소
train: images/train
val: images/train #train 폴더를 그대로 가져다가 쓸 예정입니다.
#classes
nc: 3
names: ['human', 'dounut', 'coffee']
저는 위와 같이 yaml파일을 작성했습니다.
하나씩 살펴보자면 먼저 path
는 실제 데이터가 저장된 주소를 작성해주면 됩니다. 저는 구글 드라이브와 연동하여 사용하였기 때문에 주소가 /content/drive/MyDrive/
로 시작했습니다. train
과 val
은 학습데이터 경로와 검증 데이터의 경로를 작성해주는데 train 폴더를 그대로 가져다 검증용으로 사용하기 위해 두 개의 경로를 갖게 설정해주었습니다.
다음으로 calsses부분인데 nc는 클레스의 갯수를 표시해주면 됩니다. 저는 사람 도넛 커피 총 3개의 클레스에 대해 라벨링했기 때문에 3을 작성했고 names는 Ybet와 같은 순서인 ['human', 'dounut', 'coffee']
로 작성했습니다. YAML에서의 클레스이름을 표기해줄 때 Annotation의 클레스와 순서가 같아야합니다.
yaml파일은 그냥 메모장에 적고 확장자를 .yaml
으로 설정해주었습니다.
이제 라벨링과 yaml파일의 작성이 완료되었으면 본격적인 모델 작업을 들어가겠습니다.
▶YOLOv5 설치
제 실습 환경은 코랩입니다. 코랩에 YOLOv5를 다운 받아 줍니다.
!git clone https://github.com/ultralytics/yolov5
YOLO를 다운 받고 필요 패키지를 설치시에 에러가 발생할 수 있으므로 아래 코드를 작성해줍니다.
temp_str = 'setuptools<=64.0.2\n'
f = open('/content/yolov5/requirements.txt', 'r')
f_str = f.readlines()
f.close()
f2 = open('/content/yolov5/requirements.txt', 'w')
for idx, val in enumerate(f_str) :
if 'setuptools' in val :
idx_v = idx
f_str.remove(val)
f_str.insert(idx_v, temp_str)
for val in f_str :
f2.write(val)
f2.close()
마지막으로 YOLO의 requirements.txt를 설치해줍니다.
!cd yolov5; pip install -r requirements.txt
먼저 yolov5로 이동해서 필요한 것을 추가적으로 설치해줍니다.
▶사전 라벨링한 것 옮겨주기
저는 라벨링 한 작업물을 구글 드라이브로 옮겼기 때문에 코랩과 구글드라이브를 연결해줍니다.
#코랩이랑 구글드라이브랑 연결
from google.colab import drive
drive.mount('/content/drive')
▶yaml파일 준비
yaml_path = '/content/drive/MyDrive/경로/human_dounut_coffee.yaml'
해당 yaml_path에 드라이브에 있는 제가 만든 custom yaml파일의 경로를 저장해둡니다.
▶Pretrained Weights 다운
YOLOv5의 pretrained 모델을 다운받아 줍니다.
먼저 해당 모델을 저장할 파일을 만들어 줍니다.
!mkdir /content/yolov5/pretrained
코랩 자체 내에서 pretrainde라는 파일을 만들어주고 해당 경로에 저장하겠습니다.
!wget -O /content/yolov5/pretrained/yolov5s.pt https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5s.pt
▶train.py 실행
!cd yolov5; python train.py \
--data '/content/drive/MyDrive/경로/human_dounut_coffee.yaml' \
--cfg '/content/yolov5/models/yolov5s.yaml' \
--weights '/content/yolov5/pretrained/yolov5s.pt' \
--epochs 1000 \
--patience 7 \
--img 640 \
--project 'trained' \
--name 'train_street' \
--exist-ok
먼저 위에 Custom한 yaml파일를 기준으로 YOLO 모델을 학습시키는 것입니다. 주어진 yaml 파일을 이용하여 모델을 생성하고, 해당 모델을 학습시키는 단계라고 보면 됩니다.
먼저 데이터에 내가 만든 yaml의 경로를 --data
에 입력해서 학습에 사용할 yaml의 위치를 지정해줍니다. 다음으로 --cfg
에는 모델 구조를 정의한 YAML 파일의 경로를 지정해야 함으로 yolov5s.yaml파일을 사용할 것이기 때문에 해당 경로로 설정해주었습니다. 이제 patience
를 통해 7번 동안 성능 향상이 없으면 EarlyStopping을 해주도록 설정했습니다.
▶테스트용 이미지 다운
저는 앞서 사람 커피 도넛으로 라벨링을 했기 때문에 해당 사진들이 있는 이미지파일을 다운 받아 놨기 때문에 그냥 코랩에서 파일을 만들고 해당 파일로 이미지를 옮겨두겠습니다.
!mkdir /content/yolov5/data/images
images파일에 테스트할 사진들을 옮겼습니다.
▶Detection 시작(detect.py 실행)
!cd yolov5; python detect.py \
--weights '/content/yolov5/trained/train_street/weights/best.pt' \
--source '/content/yolov5/data/images/' \
--project '/content/yolov5/detected' \
--name 'images' \
--img 640 \
--conf-thres 0.4 \
--iou-thres 0.6 \
--line-thickness 1 \
--exist-ok
그러면 이제 source의 경로에 있는 데이터들을 모두 학습합니다.
▶결과확인
이제 마지막으로 결과확인을 진행합니다.
from IPython.display import Image
from google.colab import files
필요패키지를 불러오고 마지막으로 이미지를 다운 받거나 코랩 내에서 확인하면 됩니다.
Image(filename='/content/yolov5/detected/images/t-8.jpg', width=640)
아래의 결과를 얻을 수 있었는데 커피를 도넛이라하고 다소 아쉬운 결과를 보여주는 것을 확인할 수 있었습니다. 위 사진 말고 다양한 결과 이미지가 있는데 저작권이 무서워서 해당 사진도 일부만 보여드립는게 조금 아쉽습니다.
▶추가
추가적으로 만약 내가 직접 YAML 파일을 만들어서 학습했다면 모든 물체에 대해서 Detection을 해주는 것이 아니라 내가 직접 라벨링에 사용한 클레스에 대해서만 Detection을 해줍니다.
오늘로 시각지능_딥러닝이 끝났습니다. YOLO의 전반적인 사용법과 이론에 대해서 학습했습니다.
※공부하고 있어 다소 틀린점이 있을 수 있습니다. 언제든지 말해주시면 수정하도록 하겠습니다.
※용어에 대해 조금 공부 더 해서 수정하겠습니다.
선생님 안녕하세요,
많은 도움 얻고 갑니다.
질문 드릴 내용은 아래와 같습니다.
Detection 결과에서 도넛에 해당되는 bounding box가 중복되어 나타나는데,
상기 이슈에 대해서 해결하셨을까요?
제가 해본 실험으로는 detect.py 내 NMS 함수를 같은 객체에 대해 유니크한 bounding box가 존재하도록 수정하였지만 bounding box가 중복되어서, iou threshold를 조정하여 bounding box 중복을 해결했습니다만
제 해결방안은 고정된 iou threshold는 다른 데이터에 대해 일반성이 떨어질 수도 있다는 단점 때문에 고민이네요,,,
상기 이슈에 대한 해결방안을 공유해주시면 감사하겠습니다.