본문 바로가기

갈아먹는 Semantic Segmentation [1] Fully Convolutional Network

들어가며

이번에 리뷰해 볼 논문은 Fully Convolutional Network[1]입니다.(이하 FCN) 이전까지 Semantic Segmentation 분야에서는 각 픽셀 별로 일정한 Bouding Box 크기 만큼 Classification을 적용하여 해당 픽셀의 종류를 추론하는 비효율적인 방식의 접근들이 있었습니다. 하지만 이 논문은 Fully Connected Layer 대신 1x1 컨볼루션을 사용하여 연산량을 획기적으로 줄였고, Segmentation의 퀄리티까지 높이는 성과를 내었습니다. 이 기법은 이후 많은 논문들에서 사용되면서 컴퓨터 비젼 분야 전체에 영향을 주었습니다. 

 

그럼 시작해보겠습니다! 

 

영향력: 인용 횟수가 약 14000회에 달하며, 다른 컴퓨터 비젼 분야의 접근들에게도 많은 영향을 주었습니다.

주요 기여: 1x1 컨볼루션을 사용하여 입력 크기에 상관없이 클래시피케이션을 수행할 수 있는 기법 제시 

핵심 아이디어

앞서도 언급했듯이 FCN의 핵심 아이디어는 FC 레이어를 1x1 컨볼루션 레이어로 대체하는 것과, 이를 통해 얻은 피쳐 맵을 Upsampling 하여 Segmentation을 수행하겠다는 것입니다. 아래는 FCN의 전반적인 구조입니다.

Fully Convolutional Network

일반적인 CNN 같아 보이지만, 자세히 보시면 컨볼루션을 거친 뒤, 이를 쫙 펴서 FC에 넣어주는 것이 아니라, 1x1 컨볼루션을 계속 진행하는 것을 볼 수 있습니다. 그리고 이를 Upsampling 과정을 거쳐서 원래 이미지와 똑같은 크기의 피쳐맵을 만들어줍니다. 이 피쳐맵의 픽셀 하나하나를 클래시피케이션 결과 값으로 하여 세그멘테이션을 진행하는 것입니다.

 

그 결과로 픽셀마다 클래시피케이션을 할 필요없이! 컨볼루션 레이어들만으로! Semantic Segmentation을 수행할 수 있게됩니다. 그렇다면 좀 더 자세히 FCN에 대해서 알아보도록 하겠습니다.

Fully Convolutional Network

논문에서는 FCN은 1x1 컨볼루션으로 대체할 수 있으며, 이는 Classification을 수행하는 다른 일반적인 CNN 모델에도 동일하게 적용할 수 있습니다. 아래 그림은 Conv 레이어 이후 클래시피케이션을 수행하는 모델에서 뒷 단을 1x1 컨볼루션 레이어로 바꾸면 어떤 결과가 나오는 지를 보여줍니다.

Replacing FC layer with 1x1 Conv

1x1 컨볼루션으로 대체한 결과, 고양이가 있을 법한 영역을 나타내주는 히트맵이 뽑혀져 나오는 것을 확인할 수 있습니다. 그런데 여기서 문제가 있습니다. Conv 레이어와 Pooling의 특성 상, 레이어를 거치면 거칠 수록 입력 이미지보다 H x W  크기가 줄어듭니다. 그 결과 Semantic Segmentation과 유사하지만, 이는 우리가 원하는 결과가 아닙니다. 따라서 이를 인풋 크기에 맞춰주는 조치가 필요합니다.

Upsampling 

앞서 1x1 Conv를 거쳐서 인풋 이미지보다 크기가 작은 피쳐맵을 뽑아냈습니다. 이를 다시 키워주기 위해서 여러가지 기법들을 적용할 있습니다. 다음 자료는 [2]에서 가져왔습니다. 먼저 Unpooling입니다.  Maxpooling을 그래도 거꾸로 재현하여 주변 픽셀들을 동일한 값으로 채우거나, 0으로 채워주는 방식이 있습니다. 하지만 이는 원래 Pooling을 적용하였을 때 상태의 위치 정보를 기억해내지 못합니다.

