해당 포스팅은 네이버 부스트캠프 P-stage를 위해 개인 학습 내용을 정리했습니다.
1. 강의
High Performance를 자랑하는 Unet 계열의 모델들
1) U-Net
U-Net은 Biomedical 분야뿐만 아니라, 다양한 분야에서 좋은 성능을 보여주고 있습니다. 특히 medical 분야는 데이터가 부족합니다. 고급인력인 전문가들이 직접 라벨링을 해줘야 하기 때문에 데이터 수집이 쉽지 않습니다. 그리고 의료 데이터의 경우 같은 클래스가 인접한 셀 구분할 필요가 있습니다. 하지만, 일반적인 Semantic Segmentation에서는 이것을 구분하기가 굉장히 어렵습니다. 그래서 이것들을 해결하기 위해 만들어진 구조가 바로 U-Net입니다.
U-Net은 입력 이미지의 전반적인 특징을 추출하고 차원을 줄여주는 Down-sampling이 포함된 Contracting Path와 Localization을 가능하게 하고 차원을 늘리는 Up-sampling이 포함된 Expanding Path가 존재합니다.
위의 그림처럼 U자 형태를 가지고 있으며, 3*3 Conv와 Batch normalization, Relu가 2번씩 반복되는 구조를 가지고 있습니다. 특징점으로는 Zero-Padding을 하지 않고 네트워크가 진행되기 때문에 크기가 조금씩 줄어드는 것을 확인할 수 있습니다. 중간의 회색 부분은 같은 계층의 Encoder 출력물을 Skip-connection 형태로 넘겨주는 부분입니다. 하지만, 앞쪽에서 나온 Encoder 출력물과 이미지 사이즈가 맞지 않는 문제가 있어서 이를 해결하기 위해 Encoder 출력물을 Center Crop해서 동일 사이즈로 넘겨줍니다. U-Net을 통해서 더 고차원에서 정보를 매핑할 수 있고, Encoder의 출력물을 Decoder와 결합시키는 과정으로 이전의 정보를 효율적으로 사용한다는 장점이 있습니다.
U-Net에서는 데이터 부족을 극복하기 위해 Random Elastic deformations로 Augmentation을 수행했습니다. Random Elastic deformations는 물체를 살짝 찌그러뜨린 형태로 변형하는 방법입니다. sliding window를 사용해서 데이터를 더 많이 활용했습니다. 이 때, 겹치는 부분이 없도록 sliding window를 사용했습니다. 하지만, sliding window는 background만 존재하는 부분이 있을 수도 있고, 일부의 모습으로 클래스를 예측하도록 학습될 수 있어서 주의할 필요가 있습니다.
U-Net에서는 경계를 잘 구분하기 위해서 가중치 맵을 활용했습니다. 셀과 셀이 만나는 영역과 셀의 중심부를 weight를 통해서 구분하는 방법입니다.
$$ w(x) = w_{c}(x) + w_{0} \, exp(- \frac{(d_{1}(x) + d_{2}(x))^{2}}{2 \sigma^{2}}) \, E = \sum_{x \in \omega} w(x) log(p_{l(x)}(x))$$
$d_{1}$은 가장 인접한 cell과의 거리, $d_{2}$는 두번째로 인접한 cell과의 거리를 나타냅니다. $w_{c}(x)$는 class 별 빈도에 따른 가중치입니다. $d_{1}$과 $d_{2}$가 증가하게 되면 exp값이 작아지게 되면서 낮은 값을 가지게 됩니다. 이를 이용해서 셀 마다의 가중치를 다르게 부여합니다.
하지만 U-Net은 깊이가 4로 고정되어 있어서 데이터셋마다 최고의 성능을 보장하지는 않습니다. 단순한 Skip Connection은 동일한 깊이를 연결하는 면에서 제한적이라는 한계점을 가지고 있습니다. 이를 보완한 방법으로 나온 것이 U-Net++입니다.
2) U-Net++
해당 논문에서는 다양한 데이터셋을 대상으로 Depth를 제한했을 때, 최고 성능이 다양한 Depth에서 나오는 것을 확인할 수 있습니다. 그래서 U-Net++에서는 다양한 깊이의 U-Net을 생성하고 단순한 skip connection 형태를 Deep skip Connection을 활용해 극복했습니다. U-Net++에서는 loss function을 Pixel wise Cross Entropy와 Soft Dice Coefficient를 결합한 hybrid loss를 활용했습니다.
U-Net++는 U-Net에 비해 성능 향상을 보였습니다. 하지만, 복잡한 Connection으로 인해 parameter 수가 증가했고, 많은 connection으로 인해 memory가 많이 필요하다는 단점이 있었습니다. 또한 동일한 크기를 갖는 Feature map에서만 Connection이 일어났다는 단점도 존재했습니다. 그래서 이것을 극복한 U-Net 3+이 등장합니다.
3) U-Net 3+
U-Net 3+에서는 동일한 scale 이외의 encoder layer로부터 low-level feature map을, decoder layer로부터 high-level feature map을 받는 Full-scale Skip Connection을 구성했습니다. 이렇게 함으로써 풍부한 공간 정보를 얻어서 경계를 강조할 수 있었고, 어디에 객체가 존재하는 지 위치 정보 구현이 가능했습니다. 그리고 이 과정에서 Parameter를 줄이기 위해 모든 decoder layer의 채널 수를 320으로 동일하게 적용했습니다.
또한 U-Net 3+에서는 low-level layer에 남아있는 background의 noise가 발생해서 많은 false-positive 문제가 발생했습니다. 그래서 정확도를 높이기 위해서 Classification-guided Module을 사용했습니다. 그리고 U-Net ++처럼 hybrid loss를 사용합니다. 클래스의 불균형을 해소하기 위한 Focal loss와 경계 인식을 강화하는 ms-ssim loss, 픽셀의 분류 정확도를 높이기 위한 IoU를 더해서 사용했습니다.
이후에는 Residual U-Net, Mobile-UNet, Eff-UNet처럼 backbone을 다양하게 활용하는 U-Net이 많이 등장했습니다.
2. 목표
- Github 서버랑 연결하기
- Daily mission : Unet 구조 만들어보기
- Focal loss 적용해보기
- DeepLabv3 + resnet101
3. 진행 내용
1) Github 서버랑 연결하기
우선, git 명령어를 정리해주신 영민님께 감사합니다! "git clone -b <branch name> https://github.com/주소"로 git 폴더에 접근이 가능합니다.
2) DeepLabv3 + resnet101
DeepLabv3 모델에 backbone으로 resnet101을 적용했고, 다른 것들은 바꾼 것 없이 batch_size만 줄여서 학습했더니 약 17에폭 정도에서 최고 mIoU가 0.51 정도 나왔습니다. submission 결과는 0.54가 나왔습니다. CrossEntropy를 적용했었는데, FocalLoss(gamma=2)로 적용해보고 결과를 비교할 예정입니다.
3) FocalLoss 적용해보기
FocalLoss는 cross entropy를 변형한 것으로 Gamma값이 커질 수록 적은 클래스에 대해 가중치를 주는 방식으로 학습합니다. 이번 주어진 데이터는 클래스 불균형이 꽤 심하다고 생각이 되어 적용해보고 있습니다. Gamma=2, 5로 돌려볼 예정입니다.
4) UNet 구조 만들기
U-Net은 기존에는 padding 없이 사용하고, crop_img를 활용했지만 zero_padding을 1해주면, crop_img를 하지 않아도 동일한 사이즈로 concat을 할 수 있습니다.