본문 바로가기
프로그래밍/AI

VAE(Variational Autoencoders)이란?

by 꾸션 2023. 3. 13.

VAE (Variational Autoencoder)는 생성 모델(Generative Model) 중 하나로, 인코더(Encoder)와 디코더(Decoder)로 구성된 인공신경망(A Neural Network)입니다. VAE는 입력데이터를 잠재 공간(Latent Space)으로 인코딩하고, 이 공간에서 무작위 샘플링(Random Sampling)을 통해 새로운 데이터를 생성할 수 있습니다. 이러한 특성 때문에 VAE는 이미지, 음성, 자연어 등 다양한 분야에서 활용되고 있습니다.

VAE의 기본 체계
VAE의 기본 체계 - 이미지출처 위키페디아

1. VAE란?

VAE는 Variational Autoencoder의 약자로, 인코더(Encoder)와 디코더(Decoder)로 이루어진 생성 모델(Generative Model)입니다. 인코더는 입력 데이터를 잠재 공간(Latent Space)으로 인코딩하고, 디코더는 잠재 공간의 벡터를 입력으로 받아 입력 데이터를 재구성합니다. VAE는 이러한 구조를 가지면서, 입력 데이터를 더욱 정확하게 재구성하기 위해 KL divergence와 같은 통계적 기법을 활용합니다.

2. VAE의 구조

VAE는 크게 인코더(Encoder)와 디코더(Decoder)로 이루어져 있습니다. 인코더는 입력 데이터를 잠재 공간(Latent Space)으로 인코딩하고, 디코더는 잠재 공간의 벡터를 입력으로 받아 입력 데이터를 재구성합니다. 인코더와 디코더는 각각 다층 퍼셉트론(MLP)으로 구성되어 있습니다.

3. VAE의 학습 과정

VAE의 학습 과정은 크게 두 단계로 이루어집니다. 첫 번째 단계는 잠재 공간에서의 무작위 샘플링(Random Sampling)입니다. 이 과정에서는 평균과 분산을 계산하고, 이를 바탕으로 정규 분포에서 무작위 샘플링합니다. 두 번째 단계는 재구성 오차(Reconstruction Error)와 KL divergence를 이용한 손실 함수를 최소화하는 과정입니다.

4. VAE의 활용 분야

VAE는 이미지, 음성, 자연어 등 다양한 분야에서 활용됩니다. 예를 들어, 이미지 분야에서는 VAE를 이용해 이미지 생성, 이미지 압축, 이미지 복원 등의 작업을 수행할 수 있습니다. 음성 분야에서는 VAE를 이용해 음성 생성, 음성 분류, 음성 인식 등의 작업을 수행할 수 있습니다. 자연어 분야에서는 VAE를 이용해 문장 생성, 문장 분류, 문장 감정 분석 등의 작업을 수행할 수 있습니다.

5. VAE의 한계와 개선 방향

VAE는 잠재 공간의 구조가 가우시안 분포(Gaussian Distribution)라는 가정을 기반으로 하고 있습니다. 이 가정이 잘못될 경우, 생성된 데이터의 질이 저하될 수 있습니다. 또한, VAE는 생성된 데이터가 입력 데이터와 완벽하게 일치하지 않는다는 한계가 있습니다. 이러한 한계를 극복하기 위해, VAE에 대한 연구가 계속되고 있습니다. 예를 들어, VAE의 구조를 변형하거나, 다른 분포를 이용하는 방법 등이 연구되고 있습니다.

6. VAE의 코드 예시

아래는 Python에서 구현된 VAE의 간단한 예시 코드입니다.

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# 인코더 구현
encoder_inputs = keras.Input(shape=(28, 28, 1))
x = layers.Conv2D(32, 3, activation="relu", strides=2, padding="same")(encoder_inputs)
x = layers.Conv2D(64, 3, activation="relu", strides=2, padding="same")(x)
x = layers.Flatten()(x)
x = layers.Dense(16, activation="relu")(x)
z_mean = layers.Dense(2, name="z_mean")(x)
z_log_var = layers.Dense(2, name="z_log_var")(x)
z = layers.Lambda(sampling)([z_mean, z_log_var])
encoder = keras.Model(encoder_inputs, [z_mean, z_log_var, z], name="encoder")

