다시 이음

Python TensorFlow기반 Yolo 모델 구현하기 ( Object Counting, Customize, Colab ) 본문

프로젝트

Python TensorFlow기반 Yolo 모델 구현하기 ( Object Counting, Customize, Colab )

Taeho(Damon) 2022. 2. 11. 16:21

안녕하세요.

 

오늘은 딥러닝 프로젝트를 진행하고 나서 그 후기를 전달드리려고 합니다.

 

이 글은 현재 Python을 공부하시면서 TensorFlow 라이브러리를 사용하여 Yolo 모델을 구현함과 동시에 Object counting 기능과 Custom 학습도 병행하시길 원하는 분들께 도움이 되는 글입니다.

 

필자는 Mac air(M1)을 사용중으로 GPU 학습이 불가한 환경으로 Colab 환경에서 GPU를 활용하여 구현하도록 하겠습니다.

 

 

Project : Python TensorFlow기반 Yolo 모델 구조 원리 이해 및 구현하기  ( Object Counting, Customize ) 프로젝트


 

프로젝트 선정 이유

1. 관심사

  • 자율주행과 물류

2. 문제점

  • 물류 분야에서는 코로나로 인해 물동량이 코로나 이전보다 급격히 상승되었고 상승한 물동량을 제대로 처리하지 못하는 물류 대란이 일어나기도 했습니다.
  • 이러한 과부하로 업무량이 늘어나면서 물류 종사자들의 파업 과 과도한 업무가 문제가 되기도 했습니다.

3. 해결방법

  • 이러한 문제를 해결하기 위해 이전부터 글로벌 물류 기업인 아마존, 알리바바 등에서는 로봇AI를 사용하여 창고 수용량과 효율성을 높히기 위해 노력하고 있습니다.
  • 물류 창고에서의 상품 보관 및 선별, 포장, 배송, 재고관리를 모두 관리하는 풀필먼트(통합물류서비스)에서 업무의 효율성 증진, 종사자의 업무 편의성 증진을 위해서 AI로봇의 도입은 필요합니다.

프로젝트 목표

 

  • 자율 주행과 물류AI로봇에서 사용되는 Object Detection 기술을 구현함으로써 차세대 중요 기술의 기초적인 지식을 쌓는 것에 목표를 두고 있습니다.

 

프로젝트 진행 방향

 

  1. Object Detection에 대한 기본 지식과 Yolo v3,4모델에 대한 이해
  2. C언어로 작성된 물체 인식 오픈 소스 신경망(Darknet)으로 학습된 대중적인 가중치를 사용하여 구현예정.
  3. C언어로 작성된 가중치를 TensorFlow에 적용하기 위해 변환이 필요하고 변환 후 TensorFlow를 사용하여 YOLO v3,4 모델을 통해 Object Detection 구현 (Basic Target)
  4. 추가 기능 Total Object counting, Class counting 구현
  5. 커스텀 학습 후 실험 (Advanced Target)

Yolov4의 구조 이해

 

1. backbone network : Darknet53

 

  • backbone 이란? classification용으로 만든 pre-trained 모델(ResNet등)을 FC layer부분을 바꿔 다른 용도인 Detection, Segmentation, Pose Estimation 등으로 사용하는 것.
  • 기존의 목적이었던 분류 기능(FC layer)를 유지하되 사전학습된 Dataset 가중치를 그대로 가져가 사용하는 Transfer-learning과 사전학습된 가중치를 새로운 Dataset을 통해 조정하여 다른 용도로 사용하는 Fine-tuning과 구분해야한다.
  • C언어를 기반으로 하기 때문에 Python에서 구현한 모델(TensorFlow, Pytorch)을 사용할 때에 가중치를 변환시켜주어야 합니다.

 

2. Head : Yolo v4

 

Object Detection에선 classification과 localization을 어떻게 수행하느냐에 따라서 two-stage detector(나누어 수행)와 one-stage detector(동시 수행)로 모델이 구분되고 그 하위에서는 Anchor의 사용 유무로 Anchor-based, Anchor-free 로 분류 됩니다.

 

 

