[Segmentation] 3. FCN 의 한계를 극복한 모델들 (2)
- FCN의 한계를 극복한 모델들2 [DeepLab v2, PSPNet, DeepLab v3, DeepLab v3+]
- 지난 강의에 이어서 Receptive Field 를 확장시킨 model 들에 대해서 살펴볼 것.
- DeepLab v2
-
이전 강의에서 dilated conv 를 이용한 DeepLabv1 과 DilatedNet 에 대해서 배움.
-
두 모델 모두 Conv 에 dilated rate 을 줘서 훨씬 효율적인 receptive field 를 가지는 conv 를 적용했음. 추가적으로 기존의 encoder-decoder, FCN 에서는 5개의 max pooling 을 통해서 입력 이미지를 1/32 만큼 줄이고 다시 원본이미지로 키운 반면, 이 두 모델에서는 1/8 만큼 줄이고 다시 이를 8배 만큼 키우는 차이점을 보임.
- DeepLab v2 에서 앞 네트워크의 backbone 구조는 기존의 DeepLab v1 과 동일. 그러나 한가지 차이점은 conv5 block 에 있었던 3x3 Avgpool 부분이 사라지게 됨. 추가적으로 fc6 ~ fc8 에서 기존에는 하나의 conv 만 적용됐다면, 여기서는 4가지의 서로다른 dilated conv rate 를 가지는 branch 형태로 뻗어나감.
- 논문에서는 이를 ASPP 라는 Atrous Spatial Pyramid Pooling 이라고 표현함. 다양한 dilated rate 를 독립적으로 4가지 브랜치 형태로 적용한 다음 sum 을 취하는 구조임.
- 기존의 LargeFOV(v1) 과 비교했을 때 ASPP 를 적용하면 성능 향상을 보임.
-
ASPP 의 의미
- conv5 를 지나고 나온 feature map 은 다양한 object 에 대한 정보를 담고 있음. fc6 부분에서 dilated rate 가 낮은 block 은 작은 object 에 집중. rate 가 높은 부분은 큰 object 에 집중했을 것.
- 작은 object 와 큰 object 를 각기 잘 포착하기 때문에, 이 결과들을 summation 해서 좀 더 다른 부분에 집중한 결과를 앙상블 처럼 합쳐서 더 좋은 성능향상을 가져옴.
-
backbone
- DeepLabv2 에서는 ASPP 말고도 backbone 을 resnet 으로 변경함. resnet 을 적용한 구조를 보자.
- DeepLabv2 구조 - ResNet 적용
-
conv1 block 은 7x7, 64 channel, stride 2 를 적용 (7x7 conv → BN → ReLU)
- padding 은 3을 가짐. BN 은 output channel 만큼 64 를 가짐.
- 이 때 stride 2 를 통해서 입력 이미지의 resolution 을 512 → 256 으로 감소시킴. 오른쪽에 공식이 있음. floor 주의
-
3x3 max pooling, stride 2 를 적용해서 입력이미지의 크기를 256 → 128 로 감소시킴. 동일하게 2배만큼 감소시켜주기 위해서 padding 을 1 을 적용해줌.
-
conv2 block. 1x1, 3x3, 1x1 의 conv 가 하나로 이루어진 bottle neck 이 3번 반복됨.
- sub-block 을 보면 conv → BN → ReLU 를 적용하는데, 마지막 1x1 conv, BN 후에는 입력 feature map 과 skip connection 후 ReLU 를 적용함.
- 첫번째 들어오는 채널이 64인데, 나오는 채널은 256. 이 둘을 skip connection 을 통해서 sum 을 해주려면 채널을 맞춰줘야 함. ResNet 에서 채널이 다른 것을 어떻게 맞출 수 있었을까?
- 채널 수를 맞추기 위해서 1x1 conv 를 추가(64 → 256)
- 128, 128, 64 의 feature map 이 1x1 conv, BN 을 통과해서 256 채널을 가지고 이를 summation 해서 최종 skip connection 의 결과를 얻음.
- identity block 으로 1x1 conv 수행하면서 output 채널을 64 → 256
- sub block 을 총 3번 반복. 2번째 sub block 부터는 들어오는 채널이 256이고 나오는 채널수도 256이기 때문에 그대로 skip connection 을 수행함 (identity mapping 을 해주는 1x1 conv 를 제거함)
- conv3 block
- 1x1, 3x3, 1x1 conv 를 적용하지만 채널은 2배만큼 키워지고, 반복횟수도 증가함.
- 조금의 차이점이 있다면, 첫번째 sub block 내부에 3x3 conv, stride 2 를 적용해서 down sampling 을 적용함. 그래서 입력 feature map 이 128, 128 일 때 output feature map 은 64x64 가 됨.
- 일반적으로 3x3, stride 1, padding 1 이 입력 이미지 크기의 변동이 없는데, stride 2 를 줘서 크기가 1/2 만큼 감소한 것.
- 참고할 점은 identity mapping . 입력 채널은 256, 출력 채널은 512 (sub block 관점). 둘의 채널을 맞춰줘야 함. 해상도 부분에 대해서도 입력 해상도는 128 이지만 stride 2 conv 를 통해서 64 로 감소했기 때문에 해상도를 맞춰줄 필요가 있음.
- 그래서 이를 1x1 conv 를 통해서 채널을 맞춰줌과 동시에, stride 2 를 통해 해상도를 맞춰줌.
- stride 2 로 이미지 해상도가 128 → 64 로 바뀌고, 256 channel 을 512 와 맞춰주기 위해서 1x1 conv 의 채널을 512 로 세팅함.
- 정리하면, conv3 의 첫번째 sub block 에서 stride 2 를 통해서 down sampling 을 진행하면서도 residual unit 을 생성함. 이 구조를 반복해줌.
- 2번째 sub block 부터는 down sampling 을 제거하고 채널도 맞으니까 skip connection 할 때 1x1 conv identity mapping 이 없음을 확인할 수 있음. 3번째, 4번째 sub block 에서도 동일하게 진행됨.
- conv4 block
- conv3 block 과 거의 동일함. 대신 채널이 2배만큼 증가하고, 반복횟수가 23회임.
- 그 외의 부분은 동일하게, 첫번째 sub block 부분은 down sampling 을 수행하고 그 외의 부분은 기존과 동일하게 conv 이 구성됨.
-
conv5 block
- 마찬가지로 첫번째 sub block 에서는 stride 2 를 적용해서 down sampling 을 하고 그 외 나머지 부분은 기존과 동일.
-
참고할 점은, DeepLab v2 에서는 일반적인 ResNet 에 비해서 몇 가지 차이점이 있음. (DeepLab v2 의 ResNet 의 특징)
- conv4, conv5 block 부분에 기존에는 down sampling 하는 부분을 stride 1로 down sampling 을 적용하지 않음.
- 3x3 conv 를 그냥 conv 가 아니라 dilated conv 를 사용함.
-
-
DeepLab v2 LargeFOV(ResNet-101 Backbone) (FOV 는 Field Of View)
- DeepLab v1 LargeFOV 구조에 ResNet 을 적용한 모습.
-
DeepLab v2 ASPP (ResNet-101 Backbone)
- LargeFOV 에서 기존의 VGG 16 과 ResNet-101 을 비교하면 4.31 만큼 성능(mIOU)이 올라감.
- 동일하게 ResNet-101 에서 LargeFOV 를 ASPP 로 변경하면 1.2 만큼 성능이 올라감.
- CRF 까지 적용하면 성능 향상이 더 됨.
-
- PSPNet
- 동일하게 receptive field 를 넓히는 시도지만 조금은 다른 방식으로 도입됨.
- PSPNet 에서는 세가지의 문제점을 제시함.
- 첫번째로는 객체들 간의 관계를 제대로 캐치하지 못하는 점. (Mismatched Relationship)
- FCN 이 boat 를 잘못 예측함. 외관이 비슷해서.
- PSPNet 에서는 주변의 특징을 고려하도록 함.
- 두번째로는 비슷한 클래스 혹은 카테고리를 혼동함. (Confusion Categories)
- 카테고리가 유사한데, 지역적인 정보만 봐서는 분류하기 힘들다.
- PSPNet 에서는 카테고리 간의 관계를 사용해서 해결함.(global contextual information 사용)
- 무늬가 비슷하고 작아서 잘 안보이는 객체를 제대로 구분하지 못함. (Inconspicuous Classes)
- 모습이 비슷하고 객체의 크기가 작으면 잘 예측을 못함.
- 작은 객체들도 global contextual information 을 사용함.
- 첫번째로는 객체들 간의 관계를 제대로 캐치하지 못하는 점. (Mismatched Relationship)
- PSPNet 이 도입된 배경 중 두번째는, FCN 의 receptive field 와 관련.
- FCN 의 경우 5개의 max pooling 을 통해서 크기를 줄이고, 거기에서 특징을 추출했기 때문에 큰 receptive field 를 가지고 예측을 진행했을 것. 이렇게 receptive field 가 큰데도 객체간의 관계를 잘 포착하지 못했을까?
-
그 이유는 아래 논문에서 얻을 수 있음.
- 이 논문에서 주장하는 바는, 실제로 가지는 receptive field 와 이론적인 receptive field 의 크기 사이즈가 많이 다르다고 함.
- 이론적인 사이즈와 실제 사이즈를 비교해보면 pooling 이 진행되면 진행될수록 차이가 굉장히 다른 점을 알 수 있음.
- PSPNet 에서는 이런 문제를 효율적으로 해결하기 위해서 global average pooling(GAP) 를 도입해서 해결함.
-
PSPNet Architecture
- PSPNet 은 다른 average 크기를 가지는 average pooling 을 적용하는데, 같은 feature map 에 비해서 average pooling 적용했을 때 결과가 1x1, 2x2, 3x3, 6x6 서로 각기 다른 크기를 가지는 것을 확인할 수 있음.
-
Global Average Pooling (GAP)
- 전체 feature map 을 하나의 1x1 형태로 줄임.
- 각기 다른 채널에 대해서 모든 정보를 요약한 하나의 픽셀 형태를 만드는 것.
- feature map 전부에 있는 영역을 평균내서 대표하는 값을 만들기 때문에 global 한 context 를 더 잘 캐치할 수 있음.
- 사실상 average pooling 과 비슷한 역할이지만 1x1 의 크기로 줄인 것.
- 전체 영역을 다 평균내서 대표하는 값으로 하나를 만든 것.
- 원래의 average pooling 은 기존의 feature map 을 영역을 나눠서 각 영역을 대표하는 평균값으로 추출한 것. 그것을 채널마다 수행하는 것.
- Convolution vs Average Pooling
- 넓은 영역으로 average pooling 을 적용한 결과 conv 와 약간의 다른 feature map 의 양상을 보임.
- conv 는 입력 이미지의 특징적인 부분을 통해서 feature map 을 구성.
- average pooling 은 영역을 나눠서 평균을 내서 대표값을 추출함.
- conv 는 좀 더 외관의 모습인 local 한 정보들을 많이 추출. average pooling 은 global 한 영역에 대해서 context 를 추출.
-
그래서 PSPNet 에서는 이러한 global context 영역을 추출하기 위해서 크기가 다른 average pooling 을 적용함. 1x1, 2x2, 3x3, 6x6 이렇게 다르게 적용함.
- 이 때 각기 다른 영역에 대해서 1x1 conv 를 통해서 채널을 같게 맞춰줌.
- 각기 다른 average pooling 에 의한 결과와 feature map 의 결과를 concatenation 해서 skip connection 을 활용함. 4개의 가지 영역의 크기가 다르기 때문에 크기를 맞춰주기 위해서 upsampling 도 적용함.
- PSPNet 은 기존의 baseline 에 대비했을 때 훨씬 정보들이 더 잘 살아남.
-
DeepLab v3
-
DeepLab v3 는 DeepLab v2의 ASPP 에, feature map 을 평균내서 1x1 의 크기를 만들어준 GAP(global average pooling) 이 추가되어 global 한 context 를 더 잘 캐치하도록 만들었음.
- 기존의 ASPP 와 동일하게 브랜치 형태로 구성. 몇가지 차이점은, 6, 12, 18, 24 (DeepLab v2) 에서 6, 12, 18 3가지 브랜치만 사용. 그리고 1x1 conv 가 새로 추가됨. 그리고 GAP 가 적용되고, DeepLab v2 에서는 summation 하는 형태였다면 v3 에서는 concat 후에 1x1 conv 를 적용함.
- GAP 의 결과는 1x1 의 크기를 가짐. 따라서 위 ASPP 와 많이 다름. 그래서 이를 맞춰주기 위해서 Bilinear interpolation 을 적용해줌.
- 4개의 ASPP conv 에 의해서는 feature map 의 크기가 변화하지 않도록 zero padding 을 적절하게 넣어서 크기를 고정해줌.
- 구현체마다 rate 의 비율이 어느정도 차이는 있음.
-
-
DeepLab v3+
- 이전 DeepLab v1 ~ v3, DilatedNet 은 몰라도 DeepLab v3+ 는 유명한 네트워크. backbone 부터 시작해서 이전과 다르게 어떻게 변형됐는지 보자.
- Encoder-Decoder 구조
- v1 에서 v3+ 로 넘어오면서 encoder decoder 의 구조를 사용함.
- 기존의 deeplab 은 이미지를 크기를 줄인 다음에 Spatial Pyramid Pooling, 즉 ASPP 를 적용해서 결과를 만든 다음에 concat 이나 sum 을 취해주고 8배 혹은 16배만큼 bilinear interpolation 으로 키워주는 모습을 보임.
- DeepLab v3+ 는 encoder, decoder 형태를 가져서 이미지 크기를 줄이는 부분은 유사하지만 0.5 배만큼 줄이는 게 하나 더 추가되고 이후 크기도 4배씩 두번 키우며, Encoder-Decoder 구조의 Skip connection 의 구조를 적용해서 같이 활용함.
- 기존 encoder 에서 spatial dimension 의 축소로 인해 손실된 정보를 decoder 에서 점진적으로 복원해주는 테크닉을 활용함. 특히 skip connection 을 이용한 것도 특징.
-
encoder 구조
- resnet 이 아닌 수정된 Xception 을 backbone 으로 사용.
- Atrous separable convolution 을 적용한 ASPP 모듈 사용. 여기에 1x1 conv 으로 ASPP output 을 생성
- 추가적으로 backbone 내에 low level feature 를 decoder 로 전달해줌.
-
decoder 구조
- ASPP output 을 전달받아서 upsampling 을 통해서 low level feature 와 concat 하는 부분을 볼 수 있음.
- 기존에는 ASPP output 에 upsampling 을 8배 혹은 16배로 키웠다면, 훨씬 세련되게 low level feature 를 활용하고, ASPP output 을 4배 키우고 concat 후에 다시 4배 키우는 테크닉들을 보임. → 디테일을 더 잘 유지할 수 있도록 함.
- Modified Xception backbone
- Xception 은 효율적인 연산을 위해서 Depthwise Separable Conv 을 사용함.
- 일반적인 conv 가 spatial 및 channel dim 에 대해서 모두 한번에 연산을 진행했다면, depthwise separable conv 는 channel 과 spatial 부분의 연산을 따로따로 진행함.
- depthwise separable conv 의 경우, depthwise conv 와 pointwise conv 2개가 같이 결합되서 이루어진 구조.
-
depthwise conv
- 서로 다른 채널에 대해서 conv 연산을 각기 다른 것을 수행해준 뒤, conv 결과를 합치는 것이 depthwise conv.
- 입력 채널과 groups 의 값을 동일한 값을 설정해줘서 구현할 수 있음.
-
pointwise conv
- depthwise separable conv 를 구성하는 pointwise conv 도 있음.
- pointwise conv 는 1x1 conv 연산을 의미.
- kernel size 만 1을 줘서 구현할 수 있음.
-
Depthwise Separable Convolution
- depthwise conv → pointwise conv
- 이를 통해 더 효율적인 연산을 취함.
- depthwise conv 는 gropus 와 in_channels 를 맞춰주면서 적용할 수 있음.
- pointwise conv 는 1x1 의 kernel_size 를 줘서 적용.
- 구현체에 따라서 가운데에 BatchNorm 이 들어가기도 안 들어가기도 함.
-
이러한 depthwise separable conv 를 사용해서 만든 네트워크가 Xception 인데, DeepLab v3 에서는 기존의 Xception 과는 다른 modified Xception 을 사용함.
- 실제 Original 과 비교. 3개의 flow 인 entry flow, middle flow, exit flow 에서 어떤 차이점이 있는지 보자. (Modified Xception)
-
Entry flow
- max pooling 연산이 Depthwise separable conv 연산으로 바뀜.
- max pooling 은 중요한 영역만 추출했다면, Depthwise separable conv 에 stride 2 를 적용해서 크기를 줄이면서 학습 가능한 파라미터를 통해서 어느 부분이 중요할지, 어떻게 추출하는게 정보의 손실을 좀더 방지할 수 있을지 역할을 수행함.
- channel 은 32, 3x3, stride 2 로 크기를 1/2 만큼 줄여줌. 동일하게 BN, ReLU 가 적용됨. 다음 conv 는 3x3, in 32, out 64
- 그 이후 depthwise separable conv 는 depthwise conv + pointwise conv. depthwise에서 중요한 것은 in_channels 와 groups 의 값을 128 로 같게 맞춰준 것. pointwise 에서 중요한 것은 kernel size 1x1
- depthwise 와 pointwise 사이에 BN 을 적용함.
- 여기서 stride 가 2 라서 크기가 1/2만큼 줄었을 것.
- 이를 identity mapping (skip connection) 해주는 부분에서 맞춰주기 위해서 stride2 를 갖게 해서 resolution 을 맞춰줌.
- 이후 summation 함.
-
Middle Flow
- repeated 횟수를 8에서 16으로 증가시킴으로써 더 깊은 구조를 사용함.
-
Exit Flow
- entry flow 처럼 max pooling 연산을 depthwise separable conv 에 stride 2 를 적용한 구조로 바꾸고 최종 부분을 두개의 depthwise separable conv 을 적용한 상태에서 3개로 바꾸고, 채널 수 또한 1536, 2048 구조를 1536이 2번, 2048 적용하는 형태로 바꿈.
- depthwise separable conv 가 3개가 반복되는 구조. 채널은 1024 → 1536 → 2048. 3x3, stride 1, padding 1, dilation 2 로 3개가 모두 같음.
- modified Xception backbone 을 DeepLab v3+ 로 가져오면서 몇 가지 차이점이 있는데, 기존의 Xception 을 classification 에 적용하는 경우에는 총 5개의 stride conv 를 통해서 입력의 크기를 1/32 로 줄였음.
- 그러나 segmentation task 에 적용할 때는, 마지막 exit flow 에는 stride conv 를 제거해서 입력을 1/16 으로 줄임. 또한 모델 설정에 따라서 4번째의 stride conv 도 지워서 입력을 1/8로 줄이기도 함. → 즉 이를 통해서 더 미디엄한 resolution 에서 특징을 추출하고 high resolution 으로 복원하기 위함.
-
-
DeepLab v3+ 의 전체적 구조
- Encoder
-
DCNN 에 부분에서 modified Xception 을 이용해서, 512x512 의 입력을 32x32 로 총 4개의 stride conv 로 1/16 만큼 크기를 줄임.
-
첫번째 block 을 지난 결과에 ReLU 를 적용해서 decoder 에 low level 의 feature 를 전달함.
-
modified Xception 결과에 ASPP 를 적용해서 출력을 만들고, kernel size 는 1, 3. 그리고 padding 과 dilation 비율을 같게 만들어서 크기 변동을 방지해줌. GAP 의 경우 AdaptiveAvgPool2d 를 이용해서 output size 가 1x1 이 나오도록 구현한 뒤 서로의 크기가 맞지 않으니 이를 맞춰주기 위해서 1x1 으로 채널수를 맞춰줌.
-
GAP 부분은 bilinear interpolation 을 통해서 resolution 크기를 맞춰줌. 그 이후 이렇게 나온 5개의 결과를 concatnation 를 해주고 그 이후 1x1 conv 를 적용해서 채널을 256 * 5 에서 256 으로 감소시켜줌. 그 결과를 decoder 로 넘겨줌으로써 encoder 의 부분이 끝나게 됨.
-
-
Decoder
- Xception backbone 의 entry flow 내 첫번째 블록의 출력인 1/4 만큼 줄어든 128x128 의 low level feature 가 건네져 옴.
- ASPP 출력은 1/4 * 1/4 로 1/16 된 결과가 건네져 옴.
- low level feature 1x1 conv 을 적용해서 채널을 128 → 48.
- ASPP 결과에 bilinear upsampling 을 통해서 4배 만큼 키워서 128x128 을 맞춰줌.
- low level feature 와 upsampled ASPP output 을 concat 해줌.
- concat 한 결과에 3x3 conv 로 segmentation 의 probability map 을 만들고, bilinear interpolation 으로 4배만큼 키워서 512x512 의 최종 결과를 도출함.
- DeepLab v1 부터 v3+ 까지 정리
- FCN 한계부터 출발해서 receptive field 를 확장해서 성능을 올렸던 DeepLab 계열, Dilated Conv, PSPNet 까지 다 살펴봄. DeepLab v3+ 까지 꽤 큰 성능 향상을 가져옴.
- Encoder Decoder 대칭 → DeconvNet, SegNet → upsampling 기법으로 Unpooling.
- Unpooling 은 max pooling 에 의해서 잃어버린 spatial 한 정보를 Max indices, max pooling 시 어느 위치에서 정보가 추출됐는지 인덱스 정보를 기록했다가 복원하는 과정으로 역할을 수행함.
- DeconvNet Activation map 을 보면 low 한 정보는 색상, 형상 등이 활성화, 딥하게 레이어가 깊어지면 디테일하게 자세한 구조들이 생겨남. 이를 unpooling 과 transposed conv 로 나눠볼 때, unpooling 은 자세한 구조적 모습이 활성화되고, transposed conv 는 unpooling 에서 sparse한 matrix 가 형성됐다면 이 내부를 채워주는 역할을 수행 → 디테일한 모습들이 잘 살아남.
- SegNet 은 성능 외에도 속도적 측면에 대해서 real time semantic seg 를 가능하도록 한 모델
- DeconvNet 과 유사하지만 내부의 fc layer 를 제거해서 파라미터 수를 줄여서 속도적으로 빠르게 만듦.
- Skip Connection 적극 활용 모델
- DenseNet 의 skip connection 을 이용한 FCDenseNet, UNet.
- Receptive Field 를 확장시킨 모델
- receptive field 가 작다면 seg task 예측 정확도가 낮음.
- receptive field 는 하나의 픽셀이 입력 이미지에서 얼만큼의 영역을 바라보고 있는지를 의미함.
- conv → max pooling → conv 를 반복해서 효율적으로 receptive field 를 높혔지만 그러나 seg 에서는 resolution 측면에서 결과가 나빴음.
- 이를 해결해주기 위해서 Dilated Conv 가 등장해서 파라미터의 수는 그대로지만 훨씬 receptive field 를 넓힌 기법이 등장함.
-
그래서 down sampling 과 up sampling 을 제거하고 커널 사이즈도 동일하지만 dilation rate 를 증가시켜서 훨씬 resolution 정보를 더 잘 활성화 하도록 함.
-
Dilated Conv 는 파라미터의 수는 동일하지만 내부에 0을 채워서 효율적으로 receptive field 를 넓히는 방법
- DeepLab v1, Dense CRF(후처리)
- DilatedNet ( + basic context module)
- DeepLab v2 (ASPP) + VGG16 → ResNet-101 backbone
- PSPNet → FCN 3가지 문제점 언급 → 해결을 위한 언급 ⇒ global context 도입 (GAP, average pooling 을 도입)
- Average Pooling 은 주변 정보(문맥)를 파악해서 객체를 예측하는데 사용
- 각기 다른 크기를 가지는 Average Pooling 들. (GAP 는 1x1 출력)
- DeepLab v3 → GAP 를 ASPP 에 적용, sum → concat
- DeepLab v3+
- Modified Xception (backbone)
- Encoder-Decoder (low level feature + ASPP feature 결합 활용. concat)
- decoder 에서 4배씩 순차적으로 크기를 키움.
댓글 남기기