이러한 문제를 해결하여 위치 정보를 기억한 다음, 그 자리에 원래의 값을 위치 시키고 주변을 0으로 채워주는 기법이 등장하였으며, 이를 Max Unpooling이라 합니다. 이는 곧 FCN 후속 논문인 Deconvolution Network의 핵심이 됩니다. (곧 이 논문도 리뷰해보겠습니다!)

 

다음으로 알아볼 기법은 이 논문에서 핵심적으로 사용한 deconvolution입니다. 논문에서는 deconvolution으로 적혀있지만 transpose convolution으로도 불립니다. 핵심 개념은 컨볼루션 레이어를 거꾸로 적용하자는 것입니다. 다음 그림 자료는 [3]과 [4]에서 가져왔습니다. 먼저 Convolution 연산을 행렬 곱으로 표현하면 다음과 같습니다. 

예시로 주어진 행렬 곱의 크기는 컨볼루션 (4x16) x 입력 이미지(16 x 1) = 피쳐 맵(4 x 1)이 됩니다. 우리가 하고 싶은 것은 (4x1)의 피쳐 맵에 컨볼루션을 거꾸로 수행하여 원래 이미지 크기를 복원하는 것입니다. 이를 위해서 컨볼루션 행렬의 transponse를 피쳐 맵에 곱해주면 됩니다. 아래 그림을 보겠습니다.

이 행렬 곱의 크기를 구하면 컨볼루션의 transpose(16 x 4) x 피쳐 맵(4 x 1)  = 입력 이미지(16 x 1)가 됩니다. 실제로는 transpose convolutoin에 쓰이는 컨볼루션 웨이트 역시도 학습을 진행하는 레이어기 때문에 구체적인 웨이트는 다릅니다. 다만, 여기서는 이러한 방식으로 deconvolution이 진행된다는 개념을 잡고 넘어가면 좋을 듯 합니다. 

 

다시 논문으로 돌아오겠습니다. 먼저 가장 마지막 레이어인 conv7에서 얻은 피쳐맵을 대상으로 32배 Upsampling을 적용합니다. 아무래도 적은 양 피쳐맵을 과도하게 늘리면 세밀한 특징 정보가 많이 유실되어 있겠죠? 이를 해결하기 위해서 그 앞단 피쳐 맵들을 가져와줍니다. 예를 들어 pool4를 거친 피쳐맵을 가져온 다음, conv7 피쳐 맵에 x4 Upsampling을 적용한 다음 이 둘을 더해줍니다. 그리고 x16 Upsampling을 적용하면 동일한 크기의 결과 피쳐 맵을 얻을 수 있습니다.

FCN Upsampling

아래는 위 기법을 각각 적용하여 얻은 시맨틱 세그맨테이션 결과입니다. 보시면 앞단의 컨볼루션 피쳐맵들을 합쳐서 구한 결과가 디테일이 더 많이 잡히는 모습을 볼 수 있습니다.

마치며

FCN의 한계점은 Upsampling에 너무 의존하여 결과 값을 추출한다는데 있습니다. 컨볼루션과 풀링을 거치면서 사라진 위치 정보 값을 복원하는데에는 Upsampling만으로는 한계가 있었던 모양입니다. 다음 논문으로는 이를 개선한 Deconvolution Network를 리뷰해보겠습니다. (저자가 자랑스러운 한국인, 노현우 님입니다 ㅎㅎ)

Reference

[1] J.Long et al, Fully Convolutional Networks for Semantic Segmentation, 2015, CVPR

[2] cs231n 11강, http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture11.pdf 

[3] 어쩐지 오늘은, cs 231n 11강, https://zzsza.github.io/data/2018/05/30/cs231n-detection-and-segmentation/  

[4]Naoki Sibuya, Upsampling with Transposed Convolution, https://medium.com/activating-robotic-minds/up-sampling-with-transposed-convolution-9ae4f2df52d0