Image Segmentation - Single Layer Model
Back to : deep-learning-study
์ด๋ฒ ํฌ์คํ ์์๋ ๊ตฌํ์ด ์ด๋ค ์์ผ๋ก ๋์ํด์ผ ํ๋์ง๋ฅผ ๋์ถฉ ์์๋ณด๊ธฐ ์ํด, ์๊ฐํ ์ ์๋ ๊ฐ์ฅ ๋จ์ํ ๋ชจ๋ธ์ธ 1-layer convolution์ ์ด์ฉํด semantic segmentation์ ์๋ํฉ๋๋ค.
Preparation post ์์ ์ด์ด์ง๋๋ค.
Model ๋ง๋ค๊ธฐ
Pytorch์์ model์ torch.nn.Module
ํํ์ ํด๋์ค๋ก ๋ง๋ค ์ ์์ต๋๋ค.
# models/single_conv.py
import torch.nn as nn
class SingleConvolution(nn.Module):
def __init__(self):
super(SingleConvolution, self).__init__()
self.conv_layer1 = nn.Sequential (
nn.Conv2d(3, 23, kernel_size = 3, padding=1),
nn.ReLU()
)
def forward(self, x):
output = self.conv_layer1(x)
return output
์ฐ๋ฆฌ๋ RGB 3๊ฐ ์ฑ๋์ ๊ฐ๋ ์ด๋ฏธ์ง๋ฅผ ๋ฐ์์, 23๊ฐ ํด๋์ค ์ค ํ๋๋ฅผ ๊ตฌ๋ถํ ๊ฒ์ ๋๋ค. ์ฆ, ์ ๋ ฅ์ $3 \times W \times H$ ํํ์ผ ๊ฒ์ด๋ฉฐ, ์ถ๋ ฅ์ ๊ฐ $(i, j)$ ๋ง๋ค 23๊ฐ์ ํด๋์ค์ ๋ํ probability๋ฅผ ์ถ๋ ฅํด์ผ ํฉ๋๋ค. ($23 \times W \times H$)
์ฐ๋ฆฌ๊ฐ ์๊ฐํ ์ ์๋ ๊ฐ์ฅ ๊ฐ๋จํ ํํ์ ๋ชจ๋ธ์ ๋จ ํ ๋ฒ์ convolution layer๋ก ๊ตฌ์ฑ๋ ๋ชจ๋ธ์ผ ๊ฒ์ ๋๋ค. ์ด ๋ชจ๋ธ์ $3 \times f \times f$ ํฌ๊ธฐ์ convolution filter 23๊ฐ๊ฐ ๊ฐ ํด๋์ค์ ๋์ํ๋ฉฐ, ๊ฐ filter๋ trainable weight๊ณผ bias๋ฅผ ๊ฐ์ต๋๋ค. ์ฆ ํ๋ผ๋ฏธํฐ๋ ์ฌ๊ธฐ์ $27 \times 23$๊ฐ์ weight๊ณผ 23๊ฐ์ bias๋ก ์ด 644๊ฐ๊ฐ ๋ฉ๋๋ค. ๊ฐ ํด๋์ค์ ํ๋ฅ ๊ฐ์ convolution์ฐ์ฐ๊ณผ ReLU ํ๋ฒ์ผ๋ก ๋ฐ๋ก ๊ฒฐ๊ณผ๊ฐ์ด ๋์ถ๋ฉ๋๋ค.
์ด ๋ชจ๋ธ์ ์ ์ํ๋ ๊ฒ๊น์ง๋ฅผ ์ฝ๋๋ก ์ฎ๊ธฐ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
# main.py
from basics import *
from datautils import *
from metrics import *
from evaluate import *
from train import *
from models import *
batch_size = 6
train_set, test_set = import_drone_dataset()
train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True)
model = SingleConvolution().to(device)
print(summary(model, (3, 600, 400)))
์ฌ๊ธฐ์ batch size๋ GPU ๋ฉ๋ชจ๋ฆฌ์ ๋ค์ด๊ฐ๋ ํ ๋ง์ด ์ฑ์ฌ๋ฃ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค. ์ ๋ 1070Ti๋ฅผ ์ฐ๊ธฐ ๋๋ฌธ์ 6์ ๋๋ ๊ด์ฐฎ์๊ฒ ๊ฐ์ต๋๋ค. ๋ค๋ฅธ ํจ์๋ค์ ์์ Prep์์ ์ค๋นํ ํจ์๋ค์ ๋๋ค. summary๊ฐ ๋ฐํํ๋ ๊ฒฐ๊ณผ๊ฐ ์๋์ ๊ฐ์ด ๋ํ๋ฉ๋๋ค.
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [-1, 23, 600, 400] 644
ReLU-2 [-1, 23, 600, 400] 0
================================================================
Total params: 644
Trainable params: 644
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 2.75
Forward/backward pass size (MB): 84.23
Params size (MB): 0.00
Estimated Total Size (MB): 86.98
----------------------------------------------------------------
์ฐ๋ฆฌ๊ฐ ์์ํ๋ ๋๋ก 644๊ฐ์ trainable param์ ๊ฐ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
Training
์ด์ ๋ชจ๋ธ์ ์ ์ํ๋ค๋ฉด, ์ด ๋ชจ๋ธ์ 633๊ฐ์ parameter๋ฅผ ์ค์ ๋ก trainํด ์ค์ผ ํฉ๋๋ค. Train์ ํฌ๊ฒ ๋ ๊ณผ์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋๋ค.
- Forward pass๋ก ํ๋ จ์ฉ ๋ฐ์ดํฐ๋ฅผ ๋จน์ฌ์, ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ๋์ถํ ๋ค์, ์ด ๊ฒฐ๊ณผ๋ฅผ ground truth์ ๋น๊ตํด์ ์ผ๋ง๋ ๋ค๋ฅธ์ง (loss function)์ ๊ฐ์ ์ธก์
- ๊ทธ ๊ฐ์ ์ต์ํํ๋ ๋ฐฉํฅ์ผ๋ก ๋ญ๊ฐ optimization ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉ.
์ ์ฒด์ ์ธ CNN ๋ชจ๋ธ ํ๋ จ์ ์ด๋ก ์ ๋ํด์ ๋ค๋ฃฌ ํฌ์คํ ๋ค๊ณผ, LeNet์ ์ด์ฉํด์ pytorch์์ classification ํ๋ ํฌ์คํ (LeNet์ผ๋ก MNIST ํ์ด๋ณด๊ธฐ)๊ฐ ์์ผ๋ฏ๋ก ์ด์ชฝ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
์ฌ๊ธฐ์์ ํ๋ จ๊ณผ์ ์ LeNet MNISTํ๋ จ๊ณผ ํฌ๊ฒ ๋ค๋ฅด์ง ์์ต๋๋ค.
# train.py
from basics import *
from metrics import *
def train(
model : nn.Module,
epochs : int,
train_loader : DataLoader,
loss_func, optimizer,
acc_metric = pixel_accuracy
):
torch.cuda.empty_cache()
train_losses = []
train_acc = []
model.to(device)
start = time.time()
for _ in range(epochs):
print(f"EPOCH {_+1} training begins...")
train_start = time.time()
model.train()
train_accuracy = 0
train_loss = 0
for i, data in enumerate(tqdm(train_loader)):
img, mask = data
img = img.to(device)
mask = mask.to(device)
output = model(img)
train_accuracy += acc_metric(output, mask)
loss = loss_func(output, mask)
train_loss += loss.item()
loss.backward()
optimizer.step()
optimizer.zero_grad()
print(f"Train epoch {_+1} / {epochs}",
f"Training Loss {train_loss/len(train_loader):.4f}",
f"Training Accr {train_accuracy/len(train_loader):.4f}",
f"Training Time {(time.time()-train_start)/60:.2f} min")
history = {'train_loss' : train_losses, 'train_acc' :train_acc}
print(f"Total training time {(time.time()-start)/60:.2f} minutes taken")
return history
LeNet์ผ๋ก MNIST ํ์ด๋ณด๋ ํฌ์คํ ์์ ๋ค๋ค๋ ๊ฒ๊ณผ ๊ฑฐ์ ๊ฐ์ต๋๋ค. ์ฌ๋ฌ ๋ชจ๋ธ์ ๋ํด ์คํํ๊ธฐ ์ํด ํจ์๋ก ๋ง๋ค์๋ค๋ ์ ๋๋ง ์ฐจ์ด๊ฐ ์์ต๋๋ค. ๋ฌ๋ผ์ง๋ ๋ถ๋ถ์ด ๊ฑฐ์ ์์ผ๋ฏ๋ก, LeNet ํฌ์คํ ์ ์ฐธ์กฐํด ์ฃผ์ธ์.
- train data๋ฅผ ๋ก๋ฉํ data loader๋ฅผ ๋ฐ๊ณ
- ๋ช epoch ๋๋ฆด์ง๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ๊ณ
- ์ด๋ค loss function์ ์ด๋ค optimizer๋ก ํ๋ จํ๊ณ
- ์ด๋ค ๋ฐฉ๋ฒ์ผ๋ก accuracy๋ฅผ ์ธก์ ํ ์ง (์ฌ์ค ํ๋ จ ์์ฒด์๋ ์๊ด์ด ์๋๋ฐ, ๋์ผ๋ก ๋ณด๊ธฐ ์ํด์์ ๋๋ค) ์ ํฉ๋๋ค.
์ด์ , ๋ง์ง๋ง์ผ๋ก ์ด ๋ชจ๋๋ฅผ ํฉ์ณ์ ์ต์ข ๋ก์ง์ ์์ฑํฉ๋๋ค.
# main.py
train(
model = model,
epochs = 5,
train_loader = train_loader,
loss_func = nn.CrossEntropyLoss(),
optimizer = torch.optim.Adam(model.parameters(), lr=0.003)
)
evaluator = ModelEvaluation(model, test_set, pixel_accuracy)
evaluator.evaluate_all()
์ด ๋ชจ๋ธ์ ๋ญ๊ฐ ๋ ธ๋ ฅ์ ๊ธฐ์ธ์ด๋ ๊ฒ์ ์๋ฏธ๊ฐ ์์ผ๋ฏ๋ก, ์๋ฌด๋ ๊ฒ๋ 5 epoch๋ฅผ ๋๋ฆฝ๋๋ค. loss function๊ณผ optimizer๋ ์ผ๋ฐ์ ์ธ Cross Entropy Loss ์ Adam์ ๊ทธ๋๋ก ์ง์ด๋ฃ์ต๋๋ค. ์ด๋ ๊ฒ ์ข ๊ธฐ๋ค๋ ค ๋ณด๋ฉดโฆ
Results
์ด ๊ฒฐ๊ณผ๋ 8๋ฒ ์ด๋ฏธ์ง์ ๋ํ ๊ฒฐ๊ณผ์
๋๋ค. ๋ชจ๋ธ์ด ๋๋ถ๋ถ์ void๋ก ์ก์๋ด๊ธด ํ๋๋ฐ, ๋ญ๊ฐ ์ด๋ฏธ์ง์ ํฐ ์ฒญํฌ๋ค์ ๋ํด ๋ถ๋ช
trivialํ์ง ์๊ฒ ๋ญ๊ฐ๋ฅผ ์ก์๋ธ ๊ฒ ๊ฐ์ ๋ณด์
๋๋ค.
์ด๋ show_qualitative
๋ก ๋ฝ์ ๊ฒฐ๊ณผ์ธ๋ฐ, evaluateํ ๊ฒฐ๊ณผ๋ ํ๊ท pixel accuracy 47%์ ๋๊ฐ ๋์์ต๋๋ค. ์ด ํ๋ก์ ํธ๋ ์์ผ๋ก ๋ค์ํ ๋ฐฉ๋ฒ์ ์ด์ฉํด ์ด๋ฅผ 85% ๋ด์ง๋ ๊ทธ ์ด์์ผ๋ก ์ฌ๋ฆด ๊ณํ์
๋๋ค.
Back to : deep-learning-study