가장 쉬운 VAE (variational autoencoder) 예제 by 바죠

가장 쉬운 VAE (variational autoencoder) 예제

생성모델들:

Boltzmannmachine, GAN, VAE, RNN, PixelCNN

가장 쉬운 생성적 적대 모델, GAN : http://incredible.egloos.com/7473304
가장 쉬운 오토인코더: http://incredible.egloos.com/7473318
디노이징 오토인코더 : http://incredible.egloos.com/7479749

또 다른 생성모델로서 VAE. 
VAE는 변분자동암호기로 번역될 수 있다.
이것은 자동암호기와 유사한 것이다. 데이터를 축약하는 기능과 데이터를 생성하는 기능을 동시에 가진다.
암호기, 생성기가 붙어서 훈련을 한다. 둘 다 인공신경망으로 구성되어 있다. 
암호기를 떼어낼 수 있다. 생성기에 해당하는 인공신경망을 이용하면 본격적으로 생성모델이 되는 것이다.
데이터를 축약적으로 표현하는 암호를 만들어냄에 있어서 보다 더 일반적인 확률 분포를 생각하는 것이 특징이다.
자동암호기가 잠재공간의 한 점으로 데이터를 축약한 점을 생각해야만 한다.
한 개의 점보다는 하나의 분포로 바꾸어 보자는 것이 VAE의 특징이다.
이렇게 확률적 분포를 활용하게되면 보다 더 자연스러운 생성모델이 탄생할 수 있다.

AE : vector로 정보를 축약함.
VAE : vector로 정보를 축약하지 않고 평균 그리고 편차로 정의되는 함수로 정보를 축약함.


VAE 에는 아래의 세가지 구성 요소들이 있다. encoder,  decoder, and predictor
VAE ~ ( approximate inference in a latent Gaussian model )
[ approximate posterior and model likelihood are parameterized by neural networks ]

먼저 많은 데이터가 있다고 가정한다.
각 데이터가 축약된 형식으로 표현된 다음에 다시 원본으로 표현되는 과정을 생각해 볼 수 있다. 
특별하게도 중간 단계의 표현력이 부족하게 만들어 둔 경우를 생각한다. 
즉, 데이터 정보를 의도적으로 잃어 버리게 만들어 둔다.
따라서, 완전한 데이터의 복구는 불가능할 것이다.
왜냐하면, 원본이 가지고 있는 데이터를 표현하는 차원보다 중간 단계에서 낮은 차원으로 데이터가 강제적으로 표현되기 때문이다.
Convolution 을 수행하는 것은 입력과 출력의 비대칭 크기를 의미한다.

많은 데이터에 대해서 이러한 훈련을 반복하면, 결국, encoder, decoder는 데이터에서 나타나는 공통된 또는 함축적인 표현에 인공신경망은 집중할 수밖에 없을 것이다. 
결국, 인공신경망은 필수불가결한 어떤 암호화된 양들을 찾으려고 노력할 것이다. 
그것들에 집중할 수밖에 없을 것이다. 
그 표현이 얼마나 효율적일지는 잘 모르겠지만, 축약과 회복이라는 것에 집중하여 인공신경망은 훈련이 될 것이다.
데이터 스스로를 학습하는 것이다. 데이터의 축약된 정보를 도출해낸다. 
인공신경망을 훈련할 때, 두 가지 loss 함수들을 동시에 이용한다. 
원본 복구가 되도록 하는 항, 원본이 잠재 공간에서 분포가 되도록 해 주는 항, 이렇게 두 항이 동시에 일을 하도록 한다.

1억개의 데이터가 있다면, 2차원에 1억개의 데이터 점들을 만들어 낼 수 있다.
이들 모든 점들은 모두 하나의 개체를 대표하는 점들이다. 
이들 점들이 특정한 분포를 가질 수 있는가?
분류에 활용할 수 있을 정도로 공간에서 분리되어 분포할 수 있는가?
무리와 동떨어져서 분포하는 점들의 의미는 이상한 개체를 나타내는가?

