VAE (Variational AutoEncoder, 변이자동인코더)실행

인공신경망 중 이미지생성 모델, VAE을 GPT만 의존하면서 코딩해 볼 수 있는지 시도해 봄.

학습시키느라 시간은 오래 걸렸지만 정말 혼자 다 해줌.



3. VAE 모델 구성

  • VAE는 인코더와 디코더로 구성됩니다. 인코더는 입력 이미지를 잠재 벡터의 평균과 로그 분산으로 변환하고, 디코더는 이 잠재 벡터를 사용하여 이미지를 재구성합니다.


3.1 인코더 모델

from tensorflow.keras.layers import Input, Conv2D, Flatten, Dense, Lambda

from tensorflow.keras.models import Model

import tensorflow as tf

latent_dim = 2 # 잠재 공간의 차원

encoder_inputs = Input(shape=(28, 28, 1))

x = Conv2D(32, 3, activation="relu", strides=2, padding="same")(encoder_inputs)

x = Conv2D(64, 3, activation="relu", strides=2, padding="same")(x)

x = Flatten()(x)

x = Dense(16, activation="relu")(x)

z_mean = Dense(latent_dim)(x)

z_log_var = Dense(latent_dim)(x)

def sampling(args):

z_mean, z_log_var = args

batch = tf.shape(z_mean)[0]

dim = tf.shape(z_mean)[1]

epsilon = tf.keras.backend.random_normal(shape=(batch, dim))

return z_mean + tf.exp(0.5 z_log_var) epsilon

z = Lambda(sampling)([z_mean, z_log_var])

encoder = Model(encoder_inputs, [z_mean, z_log_var, z], name="encoder")

encoder.summary()


3.2 디코더 모델

from tensorflow.keras.layers import Reshape, Conv2DTranspose

latent_inputs = Input(shape=(latent_dim,))

x = Dense(7 7 64, activation="relu")(latent_inputs)

x = Reshape((7, 7, 64))(x)

x = Conv2DTranspose(64, 3, activation="relu", strides=2, padding="same")(x)

x = Conv2DTranspose(32, 3, activation="relu", strides=2, padding="same")(x)

decoder_outputs = Conv2DTranspose(1, 3, activation="sigmoid", padding="same")(x)

decoder = Model(latent_inputs, decoder_outputs, name="decoder")

decoder.summary()


4. VAE 모델 훈련

  • VAE의 손실 함수는 재구성 손실과 KL 발산을 포함해야 합니다.

class VAE(Model):

def init(self, encoder, decoder, **kwargs):

super(VAE, self).__init__(**kwargs)

self.encoder = encoder

self.decoder = decoder

def call(self, inputs):

z_mean, z_log_var, z = self.encoder(inputs)

reconstructed = self.decoder(z)

kl_loss = -0.5 * tf.reduce_mean(

z_log_var - tf.square(z_mean) - tf.exp(z_log_var) + 1)

self.add_loss(kl_loss)

return reconstructed

vae = VAE(encoder, decoder)

vae.compile(optimizer='adam', loss=tf.keras.losses.MeanSquaredError())

vae.fit(x_train, x_train, epochs=30, batch_size=128)


5. 이미지 생성 및 잠재 공간 시각화

  • 훈련된 모델을 사용하여 새로운 이미지를 생성하고, 잠재 공간을 시각화하여 모델의 학습을 평가합니다.

이 과정을 따라하면 VAE를 이해하고 실제로 MNIST 데이터셋을 사용하여 손글씨 숫자 생성 모델을 실험해 볼 수 있습니다.



5번 단계에서는 훈련된 VAE 모델을 사용하여 새로운 이미지를 생성하고, 잠재 공간을 시각화하는 작업을 진행할 수 있습니다. 이를 위해 다음과 같은 세부 작업을 수행할 수 있습니다:

1. 이미지 생성

  • 훈련된 VAE 모델의 디코더를 사용하여 임의의 잠재 벡터에서 이미지를 생성합니다. 잠재 공간에서 무작위로 포인트를 샘플링하여 디코더에 입력하고, 결과 이미지를 관찰합니다.


import matplotlib.pyplot as plt

def plot_images(images, title):

fig, axes = plt.subplots(1, len(images), figsize=(20, 4))

for img, ax in zip(images, axes):

ax.imshow(img.squeeze(), cmap='gray')

ax.axis('off')

plt.suptitle(title, size=16)

plt.show()

n = 10 # 이미지를 생성할 샘플 수

random_latent_vectors = tf.random.normal(shape=(n, latent_dim))

generated_images = decoder(random_latent_vectors)

plot_images(generated_images.numpy(), "Generated Images")


결과

=========

2. 잠재 공간 시각화

