본문 바로가기

BLOG/딥러닝

AAE (Adversarial AE)

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

AAE (Adversarial AE)

 

이번에는 AAE(Adversarial AE)를 배워보자.

AAE는 VAE와 GAN을 합친 모델이다.

GAN은 다음시간에 배울 내용이며 GAN을 보고 오시면 이해가 쉽다.

AAE는 GAN에 구조를 띄고 있고 제너레이터(generator)를 VAE로 바꾼 모델이다

 

try:

  %tensorflow_version 2.x"

except Exception:

  pass

import tensorflow as tf 



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

import numpy as np

import matplotlib.pyplot as plt

 

모델을 만들기 전 패키지를 선언하자.

 

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

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

 

실습에 사용할 데이터는 Mnist이다.

GAN의 구조를 사용하기 때문에 테스트값은 불러오지 않는다.

 

encoded_dim = 3

epochs = 5000 #에폭

lr = 0.0002 #Adam 규제

img_shape=(28, 28) #이미지 크기

batch_size = 128 #배치사이즈

alpha = 0.2 #Relu의 Alpha

 

모델을 작성하기에 앞서 여러 규제상황들을 선언하고 진행한다.

encoded_dim은 차원축소의 크기를 나타낸다.

 

encoder = models.Sequential()

encoder.add(layers.Flatten()) #3차원 이미지를 2차원으로 축소

encoder.add(layers.Dense(512))

encoder.add(layers.LeakyReLU(alpha)) #:LeakyReLU 활성함수

encoder.add(layers.Dense(512))

encoder.add(layers.LeakyReLU(alpha))

encoder.add(layers.Dense(encoded_dim)) #차원축소

 

인코더 부분을 살펴보자

처음에는 이미지의 축소를 진행을 하게 된다.

이는 GAN에서는 3차원의 이미지를 사용하게 되지만 VAE는 2차원의 이미지를 사용한다

차원이 맞지 않기 때문에 플래팅을 통해서 축소 후 진행을 하는 것이다.

사용한 활성함수가 렐루가 아닌 리키렐루(leaky relu)를 사용하였다.

마지막에는 이전에 설정한 차원의 크기로 차원축소를 진행한다.

 

decoder = models.Sequential()

 

decoder.add(layers.Dense(512,input_dim=encoded_dim))

decoder.add(layers.LeakyReLU(alpha))

 

decoder.add(layers.Dense(512))

decoder.add(layers.LeakyReLU(alpha))

 

decoder.add(layers.Dense(np.prod(img_shape), activation='sigmoid'))

decoder.add(layers.Reshape(img_shape))

 

디코더를 살펴보자

인코더를 역순으로 바꾼 모습을 취한다.

차원축소를 진행하였던 이미지를 원복시키는 코드다.

 

VAE를 통해서 GAN의 제너레이터를 만들었다.

 

이번에는 GAN의 판별자(discriminator)를 만들어볼 것이다.

판별자는 VAE에서 나온 인코더를 가지고 진짜인지 가짜인지 판별을 하게 된다.

 

discriminator = models.Sequential()

 

discriminator.add(layers.Dense(512,input_dim=encoded_dim))

discriminator.add(layers.LeakyReLU(alpha))

 

discriminator.add(layers.Dense(512))

discriminator.add(layers.LeakyReLU(alpha))

 

discriminator.add(layers.Dense(1, activation='sigmoid'))

 

구조를 보게 되면 디코더와 비슷한 형태를 가지고 있지만 마지막 순환 신경망에서 유닛이 1개 이고 시그모이드 함수를 사용했다.

이는 참인지 거짓인지를 판별해주는 층이 되는 것이다.

 

inputs_shape = layers.Input(shape=img_shape) #Input 레이어

adam = optimizers.Adam(lr) #Adam optimizer lr = 0.0002

 

encoded = encoder(inputs_shape) #인코더 모델

decoded = decoder(encoded) #디코더 모델

discriminated = discriminator(encoded) #discriminator 모델

 

vae = models.Model(inputs_shape, decoded) #VAE 모델 생성

 

aae = models.Model(inputs_shape, discriminated)

 

discriminator.compile(optimizer=adam,loss='binary_crossentropy')

 

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

 

discriminator.trainable = False 

 

aae.compile(optimizer=adam,loss='binary_crossentropy',metrics=['acc'])

 

모델을 생성해보자

위에서 인코더, 디코더, 판별자 모델들은 만든 상태고 이를 사용하여 AAE 모델과 VAE 모델을 만들었다.

 

for e in range(epochs):

   image_batch = x_train[np.random.randint(0,x_train.shape[0],batch_size)]     

    fake_img = encoder.predict(image_batch) 

    real_img = np.random.normal(size=(batch_size, encoded_dim)) 

    real_y = np.ones((batch_size,1))*0.9 

    fake_y = np.zeros((batch_size,1)) 

 

    discriminator.train_on_batch(real_img, real_y) 

    discriminator.train_on_batch(fake_img, fake_y) 

 

    real_img = x_train[(np.random.randint(0, x_train.shape[0], batch_size*2))] 

 

    real_y = np.ones((batch_size*2, 1))

 

    loss_1 = vae.train_on_batch(real_img, real_img) 

 

    loss_2 = aae.train_on_batch(real_img, real_y) 



    if (e+1) % 100 == 0 : 

       print("epochs : ",e+1,"[G acc: %f, mse: %f]" %(loss_2[0],loss_1))

 

이제 모델을 다 만들었으니 학습을 시켜보자.

mnist 데이터 중 배치사이즈 크기만큼 이미지를 랜덤하게 추출하고 VAE 인코더에 넣어 가짜 이미지를 생성한다

배치 사이즈 크기만큼 랜덤한 값을 생성한다.

판별자에 랜덤함 값을 라벨스무딩을 하여 0.9값으로 진짜 이미지로 학습을 시키고 생성한 이미지는 0값으로 하여 가짜 이미지를 학습을 시킨다.

 

VAE에서는 진짜 이미지로 학습을 시키고 AAE는 진짜 이미지와 이미지 갯수에 맞는 1로 이루어진 라벨로 학습을 시킨다.

 

 

100번 마다 로스를 출력을 하게 되면 줄어드는 것을 확인 할 수가 있다.

 

에폭 5000번 정도 돌린 mnist를 생성한 이미지다.

흐릿하지만 생성이 잘 된 것을 알 수가 있다.

 

 

 


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