공돌이 공룡의 서재

[논문 리뷰] YOLACT : Real-time instance segmentation 본문

딥러닝/Vision

[논문 리뷰] YOLACT : Real-time instance segmentation

구름위의공룡 2021. 9. 2. 02:32

YOLACT: Real-time Instance Segmentation (ICCV 2019)

https://arxiv.org/pdf/1904.02689v2.pdf

 

Real-time instance segmentation에서 top-ranking을 차지하고 있는 모델이다. You Only Look At CoefficienTs의 약자다. 모델의 핵심 내용 중에 coefficient prediction branch가 있다 보니, 이렇게 이름 지은 것 같다. YOLACT를 살펴보고, YOLACT++까지 리뷰해보고자 한다.

 


<1.> Introduction

 

 

mask r-cnn 같은 2-stage 모델들은 성능에 초점이 맞춰져 있어서 real-time으로 적용하기에는 아쉬운 속도다. YOLACT의 목표는 1 stage instance segmentation을 해서 속도를 올리고자 한다.

 

Instance segmentation은 object detection보다 더 복잡해서, YOLO에서 Mask R-CNN의 second stage를 지운 것처럼 적용하기에는 어려움이 있다. (지우는 대신 이미지를 grid로 나눈 다음 grid 내에서 object를 찾았다. 자세한 건 여기)

 

기존 SOTA two-stage instance segmentation 방법은 mask를 생성하기 위해서 feature localization에 크게 의존한다. (왜 크게 의존하는지 밑에 섹션에서 다시 설명하겠다.) 즉, bounding box 안에서 feature를 다시 계산하는 것이다. (논문에서는 re-pool이란 표현을 썼다.) 이렇게 나온 새로운 localized feature를 mask predictor에 통과시킨다. 이 과정은 sequential 하게 이루어지기 때문에 속도를 더 빠르게 하기가 어렵다. 2 stage model의 한계라고 볼 수 있다. (Mask R-CNN 논문을 이해하고 오면 좋겠다)

 

논문에서 explicit localization 이라는 표현을 쓰는데, Mask R-CNN처럼 localization 정보를 넣어주는 것을 말한다. (ROI-align이 해당된다.) YOLACT는 explicit localization 없이, segmentation 과정을 sequential이 아닌 2개의 parallel 한 task로 나눈다.

  1. 전체 이미지에 대해 non-local prototype mask를 생성
  2. 각 instance마다 linear combination coefficient set를 예측

1번에서는 non-local이란 말이 중요하다. explicit localization 없이 만든 mask이기 때문이다. 이 두 가지 요소로 전체 이미지 상 instance segmentation을 하게 된다. 네트워크는 instance mask를 이런 coefficient를 통해서 localize 하는 법을 배운다. 그 외 더 부가적인 설명이 있는데, main method를 보지 않으면 이해가 잘 안 될 말이라 생략해도 될 것 같다.

 

어쨌든 이런 방식을 취했을 때 여러 장점들이 있다. 첫번째는 빠르다. YOLACT는 병렬로 구성한 branch와 전체적으로 가볍게 구성한 prediction head나 design들 때문에, ResNet101을 사용해도 30 fps가 가능하다. 두 번째는 re-pooling 하면서 생기는 loss 없이, high-quality 정보를 얻을 수 있다. 이런 특징 때문에 큰 object에 대해서도 잘 적용이 된다. 마지막으로는 방법이 일반적이라는 것. mask prototype과 mask coefficient 사용은 다른 object detector에도 적용될 수 있다고 한다.

 


<2. Main>

 

 

 

Introduction에서 보았듯이 YOLACT는 instance segmentation을 위한 모델이라서 기본적으로는 Mask R-CNN 구조를 따라간다. 그러나 mask branch를 추가하는 과정이 다르다. explicit feature localization step이 없고, branch들을 병렬로 연결한다는 점이 다르다. 첫번째 branch에서는 prototype mask를 예측하기 위해 FCN(Fully Convolutional Network)을 사용한다. 두 번째 branch에서는 mask coefficient를 예측하기 위해 object detection에 extra head를 추가한다. 결과적으로, NMS에서 남아 있는 instance에 대해 branch들을 결합해서 mask를 만든다. 각각 뭔지는 밑에서 다시 보겠다.

 

mask가 spatially coherent 하기 때문에 주로 이런 방법으로 instance segmentation을 수행한다. 여기서 spatial coherence란 이웃 픽셀들은 같은 instance에 있을 가능성이 크다는 것을 예로 들 수 있다. convolution layer는 필터를 이용한 convolution 연산 때문에 이 coherence를 고려할 수 있지만, fc layer는 그렇지 않다. 

 

