[Object Detection] Yolo v1 리뷰 & Python을 이용한 구현

Sion Park·2021년 7월 26일
0

DL

목록 보기
1/2

Yolo 는 You only live once 가 아니라.. You only look once 입니다! Yolo v1으로 말할 것 같으면 최초의 1-step 객체 검출(Object detection)알고리즘 입니다.

1-step 알고리즘이다 보니 real-time 객체 검출에서 아주 좋은 성능을 보이고 그 성능을 입증해 보였죠!

이전의 RCNN을 공부하고 구현하면서 너무 느린 속도가 답답해서 꽤 힘들었던 기억이 있는데 빠르다고 하니 벌써 기분이 좋아지네요.

Motivation and Problems

  • Traditional methods
    -Deformable parts models (DPM): 분류기가 전체 이미지에 걸쳐 일정한 간격으로 실행되는 슬라이딩 윈도우(sliding window) 방식을 사용.
    - regions with convolusional neural network (RCNN): 영역 제안(region proposal) 방법을 사용하여 먼저 이미지에서 잠재적 경계 상자를 생성한 다음 제안된 상자에 대한 분류방식을 사용

기존의 방법들은 정확한 bounding box를 찾기 어렵거나 복잡한 파이프 라인때문에 최적화하기 어려울 수 있고 아주 느린 속도를 보여줍니다. RCNN은 제가 직접 구현해보면서 느낀 것이지만 하나의 이미지에 대해 실행하면 2000번 CNN을 계산하여야 하기 때문에 엄청 느렸습니다.

Yolo는 이를 완화할 수 있었고, CNN을 통한 단 한 번의 계산으로 결과를 나타낼 수 있습니다.

Yolo v1

Yolo는 이미지 픽셀에서 bounding box와 클래스의 확률을 계산하는 간단한 회귀문제로 객체를 탐지하는데 이러한 방식으로 이미지를 딱 1번만 보고 어떤 개체가 있는지, 어디에 있는지 예측할 수 있습니다.

Unified Detection

CNN 을 이용해 unified detection을 수행하는데요. 이를 이용해서 다음과 같은 항목들을 예측합니다.

  1. 우선 그림을 S×SS \times S로 나눈 다음 각 셀에서 객체를 포함하는 BB개의 바운딩박스를 만들고 그 중심좌표와 너비 (x,y,w,h)(x,y,w,h).

  2. B개의 박스별 Confidence. 저자는 박스별 Confidence 를
    Confidence=Pr(Object)IoUpredtruth\hspace{33mm}Confidence = Pr(Object)*IoU^{truth}_{pred}
    라고 정의하였으며, 박스내에 객체가 없다면 0, 있다면 ground truth box 와 prediction box의 IoUIoU값을 갖기를 원한다 라고 쓰여 있네요.

  3. 오브젝트가 있을 경우 CC 개의 클래스별 확률 Pr(ClassiObject)Pr(Class_i \mid Object).

이를 정리해보면 셀별로 BB개의 박스정보와 클래스별 확률 이니까. S×S×(B×5+C)S \times S \times (B\times 5 + C) 텐서를 아웃풋으로 합니다. ( 5 는 [x,y,w,h,Confidence][x,y,w,h, Confidence]의 길이)

Test-time 에는 다음과 같은 식으로 Class 별 Confidence 를 계산한다고 합니다!

Pr(ClassiObject)Pr(Object)IoUpredtruth=Pr(Classi)IoUpredtruth\hspace{13mm}Pr(Class_i\mid Object)* Pr(Object)*IoU^{truth}_{pred} = Pr(Class_i)*IoU^{truth}_{pred}

이 논문에서는 VOC 데이터 셋의 클래스의 수가 20개이므로 C=20C = 20이고 SSBB는 각각 7과 2로 두었습니다.

Network Design

  1. 우선 이미지의 input 은 448×448448 \times 448 입니다. 들어가는 모든 이미지를 인위적으로 조정하여 줍니다.
  1. 노란색 선까지 20개의 CNN은 ImageNet data를 통해 pretraining 해줍니다. ( RCNN에 쓰였던 supervised pretraining 방법입니다.)

  2. 이후 4개의 Convolution 레이어와 2개의 fully connected 레이어를 fine-tuning 하여줍니다.

  3. 마지막 레이어는 그림의 grid cell 별 바운딩박스와 class probablity를 예측합니다.

여기서 활성함수는 0.1 Leaky ReLU를 이용하여줍니다!

0.1 Leaky ReLU란 다음의 그림과 같이 함수의 인자가 0보다 크면 같은 값을 갖지만 0보다 작을 경우 0.1배의 값을 가지게 하는 것입니다.

Loss Function

