AutoEncoder를 구현해 볼까 합니다.
AutoEncoder는 이런 식으로 생겼고요. 이걸 쉽게 설명하자면, 압축했다가 풀어내는데 압축된 것을 Latent Vector라고 하고요, 이걸 다시 원래 데이터로 풀어내는데 이걸 신경망에 학습시켜서 알아서 압축했다가 풀어내도록 하는 것입니다. 꽤나 흥미롭지요.
자, 그러면 AutoEncoder를 만들어 봅시다.
784의 MNIST Vector가 입력이고요, Latent Vector(압축 벡터)는 32로 구성할 것입니다.
# MNIST를 읽어들이고요
import numpy as np
from keras.datasets import mnist
(x_train, _), (x_test, _) = mnist.load_data()
# MNIST 데이터를 정규화 하고요, 784로 맞춰 주고요
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((len(x_train), 784))
x_test = x_test.reshape((len(x_test), 784))
print (x_train.shape)
print (x_test.shape)
2024-01-27 16:14:20.690388: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1
(60000, 784) (10000, 784)
입력데이터를 읽어들였고, 이제는 AutoEncoder 모형을 만들어 봅시다.
from keras.layers import Input, Dense
from keras.models import Model
import tqdm
# 인코딩 된 후의 Laten Vector의 크기
encoding_dim = 32
# AutoEncoder의 입력에 퍼셉트론 신경망 1개, 출력에 퍼센트론 신경망 1개로 구성!
input_img = Input(shape=(784,), name='input')
encoded = Dense(encoding_dim, activation='relu', name='encoder')(input_img)
decoded = Dense(784, activation='sigmoid', name='decoder')(encoded)
# AutoEncoder를 정의
autoencoder = Model(input_img, decoded)
# AutoEncoder의 Encoder와 Decoder를 각각 Model로 만들어 놓음시다.
# 이것은 재미있는 결과를 하나 더 보려고 하는 건데요. 일단 만들어 둡시다.
encoder = Model(input_img, encoded)
encoded_input = Input(shape=(encoding_dim,), name='encoder_input')
decoder_layer = autoencoder.layers[-1] # autoencoder의 마지막 layer가 decoder잖아요?
decoder = Model(encoded_input, decoder_layer(encoded_input))
자, 다 왔습니다. 이제 훈련을 할 차례입니다. 학습 로그는 너무 길어서 지워 버렸습니다.
# AutoEncoder를 compile해서 학습을 시켜 봅시다.
autoencoder.compile(optimizer='adam', loss='binary_crossentropy')
import tensorflow_addons as tfa
import tqdm
autoencoder.fit(x_train, x_train,
epochs=50,
batch_size=256,
shuffle=True,
verbose=0,
validation_data=(x_test, x_test))
verbose를 0으로 세팅했더니, 학습 progress가 표시가 안되니까, 이런 걸 글로 쓸 때는 유용한 옵션인 것 같습니다.
# MNIST의 숫자들을 AutoEncoder를 통해서 인코딩 / 디코딩해서 학습된 AutoEncoder를 동작시킴!
decoded_imgs = autoencoder.predict(x_test)
# Matplotlib 사용해서 Test데이터를 제대로 Decoding하는지 함 봅시다.
import matplotlib.pyplot as plt
from random import randint
n = 10 # 몇 개의 숫자를 나타낼 것인지
plt.figure(figsize=(20, 4))
for i in range(n):
idx = randint(0, len(x_test))
# 원본 데이터
ax = plt.subplot(2, n, i + 1)
plt.imshow(x_test[idx].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
# 재구성된 데이터
ax = plt.subplot(2, n, i + 1 + n)
plt.imshow(decoded_imgs[idx].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
어떄요. 아직 Deep한 신경망을 붙인 것도 아닌데, 잘 압축하고, 잘 풀어냅니다. 헤헤.
신기하죠? 그런데, 한가지만 더 재미있는 걸 해볼까 하는데 말이죠.
그러면 Latent Vector를 random 32길이 sequence로 만들어서 Decoder에 넣으면 어떻게 될지 궁금해져 버렸습니다.
아마도 뭔지 모를 그림을 만들어 낼 거라 생각합니다.
함 보시죠.
import numpy as np
import random
plt.figure(figsize=(5, 3))
# latent random vector를 32짜리 만들고,
latent = np.array([random.random() for i in range(32)]).reshape(1,32)
# decoder에 latent vector를 넣습니다.
generated = decoder.predict(latent)#.reshape(28,28)
# 당연히 그려봐아죠.
plt.imshow(generated[0].reshape(28, 28))
plt.show()
[[0.56753204 0.94368045 0.21400637 0.9332447 0.2913995 0.07925668 0.11293001 0.66696223 0.7373406 0.69876503 0.97945764 0.16466649 0.92705805 0.1076675 0.30283673 0.45089712 0.38488941 0.44721336 0.96099704 0.23669158 0.25621634 0.95918701 0.12784121 0.08946924 0.41738586 0.66790835 0.73291592 0.23469399 0.47582001 0.63705097 0.18545611 0.22581379]]
꽥. 그냥 랜덤한 latent vector를 decoder에 넣었더니 decoder가 아주 기괴한 그림을 그려냈군요. latent vector가 학습에 참여하지 않은 완전 랜덤 latent vector니까 당연한 결과입니다만, 이걸 보니 뭔가 이 학습된 디코더를 다른 방식으로 학습시켜서 뭔가 생성해 낼 수 있을 것 같은 느낌이 들지 않나요?
나중에 생성형 인공지능을 다룰 때 이런 아이디어가 모여 모여 큰 결과물을 만들어 냅니다. 이런 장난을 자주 쳐보면 좋겠군요. 개인적으로 이 Decoder가 만들어 낸 작품의 이름은 미소짓는 디코더 정도로 지으면 어떨까 합니다.
더 자세한 내용은 강좌에서 만나면 좋겠군요.
댓글