이번 포스터에서는 Object Detection 모델인 YOLO(You Only Look Once)에 대해 알아보자. YOLO는 You Only Look Once: Unified, Real-Time Object Detection이라는 논문에서 발표되었다. RCNN계열의 Object Detection이 높은 정확도를 보이면서 Detection분야에서 왕관을 차지하고 있었지만, YOLO가 비록 정확도는 비교적 낮지만 속도를 획기적으로 향상시킨 모델이다.
YOLO 개요
Object Detection을 하기 위해서는 여러 단계를 거쳐야한다. 먼저 image가 Input으로 들어오면 Image로부터 Feature를 추출하고, 물체가 있을법한 부분에 bbox를 생성하고(Region Proposals) 각 bbox의 objectness scroe와 classification, bbox regression 등을 수행한다. 이전 연구에서는 RCNN계열이 좋은 성능을 보이고 있었는데, 단계가 매우 복잡하고 속도가 느리다는 문제점이 있었다. 이러한 문제점을 해결하기 위해 YOLO가 탄생하게 되었다. YOLO의 장점은 다음과 같다.
- 속도가 매우 빠르다.
- 결과의 원인을 설명할 수 있다.
- Detection을 일반화할 수 있는 요소를 학습한다.
YOLO는 Faster RCNN모델 이후에 등장한 Object Detection모델이다. 풀네임은 You Only Look Onces인데, 이름에서도 알 수 있듯이 한 번만 보고도 물체를 탐지하는 것이 특징이다. 기존에 모델들은 detection을 하는 과정이 여러 단계로 나눠져있었지만, YOLO의 경우 단계들이 하나의 시스템으로 합쳐진 모델이다. 따라서 모델의 architecture가 매우 simple하고 속도가 매우 빠르다는 특징이 있다. YOLO모델에서 중점적으로 봐야하는 요소는 다음과 같다.
- Unified Model(1-Stage vs 2-Stage)
- Grid Cell(Region Proposals)
- Loss Function(sum-squared error, Multi-part loss function)
- Leaky ReLU(화성화 함수)
YOLO 구조
YOLO의 구조를 보면 다음과 같다.
YOLO의 Forward 과정은 다음과 같다.
- Input 이미지를 입력한다.
- CNN Layer를 거쳐 Feature를 추출한다.
- FC Layer를 거쳐 (2)번에서 추출한 Feature를 조합한다.
- 사전에 정의한 Grid Cell의 크기와 class개수, bbox개수에 맞게 (3)번 결과를 Reshape한다.
- Grid Cell: 7x7($S$) / class개수: 20($C$) / Cell당 bbox개수: 2($B$)
- 최종 Output은 $S \times S \times(B * 5+C) = (7 \times 7 \times 30)$
- $B*5$에서 $5$는 bbox좌표$(x,y,w,h)$와 Confidence Score
- Output 1개의 cell당 포함된 요소$(x,y,w,h,confidence,class확률)$
- 각 cell별로 생성된 bbox별로 confidence socre와 class score를 곱한다.(총 98개의 bbox)
- (5)번의 결과 중 Threshold(0.2)보다 낮은 값은 모두 0으로 대체
- 0 class부터 내림차순으로 bbox들을 정렬
- (7)번의 결과에 NMS적용
- (8)번의 결과로 나온 bbox중 class score가 모두 0인 bbox는 삭제
- (9)번에서 살아남은 bbox에 argmax를 적용해 class 부여
- 원본 이미지에 (10)번 bbox 출력
글로만 읽으면 진행방식이 정확히 그려지지가 않는다. 따라서 YOLO의 특징을 설명하면서 동시에 Forward과정도 더 자세히 다루기로 하자.
Unified Model(1-Stage vs 2-Stage)
Object Detection모델은 크게 2가지로 분류할 수 있다. 가장 큰 차이점은 이미지 내에서 물체가 있을법한 지역을 미리 설정하고 해당 부분에 Detection과 classifier, box regression을 적용하는 2-Stage(a)모델과 따로 후보군을 생성하지 않고 바로 Detection을 하는 1-Stage(b)모델이 있다. 또한 2-stage 모델은 class와 bbox좌표를 다른 과정을 통해 구하는 반면 1-stage모델은 두 요소를 한 번에 예측을 한다. 아래는 두 모델을 나타낸 사진이다.
2-Stage의 대표적인 모델로는 RCNN계열이 있다. RCNN의 경우 Selective serach알고리즘이나 Region Proposal Network를 이용해 물체가 있을법한 지역을 잘라내 후보(Region Proposlas)를 생성하고, 각 후보들에 Detection을 적용한다. Proposals를 생성하는 과정에서 많은 시간이 소요되기 때문에 전체적으로 모델의 속도가 느리다. 하지만 이와 반대로 YOLO는 전체 과정을 하나의 process로 Unified함으로서 정확도를 유지한 상태에서 연산 시간을 획기적으로 향상시켰다. 이러한 변화 덕분에 YOLO는 real-time application에 적용될 수 있을 정도로 매우 빠른 모델이 되었다.
하지만 YOLO도 Detection을 하기 전에 후부군을 생성하는 과정을 거친다. 하지만 RCNN계열(약 2000개)에 비해 YOLO(약 98개)의 Region Proposals의 개수가 월등히 적기 때문에 연산량에 영향을 주지 않는다. 또한 YOLO의 경우 Region Proposals를 하는 과정에서 특별히 사용되는 알고리즘이 없기 때문에 시간소요가 크지 않다. 따라서 YOLO는 Region을 예측하기 보다는 Grid Cell이라는 방식을 이용해 따로 Proposal를 해주지 않고 Process내에서 비교적 자연스럽게 bbox를 생성한다.
Output Channel
YOLO를 이해하기 위해서는 먼저 YOLO의 Output의 특징에 대해 알아야한다. 위에서 YOLO는 Unified Model라고 했는데, RCNN계열과 다르게 후보군을 생성하는 단계 뿐만 아니라 objectness score와 classification, box regression이 한 번에 진행된다. 즉, objectness와 class의 score, bbox의 좌표값를 동시에 예측한다는 뜻이다.
위 사진에서 7x7x30으로 출력된 부분이 output channel의 shape이다. output의 size인 7x7은 밑에서 다루게 될 Grid Cell이고, 30개의 channel에 objectness(Confidence) score와 class score, bbox의 좌표가 모두 포함되어 있다. $(x,y,w,h)$는 각각 Region bbox의 중심 좌표$(x,y)$와 길이$(w,h)$를 나타낸다. $obj score$의 경우 물체가 존재할 확률인 Confidence score를 말하고 class probability부분은 각 class별로 해당 class일 확률을 나타낸다. 모든 class의 확률값이 출력되는데, 이 값들 중 가장 큰 값이 해당 bbox의 class가 되는 것이다.
그림을 자세히 보면 output channel의 길이가 $5B + C$인것을 알 수 있는데, $B$는 각 grid cell별로 출력하는 bbox의 개수이다.
Grid Cell
YOLO는 Grid Cell이라는 방식을 사용했다. 이미지를 SxS개의 Grid로 나누고 각각의 공간을 cell이라고 칭한다. Cell 안에는 bbox의 정보$(x,y,w,h,confidence)$와 class probability가 포함되어있다. 특히 confidence score는 다음과 같이 정의된다.
$\operatorname{Pr}(\text { object })$은 물체가 해당 cell에 존재할 확률을 말한다. IOU는 Intersection over Union으로 정답과 예측된 bbox의 IOU값을 사용한다.
각각의 Grid cell은 class의 조건부확률인 $\operatorname{Pr}(class_i \mid object)$를 예측한다. 각 cell마다 생성하는 bbox의 개수에 상관없이 cell당 1개의 class만 예측한다. Test시에는 class-specifc한 confidence를 구하게 된다.
결과적으로 class-specific confidence와 IOU값을 곱한 값이 각 grid cell의 confidence값이 된다.
Forward Detail
위 내용만 봐서는 YOLO의 정확한 forward과정이 머릿속으로 그려지지 않는다. 그래서 YOLO의 inference과정을 자세히 설명하고자 한다. 러시아 형님들이 정리해놓은 PPT자료를 참고했다. 편리함을 위해 파라미터를 정의하면 다음과 같다.
- S: Grid Cell의 사이즈, $S=7$
- C: class의 개수, $C=20$
- B: 1개의 cell당 생성할 bbox 개수, $B = 2$
1. Feature Extracion & Output Channel
먼저 CNN Layer와 FC Layer를 통해 Feature를 추출하고, 위에서 언급한 Output Size로 reshape했다. 1개의 cell당 2개의 bbox를 생성했기 때문에 총 길이는 30이 되고, 앞 부분에는 각 bbox의 정보가 출력되고 뒤에는 Cell의 $\operatorname{Pr}\left(Class \mid Object \right)$가 출력된다. 즉, 1개의 cell에 bbox가 여러개 생성되어도 class probability는 1개만 출력된다.
2. Class Score per bbox
다음은 NMS를 하기 위한 사전작업이다. Cell에 있는 각 bbox별로 confidence값과 class probability를 곱해 class별 score를 계산한다. $C=20$로 설정했기 때문에 각 bbox별로 20개의 class score가 산출된다. 모든 상자에 대해 이와 같은 계산을 실시한다. 따라서 $7(S) \times 7(S) \times 2(B) = 98$개의 class score가 발생한다.
3. Before Non-Maximum Suppression
98개의 bbox들은 서로 겹쳐진 부분이 많다. 특히 같은 cell에서 생성된 bbox의 경우 겹쳐질 확률은 매우 크다. 따라서 비슷한 위치에 있는 bbox들을 class score를 기준으로 NMS를 적용해야한다. 하지만 NMS를 적용하기 전에 각 class별로 사전작업을 실시한다. 아래는 dog class를 예시로 사용했다.
- bbox별로 해당 class의 score가 특정 threshold를 넘지 못하면 0으로 대체한다.
- Class score를 기준으로 bbox들을 내림차순으로 정렬한다.
- NMS를 적용한다.
위 과정은 class별로 진행된다.
4. Non-Maximum Suppression
위 과정을 통해 준비가 되었으면 NMS를 적용한다. NMS를 적용하는 방식은 다음과 같다.
- Class score가 가장 높은 bbox(A)를 기준으로 다음 score의 bbox(B)와 IOU를 계산한다.
- IOU값이 특정 Threshold(0.5)를 넘으면 두 bbox는 같은 물체로 간주하고 bbox(B)의 score를 0으로 대체한다.
- 만약 IOU값이 threshold보다 작으면 다른 물체로 간주하고 다음 bbox로 넘어간다.
- 첫 번째 bbox(A)를 기준으로 모두 완료했으면 score가 0이 아닌 다음 bbox를 기준으로 (1)~(3)번 과정을 반복한다.
위 과정을 통해 살아남은 bbox들 중에는 여러 class가 동시에 살아남은 bbox가 존재할 수 있다. 왜냐하면 NMS과정을 class별로 진행을 했기 때문이다. 총 98개의 bbox중 dog class가 1 bbox에 대해 0.1로 존재하고 나머지는 0이라고 했을 때 이 bbox에는 dog가 있다고 판단이 되기 때문이다. 따라서 NMS가 끝난 후에는 class별이 아닌 bbox별로 가장 높은 score를 낸 class를 추출해야한다. 그 class가 곧 bbox가 예측한 class가 되기 때문이다.
- 각 bbox별로 가장 높은 score와 index(=class)를 추출한다.
- Score가 0보다 크면 해당 bbox는 탐지를 했다고 간주하고 원본 이미지에 bbox를 그린다.
위 과정을 통해 YOLO모델의 구조를 파악했다. 그렇다면 이 모델은 어떻게 학습을 할까?
Loss Function
YOLO에서 사용하는 Loss함수는 약간 복잡해보인다. 아래는 논문에 나와있는 Loss의 수식이다.
여러 상황별로 loss를 계산하기 때문에 다소 복잡해보일 수 있지만, 자세히보면 모두 sum-squared error를 사용하고 있다는 사실을 알 수 있다. 크게 2파트로 나눠서 loss함수를 이해해보자.(loss함수를 찢기전에 파라미터들을 간단히 정의하겠다.)
- $x,y,w,h,C$: 예측된 bbox에 대한 좌표와 confidence값
- $\hat{x},\hat{y},\hat{w},\hat{h},\hat{C}$: 정답 bbox에 대한 좌표와 confidence값
- $\lambda_{coord}$와 $\lambda_{noobj}$: 물체가 탐지됐을 때와 안 됐을 때 발생하는 loss의 비율을 조절
- $\mathbb{1}_{i j}^{\text {obj }}$: 물체가 있을 때 $i$번째 Cell에 있는 $j$번째 bbox
- $\mathbb{1}_{i j}^{\text {noobj}}$: 물체가 없을 때 $i$번째 Cell에 있는 $j$번째 bbox
- $p_i$: $C$는 class probability에 confindence값을 곱한 것이라면, $c$는 단순히 class probability
먼저 loss함수의 앞부분인 물체가 있을 때 loss가 발생하는 파트이다. 물체를 얼마나 잘 탐지했는지에 대해 패널티를 부여하는 부분이다. 먼저 $i$와 $j$는 각각 cell과 bbox의 index를 말한다. $\sum$을 잘 보면 각각 $S$와 $B$를 나타내고 있기 때문이다. 따라서 $\mathbb{1}_{i j}^{\text {obj }}$는 $i$ cell의 $j$ bbox에 물체가 있을 때를 나타낸다. 그리고 각 bbox의 좌표와 가로,세로에 대한 sum-squared error를 구해준다.
다음은 loss함수의 뒷부분인 물체가 없을 때 loss가 발생하는 파트이다. 물체가 있는데 없다고 판단했을 때 부여하는 패널티이다. 물체가 있든 없든 bbox는 1 cell마다
$\lambda_{coord}$와 $\lambda_{noobj}$를 사용한 이유
논문에서는 sum-squared error가 매우 심플하고 구현하기 쉽지만 어울리는 loss는 아니라고 한다. 그 이유는 localization와 classification은 다른 테스크인데도 불구하고 각각 발생하는 loss의 가중치를 같다고 두기 때문이다. 또한 대부분의 cell에는 물체가 존재하지 않는다. 그래서 물체가 없는 경우에 발생하는 loss가 압도적으로 많기 때문에 학습 시 매우 악영향을 준다. 따라서 물체를 탐지했을 때와 물체가 없을 때의 loss에 서로 다른 가중치를 주기 위해 위와 같은 파라미터를 사용했다.
$\sqrt{w}$ 와 $\sqrt{h}$를 사용한 이유
Loss함수를 보면 좌표는 그대로 차를 구했지만, 가로와 세로에는 루트를 씌여 차이를 계산했다. 그 이유는 sum-squared error가 큰 bbox의 길이변화와 작은 bbox의 길이변화에 대해 같은 가중치를 갖는다는 가정을 하기 때문이다. 따라서 두 차이를 크게 하기 위해 루트를 사용한 것이다.
Leaky ReLU
YOLO의 특징 중 하나는 마지막 출력을 제외하고 대부분의 layer에서 활성화 함수를 Leaky ReLU를 사용했다는 점이다. 이전 연구들에서 사용한 활성화 함수는 ReLU인데, 왜 YOLO는 Leaky ReLU를 사용한걸까?
Leaky ReLU의 특징은 음수 부분에서도 활성화가 된다는 것이다. 음수 부분은 모두 0으로 처리하는 ReLU와 다르게 입력값이 음수가 들어와도 활성화가 된다는 뜻이다. 이러한 특징은 다음과 같은 장점이 있다.
- 노드가 죽어버리는 ReLU의 문제점인 ‘Dying ReLU’ 문제를 해결한다.
- 학습 시 더 빠르다. 즉, ReLU보다 더 ‘balanced’하고 mean activation이기 때문이다.(zero-mean activation function과 같은 원리)
논문에서 Leaky ReLU를 자세히 언급하지 않아서 사용한 이유는 정확히 모르겠다. 하지만 위와 같은 이유로 Leaky ReLU가 더 좋은 경우가 있는 것 같다. 새로 접한 활성화함수이기 때문에 설명했다.
Architecture Details
지금까지는 모델의 뒷부분에 대해 자세히 다뤘다. 하지만 Feature를 추출하는 CNN Layer에서도 다양한 특징이 있다.
1x1 Filter
논문에서 말하길 CNN Layer의 구조는 GoogLeNet모델에서 영감을 얻었다고 한다. 물론 GoogLeNet의 inception모듈을 사용한 대신 간단하게 1x1 reduction layer를 사용했다. Reduction이라고 표현한 이유는 channel과 파라미터의 수를 줄여주기 때문이다. 물론 이런 장점도 있지만, YOLO에서 1x1 Filter의 역할은 Non-Linearity를 효과적으로 증가시켜주는 것이다. GoogLeNet이 Network in Network모델을 보고 참고했기 때문이다.
Training
학습을 할 때 다음과 같이 진행했다.
- ImageNet으로 20번째 CNN Layer까지 사전학습을 진행(Average Layer 전까지)
- 이후에 4개의 CNN Layer와 2개의 FC Layer를 학습
- 사전학습 때는 224x224, Detection학습 때는 448x448로 확장
- 마지막 layer는 ReLU, 나머지 Layer는 Leaky ReLU를 사용
- bbox의 좌표값과 가로,세로는 0과 1 사이로 정규화
Training Details
- 총 135epoch동안 PASCAL VOC2007과 2012으로 학습을 진행
- 64배치, MOMENTUM 0.9, decay 0.0005로 설정
- LR은 첫 epoch을 $10^{-3}$에서 시작해 $10^{-2}$로 점차 증가시켜 75epochs 진행
- 76epochs 부터는 $10^{-3}$으로 30epochs 학습
- 마지막으로 $10^{-4}$로 30epochs간 학습
지금까지는 YOLO에 대해 자세히 알아보았다. 아래 내용은 모델을 이용해 여러가지 실험을 진행한 결과에 대해 설명할 예정이다.
Experiments
Real-time comparison
가장 최신 모델이었던 Faster-RCNN모델과 비교를 진행했다.
Error Analysis
이 실험결과는 개인적으로 매우 인상적이다. YOLO와 다른 모델의 차이점을 더욱 자세히 알아보기 위해 모델 내에 각 테스크별로 발생하는 error의 비율을 계산했다. 이 실험에서는 Fast-RCNN과 비교했는데, 그 당시 PASCAL데이터셋에 대해 가장 좋은 성능을 내는 모델이었기 때문이다.
위 그래프를 해석하면 다음과 같다.
- YOLO의 경우 Localization을 할 때 error가 가장 많이 발생했다. 즉, Fast-RCNN보다 localization 성능이 떨어진다.
- YOLO의 경우 Background에 대한 error가 매우 작다. 즉, Fast-RCNN보다 False Positive를 더 잘 잡아낸다는 뜻이다.
그냥 굉장히 재미있는 실험인 것 같아서 언급했다.
Combining Fast R-CNN and YOLO
두 개의 모델을 합치니까 성능이 올라갔다. 더 신기한 것은 Fast-RCNN이 YOLO에 비해 너무 느리기 때문에 두 모델을 합쳐도 속도에 큰 변화가 없다는 것이다.(물론 있겠지만, 정확도 향상 대비 효율적)
Generalizability
정말 이런 실험까지 했다니 대단하다는 말 밖에 안 나온다. YOLO가 얼마나 일반화 되었는지 알아보기 위해 artwork 데이터셋에 적용을 했다. 물론 class가 person인 것에 대해서만 측정을 진행했는데, YOLO가 Fast-RCNN에 비해 일반화가 매우 잘 되어있다는 결론을 도출했다. YOLO는 AP감소가 매우 적은 반면 Fast-RCNN은 성능이 매우 떨어졌다. 즉, Fast-RCNN은 주로 Natural한 데이터셋에 과적합되어있다고 할 수 있다.
지금까지 YOLO에 대해 살펴보았다. RCNN계열에 비해 속도가 월등히 빨라졌기 때문에 매우 혁신적인 모델이었다. 그렇다고 trade-off관계가 크게 작용하지 않아서 정확도도 매우 준수했다. YOLO의 경우 V5모델까지 나온걸로 아는데, 아직 갈 길이 멀다!