Semantic Segmentation을 처음 시도한 성공적인 convolution network이다. FCN은 Fully-Connected Layer를 제거함으로써 conv.layer와 pooling.layer로만 구성된다.
input: m x n x 3의 color image output: m x n x (C+1) tensor - 이때, C는 class개수이고 C+1에서 +1을 해주는 이유는 배경이 포함되기 때문이다. - output tensor의 0번 map은 background를 의미하며 이후는 class에 속한다.
FCN은 m x n x 3크기의 input image를 Downsampling하여 점차 작게 만든다. 이후 m x n으로 다시 키우는 Upsampling (= Deconvolution)과정이 필요하다.
Downsampling을 계속하면 receptive field가 커지므로 detail이 떨어진다. 앞쪽의 feature map의 경우, detail한 정보를 갖지만 전역정보가 부족하다. ∴ FCN은 여러 scale의 feature map을 결합해 segmentation성능을 최고로 유지한다. → by skip connection !! https://arxiv.org/abs/1411.4038
뒤에서 소개되는 model들은FCN이 성공을 거둔 후 FCN의 성능을 개선하여 다양하게 변형된 model들이다.
[DeConvNet]
DeConvNet은 FCN과 Auto-Encoder를 결합한 구조이다. [Noh2015] FCN의 경우, 사람이 개입해 Upsampling을 설계했기에 구조가 복잡하고 어색하다. DeConvNet의 경우, 대칭구조의 표준 auto-encoder를 사용해서 구조와 학습, 성능이 우월하다. https://arxiv.org/abs/1505.04366
[U-Net]
의료 영상처리분야에서 가장 권위있는 학술대회 중 하나인 MICCAI(Medical Image Computer Assisted Intervention)에서 발표된 U-net은 의료영상 분할을 목적으로 개발되었다.[Ronneberger2015] (같은 해 ISBI 세포 추적 대회에서 우승 차지는 안비밀)
U-net은 Downsampling과정과 Upsampling과정을 각각 다음과 같이 부른다. - Downsampling = contracting path - Upsampling = expansive path
📌 Down Sampling과정 →: Convolution layer과 ↓: Pooling layer을 통과하면? 여타 모델처럼 feature map의 spatial resolution은 줄어들고 depth(=channel)는 늘어난다. 이 과정을 4번 반복하면 가장 아래의 32X32X512의 feature map이 된다.
📌 Deconvolution (≒ Upsampling)과정 Transpose Convolution (= Deconvolution)을 이용해 원래 image size로 복원한다.
🌟 U-net의 주안점은 →로 표시된 shortcut connection이다!! Downsampling, Upsampling에 대응되는 층에 대해 각각 다음과 같이 연산한다. - 좌측에서 발생한 feature map에 대해 중앙에서 crop을 진행, expansive path로 전달. - 우측은 전달받은 tensor(HxWxC)를 이어붙여 (HxWx2C)의 tensor를 생성한다.
원래 U-net은 Conv2D(filters, (3,3), strides=1, padding='valid')로 사용한다. 따라서 input image가 572x572는 570x570, 568x568로 줄어든다.
풀링층의 경우, 2x2 filter사용으로 feature map의 크기는 반으로 줄어든다. 따라서 568x568맵이 284x284가 된다. https://arxiv.org/abs/1505.04597
[DeepLabv3+]
Encoder-Decoder구조에 기반한 신경망은 기존의 image를 16~32배까지 축소 후 Upsampling으로 기존 크기로 복원한다. 예를들어 U-net은 572x572 image를 32x32로 축소 => 388x388로 복원한다.
But! 상당히 작게 축소했다 복원하기에 "detail한 feature"를 잃어버릴 가능성이 높다. → DeepLabv3+는 이런 단점을 팽창 컨볼루션(dilated convolution = atrous convolution)으로 완화한다.[Chen2018] https://arxiv.org/abs/1802.02611 dilated(=atrous) convolution에 대한 그림atrous convolution은 팽창계수 r을 가지며, r=1의 경우 좌측사진처럼 보통 convolution과 같다. r=2의 경우, 3x3 filter는 이웃 9개의 pixel을 조사한다.(다만 우측처럼 한 pixel을 건너 진행한다.) 즉, 더 넓은 receptive field를 적용하는 셈이 될 수 있다!
thing: 셀 수 있는 물체 (자동차, 사람) // stuff: 셀 수 없는 물체 (땅, 하늘) - semantic segmentation: 같은 class의 thing의 경우, 구분하지 않고 같은 class로 할당 - instance segmentation: thing에 대해서만 분할, 같은 class라도 고유번호를 할당해 구분한다. - panoptic segmentation: 모든 pixel에 대해 thing과 stuff를 할당,분할을 진행한다.
🧐 Metric
classification은 image에 대한 하나의 class 확률벡터를 출력한다. 하지만 segmentation은 pixel단위로 class를 지정한다. 그렇기에 segmentation을 dense classification이라고도 부른다.
segmentation에 사용되는 정확률을PA: Pixel Accuracy(화소 정확률)이라 하며 아래와 같이 측정한다.
또한 class별로 PA를 계산하고 결과를 평균한 식인 MPA를 metric으로 사용할 수도 있다.
또 다른 metric는 Object Detection에서 사용되는 IoU(Intersection over Union)를 segmentation에 맞게 고쳐 사용하는 방법이다. i. class별 AP(Average Precision)을 계산 ii. AP를 모든 class에 대해 평균해 mAP를 계산 이때, 아래 식에서 A와 B가 객체가 아닌 영역이라는 점만 다르다.
마지막으로 Dice coefficient를 metric으로 이용할 수도 있다.
cf. instance segmentation with Object Detection
instance segmentation은 object detection과 연관성이 많고
semantic segmentation은 object classification과 연관성이 많다.
- semantic segmentation은 개별 객체의 경계를 구분하는 것보다는 image내의 pixel수준에서 class에 대한 classification에 중점을 두기 때문이다. 즉, 개별 객체의 경계식별보다는 이미지 전체에 대한 class분류에 중점을 둔다.
따라서 본 글에서는 semantic segmentation에 집중하며이후 Object Detection 이후 instance segmentation을 소개할 것이다.
본 글에서는 간단하게 instance segmentation을 사용만 해볼 것이다.
[Semantic Segmentation]
Semantic Segmentation => 이미지 내 피사체에서 의미를 갖고 분할을 진행 - 상위버전=> Instance Segmentation: 같은 클래스 피사체여도 다른 물체를 구분. (정보 多)
[방법] pixel by pixel - 클래스 개수만큼 pixel당 channel을 생성
polygon(다면체) - 물체의 특정부분의 점들을 잇는 방법 - 좌표를 이용해 라벨에 대해 적은 비용이 들어감 - 점의 개수가 많아질수록 정확도는 올라감 ,, key point detection 기반
import os
import math
import wandb
import random
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras.preprocessing.image import load_img
from tensorflow.keras.models import *
from tensorflow.keras.layers import *
from tensorflow.keras.losses import *
from tensorflow.keras.metrics import *
from tensorflow.keras.optimizers import *
from tensorflow.keras.activations import *
from tensorflow.keras.regularizers import *
from tensorflow.keras.callbacks import *
from tensorflow.keras.preprocessing import *
import tensorflow_datasets as tfds
dataset, info = tfds.load('oxford_iiit_pet:3.*.*', with_info=True)
이때, 255로 나누는 이유는 정규화를 위해서인데, X와 y사이의 "Loss map"을 simple하게 유도하여 조금만 변화시켜줘도 되기 때문에 사용한다!!
🤔[Loss Map...?]
Loss map이란??
Loss map은 input image의 각 pixel에 대한 Loss값을 나타내는 map이다. 이를 통해 predict와 target값 간의 차이를 시각화 할 수 있다.
일반적으로는 predict와 target간의 차이를 계산하기 위해 Loss function이 사용된다. Loss function으로 pixel별 Loss를 얻은 후 이를 시각화하면 Loss map을 얻을 수 있다.
이런 Loss map은 아래와 같은 특징을 갖는다.
1. Loss map은 쉽게 쌓을수록 좋다. 2. ReLU는 Loss map을 쉽게 쌓을 수 있다! 3. Layer를 깊게 쌓을수록 Loss map이 복잡해져 X와 y사이의 복잡한 문제를 해결할 수 있다!
[Loss function]
기울기 그래프를 수렴속도 그래프라 생각해보자!
MSE (Mean Squared Error) MAE는 L1 Norm을 사용한 Loss function이다. MAE = (1/n) * ∑|yᵢ - ȳ| 로 표현되며, 쉽게 말하자면 |x|형태이다.
- 절댓값의 합을 평균으로 계산하기에 이상치(outlier)에 더 강인한 성질을 갖는다. 즉, 이상치에 큰 영향을 받지 않고 전체적인 오차를 잘 반영한다. MSE와 달리 local minima 탈출은 쉬우나 과하다는 점...
- 수렴속도의 관점에서, x=1을 기점으로x>1에서는 수렴속도가 너무 느리고x<1에서는 너무 빠르다. 따라서 data 집단이 1~100사이의 값을 다룰 때 사용이 용이하다.
MSE (Mean Squared Error) MSE는 L2 Norm을 사용한 Loss function이다. MSE = (1/n) * ∑(yᵢ - ȳ)² 로 표현되며, 쉽게 말하자면 x²형태이다.
- 예측값과 실제값의 차이를 제곱하여 계산하기에 이상치(outlier)에 민감하게 반응할 수 있다. 또한, 오차값이 커질수록 제곱으로 인해 더 큰 가중치를 부여할 수 있다.
- 수렴속도 관점에서, 2차함수 형태이기에 극점에 가까워질수록 속도가 느려진다. x=1을 기점으로 x>1에서는 속도가 빠르고 x<1에서는 속도가 느리다. 다만, 어느기점(x<1)에서 갖혀버리는, local minima문제가 발생할 수 있다. 즉, local minima에 빠질 가능성이 높다.
RMSE (Root Mean Squared Error) - RMSE는 √(MSE)로 다변량함수이며, MAE와 달리 0에서 미분가능하다는 장점이 존재한다! - 즉, MAE의 대체라는 느낌이라 생각하면 좋을 것 같다.
보통 MSE, MAE의 경우, 기울기기반 최적화와 사용시 일부출력이 포화하면서 기울기가 아주 작아진다.
→ 따라서 보통 Cross Entropy를 많이 사용한다.
Cross Entropy. &. Categorical Cross Entropy - Cross Entropy, CE 및 CCE는 확률값을 평가(loss) 시 사용된다. (0≤y≤1의 값이 분포) CCE = -yᵢ * Σlog(ȳ)) 으로 yᵢ 즉, 참값에 대한 결과를 반영가능하다! => 따라서 softmax와 같은 multi activation function output, multinoulli Distribution과 연관된다. => 쉽게 말하자면, 0~1사이일 때, softmax output일 때 사용가능하다.
Binary Cross Entropy - Binary Cross Entropy, BCE는 이진문제에 적용하는 Cross Entropy 방식이다. BCE = -yᵢ * log(ȳ) - (1-yᵢ) * log(1-ȳ) - yᵢ와 (1-yᵢ)가 곱해짐을 통해 update시 정답과 오답을 모두 사용한다. - 유의할 점은 softmax를 사용하면 편향이 되서 sigmoid output 즉, 독립적인 활성화 함수의 output일 때 사용한다. - 문제점: softmax output을 사용하게 되면, 정답을 맞추기 위해 update되는 것이 아닌, 오답을 피하기 위해서 학습이 되어 버린다.
[Activation function]
cf. Distribution에 따른 Activation function 사용법
1. Gaussian Distribution: affine transform에 기초한 "linear" unit
softmax는 총 클래스의 확률값의 합이 1인 다변량함수로 변수하나가 바뀌면 동시에 나머지도 변하기에
하나라도 모델이 맞히게 된다면 전체적으로 학습의 정확도가 올라갈 가능성이 높다.
만약 MSE와 사용하면 부정확한 예측을 크게 확신해도 출력변경이 불가능하기 때문이다.
→exp는 Maximum Likelihood를 이용해 y출력에 도움을 준다.
→ log(softmax) = z - log∑exp(z)
이를 해석하면,
i) z로 인해 기울기기반알고리즘은 z를 높이는 방향으로 학습하며
ii) log∑exp(z)로 인해 z 전체값이 작아지는 방향으로도 학습된다.
ReLU - hidden layer에서 사용이 용이 - hidden layer의 activation은 0또는 1에 분포할 확률이 높아야 한다.
Sigmoid - 요즘은 거의 output layer에서 특히나 확률분포(Probabiliy)의 문제에서 사용한다. - 특히나, 0과 1의 분포가 많은 확률분포문제에 좋다. (즉, 두개의 군집으로 구분되는 경우.) - 분포가 균등할 때는 linear를 통해 mse를 사용한다.
tanh - 사실상 (0,0)을 지나는 sigmoid식이라 볼 수 있다. - correlation과 같은 경우에서, 2개의 군집같은 문제에서 많이 사용
Leaky ReLU - backpropagation시 음수부분을 살리고자 사용. - 확률적으로 전체적으로 왼쪽(x<0)으로 치우치게 될 가능성이 높다. - 오히려 방해가 되어 ReLU보다 성능이 안나올 가능성이 높다.
ReLU6 - f(x) = clip(x, 0, 6) - 데이터가 많을 수록 좋은 함수 - 기울기가 1인 폭이 좁아서 데이터가 적으면 0으로 모두 죽어버릴 수 있다.
Hard-sigmoid - f(x) = ReLU6 / 6 - 0.5 및 스케일링 - f(x) = max(0, min(1, (x+1)/2)) - 분포가 0~1로 되며, 데이터가 많을 수록 좋은 함수
Swish - x*sigmoid(x) - 1차 미분이 sigmoid와 거의 비슷.(continuous) - 1차미분 = 속도로 생각해보면, 음수부분과 양수부분 모두 속도가 비슷하기에 쉽게 update가능 - 2차미분식이 Gaussian과 비슷 - 2차미분 = 가속도라 생각하면 2차미분의 대칭성으로 인해 살아날 가능성이 높다.
Hard-Swish - x * hard_sigmoid(x) - swish와 거의 비슷하지만 연산속도가 빠르다.
Smooth L1 - x < 1에서 (1/2)*(y-ȳ)² - x ≥ 1에서 |y-ȳ| - (1/2)
CNN, Convolutional Neural Network은 기존 딥러닝 신경망이었던 Fully-Connected Layer를 대체하기 위해 나왔다.
CNN은 Locally-Connected Layer로 Fully-Connected Layer에 비해 정보손실이 발생할 수 있다.
하지만 CNN은 이런 정보손실에 대해 channel을 많이 줌을 통해 정보손실을 방지할 수 있다.
또한 CNN은 FC보다 훨씬 weight수 즉, param#이 더 줄어든다
weight의 개수 = input_channel수 x kernel개수 x kernel개수 x output_channel
(단, padding='same')
filter를 weight로 하며, 이때 model은 weight를 조정하여 filter를 모델이 '알아서' 만들도록 한다.
(filtering을 모델에게 맡겨 상황에 따라 필요한 filter를 자체적으로 만들 수 있게 하는 것이다.)
[Auto-Encoder]
[본 목적]
input의 압축 => 스스로 압축 알고리즘을 학습할 수 있는, input에 근사한 압축값을 뽑아낼 수 있음. - 특정 분야에서 정상적으로 동작한다.
(글자->강아지로 클래스가 변하게 된다면? 특징을 못뽑을 수도 있는, 특정 dataset에서만 가능한 비범용적 방법이다.)
- 주로 언어모델, segmentation 등등에서 사용됨.)
Encoding
- 코드화 시키는 것 = 어떠한 코드로 1:1 매칭시키는 것 - 암호화 즉, 용량 압축의 효과 및 일반화도 가능하다.
bottleneck
- 정보가 embedding되어 있음(= 필요 정보만 모여있는 것)
Decoding
- decoding은 사람이 이해하도록 바꿔주는 것으로 encoding과 반대 개념이다. - 이때, input image에 비해 손실이 발생한다.
[Curse of Dimensionality., 차원의 저주]
- 차원이 늘어날수록 문제를 풀기 쉬워지는것은 어느 정도까지이다! - 즉, 역효과가 발생가능하다. → 도리어 학습이 안될 수 있다는 것!
[ERF (Effective Receptive Field)]
- 학습이 되면서 점점 receptive field가 Gaussian distribution 형태에 가까워지는데, 이를 effective receptive field라 한다. - (가장 최외각의 patch는 뒤로 갈수록 영향력이 줄고, 가운데 patch의 영향력이 커져 뒤로갈수록 정규분포와 비슷해져버림) - 이러한 문제로 인해 CNN이 깊게 쌓을 수 없게 된다. → attention을 이용한 transformer, ViT가 나오게 된 배경이 되어 버림!
이때, window가 움직이면서 표본을 계속 뽑아 연산을 해 새로운 값을 도출하는 기법. (sliding되는 것을 window(kernel) = filter라고도 부른다.)
- 또한, 상하좌우와 channel검사도 해야해서 3중for문으로 구현해야한다. - 이때, filter로 인해 발생한 표본집단을 patch라고 한다. - mean filter = patch와 kernel의 합성곱이 patch의 평균값이 되는 것
이를 이용해 blurring이 가능하다. (average blurring)
if sharp한 image의 경우:
(차이가 큰 value) mean filter의 사용은 sharpness를 없앤다.
이때, 평균이 아닌 중앙값을 이용한 median filter를 사용하면?
-> sharpness의 특성을 위보다 더 살릴 수 있다.
단, 나머지 픽셀의 정보를 소실한다.
-> 여러번 반복하면 소실이 반복, 남는 픽셀의 개수가 줄어든다.
-> 즉, 반복이 많아질수록 정보의 손실이 커진다.
밝기값을 찾기 위해 원본 image를 vectorize하여 밝기값을 구하고 rasterize를 다시 시켜 scale을 진행한다. pixel과 pixel사이를 채워주는 것을 의미. • 예를 들어 a만큼 scale을 한다면 (x, y) 위치의 값으로 들어간다. (new) ← (ax , ay) 의 값을(original)이를 rasterize시키면 된다.
[실습] - vectorization을 위해 Bilinear interpolation 이용
§ 확대하기
§ 축소하기
※ Rotate 실습
[과제]
과제 1) 크기 손상 없이 그대로 rotation 하기 - for i in range(H-1) 부분에서 1픽셀 잘림
과제 2) for문 대신 선형대수 식으로 변형해서 구현해보기
과제 3) bilinear 대신 bicubic 또는 triangulation 방식으로 해보기