- 네트워크 참조 : https://github.com/jakeret/tf_unet
Unet 연습 파이썬 치트코드 (1)¶
- 딥러닝연습 (영상이미지 판독) – 삼성 SDS 스터디 그룹 진행용
- Unet으로 병변부위를 예측하는 연습을 합니다.
- https://www.kaggle.com/c/siim-acr-pneumothorax-segmentation 대회의 데이터 참조입니다.
In [1]:
import glob
import shutil
import os
import random
from PIL import Image
import seaborn as sns
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split,StratifiedKFold
In [2]:
from tensorflow.keras.layers import Dense, Input, Activation, Flatten
from tensorflow.keras.layers import BatchNormalization,Add,Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.models import Model, load_model
from tensorflow.keras.layers import LeakyReLU, ReLU, Conv2D, MaxPooling2D, BatchNormalization, Conv2DTranspose, UpSampling2D, concatenate
from tensorflow.keras import callbacks
from tensorflow.keras import backend as K
데이터 로드¶
- data 아래의 디렉터리인 mask, test, train을 불러옵니다.
- glob은 리눅스명령어로 파일찾기가 가능합니다.
- 실제 마스크가 있는 경우에 대해 표기, 어느정도 차지하고 있는지에 대한 정보 저장
In [3]:
mask_filenames = glob.glob('../input/imagedata128/masks/*')
mask_df = pd.DataFrame()
mask_df['filename'] = mask_filenames
mask_df['mask_percentage'] = 0
mask_df['labels'] = 0
mask_df.set_index('filename', inplace=True)
for file in mask_filenames:
mask_df.loc[file, 'mask_percentage'] = np.array(Image.open(file)).sum()/(128*128*255)
mask_df.loc[mask_df.mask_percentage > 0, 'labels'] = 1
In [4]:
train_valid_filenames = glob.glob('../input/imagedata128/train/*')
train_filenames, valid_filenames = train_test_split(train_valid_filenames, stratify = mask_df.labels, test_size = 0.1, random_state = 10)
mask_train_filenames = [f.replace('/train', '/masks') for f in train_filenames]
mask_valid_filenames = [f.replace('/train', '/masks') for f in valid_filenames]
In [5]:
# from efficientnet import EfficientNetB0
In [6]:
train_x = np.zeros((len(train_filenames),128,128))
valid_x = np.zeros((len(valid_filenames),128,128))
train_mask_y = np.zeros((len(train_filenames),128,128))
valid_mask_y = np.zeros((len(valid_filenames),128,128))
train_y = np.zeros((len(train_filenames)))
valid_y = np.zeros((len(valid_filenames)))
# 훈련용
for (index, image) in enumerate(train_filenames[:]):
train_x[index] = np.array(Image.open(image))
# 검증용 및 변병여부
for (index, image) in enumerate(valid_filenames[:]):
valid_x[index] = np.array(Image.open(image))
# 훈련용 마스크 답지 및 병변여부
for (index, image) in enumerate(mask_train_filenames[:]):
train_mask_y[index] = np.array(Image.open(image))
train_y[index] = mask_df.loc[image, 'labels']
# 검증용 병변 답지 및 병변여부
for (index, image) in enumerate(mask_valid_filenames[:]):
valid_mask_y[index] = np.array(Image.open(image))
valid_y[index] = mask_df.loc[image, 'labels']
- Grayscale이므로 1채널
In [7]:
train_x = train_x.reshape(len(train_filenames),128,128,1)
valid_x = valid_x.reshape(len(valid_filenames),128,128,1)
train_mask_y = train_x.reshape(len(train_filenames),128,128,1)
valid_mask_y = valid_x.reshape(len(valid_filenames),128,128,1)
U-net 모델 만들기¶
- 128*128을 가정한 모델 작성
In [8]:
def UNet(pretrained_weights = None,input_size = (128,128,1)):
inp = Input(input_size)
conv1 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(inp)
conv1 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv1)
pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
conv2 = Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(pool1)
conv2 = Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv2)
pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
conv3 = Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(pool2)
conv3 = Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv3)
pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)
conv4 = Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(pool3)
conv4 = Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv4)
drop4 = Dropout(0.5)(conv4)
pool4 = MaxPooling2D(pool_size=(2, 2))(drop4)
conv5 = Conv2D(1024, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(pool4)
conv5 = Conv2D(1024, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv5)
drop5 = Dropout(0.5)(conv5)
up6 = Conv2D(512, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(UpSampling2D(size = (2,2))(drop5))
merge6 = concatenate([drop4,up6], axis = 3)
conv6 = Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(merge6)
conv6 = Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv6)
up7 = Conv2D(256, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(UpSampling2D(size = (2,2))(conv6))
merge7 = concatenate([conv3,up7], axis = 3)
conv7 = Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(merge7)
conv7 = Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv7)
up8 = Conv2D(128, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(UpSampling2D(size = (2,2))(conv7))
merge8 = concatenate([conv2,up8], axis = 3)
conv8 = Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(merge8)
conv8 = Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv8)
up9 = Conv2D(64, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(UpSampling2D(size = (2,2))(conv8))
merge9 = concatenate([conv1,up9], axis = 3)
conv9 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(merge9)
conv9 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv9)
conv9 = Conv2D(2, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv9)
conv10 = Conv2D(1, 1, activation = 'sigmoid')(conv9)
model = Model(inputs = inp, outputs=[conv10])
return model
In [9]:
model = UNet()
model.summary()
model.compile(optimizer = Adam(lr = 1e-4), loss = 'binary_crossentropy', metrics = ['accuracy'])
In [ ]:
history = model.fit(train_x, [train_mask_y], validation_data=(valid_x, [valid_mask_y]),epochs = 5, batch_size = 16, verbose = 1)