# 디코더 구현
latent_inputs = keras.Input(shape=(2,))
x = layers.Dense(7 * 7 * 64, activation="relu")(latent_inputs)
x = layers.Reshape((7, 7, 64))(x)
x = layers.Conv2DTranspose(64, 3, activation="relu", strides=2, padding="same")(x)
x = layers.Conv2DTranspose(32, 3, activation="relu", strides=2, padding="same")(x)
decoder_outputs = layers.Conv2DTranspose(1, 3, activation="sigmoid", padding="same")(x)
decoder = keras.Model(latent_inputs, decoder_outputs, name="decoder")

# VAE 구현
class VAE(keras.Model):
    def __init__(self, encoder, decoder, **kwargs):
        super(VAE, self).__init__(**kwargs)
        self.encoder = encoder
        self.decoder = decoder
        self.total_loss_tracker = keras.metrics.Mean(name="total_loss")
        self.reconstruction_loss_tracker = keras.metrics.Mean(name="reconstruction_loss")
        self.kl_loss_tracker = keras.metrics.Mean(name="kl_loss")

    @property
    def metrics(self):
        return [
            self.total_loss_tracker,
            self.reconstruction_loss_tracker,
            self.kl_loss_tracker,
        ]

    def train_step(self, data):
        with tf.GradientTape() as tape:
            z_mean, z_log_var, z = self.encoder(data)
            reconstruction = self.decoder(z)
            reconstruction_loss = tf.reduce_mean(
                keras.losses.binary_crossentropy(data, reconstruction)
            )
            kl_loss = -0.5 * tf.reduce_mean(
                1 + z_log_var - tf.square(z_mean) - tf.exp(z_log_var)
            )
            total_loss = reconstruction_loss + kl_loss * 0.1
        grads = tape.gradient(total_loss, self.trainable_weights)
        self.optimizer.apply_gradients(zip(grads, self.trainable_weights))
        self.total_loss_tracker.update_state(total_loss)
        self.reconstruction_loss_tracker.update_state(reconstruction_loss)
        self.kl_loss_tracker.update_state(kl_loss)
        return {
            "loss": self.total_loss_tracker.result(),
            "reconstruction_loss": self.reconstruction_loss_tracker.result(),
            "kl_loss": self.kl_loss_tracker.result(),
        }

# 모델 생성 및 학습
vae = VAE(encoder, decoder)
vae.compile(optimizer=keras.optimizers.Adam())
vae.fit(x_train, epochs=10, batch_size=128)

# 새로운 데이터 생성
z_mean, _, _ = vae.encoder.predict(x_test)
new_images = vae.decoder.predict(z_mean)

위 코드는 MNIST 데이터셋을 이용해 VAE를 학습하고, 새로운 데이터를 생성하는 예시입니다. VAE는 TensorFlow와 Keras 등 다양한 딥러닝 프레임워크에서 구현할 수 있습니다.

코드를 간단히 설명하자면, 먼저 인코더와 디코더를 각각 구현하고, VAE 클래스를 정의합니다. VAE 클래스는 train_step 메서드를 통해 모델을 학습하며, 손실 함수로는 재구성 오차와 KL divergence를 이용합니다. 마지막으로 VAE 모델을 생성하고, fit 메서드를 통해 학습을 진행합니다. 새로운 데이터 생성은 encoder를 이용해 잠재 변수를 추출하고, decoder를 이용해 새로운 데이터를 생성합니다.

더 많은 자료는 아래의 위키페디아에서...

Variational autoencoder - Wikipedia

From Wikipedia, the free encyclopedia Deep learning generative model to encode data representation In machine learning, a variational autoencoder (VAE), is an artificial neural network architecture introduced by Diederik P. Kingma and Max Welling, belongin

en.wikipedia.org

반응형

댓글