제 생각에 가장 중요하다 생각되는 loss function인데요. 한번에 바운딩박스와 confidence 그리고 class별 확률에 대한 loss를 포함하기 때문에 yolo가 1-step 알고리즘이 될 수 있지 않았나 생각합니다. 그럼 loss를 보시죠!

이 loss function이 굉장히 간단해 보일 수 있지만 모호한 부분이 굉장히 많았습니다!

이 loss function을 정확히 이해하기 위해서는 'responsible'이라는 개념을 알아야 하는데요.

이것은 간단히 설명하면 ground truth box의 중심이 위치하는 Grid cel 의 2개의 bounding box 중 ground truth box와의 iou가 가장 큰 bounding box를 말합니다. 즉, 98개의 bounding box 중 한 물체에 대해 하나의 responsible bounding box가 존재하는 것이죠!

  • 1iobj\mathbb{1}^{obj}_{i}는 ground truth box의 중심이 ii-th Grid cell에 있는지를 보여주는 indicator function 입니다.

  • 1ijobj\mathbb{1}^{obj}_{ij}ii cell에 있는 jj bounding box 가 responsible 임을 나타내는 indicator function 입니다.

  • 1ijnoobj\mathbb{1}^{noobj}_{ij}1ijobj\mathbb{1}^{obj}_{ij} 와 반대의 경우로 (11ijobj)\left(1 - \mathbb{1}^{obj}_{ij}\right)이라고 보시면 될 것 같네요!

이제 이 loss function을 단계별로 알아보겠습니다.

  1. 첫 번째 줄과 두 번째줄은 bounding 박스의 위치와 크기에 대한 loss로 보입니다. 두번째 줄의 wwhh 에 제곱근을 이용한 것은 작은 박스의 경우 예측오차가 상대적으로 작아져 작은 박스만을 찾게 되는 것을 조금 완화하고자 한 것이라고 합니다!

  2. 세 번째 줄과 네 번째 줄은 Confidence에 대한 loss입니다. 이 논문에서는 λcoord=0.5,λnoobj=5\lambda_{coord} = 0.5, \lambda_{noobj} = 5로 설정하였는데요 그 이유는 객체가 없는 Grid가 훨씬 많기 때문이라고 합니다!

여기서 특이한 것은 loss function의 목적함수에 트루값과 예측값이 모두 관여하게 되는데, 이게 무슨말이냐하면 Confidence가 Ground truth box와 예측한 bounding box의 IoUIoU 계산을 통해 구해진다는 것입니다!

  1. 다섯 번째 줄은 class분류에 대한 soft-max의 loss로 보입니다!

여기서 confidence와 class probability의 loss를 제곱합으로 처리했다는 부분은 조금 의아하네요! 보통 이러한 경우에는 cross entropy loss를 이용하는데 말이죠..?

Inference


이제 학습된 CNN을 통해 결과를 표현해 볼 시간입니다! 위 그림이 그 과정을 잘 보여주고있습니다. 아마 잘안보이실텐데 아래 설명을 보시고 다시 보시면 이해가 되실겁니다!

  1. Output으로 얻어지는 7×7×307\times 7\times 30 tensor를 통해 추정된 98개의 bounding box를 얻습니다.

  2. 클래스별로 확률이 미리 지정된 Threshold를 넘는 박스만을 남깁니다.

  3. 남은 박스들 사이에서 class별 스코어를 이용해 non-maximum suppression을 해주어 최종적인 박스만을 출력하게 됩니다.

Non-maximum suppression 은 그림에도 설명이 되어있으나 RCNN 포스트에서 한번 다룬적이 있으니 그 글을 보셔도 좋을 것 같습니다!

Limitation

우선 Yolo의 가장 큰 한계점은 그리드 셀 하나에 물체가 하나만 있어야 한다는 강한 가정이 필요합니다. 예를 들어 새떼처럼 작은 물체가 무리를 지어다니는 경우 이를 감지해내지 못하게 되죠.

또한 손실함수에서 IoUIoU를 이용하는데 이 부분에서 작은 상자가 큰 상자에 비해 더욱 예민하게 반응하게 된다는 것 또한 문제라고 합니다!

궁금하신 부분이 있다면 댓글 부탁드립니다. 또한 틀린것이 있다면 자유롭게 지적부탁드립니다!

Python Code

Pytorch를 이용해서 구현된 코드는 다른 데서 많이 찾아볼 수 있었으나, Tensorflow를 이용한 코드는 많이 없어서 Tensorflow로 구현해 보았습니다. 커스텀 Model과 Loss 클래스를 만드는 작업을 처음 해봤는데 쉽지않네요... pretrained network를 다운로드할 수 없어 구현만 해 보았고, 다운로드가 된다면 결과도 나중에 첨부하겠습니다!

profile
Statistician, Data Analyst

0개의 댓글