u-net

강지수·2024년 5월 6일
코드를 입력하세요
```import tensorflow as tf
import tensorflow_datasets as tfds
#pix2pix모델 가져옴 > segmentation map을 실제 이미지로 변환
from tensorflow_examples.models.pix2pix import pix2pix
# IPython 환경에서 출력된 내용을 지워주는 기능
from IPython.display import clear_output
import matplotlib.pyplot as plt

#Encoder
#mobilenetv2 인코더로 사용(input_shape=[height, width, RGB Channel]
#incoude_top=False: mobilenetv2의 최상위에 있는 완전 연결 레이어 제외하겠다

--> fine-tuning 가능해짐. 새로운 데이터셋에 맞게 상위레이어를 새롭게 추가하거나, 기존의 완전 연결 레이어 수정 가능

base_model = tf.keras.applications.MobileNetV2(input_shape=[128, 128, 3], include_top=False)

mobilenetv2의 각 레이어 이름 나타냄

layer_names = [
'block_1_expand_relu', # 64x64
'block_3_expand_relu', # 32x32
'block_6_expand_relu', # 16x16
'block_13_expand_relu', # 8x8
'block_16_project', # 4x4 : 차원 축소
]

#layer_names에 해당하는 각 레이어의 출력을 리스트로 저장
#이런 출력을 특징맵이라고도 하고, 특징맵은 레이어에서 추출된 이미지의 다양한 특징 나타냄.
base_model_outputs = [base_model.get_layer(name).output for name in layer_names]

#down_stack = 인코더
#down_stack에 특징맵들 입력받아 인코더 모델 정의(input), 특징 맵들 디코더에 전달하기 위해 샘플링함(output부분)
down_stack = tf.keras.Model(inputs=base_model.input, outputs=base_model_outputs)
#인코더 부분을 고정해서 학습되지 않도록 정의
down_stack.trainable = False

#up_stack=디코더 부분. 업샘플링(크기 복원)을 함
up_stack = [
pix2pix.upsample(512, 3), # 4x4 -> 8x8
pix2pix.upsample(256, 3), # 8x8 -> 16x16
pix2pix.upsample(128, 3), # 16x16 -> 32x32
pix2pix.upsample(64, 3), # 32x32 -> 64x64
]

#u-net모델 구현
def unet_model(output_channels:int):
#input레이어 정의. 128x128에 rgb 채널 3개
inputs = tf.keras.layers.Input(shape=[128, 128, 3])

#down_stack에 입력 이미지(inputs)전달. 다운샘플링된(인코딩까지 된) 특징맵 반환함
skips = down_stack(inputs)
#인코더 마지막 특징맵 반환
x = skips[-1]
#인코더 추출된 특징맵 중 마지막 특징 맵 제외하고 나머지 역순으로 가져옴. 디코더에서 스킵 연결 구축할 때 사용
skips = reversed(skips[:-1])

#zip함수 이용해서 up_stack(업샘플링 레이어)랑 skips(인코딩 결과) 묶고
#묶인 up과 skip에 한해서 반복문을 수행함
for up, skip in zip(up_stack, skips):
#특징맵 업샘플링
x = up(x)
#concat: concatenate레이어 생성. 두개의 특징맵을 연결>인코더와 디코더간의 연결
concat = tf.keras.layers.Concatenate()
#특징맵과 스킵연결의 특징 맵 skip을 연결함
x = concat([x, skip])

##################################################################################################

모델의 마지막 레이어

#전치 합성곱 수행>입력 데이터를 더 큰 공간으로 확장=업샘플링
#(채널수, 컨볼루션 필터 크기: 3x3, 필터가 이동하는 간격, 출력이미지 크기 입력 이미지 크기와 동일하게 유지)

last = tf.keras.layers.Conv2DTranspose(
filters=output_channels, kernel_size=3, strides=2,
padding='same') #64x64 -> 128x128

#업샘플링된 특징맵을 전치합성곱 수행해서 최종 출력 생성함.
x = last(x)

#새로운 캐라스모델을 생성해서 마지막 레이러로부터 입력이미지 받아서 출력이미지 생성
#즉, 특징맵을 입력받아서 각 픽셀이 속하는 클래스에 대한 정보(segmentation)를 담고 있는 이미지가 됨
return tf.keras.Model(inputs=inputs, outputs=x)

0개의 댓글