Attention please

[논문 리뷰] DeepLab v3+: Encoder-Decoder with Atrous SeparableConvolution for Semantic Image Segmentation(2018) 본문

논문 리뷰/Image Segmentation

[논문 리뷰] DeepLab v3+: Encoder-Decoder with Atrous SeparableConvolution for Semantic Image Segmentation(2018)

Seongmin.C 2023. 7. 22. 16:40
728x90

이번에 리뷰할 논문은 Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation 입니다.

 

https://paperswithcode.com/paper/encoder-decoder-with-atrous-separable

 

Papers with Code - Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation

🏆 SOTA for Semantic Segmentation on PASCAL VOC 2012 test (Mean IoU metric)

paperswithcode.com

 

 

 

 

본 논문에서 제안한 모델은 DeebLab 시리즈 중 v3+ 에 해당하는 모델입니다. 해당 모델의 시작점은 "Spatial pyramid pooling module과 encode-decoder structure을 결합하자" 였습니다.

 

 

Spatial pyramid pooling(SPP) module의 경우 여러 비율과 효과적인 field-of-vies(FoV)에서 filter 혹은 pooling 연산을 수행하여 다양한 크기의 contextual information을 인코딩할 수 있습니다.

 

encoder-decoder 의 경우 점진적으로 spatial information을 복구하여 object의 경계를 더욱 선명하게 포착할 수 있다는 특징이 존재하죠. 지금까지의 DeebLab v1~3 에서는 feature map을 단순히 bilinear upsampling을 적용한 것과의 차이를 보여줍니다. 

 

또한 encoder에 Xception model을 backbone으로 적용하였으며, Depthwise Separable convolution을 ASPP와 Decoder module에 적용하여 빠르고 강한 모델을 구축할 수 있었습니다.

 

 

 

 

 

 

 

Encoder-Decoder with Atrous Convolution

Atrous convolution

일반적인 convolution의 경우 stride나 kernel size를 조절하여 resolution을 조절할 수 있었습니다. 하지만 stride를 너무 크게 가져가면 디테일이 부족해지고, kernel size를 크게 가져가면 그만큼 파라미터 양이 많아져 계산 비용이 많아진다는 단점이 존재합니다.

 

하지만 atrous convolution의 경우 dilation rate를 조절하여 resolution을 조절할 수 있습니다. 파라미터의 증가 없이 FoV를 조절할 수 있다는 것이죠. 이는 multi-scale information을 포착하는데 도움이 됩니다. 

 

Depthwise separable convolution

일반적인 convolution의 경우 channel과 각 channel의 filter계산을 한번에 진행합니다. 

 

 

하지만 depthwise separable convolution의 경우 각 channel에 대해 독립적으로 공간 convolution을 진행하는 Depthwise convolution과 1x1 convolution으로 각 channel들에 대해 조합하는데 사용되는 pointwise convolution을 분리하여 차례대로 적용합니다.

 

 

그렇다면 왜 convolution을 굳이 나누어 계산하는걸까요? 가장 직접적인 이유로는 더 적은 파라미터로 같은 convolution계산을 할 수 있기에 상대적으로 계산 비용이 적어진다는 것입니다.

 

만약 5x5x3 input data에 대해 convolution연산을 하여 5x5x3 output data를 출력해야한다고 가정해봅시다. 만약 기존의 convolution을 사용한다고 한다면 우선 output data의 channel 수가 3이기 때문에 총 3개의 filter를 사용해야합니다. 즉, 일반적인 convolution을 사용하게 되면 필요한 파라미터 수는 5x5x3x3 = 225(개) 가 됩니다.

 

하지만 depthwise separable convolution의 경우는 어떨까요? 우선 depthwise convolution의 경우 5x5x1 filter를 사용하여 연산이 되겠죠. 다음으로 pointwise convolution의 경우 총 3개의 channel을 가진 output data를 생성해야하니 1x1x3 크기의 filter를 가지게 될 겁니다. 최종적으로 사용되는 파라미터 수는 (5x5x1x3) + (1x1x3x3) = 84(개) 가 됩니다.

 

추가로 본 논문에서는 Atrous convolution과 depthwise convolution을 결합한 Atrous depthwise convolution을 사용합니다.

 

 

실제로 본 논문에서 atrous separable convolution을 사용하였을 때 계산 복잡도가 낮추어짐과 동시에 성능을 향상시켰다고 주장합니다.

 

DeepLabv3 as encoder

atrous convolution은 생성한 feature map의 resolution을 임의로 조절할 수 있습니다. 본 논문에서는 resolution의 조절 비율을 output stride라고 표현합니다.

 

  • output stride : 입력 이미지의 공간적 해상도와 최종 출력의 해상도 사이의 비율

 

보통 Image classification의 경우 최종 feature map의 resolution은 input image resoution에 비해 32배 정도 작다고 합니다. 이 경우 output stride값은 32가 됩니다.

 

semantic segmentation의 경우 좀 더 dense한 feature extraction을 위해 output stride값을 16 혹은 8로 지정한다고 합니다.

 

