import numpy as np import matplotlib.pyplot as plt from scipy.stats import norm import cPickle from keras.layers import Input, Dense, Lambda, Flatten, Reshape, Layer from keras.layers import Conv2D, Conv2DTranspose from keras.models import Model from keras import backend as K from keras import metrics from keras import optimizers from full_params_conv_101 import * if K.image_data_format() == 'channels_first': original_img_size = (img_chns, img_rows, img_cols) else: original_img_size = (img_rows, img_cols, img_chns) x = Input(shape=original_img_size) conv_1 = Conv2D(32, kernel_size=(4, 4), strides=(2, 2), padding='same', activation='relu')(x) conv_2 = Conv2D(64, kernel_size=(4, 4), padding='same', activation='relu', strides=(2, 2))(conv_1) conv_3 = Conv2D(128, kernel_size=(4, 4), padding='same', activation='relu', strides=(2, 2))(conv_2) conv_4 = Conv2D(256, kernel_size=(4, 4), padding='same', activation='relu', strides=(2, 2))(conv_3) flat = Flatten()(conv_4) hidden = Dense(intermediate_dim, activation='relu')(flat) z_mean = Dense(latent_dim)(hidden) z_log_var = Dense(latent_dim)(hidden) def sampling(args): z_mean, z_log_var = args epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., stddev=epsilon_std) return z_mean + K.exp(z_log_var) * epsilon # note that "output_shape" isn't necessary with the TensorFlow backend # so you could write `Lambda(sampling)([z_mean, z_log_var])` z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var]) # we instantiate these layers separately so as to reuse them later decoder_hid = Dense(intermediate_dim, activation='relu') decoder_upsample = Dense(16384, activation='relu') if K.image_data_format() == 'channels_first': output_shape = (batch_size, 256, 8, 8) else: output_shape = (batch_size, 8, 8, 256) decoder_reshape = Reshape(output_shape[1:]) decoder_deconv_1 = Conv2DTranspose(128, kernel_size=(4, 4), padding='same', strides=(2, 2), activation='relu') decoder_deconv_2 = Conv2DTranspose(64, kernel_size=(4, 4), padding='same', strides=(2, 2), activation='relu') decoder_deconv_3_upsamp = Conv2DTranspose(32, kernel_size=(4, 4), strides=(2, 2), padding='same', activation='relu') decoder_mean_squash = Conv2DTranspose(3, kernel_size=(4, 4), strides=(2, 2), padding='same', activation='relu') hid_decoded = decoder_hid(z) up_decoded = decoder_upsample(hid_decoded) reshape_decoded = decoder_reshape(up_decoded) deconv_1_decoded = decoder_deconv_1(reshape_decoded) deconv_2_decoded = decoder_deconv_2(deconv_1_decoded) x_decoded_relu = decoder_deconv_3_upsamp(deconv_2_decoded) x_decoded_mean_squash = decoder_mean_squash(x_decoded_relu) # Custom loss layer class CustomVariationalLayer(Layer): def __init__(self, **kwargs): self.is_placeholder = True super(CustomVariationalLayer, self).__init__(**kwargs) def vae_loss(self, x, x_decoded_mean_squash): x = K.flatten(x) x_decoded_mean_squash = K.flatten(x_decoded_mean_squash) xent_loss = img_rows * img_cols * metrics.binary_crossentropy(x, x_decoded_mean_squash) kl_loss = - 0.5 * K.mean(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1) return K.mean(xent_loss + kl_loss) def call(self, inputs): x = inputs[0] x_decoded_mean_squash = inputs[1] loss = self.vae_loss(x, x_decoded_mean_squash) self.add_loss(loss, inputs=inputs) # We don't use this output. return x y = CustomVariationalLayer()([x, x_decoded_mean_squash]) vae = Model(x, y) sgd = optimizers.SGD(lr=0.01) vae.compile(optimizer=sgd, loss=None) vae.summary() """ with open('../datasets/101_ObjectCategories.pkl') as f: dic = cPickle.load(f) x_train = dic['all_images'] """ x_train = np.load('../datasets/full_x.npy') print "dataset loaded" history = vae.fit(x_train, shuffle=True, epochs=epochs, batch_size=batch_size, ) # build a model to project inputs on the latent space encoder = Model(x, z_mean) """ # display a 2D plot of the digit classes in the latent space x_test_encoded = encoder.predict(x_test, batch_size=batch_size) plt.figure(figsize=(6, 6)) plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test) plt.colorbar() plt.show() """ # build a digit generator that can sample from the learned distribution decoder_input = Input(shape=(latent_dim,)) _hid_decoded = decoder_hid(decoder_input) _up_decoded = decoder_upsample(_hid_decoded) _reshape_decoded = decoder_reshape(_up_decoded) _deconv_1_decoded = decoder_deconv_1(_reshape_decoded) _deconv_2_decoded = decoder_deconv_2(_deconv_1_decoded) _x_decoded_relu = decoder_deconv_3_upsamp(_deconv_2_decoded) _x_decoded_mean_squash = decoder_mean_squash(_x_decoded_relu) generator = Model(decoder_input, _x_decoded_mean_squash) vae.save('../models/object101_ld_%d_conv_%d_id_%d_e_%d_vae.h5' % (latent_dim, num_conv, intermediate_dim, epochs)) encoder.save('../models/object101_ld_%d_conv_%d_id_%d_e_%d_encoder.h5' % (latent_dim, num_conv, intermediate_dim, epochs)) generator.save('../models/object101_ld_%d_conv_%d_id_%d_e_%d_generator.h5' % (latent_dim, num_conv, intermediate_dim, epochs)) fname = '../models/object101_ld_%d_conv_%d_id_%d_e_%d_history.pkl' % (latent_dim, num_conv, intermediate_dim, epochs) with open(fname, 'wb') as file_pi: cPickle.dump(history.history, file_pi) """ # display a 2D manifold of the digits n = 15 # figure with 15x15 digits digit_size = 28 figure = np.zeros((digit_size * n, digit_size * n)) # 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 grid_x = norm.ppf(np.linspace(0.05, 0.95, n)) grid_y = norm.ppf(np.linspace(0.05, 0.95, n)) for i, yi in enumerate(grid_x): for j, xi in enumerate(grid_y): z_sample = np.array([[xi, yi]]) z_sample = np.tile(z_sample, batch_size).reshape(batch_size, 2) x_decoded = generator.predict(z_sample, batch_size=batch_size) digit = x_decoded[0].reshape(digit_size, digit_size) figure[i * digit_size: (i + 1) * digit_size, j * digit_size: (j + 1) * digit_size] = digit plt.figure(figsize=(10, 10)) plt.imshow(figure, cmap='Greys_r') plt.show() """