AE 방법은 데이터를 표현하는 축약된 양식을 정하는 방법이다.
축약된 표현식을 얻어내는 것이다. 굉장한 크기의 데이터도 2차원 latent space(잠재공간)에서는 단순히 숫자 두 개로 표현될 수 있다는 것이다.
물론, 이들 숫자 두 개가 얼마나 원본 데이터를 잘 표현하는지는 철저하게 따져보아야 할 것이다.
동시에 훈련된, encoder, decoder 신경망들을 사용하면 데이터의 특성을 굉장히 잘 표현할 수 있다는 가정을 도입하고 있다.

아주 훈련이 잘 된 decoder를 만들었다고 가정하면, latent space에서의 임의의 점을 이용하면 우리는 아주 그럴듯 한, 훈련에 사용된 것 같은 데이터를 만들어 낼 수 있다. 
이것은 유전 알고리듬에서 교차 또는 변이를 이용해서 새로운 개체를 만들어 내는 것과 비교가 가능한 것이다. 
인공신경망 훈련이 끝나면, 기본적으로, 새로운 데이터를 만들어 낼 수 있다.

Autoencoder의 latent space가 우리가 잘 아는 정규분포를 따른게 할 수 있다면, 이 분포는 소위, 평균과 표준편차만 구해낸다면 분포를 표현할 수 있습니다.

또한, latent space는 연속적이다. 이점을 활용하여 다수의 상태를 만들어 낼 수 있다. 2차원으로 latent space를 잡을 경우, VAE는 일종의 차원 축소 방식으로 볼 수 있고, 2차원 그림으로 데이터의 분포를 표시할 수 있다.
다시 말해서, VAE는 multidimensional scaling 방법을 대치할 수도 있다.

VAE :  reconstruction phase, regularization phase 두 가지를 모두 추구한다. 원본 복원을 위한 안전장치를 마련한다. 데이터들을 표현하는 더 좋은 방법을 추구하는 것이다.

입력/출력: image, video, text, audio등이 될 수 있다.
3D 결정구조의 경우, 
유한한 크기의 것으로 일관되게 만들어진 전자밀도, (원자위치로 부터 유도된 것),
결정파라미터들이 합쳐진 것들이 인풋이 될 수 있다.


denosing에 활용될 수 있다. 매우 많은 수의 필터를 활용하는 CNN을 사용하면 좋다.
이 경우, 통상의 Gaussian 함수를 활용하는 평균화시키는 방식의 denoising방법과는 다른 denoising방법이 탄생한다.
노이즈에 의해서 평균화되지 않은 것. 데이터 본연의 정보, 데이터 속, 픽셀들 사이의 상관관계가 고려된 denosing이 가능하다.
이것은 데이터 이미지를 미분할 때, 유용한 것이된다.

binary_crossentropy,  mse 두 가지 모두 동일한 점을 지향하기는 한다. 

\[ mse = \frac{1}{N} \sum_{i=1}^{N}  (t_i-y_i)^2 \]
\[ bce=  \frac{1}{N}\sum_{i=1}^{N} \{ -t_i log(y_i) -(1-t_i) log(1-y_i) \}  \]



KLD (Kullback Leibler divergence) 확률분포의 유사성을 체크하는 함수.
분포가 같을 때, 0
다를수록 더 큰 값을 가진다. [비대칭성을 보유하고 있다.]
KL divergence 는 cross entropy 와 상수만큼만 차이가 난다. 
이 때 상수는 데이터의 성질에 지나지 않는다.
KL divergence 는 상대적 엔트로피이다.

데이터를 통한 훈련이 이루어진 후를 가정하면 실질적인 데이터의 흐름:
latent variables (z_input)  →  generator 

응용: 다양한 분자구조들 학습하고 새로운 분자들을 만들어 낼 수 있다. 인물 사진들을 학습하고 새로운 인물을 만들어 낼 수 있다.


--------------------------------------------------------------------------------------------------------------------

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
from keras import backend as K
from keras.layers import Input, Dense, Lambda, Layer, Add, Multiply
from keras.models import Model, Sequential
from keras.datasets import mnist
original_dim = 784
intermediate_dim = 256
latent_dim = 2
batch_size = 100
epochs = 50
epsilon_std = 1.0