여기에서 dense feature map이란 resolution의 크기에 비해 의미론적인 정보가 많이 포함된 feature map을 의미합니다. 보통 일반적인 CNN의 경우 global contextual information을 고려하기 위해 pooling이나 stride 작업을 통해 resolution을 축소하여 의미론적 정보를 인코딩합니다. 하지만 feature map의 resolution이 너무 작아지면 객체 경계와 관련된 상세 정보들이 누락되게 됩니다. 위와 같은 이유로 최대한 해상도를 크게 유지하되 global한 contextual information을 가져가려고 하는 것이며 이러한 사항들을 고려하여 만들어진 feature map을 dense하다고 표현합니다.

 

DeepLab v3에서 사용한 Atrous Spatial Pyramid Pooling(ASPP)의 경우 서로 다른 rate의 atrous convolution을 적용하여 다양한 scale에서 convolutional feature를 측정할 수 있었다고 합니다. 본 논문의 저자 역시 Encoder-Decoder 구조에서 DeepLab v3의 마지막 feature map을 Encoder의 출력으로 사용한다고 합니다. encoder의 출력으로 나오는 feature map은 256개의 channel을 가지며, 풍부한 semantic information을 가진다고 합니다.

 

Decoder

보통 DeepLab v3의 encoder feature은 output stride=16으로 계산됩니다. 물론 segmentation을 위해 다시 16배 만큼 upsampling을 해주어야 했고 이때 사용한 기법이 bilinear upsampling입니다. 하지만 너무 큰 배수로 바로 upsampling을 하는 naive decoder module은 object의 디테일한 segmentation을 복구하기 힘들다는 한계가 존재했습니다. 즉, 한번에 upsampling을 하지 말고 점진적으로 upsampling을 하자는 아이디어에서 decoder 구조가 탄생하게 됩니다.

 

위 structure는 다음과 같은 단계를 거쳐 작동합니다.

  1. Encoder의 feature를 4배만큼 bilinear하게 upsampling
  2. backbone에서 같은 resolution을 갖는 low-feature map을 1x1 convolution으로 channel수 감소(1번과 2번의 channel 수를 동일하게 하여 concate를 가능하게 해줌)
  3. channel을 감소한 low-feature map과 upsampling한 encdoer의 feature map을 concatenation
  4. 약간의 3x3 convolution으로 feature들을 세밀하게 조정 후 bilinear upsampling을 4배로 적용

 

 

 

 

 

 

 

Xception

DeepLab v3+의 backbone으로 Xception model을 사용합니다. 물론 그대로 사용하지 않고 약간의 변형을 통해 좀 더 semantic segmentation task에 맞도록 해줍니다.

 

 

왼쪽이 original Xception model이며, 오른쪽이 변형된 Xception model입니다. 차례대로 어떤 부분이 변형되었는지 살펴보도록 하죠.

 

1. 더 깊은 Xception

Xception model은 "Entry flow", "Middle flow", "Exit flow" 3가지로 구성됩니다. Entry flow의 경우 빠른 연산과 메모리 효용을 위해 고정한 상태로 유지하여 층을 늘려 깊은 모델을 구축합니다. 실제로 Middle flow를 보면 8번 반복에서 16번 반복으로 증가했음을 확인할 수 있습니다.

 

2. 모든 Max-pooling operation들을 depthwise separable convolution으로 대체

이는 임의의 resolution을 가진 feature map을 atrous separable convolution으로 추출할 수 있기 때문에 대체할 수 있었다고 합니다. 좀 더 dense한 feature map을 뽑기 위해 max pooling 대신 atrous convolution 으로 대체하려 한 것처럼 보입니다.

 

3. 3x3 depthwise convolution 후에 batch normalization과 ReLU activation 적용

일반적으로 Conv -> BatchNorm -> ReLU 순서대로 진행되며 Depthwise separable convolution 역시 마찬가지 였습니다. 하지만 MobileNet에서는 3x3 Depthwise convolution 과 1x1 convolution 사이에 BN, ReLU 연산을 추가하였고 이는 성능 개선에 도움이 되었다고 합니다. DeepLab v3+ 역시 위 방법을 도입하여 사용합니다.

 

 

 

 

 

 

 

Decoder Design Choices

위에서 말했듯이 output stride = 16으로 down sampling을 한 후 간단하게 bilinear upsampling을 해버리면 naive decoder design이 된다고 하였습니다. 이런 naive baseline을 개선하기 위해 encoder output에 decoder module을 추가하여 적용합니다. 하지만 이런 decoder module에 선택해야한는 3가지 요소가 존재했습니다.

 

  1. feature map의 channel 수를 줄이는 1x1 conv를 사용해야하는가?
  2. 더 선명한 segmentation 결과를 얻기 위해 3x3 conv를 어떻게 design 해야하는가?
  3. encoder 중 어떤 low-level feature를 사용해야하는가?

 

우선 첫 번째 질문에 대해 해결하기 위해 한 가지 실험을 진행합니다. [3x3, 256] 와 backbone의 두 번째 feature map을 사용하도록 적용한 후 channel 수에 대해 실험한 결과 channel을 48 혹은 32로 줄였을 때 성능이 향상된다고 주장합니다.

  • [k x k, f] : kernel size : k x k, filter 개수 = f(개)인 convolution operation

두 번째 질문에 대해서는 실험을 통해 1개 또는 3개의 convolution을 사용하는 것보다 256개의 filter를 가진 2개의 3x3 conv적용이 가장 효과적이었다고 주장합니다.

 

세 번째 질문의 경우 backbone의 두 번째 low-level feature map을 사용할 때 가장 효과적이었다고 합니다.

 

 

 

728x90
Comments