one-stage model은 마지막 fc layer의 결과는 localization 정보가 없는 상태인데 이를 갖고 class랑 box coefficient까지 계산을 해야 하기 때문에 문제가 된다. mask r-cnn 같은 모델은 localization step(ex: ROI-align. feature의 spatial coherence 유지하면서 convolution layer 사용 가능)으로 해결하긴 하지만, speed penalty가 있다.

 

그래서 문제를 2가지 병렬 part로 나눈다. 하나는 fc layer: semantic vector를 만들기에 좋다. 다른 하나는 conv layer: spatially coherent mask를 생성하기에 좋다. 이 둘을 사용하는데 각각 mask coefficient와 prototype mask를 생성할 때 쓰인다. 결과적으로 이 둘이 독립적으로 계산되기 때문에, computation overhead는 이 둘을 합치는 과정에서 생긴다. 물론 이것도 matrix multiplication으로 해결된다.

 


 

<3.> Prototype Generation Net (protonet)

 

 

이미지 전체에 대해서 k개 prototype mask set를 예측한다. protonet을 FCN으로 구현했는데, 마지막 layer의 경우 channel 수가 k 개다. 다시 말해서, 1개의 channel이 1개의 predicted mask와 대응된다.

* CNN에서 1개의 channel은 1개의 feature descriptor 또는 extractor에 해당한다는 점에서 이렇게 볼 수 있다.

 

이 네트워크를 backbone에 붙인다. 이 방식은 일반적인 semantic segmentation이랑 비슷해 보이지만, prototype에 대해 explicit loss를 쓰지 않는다는 점에서 다르다. 이런 prototype에 대한 supervision은 coefficient랑 결합되고 나서 이뤄진다.

 

protonet을 디자인할 때 중요한 2가지를 말한다.

  • deeper backbone feature → more robust mask
  • higher resolution prototype → higher quality mask

첫 번째를 만족하기 위해선 ResNet101과 FPN을 사용하고, 두 번째를 만족하기 위해선 upsample 방식을 사용했다.

 

Protonet

protonet output이 unbounded한 상태로 만드는 것이 중요하다. 네트워크가 cofidence가 높은 프로토타입에 대해서는 더 큰 activation을 할 수 있도록 하기 때문이다. (정확도가 높을 것으로 보이는 mask에 대해서 값이 더 커지는 것을 말하는 것 같다.) 따라서 activation 함수들 중에 ReLU를 사용했다. (ReLU는 positive value에 대해 unbounded 하다!)

 


 

<4.> Mask Coefficient

 

밑에서 부연 설명할 예정

일반적으로 anchor-based object detection의 경우 2가지 branch가 있다. 하나는 c개의 class에 대한 confidence를 예측하는 것이고, 다른 하나는 bounding box에 대한 예측으로 4개를 예측한다. (중심 x, y 좌표 및 box의 가로 세로 길이) 여기에 mask coefficient prediction을 위해, k개 mask coefficient를 예측하는 branch를 추가한다. 결과적으로 anchor마다 4 + c + k개를 계산한다. 위의 그림을 보면 총 3개의 branch로 나눠져 있는 것을 확인할 수 있다. k개 mask coefficient에 대해 tanh를 적용해서, 더 안정적인 결과를 얻을 수 있었다. 

 

이 coefficient들은 위에 그림처럼 mask들을 결합해서 더하고 빼서 최종적인 object mask를 얻을 때, 각 mask에 적용되는 일종의 weight라고 생각하면 될 것 같다.

 


 

<5.> Mask Assembly

prototype branch랑 mask coefficient branch를 결합한다. 전자와 후자의 linear combination이다. matrix 연산과 sigmoid를 통해서 이뤄진다. (sigmoid는 nonlinearity를 위해 추가)

 

P는 h x w x k 크기의 matrix고, (k는 prototype mask 수) C는 n x k (n은 NMS 결과 남아있는 class들의 수) 크기의 matrix다.

 

loss는 classification, box regression, mask loss 이렇게 3개를 사용했다. weight는 다 다르게 두는데 mask weight가 가장 크다. mask loss로는 pixel-wise binary cross entropy를 사용했다. 

 


 

<6.> Emergent Behavior

 

FCN은 translation invariant 한데, task는 translation variance가 필요하다. ← detection이나 instance segmentation의 경우 대상의 위치가 달라지면 결과도 달라지기 때문이다.

 

