본문 바로가기

갈아먹는 Object Detection [4] Faster R-CNN

지난 글

갈아먹는 Object Detection [1] R-CNN

갈아먹는 Object Detection [2] Spatial Pyramid Pooling Network

갈아먹는 Object Detection [3] Fast R-CNN

들어가며

Fast-RCNN에 이어서 오늘은 Faster R-CNN[1]을 리뷰해보도록 하겠습니다.

본격적으로 Real Time Object Detection의 포문을 연 논문이라고 할 수 있겠습니다.

Mask R-CNN이 남긴 했지만 그동안 열심히 리뷰해오던 R-CNN Object Detection의 마지막 논문이라니 좀 시원 섭섭하네요.

아무튼, 시작해보겠습니다!

 

영향력: SPPNet의 Kaming He와 R-CNN 창시자인 Ross가 각각 2저자 3저자로 참여했으며, 인용 횟수는 무려... 무려 15000회에 달합니다.

주요 기여: 그동안 Selective Search를 사용하여 계산해왔던 Region Proposal 단계를 Neural Network 안으로 끌어와서 진정한 의미의 end-to-end object detection 모델을 제시하였습니다.

결과: 모든 단계를 다 합쳐서 5fps 라는 빠른 속도를 내며 Pascal VOC를 기준으로 78.8% 라는 성능을 냅니다. 백 본 네트워크의 발전도 있겠지만 end-to-end 모델의 위력이 어마무시하네요.

핵심 아이디어

Faster R-CNN의 핵심 아이디어는 Region Proposal Network (이하 RPN)입니다. 기존 Fast RCNN 구조를 그대로 계승하면서 selective search를 제거하고 RPN을 통해서 RoI를 계산합니다. 이를 통해서 GPU를 통한 RoI 계산이 가능해졌으며, RoI 계산 역시도 학습시켜 정확도를 높일 수 있었습니다. 이를 통해 RPN은 Selective Search가 2000개의 RoI를 계산하는 데 반해 800개 정도의 RoI를 계산하면서도 더 높은 정확도를 보입니다. 아래는 Faster R-CNN의 전반적인 구조입니다.

Faster R-CNN structure

위 구조를 살펴보시면 Feature Map을 먼저 추출한 다음 이를 RPN에 전달하여 RoI를 계산합니다. 여기서 얻은 RoI로 RoI Pooling을 진행한 다음 클래시피케이션을 진행하여 Object Detection을 수행합니다. 그렇다면 과연 RPN은 어떻게 구성되어 있고, 어떻게 학습시킬 수 있는지 찬찬히 뜯어보겠습니다.

Region Proposal Network

RPN Structure

 위 그림은 RPN의 개념을 시각적으로 보여주지만 실제 작동 방식은 보기보다 이해하기 어렵습니다. 좀 더 풀어서 그림으로 표현하면 아래와 같습니다.

RPN Structure

RPN이 동작하는 알고리즘은 다음과 같습니다. 논문에 생략된 세부 동작 원리는 pytorch 구현체[2]를 참고하였습니다. 

 

1. CNN을 통해 뽑아낸 피쳐 맵을 입력으로 받습니다. 이 때, 피쳐맵의 크기를 H x W x C로 잡습니다. 각각 가로, 세로, 체널 수 입니다.

 

2. 피쳐맵에 3x3 컨볼루션을 256 혹은 512 체널만큼 수행합니다. 위 그림에서 intermediate layer에 해당합니다. 이 때, padding을 1로 설정해주어 H x W가 보존될 수 있도록 해줍니다. intermediate layer 수행 결과 H x W x 256 or H x W x 512 크기의 두 번째 피쳐 맵을 얻습니다.

 

3. 두 번째 피쳐맵을 입력 받아서 classification과 bounding box regression 예측 값을 계산해주어야 합니다. 이 때 주의해야할 점은 Fully Connected Layer가 아니라 1 x 1 컨볼루션을 이용하여 계산하는 Fully Convolution Network의 특징을 갖습니다. 이는 입력 이미지의 크기에 상관없이 동작할 수 있도록 하기 위함이며 자세한 내용은 Fully Convolution Network에 관한 포스팅을 참고해주십시오.

 

4. 먼저 Classification을 수행하기 위해서 1 x 1 컨볼루션을 (2(오브젝트 인지 아닌지 나타내는 지표 수) x 9(앵커 개수)) 체널 수 만큼 수행해주며, 그 결과로 H x W x 18 크기의 피쳐맵을 얻습니다. H x W 상의 하나의 인덱스는 피쳐맵 상의 좌표를 의미하고, 그 아래 18개의 체널은 각각 해당 좌표를 앵커로 삼아 k개의 앵커 박스들이 object인지 아닌지에 대한 예측 값을 담고 있습니다. 즉, 한번의 1x1 컨볼루션으로 H x W 개의 앵커 좌표들에 대한 예측을 모두 수행한 것입니다. 이제 이 값들을 적절히 reshape 해준 다음 Softmax를 적용하여 해당 앵커가 오브젝트일 확률 값을 얻습니다.

 

5. 두 번째로 Bounding Box Regression 예측 값을 얻기 위한 1 x 1 컨볼루션을 (4 x 9) 체널 수 만큼 수행합니다. 리그레션이기 때문에 결과로 얻은 값을 그대로 사용합니다.

 