def nll(y_true, y_pred):
    """ Negative log likelihood (Bernoulli). """
    # keras.losses.binary_crossentropy gives the mean
    # over the last axis. we require the sum
    return K.sum(K.binary_crossentropy(y_true, y_pred), axis=-1)

class KLDivergenceLayer(Layer):
    """ Identity transform layer that adds KL divergence to the final model loss."""
    def __init__(self, *args, **kwargs):
        self.is_placeholder = True
        super(KLDivergenceLayer, self).__init__(*args, **kwargs)
    def call(self, inputs):
        mu, log_var = inputs
        kl_batch = - .5 * K.sum(1+log_var-K.square(mu)-K.exp(log_var), axis=-1)
        self.add_loss(K.mean(kl_batch), inputs=inputs)
        return inputs

decoder = Sequential([Dense(intermediate_dim, input_dim=latent_dim, activation='relu'),Dense(original_dim, activation='sigmoid')])

x = Input(shape=(original_dim,))
h = Dense(intermediate_dim, activation='relu')(x)
z_mu = Dense(latent_dim)(h)
z_log_var = Dense(latent_dim)(h)
z_mu, z_log_var = KLDivergenceLayer()([z_mu, z_log_var])
z_sigma = Lambda(lambda t: K.exp(.5*t))(z_log_var)

eps = Input(tensor=K.random_normal(stddev=epsilon_std,shape=(K.shape(x)[0], latent_dim)))
z_eps = Multiply()([z_sigma, eps])
z = Add()([z_mu, z_eps])
x_pred = decoder(z)
vae = Model(inputs=[x, eps], outputs=x_pred)
vae.compile(optimizer='rmsprop', loss=nll)

#         train the VAE on MNIST digits
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(-1, original_dim) / 255.
x_test = x_test.reshape(-1, original_dim) / 255.
vae.fit(x_train,x_train,shuffle=True,epochs=epochs,batch_size=batch_size,validation_data=(x_test, x_test))
encoder = Model(x, z_mu)

#         display a 2D plot of the digit classes in the latent space
z_test = encoder.predict(x_test, batch_size=batch_size)
plt.figure(figsize=(6, 6))
plt.scatter(z_test[:, 0], z_test[:, 1], c=y_test,alpha=.4, s=3**2, cmap='viridis')
plt.colorbar()
plt.show()

#          display a 2D manifold of the digits
n = 15              #       figure with 15x15 digits
digit_size = 28

#       linearly spaced coordinates on the unit square were transformed
#       through the inverse CDF (ppf) of the Gaussian to produce values
#       of the latent variables z, since the prior of the latent space is Gaussian
u_grid = np.dstack(np.meshgrid(np.linspace(0.05, 0.95, n),np.linspace(0.05, 0.95, n)))
z_grid = norm.ppf(u_grid)
x_decoded = decoder.predict(z_grid.reshape(n*n, 2))
x_decoded = x_decoded.reshape(n, n, digit_size, digit_size)
plt.figure(figsize=(10, 10))
plt.imshow(np.block(list(map(list, x_decoded))), cmap='gray')
plt.show()
참고:


binary-crossentropy를 사용하나요?


--------------------------------------------------------------------------------------------------------------------
#     example of calculating the KL divergence (relative entropy) with scipy
from scipy.special import rel_entr
#     define distributions
p = [0.10, 0.40, 0.50]
q = [0.80, 0.15, 0.05]
#     calculate (P || Q)
kl_pq = rel_entr(p, q)
print('KL(P || Q): %.3f nats' % sum(kl_pq))
#     calculate (Q || P)
kl_qp = rel_entr(q, p)
print('KL(Q || P): %.3f nats' % sum(kl_qp))
#     example of calculating the js divergence between two mass functions
from math import log2
from math import sqrt
from numpy import asarray
#     calculate the KL divergence
def kl_divergence(p, q):
        return sum(p[i] * log2(p[i]/q[i]) for i in range(len(p)))
