0. Before Reading
Abstract에 들어가기 앞서, 논문의 핵심 사항들을 미리 정리하고 들어가겠다.
FCN(Fully Convolutional Network)는 Classification task를 수행하는 FC Layer (Fully Connected Layer)를 제거하고, 오직 Convolutional Layer로만 Architecture를 구성하여 Semantic Segmentation을 수행한다.
이 논문에서는 모든 부분을 2가지로 나누어 설명한다.
- FCN (Fully Convolutional Networks)
- Semantic Segmentation
Fully Convolutional Network의 경우, FCN을 수행하는 방법은 크게 3가지이다.
Pixelwise Prediction, Supervised pre-training, In-network upsampling layers가 있다.
Semantic Segmentation의 경우 Skip-Architecture를 사용하여 깊은 층의 semantic 정보와 얇은 층의 appearance 정보를 결합했다.
Semantic Segmentation는 Image를 pixel 단위로 어떠한 object에 해당하는지 Classification을 수행하는 것을 의미한다.
이러한 Semantic Segmentation을 수행하는 방법에는 크게 2가지가 있다.
- Sliding Window (Patchwise Method)
- FCN (Pixelwise Method)
Sliding Window는 Patchwise 방법이라고도 하는데, 하나의 이미지를 기준으로 Patch를 sliding 하면서 주어진 Patch의 center pixel을 분류하는 방식이다.
Patchwise Learning 방식은 아래와 같다.
1) 특정 size의 patch를 설정하고 이를 CNN에 입력으로 넣어준다.
2) 입력으로 들어간 patch에 대응되는 Input Image의 일부는 CNN에 의해 Classification Task가 수행된다.
3) 이때 특정 Class로 분류가 되었다면, 해당 patch 중앙에 위치한 pixel을 해당 class로 분류해 준다.
4) 이러한 과정을 Sliding Window 방식으로 1 ~ 3번을 반복한다.
다만, Patchwise Learning 방식에는 여러 문제점들이 존재한다.
1) Network는 각 Patch마다 독립적으로 CNN연산을 수행해야 하기 때문에 너무 많은 계산량을 요구하게 되어 속도가 느려진다.
2) 각 Patch들끼리 중복되는 부분이 있으나 독립적으로 CNN 연산이 수행되기에 이를 활용하지 못한다.
3) Patch size에 따른 localization accuracy & use of context 간의 trade-off
Patch Size가 커질 경우: 최종 Down-sampled map size가 동일하기에 Subsampling(Pooling) Layer들이 더 많이 요구된다.
즉, 기존 Patch에 대응되는 이미지에 Downsampling이 더 많이 적용되어 Local, Spatial Detail들을 덜 담게 된다.
이는 Context는 많이 보지만 Localization Accuracy가 떨어지는 결과를 낳는다.
또한 하나의 patch 안에 두 개의 class가 동시에 들어가 있을 확률이 커져 class label을 어떻게 부여할지에 대한 문제도 있고,
patch끼리 겹치는 부분이 커져 중복계산이 진행되는 경우가 많아진다.
Patch Size가 작아질 경우: 기존에 Patch에 대응되는 Input Image의 영역이 더 작아지기에 Network가
이전보다 더 작은 Context를 학습할 수 밖에 없다.
이와 다르게 FCN (Fully Convolutional Network)를 사용하여 Semantic Segmentation을 진행할 수도 있다.
이는 하나의 이미지에 대해 하나의 네트워크인 FCN을 한 번에 적용하기 때문에 연산에서 Feature를 공유할 수 있다는 장점이 있고, 이러한 방식을 Pixelwise 방식이라고도 한다.
1. Abstract
위 논문의 저자들은 임의의 크기의 input을 받아 그에 대응되는 크기를 output으로 반환하는 "Fully Convolutional Networks"를 build 하여 효율적으로 learning(학습)하고, inference(추론)하는 것을 목표로 한다.
현대의 classification networks(AlexNet, VGGNet, GoogLeNet)들을 Fully Convolutional Network로 적용하고, Fine - Tuning을 통해 segmentation task를 수행한다.
이후 deep, coarse layer에서 나온 semantic information과 shallow, fine layer에서 나온 appearance information을 결합하여 정확하고 구체적인 semantic segmentation을 수행한다.
1) CNN 구조
- Input Image를 넣어 Convolution 연산을 통해 Feature Map을 추출 (Feature Extraction)
2) Convolutionalization
- $1 \times 1$ Convolution을 이용하여 Spatial coordinate를 유지한 상태로 Heatmap $(M \times N \times D)$를 형성
3) Upsampling (Transposed Convolution), Skip Architecture
- Skip Architecture: Heat Map을 Pooling Layer들과 combine
- Upsampling: Combined Heat Map을 Input Image와 동일한 크기 $(H \times W)$로 복원
4) 복원된 Heat Map의 각 pixel별로 Softmax를 적용하여 Pixel 별 Class 예측
2. Introduction
2.1) Fully Convolutional Networks
위의 논문에서는 end-to-end, pixels-to-pixels(=dense prediction) 방식의 FCN Model을 소개할 것이다.
FCN (Fully Convolutional Networks)
- Pixel-wise prediction
- Supervised pre-training
- In-network upsampling layers
- pixel-wise prediction이 가능하기 하고, subsampled pooling을 이용하여 학습
Sliding Window
- Patch-wise prediction
- 해당 방식은 Computation이 많기에 Semantic Segmentation에서는 FCN를 사용한다
1) Patch
하나의 image에서 object는 그대로 두고 background를 제거한 것을 patch라 한다
2) Patchwise 방법
Patchwise Training을 사용하는 이유는 이미지에 불필요한 정보들이 존재할 수 있으며, 하나의 이미지에서 서로 다른 object가 존재하는 경우 redundancy issue가 발생한다. 즉, object와 관련된 feature만을 추출해야 하는데 필요 없는 배경까지 본다면 불필요한 computation이 발생한다.
2.2) Semantic Segmentation
Skip Architecture를 사용해서 Shallow, Fine Layer의 Appearance Information (Local, Where)과
Deep, Coarse Layer의 Semantic Information (Global, What)을 결합할 것이다.
Appearance Information
- Shallow, Fine Layer
- Local Information
- Location: Where
Semantic Information
- Deep, Coarse Layer
- Global Information
- Semantics: What
CNN에서 일반적으로 Classification Task를 수행할 때
Layer를 통과할수록 Low-level feature에서 High-level feature가 추출되어,
Hierarchical Information들을 Edge -> Texture -> Object 순서로 얻을 수 있다.
그렇기에 Shallow, fine Layer는 객체의 외관/윤곽과 같은 Edge Feature들인 Local Information (Where)을 잘 추출하고,
Deep, coarse Layer는 객체의 외관을 파악하기 힘들지만, feature들이 활성화된 부분을 보면 옷과 같이 하나의 의미를 갖는 정보들을 보여준다. 즉, 하나의 Context Feature인 Global Information (What)을 잘 추출한다.
3. Fully Convolutional Networks
각 layer의 feature map는 3차원 배열 $h \times w \times d$ 로 정의된다.
- $h, w$: spatial dimensions
- $d$: feature or channel dimension
위의 사진과 같이 Feature Map에서 Kernel을 통해 하나의 Node가 생기는 것을 볼 수 있다. 이때, Receptive Field란 네트워크의 한 Feature(Node)에 영향을 주는 Input Space의 범위(영역)이다.
논문에서는 HIgher Layer의 각 뉴런에 대응되는 Image의 영역을 Receptive Field라 한다.
CNN의 중요한 특성 중 하나는 Translation Invariance이다.
Input Image에 Layer (Convolution, Activation, Pooling)을 통과시키더라도 위치 정보가 변하지 않는다.
오직 receptive field에 해당하는 feature map들의 영역만 영향을 받는다.
이제 CNN에서 진행되는 연산을 하나의 수식으로 표현해 보자.
$y_{ij} = f_{ks} (\{x_{si+\delta i, sj+\delta j} | 0 \leq \delta i, \delta j \leq k-1\})$
- $x_{ij}, y_{ij}$: data vector @ $(i, j)$ (Input Layer $x$, Output Layer $y$)
- $k$: kernel size
- $s$: stride or subsampling factor
- $f_{ks}$: layer type
- convolutional layer
- pooling layer (max or average)
- activation function (layer)
$x_{si, sj}$: starting point (receptive field의 좌상단 (0, 0))
$x_{si+\delta i, sj+\delta j}$: receptive field에 대응되는 feature들
$\{x_{si+\delta i, sj+\delta j} | 0 \leq \delta i, \delta j \leq k-1\}$: Receptive Field 전체
즉, Input Image의 $(i, j)$를 중심으로 하여 Convolution 연산을 적용하면 Kernel이 적용되는 좌상단 pixel $x_{si, sj}$을 starting point라 할 수 있다.
이후 Starting Point를 시작으로 $\delta i, \delta j$를 $0$에서 $k$까지 하나씩 늘려가며 receptive field $\{x_{si+\delta_i, sj+\delta_j} | 0 \leq \delta_i, \delta_j \leq k\}$를 얻을 수 있다.
여기에 $f_{ks}$를 적용하여 receptive field 전체에 Convolution, Pooling, Activation 등을 적용해 주면 된다.
$si, sj, \delta i, \delta j$는 모두 곱하는 값이 아니라 'index'값으로 해석해야 한다.
결과적으로는 곱하는 것이 아니라 Index로 해석하는 것이 맞다고 생각한다.
이후 Transformation Rule에 의해 아래와 같이 식을 정리할 수 있다.
두 개의 Layer $f_{ks}$와 $g_{k's'}$을 합성하는 것은
- $f_{ks}$: kernel size $k$, stride $s$에 해당하는 Layer
- $g_{k's'}$: kernel size $k'$, stride $s'$에 해당하는 Layer
$f_{ks} \circ g_{k's'} = (f \circ g)_{k' + (k-1)s, s's}$
위의 사진과 같이 $ f_{ks} \circ g_{k's'}$는 $g_{k's'} $의 Layer에 $f_{ks}$가 합성된 것으로 볼 수 있다.
즉, 위의 사진에서 2번째 Layer를 $g_{k's'}$, 3번째 Layer를 $f_{ks}$라 하면
3번째 Layer인 $f_{ks}$에서 Receptive Field는 starting point가 $(si, sj)$이고, ending point가 $(si + (k-1), sj + (k-1))$으로 $k^{2}$개의 정사각형으로 나뉜다.
2번째 Layer인 $g_{k's'}$는 3번째 Layer의 Receptive Field의 한 point $(si + m, sj + n)$에 대응되는 Receptive Field의 starting point는 $(s'si + s'm, s'sj + s'n)$가 된다.
Starting Point $(si, sj)$는 좌표 $(i, j)$ 앞에 stride $s$를 곱해주어 이를 일종의 Index화 해준다.
즉, 2번째 Layer의 Receptive Field에서 Starting Point도 좌표 $(si + m, sj + n)$에 stride $s'$을 곱해주어
Index화 해주어 $(s'si + s'm, s'sj + s'n)$가 된다.
여기서 starting point는 $(s'si + s'm, s'sj + s'n)$이고,
ending point는 $(s'si + s'm+ (k'-1), s'sj + s'n + (k'-1))$이 된다.
이때, 특정 point가 $(m, n)$이 $[0, k-1]$ 범위까지 움직이므로 두 Layer를 합성하면
starting point는 $(s'si, s'sj)$이고,
ending point는 $(s'si + s'(k-1) + k'-1, s'sj + s'(k-1) + k'-1)$이 된다.
즉, Stride는 인덱스로서 앞에 붙기에 $s's$가 되고, Kernel Size는 kernel의 한 변의 길이인 $s'(k-1) + k'$가 된다.
즉, $f$와 $g$라는 두 Layer를 합성했을 때 나오는 Feature Map이 하나의 Layer만을 사용했을 때 동일한 결과를 얻기 위해서라면
stride $s's$이고, kernel size는 $s'(k-1) + k'$인 Layer를 적용해야 한다.
함수 합성을 적용하는 것은 전체 Neural Network의 앞에서 뒤로 Feedforward computation을 하는 것을 의미한다.
즉, Data가 각종 Layer들을 통과하는 것을 의미하는데 $f, g$는 항상 Non-linear Layer이기 때문에 Data는 항상 Non-linear filter를 계산하게 된다.
이러한 구조를 갖는 신경망을 FCN (Fully Convolutional Network)라 한다.
FCN에서 다음과 같이 Loss Function을 final layer의 spatial dimension의 합으로 나타낼 경우,
$l(x; \theta) = \sum_{ij} l'(x_{ij}; \theta)$
Total gradient가 각 spatial components의 gradient의 합이 된다.
즉, 전체 이미지에서 계산된 SGD의 값은 min-batch를 통해 final layer의 receptive field에서 계산한 SGD의 값과 같을 것이다.
Convolution Kernel이 (e.g. stride=1)과 같이 적은 값을 가질 경우 Receptive Field가 Overlap 된다.
이때, FCN의 방법인 Pixel-wise(Layer-by-Layer)가 기존의 Sliding Window(Patch-by-Patch) 방식보다 feedforward computation과 backpropagation을 수행하는 데 있어서 더욱 효율적이다.
즉, 각 Patch 별로 Individual CNN을 적용하여 pixel 단위 classification을 수행하는 것보다 이미지 전체를 하나의 입력으로 넣는 FCN이 더 효율적이다.
지금까지는 FCN을 설명하기보다는 기존의 CNN을 설명하며 FCN이 나오기 이전 모델들을 살펴보면서 FCN의 우수성을 추상적으로 설명했다.
이후의 내용은 FCN이 왜 이전 모델보다 성능이 뛰어날 수 있었는지 FCN의 알고리즘을 구체적으로 살펴볼 것이다.
3.1) Adapting classifiers for dense prediction
기존의 Classification Task에 사용하던 CNN Models (LeNet, AlexNet, VGG, etc.) 들은 Feature Extractor 부분과 FC Layer 부분으로 구분되어 있다.
다만 위의 CNN Model들은 모두 Fixed Size의 input vector를 입력으로 받고, Non-spatial output을 출력으로 얻는다.
여기서 Non-spatial ouput이라 함은 Classification Score(0, 1)와 같은 단순 Scalar 값을 의미한다.
1) Fix-sized input
FC Layer에서 요구하는 Input vector의 크기가 고정되어 있기 때문에 Fix-sized input vector가 입력으로 필요하다.
2) Non-spatial output
FC Layer의 특성상 Feature Map이 Flatten 되어 입력으로 들어가기 때문에 spatial coordinate를 잃어버린다.
그렇기에 본 논문에서는 관점의 전환을 통해 FC Layer들을 90도 회전시켜 $1 \times 1$ Convolution Layer으로 바라본다.
그림에서 Dense Layer의 마지막 3개 Layer들을 $1 \times 1$ Convolution Layer로 바꾸는데, 이를 Convolutionalization 라 한다.
다만 이렇게 설명하면 어떻게 FC Layer가 $1 \times 1$ Convolutional Layer로 바뀌는지 이해하기 힘들 수 있기에, 아래의 예시를 보며 확인해 보자.
https://everyday-image-processing.tistory.com/32
위의 블로그 저자분께서 그리신 그림들을 참고하여 설명하겠다.
일단 기존의 Classification Task를 수행하는 CNN Model을 살펴보자.
전형적으로 Convolutional Layer이후에 FC Layer가 적용되는 Model Architecture이다.
우리는 이러한 FC Layer를 Convolutional Layer처럼 사용하고 싶기에 해당 FC Layer를 90도 회전시킨다.
FC Layer를 90도 회전시키면 아래와 같이 나온다.
여기서 FC Layer를 구성하는 Node(Feature)라고 부르는 요소가 나열되어 있다.
이러한 Node들을 전부 묶어서 하나의 $1 \times 1 \times D$ Convolutional Layer를 만든다.
최종적으로 Convolutionalization을 수행한 결과이다.
마지막 FC Layer를 $1 \times 1\times D$의 Convolutional Layer로 관점을 바꾸어 생각한 것이 Convolutionalization이다.
만약 FC Layer가 여러 개라면, 각 FC Layer 각각에 대해 위의 작업을 수행해 주면 된다.
해당 논문에서는 FC Layer가 3개 존재하므로 3개의 FC Layer를 각각 90도로 회전시켜
$1 \times 1\times 4096$, $1 \times 1\times 4096$, $1 \times 1\times 1000$의 Convolutional Layer로 다루었다.
이렇게 Convolutionalization을 수행하여 나온 Spatial Output map들은 Sliding Window(Patch-wise)를 통해 구한 Output map과 동일한 결과를 주지만, Patch들이 overlap 되면서 computational cost가 높아진다는 단점이 있다.
또한, Classification Nets를 위와 같이 Fully Convolutional Nets로 변형할 경우
임의의 크기의 Input에 대해 이에 대응되는 다양한 크기의 Output이 나오고,
Sub-sampling(Pooling or Stride 조절 or Kernel size 조절 등)을 통해 spatial dimension을 줄여준다.
만약 Pooling과 같은 연산을 통해 Feature map의 size를 줄여준다면,
이는 Kernel size를 $3 \times 3$와 같은 small size로 유지하면서
Convolutional Layer도 늘릴 수 있도록 해준다.
FCN Layer는 output dimension을 줄이기 위해 pooling 대신 convolution layer의 stride를 조절해 subsampling을 수행했다.
3.2) Shift-and-stitch is filter rarefaction
FCN 방법을 이용하면 모든 pixel에 대해 한번에 연산이 가능하지만 고해상도의 원본 이미지에 대해서는 연산량이 많아진다.
이를 해결하기 위해 FCN에서는 downsampling과 upsampling을 사용하게 된다.
Downsampling의 경우 흔히 pooling이나 strided convolution을 사용한다.
Upsampling의 경우 기존의 shift-and-stitch 방법도 있지만 skip connection을 사용한 upsampling이 더 효과적이다.
입력 값이 convolution + pooling layer를 통과하면 크기가 감소하기에 이를 복원하기 위해 shift-and-stitch 방법을 사용했다.
coarse output에서 dense prediction feature를 생성하기 위해 shift-and-stitch 방법이 고려되었다.
shift-and-stitch 방식은 Input Image를 조금씩 이동시켜서 (shifting) 얻은 출력 영상들을 겹치는 (stitch) 것이다.
Upsamling을 사용하지 않은 경우 Input Image에 비해 Output Feature Map의 해상도가 현저하게 낮는 문제가 발생한다.
예를 들어 $100 \times 100$의 input image를 넣을 경우 $10 \times 10$의 output feature map을 얻는다고 생각해보자.
다만 semantic segmentation을 위해서는 input image의 크기와 output feature map의 크기가 동일해야 한다.
그런데 output feature map을 그대로 upsampling 해주게 되면 당연히 정확하지 않다.
따라서, input image를 조금씩 이동(shift) 시키면서 upsampling을 하고 그렇게 출력된 output feature map들을 결합하여(stitch) 사용한다.
input image를 약간 이동해서 upsampling을 통해 출력을 얻고,
그 다음에 input image를 다시 조금 이동하고 출력을 얻고, 일련의 과정을 반복한다.
그렇게 되면 출력 이미지가 1개가 아니라 여러 개의 출력 이미지를 얻을 수 있게 된다.
이렇게 얻은 출력 이미지의 집합을 더 고해상도의 이미지를 얻기 위해서 서로 결합하여 사용하게 된다.
아래의 예시를 통해 이해를 해보자.
빨간색 박스의 경우 $2 \times 2$ 크기의 max pooling filter로 stride는 2로 2칸씩 이동하여 filtering을 하게 된다.
따라서 오른쪽 $3 \times 3$ 크기의 matrix는 max-pooling의 연산 결과를 보여주고 있다.
노란색 박스의 경우 동일하게 max-pooling 연산을 하지만 input image가 왼쪽으로 1 pixel만큼 shift된 것을 볼 수 있다.
그에 따라 연산 결과도 이전과 조금 달라졌다.
특히 결과 행렬의 가장 오른쪽으로 회색으로 처리되어 있는데, 이는 입력 이미지를 왼쪽으로 1 pixel 만큼 이동했기 때문에
가장 오른쪽 pixel 영역은 필요없는 정보가 된다.
위와 같은 과정을 input image의 pixel 이동 방향을 다르게 잡아 2번 더 반복해준다.
물론 다른 방향도 더 적용가능하지만 총 4번의 방향에 대해 적용했다.
이러한 결과들을 하나로 합치면 다음과 같다.
만약 어디서 max pooling 연산이 적용되어있는지에 대한 위치 정보만 저장한다면 위와 같이 input image의 크기와 동일한 output feature map을 얻을 수 있다.
즉, shift-and-stitch 방법은 위와 같이 max pooling 하고 위치 정보를 저장하여 원래의 이미지 크기로 upscaling할 수 있다.
하지만 계산 비용이 크다는 단점이 있다.
이 논문에서는 filter와 stride를 조절하여 shift-and-stitch과 유사한 효과를 내는 trick를 언급했다.
$f_{ij} = \begin{cases}
f_{i/s, j/s} & \text{if } s \text{ divides both } i \text{ and } j; \\
0 & \text{otherwise}.
\end{cases}$
원래 이미지 크기가 $j \times i$고, 해당 pixel $(j, i)$의 각 좌표가 stride $s$로 나누어 떨어지는 경우에만 값으로 채워주고, 나누어 떨어지지 않을 경우에는 0으로 채워준다.
원래 image size로 upsampling할 수 있다는 장점이 있지만
0으로 채워주기 때문에 shift-and-stitch 보다는 성능이 떨어진다.
다만 실제로는 skip connection을 활용한 upsampling 기법이 더 효과적이기 때문에 위의 trick을 사용하지는 않았다.
이 Trick은 아래의 2가지 이유로 인해 shift-and-stitch와 완전히 동일한 결과는 얻을 수 없다.
1) Max Pooling을 사용하지 않고 학습한 weight로 filter를 채운다는 점
2) 오직 stride $s$에 따라 채워지는 위치가 달라진다는 점
3.3) Upsampling is backwards strided convolution
본 논문에서는 Upsampling을 위해 Interpolation(보간법) or Deconvolution의 2가지 방법을 소개한다.
Upsampling은 위의 방법들을 통해 corase한 image를 dense하게 pixel을 채우는 과정이다.
Interpolation (보간법)
FCN의 저자들은 interpolation 기법을 사용한다고 말한다. 그 중에서도 bilinear interpolation 기법을 사용한다.
우선 linear interpolation에 대해 알아보자.
일종의 무게중심의 좌표를 찾는다고 보면 이해하기가 쉽다.
즉, 각 pixel value 사이를 등간격으로 나눈 후, 사이에 들어가는 pixel value들이 등차수열을 따르도록 설정해주면 된다.
위의 Blinear interpolation은 linear interpolation을 확장한 것이다.
예를 들어 위의 $2 \times 2$ matrix에서 2 x upsampling을 적용할 시
2과 5 사이에 두 개 pixel이 등차수열을 띄면서 들어가게 된다.
만약 공차가 정확하게 정수로 나누어 떨어지지 않으면 약간의 미세한 조정을 두어 (ceil, floor) pixel 값을 적용시킨다.
이러한 방법을 사용한다면 우리는 작은 feature map에서 더 큰 feature map을 만들 수 있다.
Deconvolution
사실 Deconvolution과 Transposed Convolution은 엄밀하게 다른 개념인데, 논문에서 제시한 pytorch tutorial code에 의하면 upsampling시 transposed convolution으로 되어 있다.
즉, transposed convolution과 deconvolution을 유사하게 본 것이라 할 수 있는데 이는 엄밀히 말해서 같지 않다.
Deconvolution: Convolution의 역과정으로, Output Feature Map을 Input으로 하여 원본 이미지를 Output으로 복원한다.
해당 과정에서 Kernel Size나 Output Size가 고정되어 있으며 동시에 Kernel Weight는 Freeze (학습 X)되어 있다.
Transposed Convolution: Kernel Size와 Output SIze가 고정되어 있다는 점에서 Deconvolution과 비슷하지만
원본 이미지를 되돌리지 못하고 최대한 가깝게 나오도록 학습을 통해 Kernel Weight를 조정한다.
Transposed Convolution에 관한 설명은 필자의 예전 Post에 있으므로 이에 대한 설명을 대체하겠다.
https://jwk0302.tistory.com/154
기존의 Convolution 연산은 다음과 같다.
이러한 Convolution 연산 과정을 Matrix Multiplication의 형태로 변환하면 다음과 같다.
그럼 이제 반대로 Output Matrix를 입력으로 넣어주고 Input Matrix를 출력으로 얻기 위해 기존의 Kernel Matrix를 Transpose 한다.
이를 Convolution Transpose Matrix라 한다.
Deconvolution Filter를 Matrix 연산에 맞게 바꿔준 후 Upsampling 한다.
기존의 Convolution 연산이 $AB = C$ 라면,
Deconvolution 연산은 $B = A^{-1}C$ 가 되고
Transposed Convolution 연산은 $\hat {B} = A^{T}C$이다.
일반적으로 Orthogonal Matrix가 아니므로 $A^{-1} \neq A^{T}$, 따라서 Deconvolution과 Transposed Convolution은 다르다.
3.4) Patchwise training is loss sampling
이후 논문에서는 Patchwise training 이라는 개념을 언급한다.
이는 모델을 training 할 때 전체 이미지를 넣는 것이 아니라
객체의 주변을 분리한 서브 이미지 즉 patch image를 사용하는 방법을 의미한다.
이러한 Patchwise training은 하나의 이미지를 100개의 patch로 분할하여 각 patch 마다의 loss값을 구한다.
이때 모든 loss를 사용하는 것이 아니라 중요한 patch들의 loss만 사용하거나 가중치를 주어 loss 값을 샘플링해 사용할 수 있다.
이는 Class imbalance 문제를 완화할 수 있지만 공간적 상관 관계가 부족해진다는 단점이 있다.
그런데 결과적으로 이미지의 부분을 학습하는 patch training과 전체 이미지를 학습하는 Fully convolutional training은 서로 동일하다.
또한 본 논문에서는 fully convolution training이 계산적으로도, 시간적으로도 유리하다고 언급한다.
4. Segmentation Architecture
define “ a skip architecture ” that combines semantic information from a deep, coarse layer with appearance information from a shallow, fine layer to produce accurate and detailed segmentations
4.1) From classifier to dense FCN
위의 논문에서는 FCN을 만들기 위해 사용한 네트워크는 AlexNet, VGG16, GoogLeNet 이다.
이 네트워크들을 Convolutionalization 과정을 통해 전부 FCN으로 변환한다.
해당 과정에서 $1 \times 1$ Convolution Layer를 사용한다.
PASCAL 데이터셋의 클래스가 21(background included)개 이므로 원래 FC Layer이였던 부분은 21개의 Channel을 가지는 Conv Layer로 바뀌게 된다.
성능을 측정한 결과 VGG16에 FCN을 적용했을 때 Metric으로 사용한 mean IU가 가장 좋게 나온다.
다만 전체적으로 보았을 때 성능이 아쉽기에 skip architecture를 도입하기로 했다.
4.2) Combining what and where
기존에는 FCN-32로, 단순히 Last Layer에서 $\times 32$ Upsampling을 하여 출력 이미지를 얻었다.
FCN-16에서는 pool4 Layer에서 $1 \times 1$ Convolution Layer를 적용하고 Last Layer에서 $\times 2$ Upsampling을 한 뒤에 합친다. 이후 $\times 16$ Upsampling을 하여 입력 이미지의 크기와 동일한 출력 이미지를 얻었다.
FCN-8에서는 pool3 Layer에서 $1 \times 1$ Convolution Layer를 적용하고 FCN-16에서 $\times 16$ Upsampling 하기 직전의 Feature Map에 $\times 2$ Upsampling을 한 뒤에 합친다. 이후 $\times 8$ Upsampling을 하여 입력 이미지의 크기와 동일한 출력 이미지를 얻었다.
위의 결과를 보면 상위 Layer에서 skip connection을 많이 한 결과 mask의 detail이 점점 좋아지는 것을 볼 수 있다.
그런데 이는 어떻게 보면 당연한 것이 FCN-32에서 $\times 32$ Upsampling을 할 경우 매우 많은 정보량의 손실된다.
따라서 이러한 정보량의 손실을 막기 위해 fine layer에서 coarse layer로의 skip connection을 적용하게 되면 더 좋은 성능을 얻을 수 잇는 것이다.
위의 표는 Skip connection을 어디에서 했는지에 따라 성능이 어떻게 차이나는지 보여주고 있다.
실제로 위에서 언급했듯이 fine layer에서는 입력 이미지의 세세한 정보가 많이 담겨있을 것이다.
그래서 convolution operation을 진행하며 조금씩 손실되는 이미지의 정보를 skip connection을 통해 손실을 막아준다.
따라서, FCN-8이 더 좋은 성능을 보이는 이유는 더 shallow, fine Layer에서 skip connection을 적용했기 때문에 Apperance Information과 같은 디테일한 이미지의 정보를 얻을 수 있었기 때문이라 볼 수 있다.
5. Summary
1) CNN 구조
- Input Image를 넣어 Convolution 연산을 통해 Feature Map을 추출 (Feature Extraction)
2) Convolutionalization
- $1 \times 1$ Convolution을 이용하여 Spatial coordinate를 유지한 상태로 Heatmap $(M \times N \times D)$를 형성
3) Upsampling (Transposed Convolution), Skip Architecture
- Skip Architecture: Heat Map을 Pooling Layer들과 combine
- Upsampling: Combined Heat Map을 Input Image와 동일한 크기 $(H \times W)$로 복원
4) 복원된 Heat Map의 각 pixel별로 Softmax를 적용하여 Pixel 별 Class 예측
본 논문은 기존에 ILSVRC의 유명한 딥러닝 기반 분류 모델을 sematic segmentation에 맞춰서 수정하여 transfer learning을 수행하고 각 네트워크에 따른 성능을 비교하였다.
segmentation의 per pixel loss를 얻으려면 입력 이미지와 출력 이미지의 shape이 동일해야 하기 때문에 upsampling을 수행하였지만 이 과정에서 많은 정보를 손실하여 성능이 좋지 않았다.
따라서 fine layer에서 coarse layer로의 skip connection을 통해서 정보의 손실을 방지하고 이를 통해 더 좋은 성능을 내는 것을 보여주었다.
6. References
https://velog.io/@leejaejun/Paper-Review-FCN-Fully-Convolutional-Networks-for-Semantic-Segmentation