Pix2Pix로 스케치그림을 사진으로 바꾸기 -3- Discriminator
노 프로젝트 기간 합법 월루 중
gan 빨랑 치우고 다른 프로젝트랑 노트 정리 좀 해야지
난 내가 한두달만에 온 줄 알았어 하지만 날짜를 보니 무려 다섯달이 넘게 지나있지 뭐야
다섯달 반만에 만들어보자 판별모델을...
사실 생성모델 만들기 전에 이거부터 했어야 했던거 아닌가 하는 생각이 든다. 왜냐면 이미지를 생성한다는 건 이미지를 분석하는 것의 심화버전이기 때문에... 모델은 이미지 데이터를 분석할 때 커널사이즈를 통해 특성을 추출하고 이 특성을 토대로 개가 개고 고양이가 고양이임을 분류하고 분석해내는데 생성은 거기서 특성을 추출하느라 인코딩 된 데이터를 다시 디코딩하여 분석을 토대로 원하는 이미지를 도출해 낸다.
컨볼루션 레이어에 대해서도 짚고 넘어가야 할까 싶은데 일단 기초는 나중에 따로 정리하기로 하고...
판별자는 말 그대로 이미지를 분석하는 모델이다. 생성자에서 생성한 이미지를 분석하여 가짜인지 진짜인지 판별하는 역할을 한다. 따라서 이진분류로 레이어를 구성한다.
하지만 이 판별모델은 단순히 이게 가짜냐 진짜냐 분석하고 끝이 아니라 결국 생성을 위한 검별이므로 일반적인 컨볼루션 모델과는 다른 전략이 필요하다.
여기에 Pix2Pix에 많이 쓰이는 PatchGan을 가져와 사용하였다.
해당 논문은 https://arxiv.org/pdf/1803.07422.pdf
국내 블로그는 https://brstar96.github.io/mldlstudy/what-is-patchgan-D/ 를 참고함
기존의 CNN 모델은 전체 이미지에서 픽셀 단위로 특성을 연산하여 이미지를 분석하지만 PatchGan은 작은 이미지 패치를 단위로 연산하여 생성자가 만들어낸 이미지 데이터가 진짜인지 가짜인지 판별한다. 이렇게 하면 전체 이미지를 전부 가져오는 것보다 연산이 적고 빠르다고 함.
이 구조를 참고해서 판별자 모델을 불러 올 함수를 만들었다
def discriminator(image_shape):
init = RandomNormal(stddev=0.02) #가중치 초기화
src = Input(shape=image_shape)
target = Input(shape=image_shape)
merged = Concatenate()([src, target]) #input merge
d = Conv2D(64, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(merged)
d = LeakyReLU(alpha=0.2)(d)
d = Conv2D(128, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(d)
d = BatchNormalization()(d)
d = LeakyReLU(alpha=0.2)(d)
d = Conv2D(256, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(d)
d = BatchNormalization()(d)
d = LeakyReLU(alpha=0.2)(d)
d = Conv2D(512, (4,4), strides=(2,2), padding='same', kernel_initializer=init)(d)
d = BatchNormalization()(d)
d = LeakyReLU(alpha=0.2)(d)
d = Conv2D(512, (4,4), padding='same', kernel_initializer=init)(d)
d = BatchNormalization()(d)
d = LeakyReLU(alpha=0.2)(d)
# output
d = Conv2D(1, (4,4), padding='same', kernel_initializer=init)(d)
out = Activation('sigmoid')(d) #fake or real (0 / 1)
# 모델 정의
model = Model([src, target], out)
# optimizer
opt = Adam(lr=0.0002, beta_1=0.5)
# 컴파일
model.compile(loss='binary_crossentropy', optimizer=opt, loss_weights=[0.5])
return model
가중치 초기화 규칙은 0을 중심으로 표준편차 0.02 정규분포로 했고 활성화 함수는 레이어마다 LeakyRelu로, 알파값(기울기)은 0.2로 잡아주었다.
가중치와 파라미터 값은 Empirical Evaluation of Rectified Activations in Convolutional Network. CoRR, 2015 등의 논문 참고
다른 파라미터 값에 대한 실험 결과는 발표에 쓴 PPT 참고 (32p 부터)
https://drive.google.com/file/d/1tk8vf_pHthygBoWDpEdXRcnBdmPGgAGO/view?usp=sharing
이제 대망의 GAN 모델을 만들어서 생성자는 판별자를 속이기 위한 이미지를 만들고 판별자는 들어온 이미지가 진짜인지 생성자가 만든 가짜인지 판별시켜야 한다. 이러한 과정을 반복하면 생성자는 좀 더 고해상도의 나은 이미지를 생성해 낼 것이다.
gan 모델과 트레이닝은 다음 포스팅에서......