(1) classification / localization

  • object가 있을 법한 위치의 후보(proposals) 들을 뽑아내는 단계(Region proposal)와 실제로 object가 있는지를 Classification과 정확한 바운딩 박스를 구하는 Regression을 수행하는 단계

 

  • 두 단계를 순차적으로 수행하는 경우 : Two-stage detector

two-stage detector

  • 두 단계를 동시에 수행하는 경우 : One-stage detector

one-stage detector

 

(2) Anchor-based, Anchor-free

  • Anchor Box의 핵심은 사전에 크기와 비율이 모두 결정되어 있는 박스를 전제로, 학습을 통해서 이 박스의 위치나 크기를 세부 조정하는 것입니다.
  • 논문에선 2개의 박스를 그리드마다 적용하여 regression 하고 class를 구분한다고 설명합니다.

(3) Yolo 특징

  • Yolo v4는 Anchor-based One-stage detector로 two-stage detector보다 실행 속도가 빠릅니다.(가장 빠른 객체 검출 알고리즘)
  • 단점으로는 작은 물체를 구별하기 어렵다는 점이 있습니다.
  • Yolo는 backbone 모델을 기반으로 하며 특징 추출기(Feature Extractor)라고도 불립니다.

(4) 작동 순서와 원리

  • 이미지가 1:1의 비율을 가지도록 전처리합니다.
  • s x s의 그리드로 이미지를 나누어 한 개의 그리드당 n개의 Anchor를 대입하여 Class Confidence Score를 계산합니다.
  • 계산된 Class Confidence Score는 C(conditional class probability=클래스의 개수)와 각 박스의 Po(confidence score=object가 있을 확률)를 곱하여 한 박스에 대해 구합니다.
  • 위의 과정을 거치면 (s x s 그리드 개수) x ([Anchor 개수=n개 * 5개(기본정보)]+클래스 개수) 만큼 정보가 생성됩니다.(아래의 output값 구하기 참고)
  • NMS(Non-Maximum Suppression) : object가 있을 확률이 가장 큰 BBox와 겹치는 상자들과 임계값을 넘지 못하는 상자들을 제거하는 과정을 거쳐 최종 BBox를 출력합니다.

(5) 최종 output값 구하기 (그림2 참고)

  • Anchor(바운딩 박스)당 가지고 있는 정보로는 Bx(x축 포인트값), By(y축 포인트값), Bw(박스 넓이), Bh(박스 높이), Po(object확률)로 5개가 기본적으로 있습니다.
  • 거기에 클래스 개수별로 확률값을 하나하나 가지기 때문에 클래스 개수값 만큼의 정보를 가지게 됩니다.
  • 예를들면 Grid가 4x4, Anchor가 2개, 클래스가 20개일 경우, 하나의 셀당 (2x5)+20 = 30의 정보를 가지며 (4,4,30)의 output 형태를 가지게 됩니다

[그림2]

 

3. 평가지표

  • IOU(Intersection Over Union) : 실측값(Ground Truth)과 모델이 예측한 값이 얼마나 겹치는지를 나타내는 지표(그림3 참고) 
    [그림3]
  • Precision(정밀도), recall(재현율) : Object Dectection 기술이 사용되는 분야에서는 특징에 따라 정확도를 높여 필요한 객체를 탐지해야하는 경우, 기준을 낮추어 최대한 많은 객체를 탐지 해야하는 경우도 있습니다. 이러한 경우 임계값 조정을 통해 원하는 결과를 얻도록 조정해야합니다.
예시
(1) 자율주행 중 사람을 확인하여 정지해야하는 경우는 사람을 절대적으로 피해가야 하기 때문에 재현율을 높여 사고가 발생하지 않도록 해야합니다.
(2) 투자 기회를 탐지하고 있다면 일부 기회를 놓치게 되더라도 잘못된 기회에 돈을 거는 일을 피하기 위해 정밀도를 높여야 합니다.

 

  • AP (Average Precision, 평균 정밀도) 와 mAP(mean Average Precision)
    • ROC 곡선 그래프의 아래 영역에 해당하는 값
    • 단일 클래스의 AP 값을 구하고 평균을 통해 mAP를 구하여 평가지표로 활용합니다.