#     calculate the JS divergence
def js_divergence(p, q):
        m = 0.5 * (p + q)
        return 0.5 * kl_divergence(p, m) + 0.5 * kl_divergence(q, m)
#     define distributions
p = asarray([0.10, 0.40, 0.50])
q = asarray([0.80, 0.15, 0.05])
#      calculate JS(P || Q)
js_pq = js_divergence(p, q)
print('JS(P || Q) divergence: %.3f bits' % js_pq)
print('JS(P || Q) distance: %.3f' % sqrt(js_pq))
#      calculate JS(Q || P)
js_qp = js_divergence(q, p)
print('JS(Q || P) divergence: %.3f bits' % js_qp)
print('JS(Q || P) distance: %.3f' % sqrt(js_qp))
KL(P || Q): 1.336 nats
KL(Q || P): 1.401 nats
JS(P || Q) divergence: 0.420 bits
JS(P || Q) distance: 0.648
JS(Q || P) divergence: 0.420 bits
JS(Q || P) distance: 0.648

참고:

--------------------------------------------------------------------------------------------------------------------
a = np.array([[4,3, 5, 7],
                    [1, 12,11, 9],
                    [2, 15, 1,14]])
np.sort(a,axis=0)
array([[ 1, 3, 1, 7],
          [2, 12, 5, 9],
          [4, 15, 11, 14]])

np.sort(a)   # axis=-1 or axis=1 ,default
array([[ 3, 4, 5, 7],
[ 1, 9, 11, 12],
[ 1, 2, 14, 15]])

--------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------------------------
동그라미들은 무작위 숫자가 연관된 연산이다.  마름모 꼴들은 고정된 연산을 의미한다.
--------------------------------------------------------------------------------------------------------------------
latent space에서 정의되는 격자점들은 각각 하나의 데이터로 해독될 수 있다. 
이것은 데이터 생성에 해당한다.
--------------------------------------------------------------------------------------------------------------------
https://towardsdatascience.com/the-variational-autoencoder-as-a-two-player-game-part-i-4c3737f0987b
https://towardsdatascience.com/the-variational-autoencoder-as-a-two-player-game-part-ii-b80d48512f46
https://towardsdatascience.com/the-variational-autoencoder-as-a-two-player-game-part-iii-d8d56c301600
code space == latent space
--------------------------------------------------------------------------------------------------------------------
좌측이 AE, 우측이 VAE 를 활용한 경우이다. VAE는 Kullback-Leibler divergence(KLD) term, 정규화 항을, 손실함수에 추가적으로, 가지고 있다. 두 가지 확률 분포(q, p)가 정확히 같으면 KLD 항은 0이 된다. 따라서, 손실함수 최소화 과정에서 두 확률 분포가 최대한 같아지는 것을 기대할 수 있다.
이것은 z1, z2, latent space에서의 확률 분포가 전반적으로 가우시안 형태의 분포가 되도록 한다. 이렇게 가우시안 분포가 되면 보다 더 일반적인 샘플링이 가능하다. 암호화된 데이터의 분포가 가우시안 형태가 되도록 한다.
모두 다 가우시안 형식이다.

\[ p_{\theta} ({\bf h}) = N ({\bf 0},{\bf I}) \]
--------------------------------------------------------------------------------------------------------------------

GAN, VAE 모두 새로운 해를 생성할 수 있는 생성적 모델이다. 
좋은 representation을 찾고, 새로운 해를 제시할 수 있는 것은, 마치, 유전 알고리듬에서 변이, 교차를 통해서 새로운 해를 얻어내는 것에 비유된다.

--------------------------------------------------------------------------------------------------------------------
Wassersein GAN with gradient penalty
Our proposed method performs better than standard WGAN and enables stable training of a wide variety of GAN architectures with almost no hyperparameter tuning,including 101-layer ResNets and language models with continuous generators.We also achieve high quality generations on CIFAR-10 and LSUN bedrooms.

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

class Sampling(layers.Layer):
    """Uses (z_mean, z_log_var) to sample z, the vector encoding a digit."""
    def call(self, inputs):
        z_mean, z_log_var = inputs
        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