TensorFlowKeras라는 라이브러리를 사용하여 구현, MNIST 데이터셋 사용

  • TensorFlow: 구글에서 개발한 오픈 소스 머신 러닝 라이브러리로, 데이터 플로우와 다양한 수학적 연산을 위한 그래프를 구성하여 복잡한 연산을 쉽고 효율적으로 처리.

  • Keras: TensorFlow 위에서 동작하는 고수준 신경망 API로, 사용자가 쉽게 신경망 모델을 구축하고 실험할 수 있게 해주는 도구.

  • MNIST: 'Modified National Institute of Standards and Technology'의 약자로, 손으로 쓴 숫자들의 큰 데이터베이스. 주로 이미지 처리 시스템을 훈련시키는 데 사용


from tensorflow.keras.datasets import mnist

import numpy as np

import matplotlib.pyplot as plt

from tensorflow.keras.layers import Input, Conv2D, Flatten, Dense, Lambda, Reshape, Conv2DTranspose

from tensorflow.keras.models import Model

import tensorflow as tf

# 데이터셋 로드 시 y_test도 함께 로드합니다.

(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = np.expand_dims(x_train, -1).astype("float32") / 255

x_test = np.expand_dims(x_test, -1).astype("float32") / 255

latent_dim = 2 # 잠재 공간의 차원

# 인코더 모델 구성

encoder_inputs = Input(shape=(28, 28, 1))

x = Conv2D(32, 3, activation="relu", strides=2, padding="same")(encoder_inputs)

x = Conv2D(64, 3, activation="relu", strides=2, padding="same")(x)

x = Flatten()(x)

x = Dense(16, activation="relu")(x)

z_mean = Dense(latent_dim)(x)

z_log_var = Dense(latent_dim)(x)

def sampling(args):

z_mean, z_log_var = args

batch = tf.shape(z_mean)[0]

dim = tf.shape(z_mean)[1]

epsilon = tf.keras.backend.random_normal(shape=(batch, dim))

return z_mean + tf.exp(0.5 z_log_var) epsilon

z = Lambda(sampling)([z_mean, z_log_var])

encoder = Model(encoder_inputs, [z_mean, z_log_var, z], name="encoder")

encoder.summary()

# 디코더 모델 구성

latent_inputs = Input(shape=(latent_dim,))

x = Dense(7 7 64, activation="relu")(latent_inputs)

x = Reshape((7, 7, 64))(x)

x = Conv2DTranspose(64, 3, activation="relu", strides=2, padding="same")(x)

x = Conv2DTranspose(32, 3, activation="relu", strides=2, padding="same")(x)

decoder_outputs = Conv2DTranspose(1, 3, activation="sigmoid", padding="same")(x)

decoder = Model(latent_inputs, decoder_outputs, name="decoder")

decoder.summary()

# VAE 모델 구성 및 훈련

class VAE(Model):

def init(self, encoder, decoder, **kwargs):

super(VAE, self).__init__(**kwargs)

self.encoder = encoder

self.decoder = decoder

def call(self, inputs):

z_mean, z_log_var, z = self.encoder(inputs)

reconstructed = self.decoder(z)

kl_loss = -0.5 * tf.reduce_mean(

z_log_var - tf.square(z_mean) - tf.exp(z_log_var) + 1)

self.add_loss(kl_loss)

return reconstructed

vae = VAE(encoder, decoder)

vae.compile(optimizer='adam', loss=tf.keras.losses.MeanSquaredError())

vae.fit(x_train, x_train, epochs=30, batch_size=128)

# 이미지 생성 및 플롯

def plot_images(images, title):

fig, axes = plt.subplots(1, len(images), figsize=(20, 4))

for img, ax in zip(images, axes):

ax.imshow(img.squeeze(), cmap='gray')

ax.axis('off')

plt.suptitle(title, size=16)

plt.show()

n = 10 # 이미지를 생성할 샘플 수

random_latent_vectors = tf.random.normal(shape=(n, latent_dim))

generated_images = decoder(random_latent_vectors)

plot_images(generated_images.numpy(), "Generated Images")

# 잠재 공간의 시각화

z_mean, , = encoder.predict(x_test, batch_size=128)

# y_test를 범주형 색상 레이블로 사용할 수 있도록 처리합니다.

y_test_categorical = np.argmax(y_test, axis=1)

plt.figure(figsize=(12, 10))

plt.scatter(z_mean[:, 0], z_mean[:, 1], c=y_test_categorical, cmap='viridis')

plt.colorbar()

plt.xlabel("z[0]")

plt.ylabel("z[1]")

plt.title("Latent Space Representation")

plt.show()


결과 : 방법을 변경했는데 유사한 결과가 나옴. 기대와 다른데 데이터 요소가 3차원을 가져오지 못할 수 있다는 생각이 듦.


3
2개의 답글

👉 이 게시글도 읽어보세요