Loss(파란색), mAP(빨간색)

 


구현 진행

-YOLO v3 : 이수안 컴퓨터 연구소 유튜브 - 객체 탐지 YOLO의 모든 것 참조

-YOLO v4 Deep sort : The AI Guy 유튜브 - YOLO v4 in the CLOUD 참조

 

저는 구현하기에 앞서 이론에 대한 이해를 높이고 유튜브를 통해 구현하는 방식에 대한 도움을 받으면서 프로젝트를 진행하였습니다.

 

물론 YOLO v4 Deep sort 구현을 할 때에는 1년 전 동영상이다 보니 TensorFlow 버전, cudnn 버전, CUDA toolkit 버전을 맞춰주셔야 해당 영상을 보시면서 구현이 가능합니다.

 

클래스 별 counting 기능의 경우, YOLO v4 Deepsort 모델에 탑재되어 있는 기능은 아닙니다.

 

The AI Guy가 배포한 다른 Git 레포지토리에서 관련된 클래스 별 counting 부분을 추출하여 Deepsort 모델에 탑재시켜서 진행하였습니다.

 

결과 확인

<YOLO v4 Deep sort model 구현>

 

1. 기본적인 sort 진행

 

2. Object counting 기능 구현

 

3. 클래스 별 counting 기능 구현

 

3-1. 클래스 별 counting 기능 구현 다른 영상

 


<YOLO v4 customized 구현>

 

Darknet(https://github.com/AlexeyAB/darknet)을 통해 기본 가중치 값을 활용하여 약 160개 이미지가 있는 마스크 데이터셋(roboflow 출처)을 학습시키고 최종적으로 그래프와 test 이미지를 통해서 확인했습니다.

 

 

Customize 순서

 

위에서 Darknet을 clone하고 커스텀 학습할 이미지 데이터셋이 준비된 후에 해당 과정을 진행하시면 됩니다.

 

 

1. Darknet cfg 복사 ( cfg, config = 소프트웨어에 특정한 설정을 저장하는 데 사용되는 구성 파일 )

 

cfg의 파라미터를 조정하여 커스텀 학습하기 위해 기존 yolov4-custom.cfg 파일을 복사하여 yolov4-obj.cfg 파일을 만들어줍니다.

!cp ./darknet/cfg/yolov4-custom.cfg ./darknet/cfg/yolov4-obj.cfg

 

 

2. 복사한 yolov4-obj.cfg의 파라미터 조정

 

  1. batch size = 64 or 32 ( size가 작을 수록 학습시간이 오래걸리나 좋은 성과를 낼 수 있습니다.)
  2. subdivisions=16
  3. max_batches = 6000 (최소 6000 권장, 클래스 개수x2000 정도로 설정)
  4. steps = 4800, 5400(max_batches의 80%, max_batches의 90%로 설정)
  5. classes = 2(클래스 개수) , filters = 18((클래스 개수 + 5)*3)
  6. image width = 416, image height = 416(최소32, 416,608이 기준)

 

 

3. 이미지 데이터셋 이름 리스트 만들기 (train.txt, valid.txt, test.txt)

 

from glob import glob

# 지정한 위치폴더 안에 .jpg 확장자 명으로 된 모든 파일의 이름을 리스트로 변환
train_img_list = glob('/darknet/build/darknet/x64/data/train/*.jpg')
test_img_list = glob('/darknet/build/darknet/x64/data/test/*.jpg')
valid_img_list = glob('/darknet/build/darknet/x64/data/valid/*.jpg')

print(len(train_img_list),len(test_img_list),len(valid_img_list))

# 이미지 이름 리스트를 txt에 저장
with open('/darknet/build/darknet/x64/data/train.txt', 'w') as f:
    f.write('\n'.join(train_img_list) + '\n')

with open('/darknet/build/darknet/x64/data/test.txt', 'w') as f:
    f.write('\n'.join(test_img_list) + '\n')

with open('/darknet/build/darknet/x64/data/valid.txt', 'w') as f:
    f.write('\n'.join(valid_img_list) + '\n')

 

 

4. obj.data, obj.nams 파일 작성하기

 

1) obj.names의 형식

 