intermediate_dim = 50
intermediate2_dim = 25
intermediate3_dim = 12
latent_dim = 2

x = keras.Input(shape=(original_dim,))
h = tf.keras.layers.Dense(intermediate_dim, activation='relu')(x)
h = tf.keras.layers.Dense(intermediate2_dim, activation='relu')(x)
h = tf.keras.layers.Dense(intermediate3_dim, activation='relu')(x)
z_mean = layers.Dense(latent_dim, name="z_mean")(x)
z_log_var = layers.Dense(latent_dim, name="z_log_var")(x)
z = Sampling()([z_mean, z_log_var])
encoder = keras.Model(x, [z_mean, z_log_var, z], name="encoder")
encoder.summary()


latent_inputs = keras.Input(shape=(latent_dim,))
h = tf.keras.layers.Dense(intermediate_dim3, activation='relu')(latent_inputs)
h = tf.keras.layers.Dense(intermediate_dim2, activation='relu')(latent_inputs)
h = tf.keras.layers.Dense(intermediate_dim, activation='relu')(latent_inputs)
decoder_outputs =tf.keras.layers.Dense(original_dim, activation='relu')(h)
decoder = keras.Model(latent_inputs, decoder_outputs, name="decoder")
decoder.summary()
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(
                tf.reduce_sum(
                    keras.losses.binary_crossentropy(data, reconstruction), axis=(1, 2)
                )
            )
            kl_loss = -0.5 * (1 + z_log_var - tf.square(z_mean) - tf.exp(z_log_var))
            kl_loss = tf.reduce_mean(tf.reduce_sum(kl_loss, axis=1))
            total_loss = reconstruction_loss + kl_loss
        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.summary()
vae.compile(optimizer=keras.optimizers.Adam())

# train the VAE on MNIST digits
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(-1, original_dim) / 255.
x_test = x_test.reshape(-1, original_dim) / 255.

vae.fit(x_train, x_train, shuffle=True, epochs=epochs, batch_size=batch_size, validation_data=(x_test, x_test))



# display a 2D plot of the digit classes in the latent space
z_test = encoder.predict(x_test, batch_size=batch_size)
plt.figure(figsize=(6, 6))
plt.scatter(z_test[:, 0], z_test[:, 1], c=y_test, alpha=.4, s=3**2, cmap='viridis')
plt.colorbar()
plt.show()

# display a 2D manifold of the digits
n = 15  # figure with 15x15 digits
digit_size = 28

# linearly spaced coordinates on the unit square were transformed
# through the inverse CDF (ppf) of the Gaussian to produce values
# of the latent variables z, since the prior of the latent space
# is Gaussian
u_grid = np.dstack(np.meshgrid(np.linspace(0.05, 0.95, n),
                               np.linspace(0.05, 0.95, n)))
z_grid = norm.ppf(u_grid)
x_decoded = decoder.predict(z_grid.reshape(n*n, 2))
x_decoded = x_decoded.reshape(n, n, digit_size, digit_size)

plt.figure(figsize=(10, 10))
plt.imshow(np.block(list(map(list, x_decoded))), cmap='gray')
plt.show()

--------------------------------------------------------------------------------------------------------------

2012년이 딥러닝의 원년이다.
2011년 Relu 함수의 출현 : vanishing gradient problem 해결, 표현력이 높은 딥러닝이 시작됨.
2012년 Dropout 방법의 출현 : overfitting problem 해결, 정규화된 훈련이 가능함. regularization의 도입.
2012년 CNN 출현 : 방대한 이미지 데이터 처리 문제 해결, 비대칭 데이터에 대한 처리가 가능함.
2013년 VAE 출현: 생성모델로서 다양한 가능성을 제안함.
2014년 GAN 출현: 생성모델로서 많은 응용 가능성을 제안함.
2015년 TensorFlow 구현의 출현과 보급 : 실질적인 딥러닝의 민주화가 단행됨.
2016년 알파고 출현 : 바둑 정복
2017년 알파고 제로 출현 : tabula rasa, first-principles 방법을 이용하여 바둑 정복, 진정한 바둑의 정복이 가능함. 기보없이 바둑 정복함. 프로기사에게 절대로 지지 않는 사실상 바둑의 신이 탄생함. 바둑의 역사 5000년 Mastering the game of Go without human knowledge | Nature http://incredible.egloos.com/7372719
2017년 cycleGAN 출현 http://incredible.egloos.com/7530913
2018년 알파폴드 출현
2021년 플로어플랜닝 (반도체 칩 설계) A graph placement methodology for fast chip design | Nature
2021년 나우캐스팅 (단기 일기예보) https://www.nature.com/articles/s41586-021-03854-z
2022년 알파코드  https://alphacode.deepmind.com/