Mask R-CNN 같은 모델에서는 translation variance를 explicitly 하게 추가한다. YOLACT에서는 final mask를 predicted bounding box로 자르는 과정 말고는 추가해주는 과정이 없다. 나아가서, 이 과정이 없더라도 잘 작용했는데 이는 YOLACT가 instance자체를 어떻게 localize 하는지를 학습한다고 볼 수 있다.

 

논문에서는 어떻게 가능할까에 대해서도 서술하고 있다.

 

padding이 없는 FCN 같은 경우는 모든 값이 똑같을 경우 결과도 똑같다. 그러나 padding이 있다면, layer를 여러 개 통과할수록 (layer 통과할 때마다 padding이 추가된다면) 픽셀이 이미지의 가장자리로부터 얼마나 멀리 떨어져 있는지를 학습하게 된다. (a 그림에 대한 mask 1 ~6 결과 확인) 그래서 논문에서는 ResNet도 이런 의미에서는 translation variant 한 특징이 있다고 보고 있다.

 

많은 prototype mask들을 관측하면서, 이들이 이미지 상에서 특정 영역에 대해 활성화가 되는 것을 확인했다. (위 그림 확인) 이런 영역들을 조합했을 때, 네트워크들은 같은 semantic class여도 다른 instance들을 구분할 수 있게 된다.

 

prototype mask들은 compressible 하다. protonet은 다수의 prototype의 기능을 하나로 합치는 것을 학습한다면, (풀어서 설명해보면, 256개일 때 다수의 prototype mask가 있고 이들을 k개로 압축!) mask coefficient branch는 어떤 상황에서 어떤 기능을 써야 하는지를 학습한다. 이 때문에 k=32 여도 성능이 좋고, 오히려 k를 늘리는 것이 coefficient를 예측하는 것이 어렵기 때문에 비효율적일 수 있다. 결론으로, 네트워크는 이 coefficient를 적절히 예측하는 것을 학습해야 한다. 실제론 실험 결과 k가 높더라도, 큰 차이가 나진 않았다 한다.


<7.> Backbone Detector

 

ResNet101 + FPN을 사용하되 RetinaNet처럼 FPN을 구성했다. 그리고 피라미드 layer하나당 anchor를 3개 놓았다. (mask r-cnn에서 사용하는 그 anchor 맞다.) 

 

RetinaNet이랑 비교했을 때, prediction head design은 더 가볍고 더 빠르다. (파라미터 수가 더 적다.)

 

train box regression에는 smooth L1 loss를 적용하고, class prediction을 학습시키기 위해서는 softmax CE를 사용한다. training example의 경우 OHEM으로 neg3 pos1로 선택했다. RetinaNet과 다르게 focal loss를 사용하진 않았다.

 


 

<8.> Other implements

 

Fast NMS

NMS는 중복된 detection들 중 low confidence을 갖는 detection들을 제거하는 작업이다. detected box 결과들로 정렬을 하고 수행하기 때문에, sequential 하게 작동한다고 할 수 있는데 이 점 때문에 더 빠른 fps를 내기에는 장애물이 된다.

그래서 instance들이 병렬로 보존되거나 버려지는 Fast NMS를 소개한다. Cython implementation 기반 원래 NMS보다 0.1 mAP 손해를 보는 대신 11.8ms 빨라졌다고 한다. (자세히는 이해를 못 했다...) GPU로 돌릴 시 속도는 더 빨라졌고, mAP는 좀 더 줄었다.

 

Segmentation loss

위에서 얻은 손실을 커버하기 위해서, 학습할 때 FPN에서 P3 layer에 1x1 conv가 있는 branch를 추가해서 c + 1 개 class에 대한 segmentation supervision을 loss term을 추가했다. (c는 class 개수. 1은 미분류 대상)

 


<9.> Result & Experiment

 

다른 model들보다 FPS가 월등히 높은 것이 보인다. 심지어 backbone도 동일하다.

 

 

mask quality를 Mask R-CNN(위)와 YOLACT(아래)를 비교한 것이다. feature repooling이 없고, 큰 사이즈의 mask도 적용 가능해서 YOLACT가 퀄리티가 더 높았다. 

 

대신에 여러 failure case들도 있었다. 

  • 너무 많은 object들이 있다면, prototype으로 localize 하는 것에 실패했다.
  • big object들끼리 거리가 충분히 멀다면, leakage가 발생했다.

 

 

Comments