본문 바로가기

BLOG/딥러닝

VAE(Variational Auto Encoder) _인코더, 평균 분산

【8】최근 AutoEncoder 응용 모델 이해하고 사용하기 / VAE

VAE(Variational Auto Encoder) _인코더, 평균 분산

 

확률분포를 이용하는 모델인 VAE(Variational Auto Encoder)를 알아보자

 

try:

  %tensorflow_version 2.x"

except Exception:

  pass

import tensorflow as tf 



from tensorflow.keras import layers,models,datasets,losses

from tensorflow.keras import backend as K

import numpy as np

import matplotlib.pyplot as plt

 

VAE모델 만들기에 앞서 패키지들을 선언을 한다.

 

새롭게 추가된 패키지에는 백엔드(backend) 패키지가 있는데 케라스내에서 텐서플로우 패키지를 사용하는 것입니다.

 

(x_train, _), (x_test,_) = datasets.mnist.load_data()

 

x_train = x_train.astype('float32') / 255.

x_test = x_test.astype('float32') / 255.

x_train = x_train.reshape(-1,784)

x_test = x_test.reshape(-1,784)

 

현재 VAE 실습에서 하는 모델은 순환 신경망이기 때문에 2차원으로 바꾸고 정규화 후 진행을 해야한다.

 

input_shape = (784,)

latent = 2 # 차원 축소의 크기

 

#인코더 

encoder_input = tf.keras.Input(input_shape)

encoding = layers.Dense(latent, activation='relu')(encoder_input)

 

#평균 분산

mean = layers.Dense(latent)(encoding)

log_var = layers.Dense(latent)(encoding)

 

인코더를 작성해보자.

latent는 차원축소 될 크기를 의미한다.

인코딩에서 유닛을 latent로 지정함으로서 2차원까지 축소가 된다.

 

VAE는 확률 분포를 이용하기 때문에 평균과 분산을 생성해야한다.

 

# 평균 + log(분산) * epsilon(0 ~ 1)

def sampling(data) : 

  mean,log_var = data

  epsilon = K.random_normal(mean=0. ,stddev=1. ,shape=(K.shape(log_var)[0],latent))

  return mean + K.exp(log_var)* epsilon

 

sampled = layers.Lambda(sampling,output_shape=(latent,))([mean,log_var])

 

VAE에서 가우시안 정규분포식을 이용하여 확률분포를 알아낸다.

 

가우시안 식은 “평균 + 분산 * 앱실론(0 ~ 1)” 이다.

그래서 평균과 분산을 람다(Lambda)로 묶고 가우시안 정규분포식의 샘플 값을 얻는 과정이다.

 

decoder_input = tf.keras.Input((latent,)) #bs (2,)

decoding = layers.Dense(784,activation='sigmoid')(decoder_input) #bs (None,784)

 

decoder = models.Model(decoder_input,decoding)  #모델을 생성

decoded = decoder(sampled) #샘플링한 모델 입력 사용

 

이제는 디코더를 만들어보자

기존에 AE에서는 이미지의 크기를 입력을 받았지만 VAE에서는 차원축소 크기를 입력으로 한다.

이미지의 원래크기인 784로 원복을 시키면 된다.

디코더 모델을 생성한 후 아까 만들었던 가우시안 샘플 데이터를 이용하여 입력데이터로 사용한다.

 

vae = models.Model(encoder_input, decoded)

VAE 생성 모델이다.

인코더 모델 입력을 디코더 모델을 출력으로 모델을 생성했다.

 

bc_loss = losses.binary_crossentropy(encoder_input,decoded) 

bc_loss *= 784

KL_loss = K.mean(1 + log_var - K.square(mean) -K.exp(log_var)) * -0.0005 

 

vae_loss = K.mean(bc_loss + KL_loss) 

vae.add_loss(vae_loss) 

 

 

VAE에는 엘보(ELBO)라는 로스함수를 사용하게 되고 구현이 되어있지 않기에 직접 만들어줘야 한다.

ELBO의 식은 크로스엔트로피와 KL(Kullback Leibler divergence)을 더한 다음 평균을 낸 Loss다.

KL의 식은 -0.5 * (1 + log_z_var - z_mean^2 - z_var)이지만 -0.5는 조정이 가능하다.

 

로스 식을 만들었으면 add_loss 명령어를 통해서 추가를 해줘야한다.

 

vae.compile(optimizer='adam',loss=None) 

VAE의 컴파일이다.

로스함수는는 이전에 만들었기 때문에 None 값으로 설정한다.

 

vae.fit(x_train,None,shuffle=True,

epochs=10,validation_data=(x_test, None))

 

학습을 시켜보자

AE는 비지도학습이므로 y의 값은 없어도 되므로 None값이다.

100번 정도 돌렸을 때 나오는 결과물입니다.

 

 

많이 선명하지 않지만 모양이 잡히는 것을 알 수가 있다.

 

 

 

 


작성자 김강빈 kkb08190819@gmail.com / 이원재 ondslee0808@gmail.com

'BLOG > 딥러닝' 카테고리의 다른 글

AAE (Adversarial AE)  (0) 2021.03.25
CVAE (Convolution VAE)  (0) 2021.03.25
Convolutional AE  (0) 2021.03.25
Deep AE를 이용한 가짜 이미지 생성  (0) 2021.03.25
<AE 이미지 생성 실습> 직접 코드 구현해보기  (0) 2021.03.25