--------------------------------------------------------------------------------------------------------------


--------------------------------------------------------------------------------------------------------------

binary crossentropy, mse 둘 다 동일한 위치에서 최소값을 가지게 된다.


--------------------------------------------------------------------------------------------------------------
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
from keras import backend as K
from keras.layers import Input, Dense, Lambda, Layer, Add, Multiply
from keras.models import Model, Sequential
from keras.datasets import mnist

original_dim = 784
intermediate_dim = 256
latent_dim = 2
batch_size = 100
epochs = 50
epsilon_std = 1.0

def nll(y_true, y_pred):
    """ Negative log likelihood (Bernoulli). """
    # keras.losses.binary_crossentropy gives the mean
    # over the last axis. we require the sum
    return K.sum(K.binary_crossentropy(y_true, y_pred), axis=-1)

class KLDivergenceLayer(Layer):
    """ Identity transform layer that adds KL divergence
    to the final model loss.
    """
    def __init__(self, *args, **kwargs):
        self.is_placeholder = True
        super(KLDivergenceLayer, self).__init__(*args, **kwargs)
    def call(self, inputs):
        mu, log_var = inputs
        kl_batch = - .5 * K.sum(1 + log_var -
                                K.square(mu) -
                                K.exp(log_var), axis=-1)
        self.add_loss(K.mean(kl_batch), inputs=inputs)
        return inputs

decoder = Sequential([ Dense(intermediate_dim, input_dim=latent_dim, activation='relu'),
    Dense(original_dim, activation='sigmoid')])

x = Input(shape=(original_dim,))
h = Dense(intermediate_dim, activation='relu')(x)
z_mu = Dense(latent_dim)(h)
z_log_var = Dense(latent_dim)(h)
z_mu, z_log_var = KLDivergenceLayer()([z_mu, z_log_var])
z_sigma = Lambda(lambda t: K.exp(.5*t))(z_log_var)
eps = Input(tensor=K.random_normal(stddev=epsilon_std,shape=(K.shape(x)[0], latent_dim)))
z_eps = Multiply()([z_sigma, eps])
z = Add()([z_mu, z_eps])

x_pred = decoder(z)
vae = Model(inputs=[x, eps], outputs=x_pred)
vae.compile(optimizer='rmsprop', loss=nll)

# train the VAE on MNIST digits
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(-1, original_dim) / 255.
x_test = x_test.reshape(-1, original_dim) / 255.

vae.fit(x_train, x_train, shuffle=True, epochs=epochs, batch_size=batch_size,validation_data=(x_test, x_test))
encoder = Model(x, z_mu)

# display a 2D plot of the digit classes in the latent space
z_test = encoder.predict(x_test, batch_size=batch_size)
plt.figure(figsize=(6, 6))
plt.scatter(z_test[:, 0], z_test[:, 1], c=y_test,  alpha=.4, s=3**2, cmap='viridis')
plt.colorbar()
plt.show()

# display a 2D manifold of the digits
n = 15  # figure with 15x15 digits
digit_size = 28

# linearly spaced coordinates on the unit square were transformed
# through the inverse CDF (ppf) of the Gaussian to produce values
# of the latent variables z, since the prior of the latent space
# is Gaussian
u_grid = np.dstack(np.meshgrid(np.linspace(0.05, 0.95, n),  np.linspace(0.05, 0.95, n)))
z_grid = norm.ppf(u_grid)
x_decoded = decoder.predict(z_grid.reshape(n*n, 2))
x_decoded = x_decoded.reshape(n, n, digit_size, digit_size)