6. 이제 앞서 얻은 값들로 RoI를 계산해야합니다. 먼저 Classification을 통해서 얻은 물체일 확률 값들을 정렬한 다음, 높은 순으로 K개의 앵커만 추려냅니다. 그 다음 K개의 앵커들에 각각 Bounding box regression을 적용해줍니다. 그 다음 Non-Maximum-Suppression을 적용하여 RoI을 구해줍니다.

 

이렇게 RPN을 이용해서 RoI를 추론해내는 구조를 알아보았습니다. 이렇게 찾은 RoI를 다시 첫 번째 피쳐맵에 project 한 다음 RoI Pooling을 적용하고, 이를 다시 클래시피케이션에 적용하면 물체의 종류도 알아낼 수 있겠죠? 이 부분은 Fast R-CNN 구조를 계승하므로 궁금하신 분들은 이전 포스팅[4]을 참고해주시기 바랍니다.

 

Loss Function

이제 RPN을 학습시키기 위한 로스를 알아보겠습니다. RPN은 앞서서 Classification과 Bouding Box Regression을 수행하였는데요, 로스 펑션은 이 두 가지 테스크에서 얻은 로스를 엮은 형태를 취하고 있습니다.

Multi Task Loss

여기서 i는 하나의 앵커를 말합니다. pi는 classsification을 통해서 얻은 해당 엥커가 오브젝트일 확률을 의미합니다. ti는 bounding box regression을 통해서 얻은 박스 조정 값 벡터를 의미합니다. pi*와 ti*는 ground truth 라벨에 해당합니다. Classification은 이제 너무 익숙하게 사용하는 log loss를 통해서 계산합니다. regression loss의 경우 Fast R-CNN에서 소개되었던 smoothL1 함수를 사용하며, 이에 대한 자세한 내용은 이전 포스팅[4]을 참고하시기 바랍니다.

 

smoothL1 Loss Function

 

특이한 점은 각각 Ncls와 Nreg 나누어 주는 부분이 있습니다. 이는 특별한 의미를 갖는 것은 아니고 Ncls는 minibatch 사이즈이며 논문에서는 256입니다. Nreg는 엥커 개수에 해당하며 약 2400개 (256 x 9)에 해당합니다. 람다는 Classifiaction Loss와 Regression Loss 사이에 가중치를 조절해주는 부분인데 논문에서는 10으로 설정되어 있어, 사실상 두 로스는 동일하게 가중치가 매겨집니다.

 

이상으로 RPN을 학습시키기 위한 로스 펑션에 대해서 알아보았습니다. 나머지는 Fast R-CNN을 학습시킨 로스 펑션이 동일하게 적용됩니다. 이제 RPN과 Fast R-CNN 두 네트워크를 사이 좋게 엮어서 학습시키는 방법에 대해서 알아보겠습니다.

Training

하지만 전체 모델을 한번에 학습시키기란 매우 어려운 작업입니다. RPN이 제대로 RoI를 계산해내지 못하는데 뒷 단의 Classification 레이어가 제대로 학습될리가 없겠죠? 여기서 저자들은 4단계에 걸쳐서 모델을 번갈아서 학습시키는 Alternating Training 기법을 취합니다. 

 

1. ImageNet pretrained 모델을 불러온 다음, RPN을 학습시킨다.

2. 1 단계에서 학습시킨 RPN에서 기본 CNN을 제외한 Region Proposal 레이어만 가져온다. 이를 활용하여 Fast RCNN을 학습시킨다. 이 때 ,  처음 피쳐맵을 추출하는 CNN까지 fine tune 시킨다. 

3. 앞서 학습시킨 Fast RCNN과 RPN을 불러온 다음, 다른 웨이트들은 고정하고 RPN에 해당하는 레이어들만 fine tune 시킨다. 여기서부터 RPN과 Fast RCNN이 컨볼루션 웨이트를 공유하게 된다.

4. 마지막으로 공유하는 CNN과 RPN은 고정시킨 채, Fast R-CNN에 해당하는 레이어만 fine tune 시킨다.

 

다소 복잡했지만, RPN을 먼저 학습시키고 이를 활용해 번갈아가면서 학습을 진행했다 정도로 이해하면 충분할 것 같습니다. 후문입니다만 본 논문의 저자가 nips 마감일에 맞추기 위해서 서두르다 보니 학습 과정이 다소 복잡하게 되었다고 하네요 ㅎㅎ 아마도 end-to-end를 사랑하는 딥 러닝 연구자들이 이런 복잡한 학습과정을 가만 놔두지 않았을 것 같아서 후속 연구들이 더 기대가 되네요.

마치며

지금까지는 Region Proposal과 Classification을 나눠서 Object Detection을 수행하는 2 Step 접근 방식들을 살펴보았습니다.

다음 논문으로는 이 틀에서 벗어나 1 Step 만으로 Object Detection을 수행하는 대표적인 모델 yolo를 리뷰해보도록 하겠습니다.

 

감사합니다.

Reference

[1] Ren et al, Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks

[2] github, faster-rcnn.pytorch, https://github.com/jwyang/faster-rcnn.pytorch 

[3] 갈아먹는 머신러닝, Fully Convolutional Network

[4] 갈아먹는 머신러닝, Fast R-CNN