├── README.md └── variational_autoencoder.py /README.md: -------------------------------------------------------------------------------- 1 | # autoencoder_explained 2 | This is the code for "Autoencoder Explained" by Siraj Raval on Youtube 3 | 4 | # Coding Challenge - Due Date- ~Thursday, Feb 1 2018 5 | 6 | Create an autoencoder using Keras. Try to think of a cool use case. Bonus points for good documentation. Submit your github link in the comment section of this video. Good luck! 7 | 8 | ## Overview 9 | 10 | This is the code for [this](https://youtu.be/H1AllrJ-_30) video on Youtube by Siraj Raval on autoencoders. 11 | 12 | ## Dependencies 13 | 14 | * keras 15 | 16 | Install keras [here](https://keras.io/). 17 | 18 | ## Usage 19 | 20 | Run the demo with python class_name.py in terminal 21 | 22 | ## Credits 23 | 24 | Credits go to the Keras team 25 | -------------------------------------------------------------------------------- /variational_autoencoder.py: -------------------------------------------------------------------------------- 1 | '''This script demonstrates how to build a variational autoencoder with Keras. 2 | 3 | #Reference 4 | 5 | - Auto-Encoding Variational Bayes 6 | https://arxiv.org/abs/1312.6114 7 | ''' 8 | from __future__ import print_function 9 | 10 | import numpy as np 11 | import matplotlib.pyplot as plt 12 | from scipy.stats import norm 13 | 14 | from keras.layers import Input, Dense, Lambda 15 | from keras.models import Model 16 | from keras import backend as K 17 | from keras import metrics 18 | from keras.datasets import mnist 19 | 20 | batch_size = 100 21 | original_dim = 784 22 | latent_dim = 2 23 | intermediate_dim = 256 24 | epochs = 50 25 | epsilon_std = 1.0 26 | 27 | 28 | x = Input(shape=(original_dim,)) 29 | h = Dense(intermediate_dim, activation='relu')(x) 30 | z_mean = Dense(latent_dim)(h) 31 | z_log_var = Dense(latent_dim)(h) 32 | 33 | 34 | def sampling(args): 35 | z_mean, z_log_var = args 36 | epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., 37 | stddev=epsilon_std) 38 | return z_mean + K.exp(z_log_var / 2) * epsilon 39 | 40 | # note that "output_shape" isn't necessary with the TensorFlow backend 41 | z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var]) 42 | 43 | # we instantiate these layers separately so as to reuse them later 44 | decoder_h = Dense(intermediate_dim, activation='relu') 45 | decoder_mean = Dense(original_dim, activation='sigmoid') 46 | h_decoded = decoder_h(z) 47 | x_decoded_mean = decoder_mean(h_decoded) 48 | 49 | # instantiate VAE model 50 | vae = Model(x, x_decoded_mean) 51 | 52 | # Compute VAE loss 53 | xent_loss = original_dim * metrics.binary_crossentropy(x, x_decoded_mean) 54 | kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1) 55 | vae_loss = K.mean(xent_loss + kl_loss) 56 | 57 | vae.add_loss(vae_loss) 58 | vae.compile(optimizer='rmsprop') 59 | vae.summary() 60 | 61 | 62 | # train the VAE on MNIST digits 63 | (x_train, y_train), (x_test, y_test) = mnist.load_data() 64 | 65 | x_train = x_train.astype('float32') / 255. 66 | x_test = x_test.astype('float32') / 255. 67 | x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:]))) 68 | x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:]))) 69 | 70 | vae.fit(x_train, 71 | shuffle=True, 72 | epochs=epochs, 73 | batch_size=batch_size, 74 | validation_data=(x_test, None)) 75 | 76 | # build a model to project inputs on the latent space 77 | encoder = Model(x, z_mean) 78 | 79 | # display a 2D plot of the digit classes in the latent space 80 | x_test_encoded = encoder.predict(x_test, batch_size=batch_size) 81 | plt.figure(figsize=(6, 6)) 82 | plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test) 83 | plt.colorbar() 84 | plt.show() 85 | 86 | # build a digit generator that can sample from the learned distribution 87 | decoder_input = Input(shape=(latent_dim,)) 88 | _h_decoded = decoder_h(decoder_input) 89 | _x_decoded_mean = decoder_mean(_h_decoded) 90 | generator = Model(decoder_input, _x_decoded_mean) 91 | 92 | # display a 2D manifold of the digits 93 | n = 15 # figure with 15x15 digits 94 | digit_size = 28 95 | figure = np.zeros((digit_size * n, digit_size * n)) 96 | # linearly spaced coordinates on the unit square were transformed through the inverse CDF (ppf) of the Gaussian 97 | # to produce values of the latent variables z, since the prior of the latent space is Gaussian 98 | grid_x = norm.ppf(np.linspace(0.05, 0.95, n)) 99 | grid_y = norm.ppf(np.linspace(0.05, 0.95, n)) 100 | 101 | for i, yi in enumerate(grid_x): 102 | for j, xi in enumerate(grid_y): 103 | z_sample = np.array([[xi, yi]]) 104 | x_decoded = generator.predict(z_sample) 105 | digit = x_decoded[0].reshape(digit_size, digit_size) 106 | figure[i * digit_size: (i + 1) * digit_size, 107 | j * digit_size: (j + 1) * digit_size] = digit 108 | 109 | plt.figure(figsize=(10, 10)) 110 | plt.imshow(figure, cmap='Greys_r') 111 | plt.show() 112 | --------------------------------------------------------------------------------