plt.figure(figsize=(10, 10))
plt.imshow(np.block(list(map(list, x_decoded))), cmap='gray')
plt.show()

--------------------------------------------------------------------------------------------------------------

CVAE 



import warnings
import numpy as np
from keras.layers import Input, Dense, Lambda
from keras.layers.merge import concatenate as concat
from keras.models import Model
from keras import backend as K
from keras.datasets import mnist
from keras.utils import to_categorical
from keras.callbacks import EarlyStopping
from keras.optimizers import Adam
from scipy.misc import imsave
import matplotlib.pyplot as plt

warnings.filterwarnings('ignore')
%pylab inline
import warnings
import numpy as np
from keras.layers import Input, Dense, Lambda
from keras.layers.merge import concatenate as concat
from keras.models import Model
from keras import backend as K
from keras.datasets import mnist
from keras.utils import to_categorical
from keras.callbacks import EarlyStopping
from keras.optimizers import Adam
from scipy.misc import imsave
import matplotlib.pyplot as plt

warnings.filterwarnings('ignore')
%pylab inline

X_train = X_train.astype('float32') / 255.
X_test = X_test.astype('float32') / 255.

n_pixels = np.prod(X_train.shape[1:])
X_train = X_train.reshape((len(X_train), n_pixels))
X_test = X_test.reshape((len(X_test), n_pixels))
y_train = to_categorical(Y_train)
y_test = to_categorical(Y_test)
m = 250   # batch size
n_z = 2    # latent space size
encoder_dim1 = 512     # dim of encoder hidden layer
decoder_dim = 512       # dim of decoder hidden layer
decoder_out_dim = 784  # dim of decoder output layer
activ = 'relu'
optim = Adam(lr=0.001)

n_x = X_train.shape[1]
n_y = y_train.shape[1]

n_epoch = 50
X = Input(shape=(n_x,))
label = Input(shape=(n_y,))
inputs = concat([X, label])

encoder_h = Dense(encoder_dim1, activation=activ)(inputs)
mu = Dense(n_z, activation='linear')(encoder_h)
l_sigma = Dense(n_z, activation='linear')(encoder_h)

def sample_z(args):
    mu, l_sigma = args
    eps = K.random_normal(shape=(m, n_z), mean=0., stddev=1.)
    return mu + K.exp(l_sigma / 2) * eps

# Sampling latent space
z = Lambda(sample_z, output_shape = (n_z, ))([mu, l_sigma])
z = Lambda(sample_z, output_shape = (n_z, ))([mu, l_sigma])

# merge latent space with label
zc = concat([z, label])

decoder_hidden = Dense(decoder_dim, activation=activ)
decoder_out = Dense(decoder_out_dim, activation='sigmoid')
h_p = decoder_hidden(zc)
outputs = decoder_out(h_p)

def vae_loss(y_true, y_pred):
    recon = K.sum(K.binary_crossentropy(y_true, y_pred), axis=-1)
    kl = 0.5 * K.sum(K.exp(l_sigma) + K.square(mu) - 1. - l_sigma, axis=-1)
    return recon + kl

def KL_loss(y_true, y_pred):
return(0.5 * K.sum(K.exp(l_sigma) + K.square(mu) - 1. - l_sigma, axis=1))

def recon_loss(y_true, y_pred):
return K.sum(K.binary_crossentropy(y_true, y_pred), axis=-1)

cvae = Model([X, label], outputs)
encoder = Model([X, label], mu)

d_in = Input(shape=(n_z+n_y,))
d_h = decoder_hidden(d_in)
d_out = decoder_out(d_h)
decoder = Model(d_in, d_out)

cvae.compile(optimizer=optim, loss=vae_loss, metrics = [KL_loss, recon_loss])
# compile and fit
cvae_hist = cvae.fit([X_train, y_train], X_train, verbose = 1, batch_size=m, epochs=n_epoch,
validation_data = ([X_test, y_test], X_test),
callbacks = [EarlyStopping(patience = 5)])

