[Image Object Detection] Faster R-CNN 리뷰
이전 포스팅 [Image Object Detection] R-CNN 리뷰 에 이어서, Faster R-CNN 까지 리뷰해 보았다. 그리고 중간 단계인 Fast R-CNN에 대한 리뷰도 포함되어 있다.
사실 논문은 겉핥기 정도로 중요한 부분만 들여다봤다. 아직 봐야할 next work가 산더미이기 때문에, 직관적인 이해와 loss function 정도를 이해한 내용을 바탕으로 작성하였다. 직관적인 이해는 쉽지만, 내부 구조를 자세히 들여다보면 꽤나 복잡한 모델임을 알 수 있다.
Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
Fast R-CNN
R-CNN의 메인 아이디어는 기존의 descriptor를 이용한 Image detection 방식에서, descriptor의 역할을 CNN이 대체하자는 것이었다. 그럼에도 여전히 분명한 문제점들이 존재했다. 우선 Selective-search 등을 이용하여 찾아낸 RP마다 CNN을 적용해 주어야 하기 때문에 속도에 큰 문제가 있었다. 게다가 SVM과 regression model까지 학습을 시켜야 하니, 더 많은 비용이 들어갔다.
그래서 도입한 개념이 바로 Rol Pooling(Region of Interest Pooling)이다. 이 개념의 핵심 아이디어는, 모든 RP마다 convolution 연산을 하는 대신에, 입력 이미지에 한번만 CNN을 적용하고 RoI 풀링으로 객체를 판별하기 위한 특징을 추출하자는 것이다. 그래서 Fast R-CNN은 입력 이미지에 대해 한번만 연산된 feature map에 RoI 풀링을 적용시키는 구조를 가지게 된다. 구조도는 다음과 같다.
기존의 R-CNN이 selective search * CNN 의 연산량을 수행했다면 Fast R-CNN은 (selective search + RoI Pooling) * 1 의 연산량이 되는 것이다. 이로 인해, 연산량은 급격하게 줄어들게 된다.
이제 중요한 것은 RoI 풀링이다. RoI 풀링 이후의 RoI feature vector로 수행하는 동작은 FC 레이어가 추가된 것 말고는 사실상 R-CNN과 유사하기 때문에 특별할 것이 없다. RoI 풀링은 SPP layer라는 개념의 부분집합으로, 어떠한 RP가 들어오더라도 max pooling을 이용하여 결과의 output size가 같도록 하는 것이다. 이해를 위해서 output size가 7x7로 고정되어 있다고 가정해보자. 만약 RP가 21x14 사이즈의 convolutional feature map 이라면, 3x2 mp(max pooling)를 (3,2) size의 stride로 7x7 사이즈로 만든다. 또한 다른 RP가 35x42라면, 5x6 mp를 (5,6) stride로 동일한 7x7 사이즈로 만들어낸다. 이를 수행하는 것이 바로 RoI 풀링이다.
RoI 풀링 이후에는 검출된 object의 클래스를 분류하는 softmax 분류기와 bounding box를 추정하는 bbox regressor를 학습시킨다. Fast R-CNN을 요약하자면, Fast R-CNN은 R-CNN으로부터 속도가 업그레이드 되었는데, 이를 수행하는 핵심은 RoI 풀링이라는 것이다.
Faster R-CNN
RP에서 CNN으로 가는 길목에서 RoI 풀링을 통해 아주 많은 시간을 절약했지만, 여전히 RP를 생성해내는 것 자체는 많은 시간이 소요된다. Fast R-CNN의 단점은 selective search를 수행하는 region proposal 부분이 외부에 존재하기 때문에 inference에서 bottleneck을 일으킨다는 것이다.
그래서 Faster R-CNN에서는 RPN(Region Proposal Network) 자체를 학습해 버린다. 즉, Faster R-CNN의 목표는 selective search 없이 RPN을 학습하는 구조로 모델을 만드는 것이다. RPN은 feature map을 input으로, RP를 output으로 하는 네트워크라고 할 수 있고, selective search의 역할을 온전히 대체한다. Faster R-CNN의 전체 구조는 다음의 그림과 같다.
우선 RPN에 대해 자세히 알아보기 전에, 1x1 conv의 의미에 대해 이해하는 것이 좋다.
1x1 conv는 pointwise convolution 이라고도 하는데, 채널을 여러 개 가진 피처 맵에 대한 채널 축소의 성격이 강하다. 만약 32x32x512 라는 피처맵이 있다고 할 때, 여기에 1x1 conv를 거치게 되면 32x32x128, 32x32x1024와 같이 채널 부분의 파라미터 사이즈를 변경하는 것이 가능하다. 일반적인 convolution의 경우, 채널의 사이즈를 맞춰서 계산하기 때문에 입력 이미지 피처 맵의 크기(FxFxN) X 필터 맵의 크기(F`xF`xN) 만큼 연산을 한다. 반면 1x1 conv는 각 픽셀에 대해 입력 이미지 파라미터와 필터 파라미터간의 fully connected layer와 같은 형태가 된다. 요약하자면, CNN 레이어에서 채널 단위의 축소(혹은 확장) 기능을 넣어주는 것이다.
이제 RPN에 대해 알아보자. RPN의 input은 shared network인 CNN의 output, 즉 feature map을 input으로 한다. 그리고 input feature map에 3x3x256-d (혹은 512. shared CNN output feature map에 따라 다르게 설정) filter로 한번 더 convolution을 해준다. 이 결과, 원래의 feature map과 동일한 size의 feature map이 된다 (만약 10x10x256-d의 feature map이라면 3x3x256-d, 1 stride 1 padding filter를 적용하여 10x10x256-d의 output 도출). 이 convolution(sliding window) 과정에서 각 anchor마다 RP를 구한다. 다음으로 이 feature map (shared CNN의 feature map에 한번 더 convolution한 feature map)에 1x1 conv를 수행하여 2개의 output을 도출한다. 2개의 output은 각각 10x10x(9x2), 10x10x(9x4)의 사이즈이다. 9x2는 anchor * class, 9x4는 anchor * 4개 좌표를 의미한다. 이 두 레이어는 adjustment layer의 역할로, output 벡터들은 앞서 생성한 RP와 class의 delta 값들을 의미한다. anchor는 아래에서 다시 설명하도록 하겠다.
이 단계에서 생성된 2개의 output은 각각 (물체인지 아닌지 판별 / bb box를 예측) 의 용도로써 사용되며, RPN의 유틸리티성에 집중하기 위해 모델을 가볍게 할 목적으로 이렇게 디자인 되었다. 그 과정에서 1x1 conv의 효과로 파라미터 개수가 급감하였고, 이에 따라 RP에 대한 overfitting을 어느정도 방지한다고 볼 수 있다. 하지만 여전히 bounding box regression에서는 initial한 bounding box를 필요로 하며, classification layer 역시 bounding box가 필요하다. 기존의 Fast R-CNN의 경우, selective search가 떠먹여주는 bounding box의 좌표를 이용해서 호의호식 하며 학습했겠지만 Faster R-CNN은 그렇지 못하다. 그래서 anchor라는 개념을 도입한다.
anchor는 미리 define된 reference bounding box이다. 다양한 크기와 비율로 n개의 anchor를 미리 정의해놓고 3x3 filter로 sliding window를 할 때, sliding 마다 n개의 bounding box 후보를 생성하는 것이다. 아래의 그림으로 직관적으로 이해할 수 있다.
위와 같은 진행 결과, window sliding 마다 물체 인식을 위한 2n개의 score와 regression을 위한 4n개의 좌표가 생성된다. 즉 anchor 마다 2, 4개의 값들을 가지는 것이다. 이를 이용해 anchor마다 positive 혹은 negative 라벨을 달아주어 이를 트레이닝 셋으로 classifier와 regressor를 학습한다. 논문에서는 128x128, 256x256, 512x512 3개의 크기와 2:1, 1:1, 1:2 3개의 비율을 이용하여 9개의 pre-defined anchor를 사용하였다.
anchor마다 positive label을 달아주는 기준은 2가지이다. 첫 번째는 가장 IoU(Intersection over Union)가 높은 anchor, 그리고 두 번째 기준은 IoU가 0.7 이상인 anchor이다. negative label의 경우, positive를 판단할때와 정 반대의 기준을 적용하며, threshold는 0.3이다. 중간에 속한 IoU들은 label을 달지 않고 학습에 포함시키지 않는다. 여기서 주의할점은, 당연하게도 대부분의 anchor는 negative sample일 것이기 때문에 샘플링도 다시 비율을 맞춰서 학습을 진행해야 한다. 그리고 positive sample의 경우 foreground라고 판단하고 반대의 경우는 background라고 판단한다.
마지막으로 모델의 학습 과정에 대해 알아보자. Faster R-CNN의 모델 학습은 다음과 같은 단계를 거친다.
1. Pre-trained CNN의 output으로 RPN만을 학습한다. 우선적으로 RP를 만들어내는 능력만을 학습하는 것이다.
2. 1의 결과로 나온 RP를 이용하여 RPN을 제외한 Faster R-CNN 네트워크를 학습시킨다. 이를 통해 shared CNN, fc layers, detector 부분이 학습된다.
3. 2의 결과로 나온 모델에서 다시 한 번 1과 같은 절차로 학습한다. 이 때, shared CNN 부분은 프리징하여 학습시키지 않는다.
4. 3의 결과로 나온 모델의 RP로 다시 한 번 모델을 학습시킨다.
참고 :
Youtube : https://www.youtube.com/watch?v=kcPAGIgBGRs
paper : https://arxiv.org/pdf/1506.01497.pdf
https://jamiekang.github.io/2017/05/28/faster-r-cnn/
http://kaiminghe.com/iccv15tutorial/iccv2015_tutorial_convolutional_feature_maps_kaiminghe.pdf
(이미지 출처 - http://kaiminghe.com/iccv15tutorial/iccv2015_tutorial_convolutional_feature_maps_kaiminghe.pdf)