주의할 점으로 annotation 파일(데이터셋에 img파일과 같이 있는 txt 파일)을 열어서 클래스가 어떻게 매핑되어있는지 확인해야합니다.

임의로 지정한 경우 라벨링의 순서가 바뀌어 학습 후에 반대로 결과를 내보낼 수 있습니다!!

 

예시)

un_mask (class 1 이름)

mask (class 2 이름)

 

 

2) obj.data의 형식

 

classes = 2 ( 클래스 개수 )
train = 현재데이터위치/darknet/build/darknet/x64/data/train.txt
valid = 현재데이터위치/darknet/build/darknet/x64/data/valid.txt
test = 현재데이터위치/darknet/build/darknet/x64/data/test.txt
names = 현재데이터위치/darknet/build/darknet/x64/data/obj.names
backup = 현재데이터위치/darknet/build/darknet/x64/backup/

 

 

 

5. 가중치 다운로드(conv layer 가중치)

#사전 훈련된 가중치 다운로드 -- Fine-tuning과 비슷한 과정을 거치기 위함
#저장위치 (/darknet/build/darknet/x64)
!wget https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.conv.137

 

 

6. 데이터 학습

 

설정한 위치에 맞게 obj.data 파일, yolov4-obj.cfg파일, yolov4.conv.137 가중치파일을 지정하고 실행하면 학습이 진행됩니다.

!./darknet detector train build/darknet/x64/data/obj.data cfg/yolov4-obj.cfg build/darknet/x64/yolov4.conv.137 -dont_show -map

--map 기능을 사용하면 iteration마다 학습되는 것을 시각화 할 수 있습니다.

(저의 경우에는 학습시간이 결코 작지 않았습니다. 4시간 이상은 돌렸을 때 유의미한 정확도를 보였습니다.)

 

정보

🌧  학습이 오래걸리기 때문에 Colab GPU 메모리나 사용시간이 초과되어 멈추는 경우가 빈번합니다..

☀️  학습한 가중치는 backup 폴더에 yolov4-obj_1000.weights, yolov4-obj_best.weights, yolov4-obj_last.weights 로 저장이 됩니다. 그렇기 때문에 중간에 런타임 오류가 나더라도 데이터 학습 시 yolov4.conv.137대신 yolov4-obj_last.weights로 학습을 하면 이어서 학습이 가능합니다.

 

 

7. 결과 확인

 

# test 확인하기 위해 cfg 변경해주기
%cd cfg
!sed -i 's/batch=64/batch=1/' yolov4-obj.cfg
!sed -i 's/subdivisions=16/subdivisions=1/' yolov4-obj.cfg
%cd ..

# 연동된 구글드라이브에 테스트할 데이터를 넣어주고 실행하세요
!./darknet detector test build/darknet/x64/data/obj.data cfg/yolov4-obj.cfg build/darknet/x64/backup/yolov4-obj_last.weights build/darknet/x64/data/mask.jpeg -thresh 0.6
imShow('predictions.jpg')

 

제대로 학습되지 않았을 경우

 

학습을 끝마친 경우

 

 

프로젝트 느낀 점

 

이렇게 TensorFlow기반 YOLO 모델을 CLOUD 환경에서 구현해보고 커스텀 해보는 시간을 가졌습니다.

 

저는 딥러닝에 대한 이해가 부족했기 때문에 YOLO를 구현하기 위해서 여러가지고 원리, 구조 이해를 거쳐서 많은 도움이 되었습니다.

 

아쉬운 점

 

커스텀할 데이터를 라벨링하는 방법도 확인해보았는 데 직접 실행하지 못한게 아쉽습니다.

 

추후에 시간을 내서 이미지를 라벨링해서 저장하는 부분도 진행을 해보는 보완 과정을 거치도록 하겠습니다.

 

긴 글 읽어주셔서 감사합니다.