plt.imshow(X_train[0].reshape(28, 28), cmap = plt.cm.gray), axis('off')
plt.show()

print(Y_train[0])

encoded_X0 = encoder.predict([X_train[0].reshape((1, 784)), y_train[0].reshape((1, 10))])
print(encoded_X0)

z_train = encoder.predict([X_train, y_train])
encodings= np.asarray(z_train)
encodings = encodings.reshape(X_train.shape[0], n_z)
plt.figure(figsize=(7, 7))
plt.scatter(encodings[:, 0], encodings[:, 1], c=Y_train, cmap=plt.cm.jet)
plt.show()

def construct_numvec(digit, z = None):
    out = np.zeros((1, n_z + n_y))
    out[:, digit + n_z] = 1.
    if z is None:
        return(out)
    else:
        for i in range(len(z)):
            out[:,i] = z[i]
        return(out)
    
sample_3 = construct_numvec(3)
print(sample_3)

dig = 3
sides = 8
max_z = 1.5

img_it = 0
for i in range(0, sides):
    z1 = (((i / (sides-1)) * max_z)*2) - max_z
    for j in range(0, sides):
        z2 = (((j / (sides-1)) * max_z)*2) - max_z
        z_ = [z1, z2]
        vec = construct_numvec(dig, z_)
        decoded = decoder.predict(vec)
        subplot(sides, sides, 1 + img_it)
        img_it +=1
        plt.imshow(decoded.reshape(28, 28), cmap = plt.cm.gray), axis('off')
plt.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=.2)
plt.show()


dig = 2
sides = 8
max_z = 1.5

img_it = 0
for i in range(0, sides):
    z1 = (((i / (sides-1)) * max_z)*2) - max_z
    for j in range(0, sides):
        z2 = (((j / (sides-1)) * max_z)*2) - max_z
        z_ = [z1, z2]
        vec = construct_numvec(dig, z_)
        decoded = decoder.predict(vec)
        subplot(sides, sides, 1 + img_it)
        img_it +=1
        plt.imshow(decoded.reshape(28, 28), cmap = plt.cm.gray), axis('off')
plt.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=.2)
plt.show()


핑백

덧글

  • 바죠 2020/01/25 11:13 # 답글

    The classifier used the reduced representation built by the VAE as features to detect cancer types.

    https://medium.com/swlh/clustering-and-visualizing-cancer-types-using-variational-autoencoders-vaes-4522ae2dfab7
  • 바죠 2020/02/28 17:04 # 답글

    https://www.quora.com/What-are-the-pros-and-cons-of-Generative-Adversarial-Networks-vs-Variational-Autoencoders?top_ans=26547608


  • 바죠 2020/08/30 11:22 # 답글

    https://towardsdatascience.com/generating-images-with-autoencoders-77fd3a8dd368
  • 바죠 2020/09/16 10:16 # 답글

    image, text, audio
    등이 인풋이 될 수 있다.
    3D 결정구조의 경우, 유한한 크기의 것으로 일관되게 만들어진 전자밀도, (원자위치로 부터 유도된 것), 결정파라미터들이 인풋이 될 수 있다.
  • 바죠 2020/09/16 10:55 # 답글

    Symmetric mean absolute percentage error
    https://en.wikipedia.org/wiki/Symmetric_mean_absolute_percentage_error

  • 바죠 2020/09/16 10:59 # 답글

    https://en.wikipedia.org/wiki/U-Net

  • 바죠 2020/09/16 11:26 # 답글

    https://pubs.rsc.org/en/content/articlelanding/2019/sc/c8sc05372c#!divAbstract

  • 바죠 2021/04/03 08:57 # 삭제 답글

    VAE learns parameters in the probability distribution representing the data.
  • 바죠 2022/04/15 20:46 # 삭제 답글

    https://stats.stackexchange.com/questions/245448/loss-function-for-autoencoders
댓글 입력 영역

최근 포토로그