Assignment - 1 (Machine Learning 2)

Autoencoders

Author: Jimut Bahan Pal

Try to improve the performance (measured on the validation dataset) of the model by the following approaches:

  • a) Varying the number of layers and units in the layers
  • b) Employing regularization
  • c) Corrupting the inputs with some noise

An autoencoder is a special type of neural network that is trained to copy its input to its output. For example, given an image of a handwritten digit, an autoencoder first encodes the image into a lower dimensional latent representation, then decodes the latent representation back to an image. An autoencoder learns to compress the data while minimizing the reconstruction error. [1]

Task a) and b) Combined

Note: Increasing layers doesn't helps much

In [149]:
#Source: https://www.tensorflow.org/tutorials/generative/autoencoder
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import tensorflow as tf

from sklearn.metrics import accuracy_score, precision_score, recall_score
from sklearn.model_selection import train_test_split
from tensorflow.keras import layers, losses
from tensorflow.keras.datasets import fashion_mnist
from tensorflow.keras.models import Model

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import ImageGrid

plt.style.use("dark_background")
In [150]:
(x_train, _), (x_test, _) = fashion_mnist.load_data()

x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.

print (x_train.shape)
print (x_test.shape)
(60000, 28, 28)
(10000, 28, 28)
In [172]:
latent_dim = 64 

class Autoencoder(Model):
  def __init__(self, latent_dim):
    super(Autoencoder, self).__init__()
    self.latent_dim = latent_dim   
    self.encoder = tf.keras.Sequential([
      layers.Flatten(),
      layers.Dense(latent_dim, activation='tanh'),
      layers.BatchNormalization(),
    ])
    self.decoder = tf.keras.Sequential([
      layers.Dense(784, activation='sigmoid'),
      layers.Reshape((28, 28))
    ])

  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded
  
autoencoder = Autoencoder(latent_dim) 

autoencoder.compile(optimizer='Adam', loss=losses.MeanSquaredError(),metrics=['accuracy'])


history = autoencoder.fit(x_train, x_train,
                epochs=10,
                shuffle=True,
                validation_data=(x_test, x_test))


encoded_imgs = autoencoder.encoder(x_test).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
Epoch 1/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0242 - accuracy: 0.1422 - val_loss: 0.0139 - val_accuracy: 0.1867
Epoch 2/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0131 - accuracy: 0.1898 - val_loss: 0.0133 - val_accuracy: 0.2088
Epoch 3/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0124 - accuracy: 0.1976 - val_loss: 0.0106 - val_accuracy: 0.2149
Epoch 4/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0122 - accuracy: 0.2001 - val_loss: 0.0104 - val_accuracy: 0.2070
Epoch 5/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0120 - accuracy: 0.2018 - val_loss: 0.0106 - val_accuracy: 0.2111
Epoch 6/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0118 - accuracy: 0.2030 - val_loss: 0.0105 - val_accuracy: 0.2194
Epoch 7/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0118 - accuracy: 0.2043 - val_loss: 0.0114 - val_accuracy: 0.2178
Epoch 8/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0117 - accuracy: 0.2041 - val_loss: 0.0107 - val_accuracy: 0.2150
Epoch 9/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0117 - accuracy: 0.2053 - val_loss: 0.0104 - val_accuracy: 0.2159
Epoch 10/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0116 - accuracy: 0.2056 - val_loss: 0.0102 - val_accuracy: 0.2209
In [173]:
plt.figure(figsize=(12,7))
legend_acc = []
for item in history.history.keys():
  if item.split('_')[-1:] == ['accuracy']:
    #print("Accuracy = ",item)
    legend_acc.append(item)
    plt.plot(history.history[item])
    #plt.plot( history.history[item], lw=3, c="springgreen")
plt.ylabel('Accuracy ->')
plt.xlabel('Epoch ->')
plt.legend(legend_acc, loc='upper left')
plt.show()

plt.figure(figsize=(12,7))
legend_acc = []
for item in history.history.keys():
  if item.split('_')[-1:] == ['loss']:
    #print("Accuracy = ",item)
    legend_acc.append(item)
    plt.plot(history.history[item])
plt.ylabel('Loss ->')
plt.xlabel('Epoch ->')
plt.legend(legend_acc, loc='upper right')
plt.show()
In [174]:
n = 10
plt.figure(figsize=(20, 4))
for i in range(n):
  # display original
  ax = plt.subplot(2, n, i + 1)
  plt.imshow(x_test[i])
  plt.title("original")
  plt.gray()
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)

  # display reconstruction
  ax = plt.subplot(2, n, i + 1 + n)
  plt.imshow(decoded_imgs[i])
  plt.title("reconstructed")
  plt.gray()
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)
plt.show()
In [ ]:
 
In [169]:
latent_dim = 64 

class Autoencoder(Model):
  def __init__(self, latent_dim):
    super(Autoencoder, self).__init__()
    self.latent_dim = latent_dim   
    self.encoder = tf.keras.Sequential([
      layers.Flatten(),
      layers.Dense(latent_dim*8, activation='relu',kernel_regularizer='l1'),
      layers.BatchNormalization(),
      layers.Dense(latent_dim*8, activation='relu',kernel_regularizer='l1'),
      layers.BatchNormalization(),
      layers.Dense(latent_dim*4, activation='relu',kernel_regularizer='l1'),
      layers.BatchNormalization(),
      layers.Dense(latent_dim*4, activation='relu',kernel_regularizer='l1'),
      layers.BatchNormalization(),
      layers.Dense(latent_dim*2, activation='relu',kernel_regularizer='l1'),
      layers.BatchNormalization(),
      layers.Dense(latent_dim*2, activation='relu',kernel_regularizer='l1'),
      layers.BatchNormalization(),
    ])
    self.decoder = tf.keras.Sequential([
      layers.Dense(784, activation='sigmoid'),
      layers.Reshape((28, 28))
    ])

  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded
  
autoencoder = Autoencoder(latent_dim) 

autoencoder.compile(optimizer='Adam', loss=losses.MeanSquaredError(),metrics=['accuracy'])


history = autoencoder.fit(x_train, x_train,
                epochs=10,
                shuffle=True,
                validation_data=(x_test, x_test))


encoded_imgs = autoencoder.encoder(x_test).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
Epoch 1/10
1875/1875 [==============================] - 9s 5ms/step - loss: 6.7826 - accuracy: 0.0564 - val_loss: 1.1304 - val_accuracy: 0.0607
Epoch 2/10
1875/1875 [==============================] - 8s 4ms/step - loss: 1.1020 - accuracy: 0.0662 - val_loss: 1.1093 - val_accuracy: 0.0567
Epoch 3/10
1875/1875 [==============================] - 8s 4ms/step - loss: 1.0932 - accuracy: 0.0692 - val_loss: 1.1211 - val_accuracy: 0.0662
Epoch 4/10
1875/1875 [==============================] - 8s 4ms/step - loss: 1.0891 - accuracy: 0.0703 - val_loss: 1.1007 - val_accuracy: 0.0664
Epoch 5/10
1875/1875 [==============================] - 8s 4ms/step - loss: 1.0862 - accuracy: 0.0703 - val_loss: 1.1084 - val_accuracy: 0.0702
Epoch 6/10
1875/1875 [==============================] - 8s 4ms/step - loss: 1.0849 - accuracy: 0.0709 - val_loss: 1.0980 - val_accuracy: 0.0621
Epoch 7/10
1875/1875 [==============================] - 8s 4ms/step - loss: 1.0849 - accuracy: 0.0713 - val_loss: 1.0886 - val_accuracy: 0.0718
Epoch 8/10
1875/1875 [==============================] - 8s 4ms/step - loss: 1.0836 - accuracy: 0.0710 - val_loss: 1.1092 - val_accuracy: 0.0695
Epoch 9/10
1875/1875 [==============================] - 9s 5ms/step - loss: 1.0843 - accuracy: 0.0711 - val_loss: 1.1051 - val_accuracy: 0.0727
Epoch 10/10
1875/1875 [==============================] - 8s 4ms/step - loss: 1.0837 - accuracy: 0.0714 - val_loss: 1.1342 - val_accuracy: 0.0691
In [170]:
plt.figure(figsize=(12,7))
legend_acc = []
for item in history.history.keys():
  if item.split('_')[-1:] == ['accuracy']:
    #print("Accuracy = ",item)
    legend_acc.append(item)
    plt.plot(history.history[item])
    #plt.plot( history.history[item], lw=3, c="springgreen")
plt.ylabel('Accuracy ->')
plt.xlabel('Epoch ->')
plt.legend(legend_acc, loc='upper left')
plt.show()

plt.figure(figsize=(12,7))
legend_acc = []
for item in history.history.keys():
  if item.split('_')[-1:] == ['loss']:
    #print("Accuracy = ",item)
    legend_acc.append(item)
    plt.plot(history.history[item])
plt.ylabel('Loss ->')
plt.xlabel('Epoch ->')
plt.legend(legend_acc, loc='upper right')
plt.show()

Image denoising

In [121]:
(x_train, _), (x_test, _) = fashion_mnist.load_data()
In [122]:
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.

x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]

print(x_train.shape)
(60000, 28, 28, 1)

Add random noise to the images

In [123]:
noise_factor = 0.2
x_train_noisy = x_train + noise_factor * tf.random.normal(shape=x_train.shape) 
x_test_noisy = x_test + noise_factor * tf.random.normal(shape=x_test.shape) 

x_train_noisy = tf.clip_by_value(x_train_noisy, clip_value_min=0., clip_value_max=1.)
x_test_noisy = tf.clip_by_value(x_test_noisy, clip_value_min=0., clip_value_max=1.)

Plotting the noisy images

In [124]:
n = 10
plt.figure(figsize=(20, 2))
for i in range(n):
    ax = plt.subplot(1, n, i + 1)
    plt.title("original + noise")
    plt.imshow(tf.squeeze(x_test_noisy[i]))
    plt.gray()
plt.show()

Task c)

Training a CVAE (Convolutional Autoencoders)

In [125]:
class Denoise(Model):
  def __init__(self):
    super(Denoise, self).__init__()
    self.encoder = tf.keras.Sequential([
      layers.Input(shape=(28, 28, 1)), 
      layers.Conv2D(16, (3,3), activation='relu', padding='same', strides=2),
      layers.Conv2D(8, (3,3), activation='relu', padding='same', strides=2),
      ])
    
    self.decoder = tf.keras.Sequential([
      layers.Conv2DTranspose(8, kernel_size=3, strides=2, activation='relu', padding='same'),
      layers.Conv2DTranspose(16, kernel_size=3, strides=2, activation='relu', padding='same'),
      layers.Conv2D(1, kernel_size=(3,3), activation='sigmoid', padding='same')])
    
  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded

denoising_autoencoder = Denoise()
In [126]:
denoising_autoencoder.compile(optimizer='nadam', loss=losses.MeanSquaredError(),metrics=['accuracy'])


history = denoising_autoencoder.fit(x_train_noisy, x_train,
                epochs=10,
                shuffle=True,
                validation_data=(x_test_noisy, x_test))



encoded_imgs = denoising_autoencoder.encoder(x_test).numpy()
decoded_imgs = denoising_autoencoder.decoder(encoded_imgs).numpy()
Epoch 1/10
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0174 - accuracy: 0.5081 - val_loss: 0.0108 - val_accuracy: 0.5071
Epoch 2/10
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0097 - accuracy: 0.5095 - val_loss: 0.0092 - val_accuracy: 0.5075
Epoch 3/10
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0085 - accuracy: 0.5097 - val_loss: 0.0082 - val_accuracy: 0.5075
Epoch 4/10
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0079 - accuracy: 0.5097 - val_loss: 0.0078 - val_accuracy: 0.5076
Epoch 5/10
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0075 - accuracy: 0.5098 - val_loss: 0.0073 - val_accuracy: 0.5076
Epoch 6/10
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0071 - accuracy: 0.5098 - val_loss: 0.0071 - val_accuracy: 0.5077
Epoch 7/10
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0069 - accuracy: 0.5099 - val_loss: 0.0069 - val_accuracy: 0.5077
Epoch 8/10
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0068 - accuracy: 0.5099 - val_loss: 0.0068 - val_accuracy: 0.5077
Epoch 9/10
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0067 - accuracy: 0.5099 - val_loss: 0.0067 - val_accuracy: 0.5077
Epoch 10/10
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0067 - accuracy: 0.5099 - val_loss: 0.0067 - val_accuracy: 0.5077
In [127]:
plt.figure(figsize=(12,7))
legend_acc = []
for item in history.history.keys():
  if item.split('_')[-1:] == ['accuracy']:
    #print("Accuracy = ",item)
    legend_acc.append(item)
    plt.plot(history.history[item])
    #plt.plot( history.history[item], lw=3, c="springgreen")
plt.ylabel('Accuracy ->')
plt.xlabel('Epoch ->')
plt.legend(legend_acc, loc='upper left')
plt.show()

plt.figure(figsize=(12,7))
legend_acc = []
for item in history.history.keys():
  if item.split('_')[-1:] == ['loss']:
    #print("Accuracy = ",item)
    legend_acc.append(item)
    plt.plot(history.history[item])
plt.ylabel('Loss ->')
plt.xlabel('Epoch ->')
plt.legend(legend_acc, loc='upper right')
plt.show()
In [128]:
autoencoder.encoder.summary()
Model: "sequential_76"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten_26 (Flatten)         (None, 784)               0         
_________________________________________________________________
dense_79 (Dense)             (None, 320)               251200    
_________________________________________________________________
dense_80 (Dense)             (None, 192)               61632     
_________________________________________________________________
dense_81 (Dense)             (None, 64)                12352     
=================================================================
Total params: 325,184
Trainable params: 325,184
Non-trainable params: 0
_________________________________________________________________
In [129]:
autoencoder.decoder.summary()
Model: "sequential_77"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_82 (Dense)             (None, 784)               50960     
_________________________________________________________________
reshape_26 (Reshape)         (None, 28, 28)            0         
=================================================================
Total params: 50,960
Trainable params: 50,960
Non-trainable params: 0
_________________________________________________________________
In [130]:
encoded_imgs = autoencoder.encoder(x_test).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
In [57]:
n = 10
plt.figure(figsize=(20, 4))
for i in range(n):

    # display original + noise
    ax = plt.subplot(2, n, i + 1)
    plt.title("original + noise")
    plt.imshow(tf.squeeze(x_test_noisy[i]))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # display reconstruction
    bx = plt.subplot(2, n, i + n + 1)
    plt.title("reconstructed")
    plt.imshow(tf.squeeze(decoded_imgs[i]))
    plt.gray()
    bx.get_xaxis().set_visible(False)
    bx.get_yaxis().set_visible(False)
plt.show()
In [132]:
from keras.layers import *
from keras.models import Model, load_model
from keras.datasets import mnist
from keras.callbacks import ReduceLROnPlateau
from keras import regularizers
from keras import optimizers
from keras import backend as K
import scipy
import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox, TextArea
import pandas as pd
import numpy as np

Bonus Experiments #Clustering using AE

In [137]:
# https://www.kaggle.com/zalando-research/fashionmnist
! wget "https://storage.googleapis.com/kaggle-data-sets/2243/9243/bundle/archive.zip?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=gcp-kaggle-com%40kaggle-161607.iam.gserviceaccount.com%2F20201011%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20201011T104838Z&X-Goog-Expires=259199&X-Goog-SignedHeaders=host&X-Goog-Signature=81a721a2b46bbb019329a0dafe9a2f8f4fb91c07f8880392a2ef5cdc5cd46fd8520c20dcf6a12170974cf4667bace6c6d1a3dfda81103e35906781e438bff3eed8a422cd9e37f8bab7c5f482b0edec6899a05b8112f4e9d30e29f291ccca48c858a5d1337afd0b2022e10f3aae33be6b956e43b7b20e7c3970dd9357e9702fa385adaf75ef6af6233c3b5695a76165a7eaeb694314a55287d889fe2bb82bc7a5e05421bd38a3bdea2d9a5ff03373ca234be5b522686913a1cd121555f6d151867954326a26928a46f8cee8af0189f22af0d6f5a8301ba76799dee69536b2eef4913b3877af11131693d99066a436a15d9dc30e52a453e1d0866e7df098734ff5" -O fashion.zip
--2020-10-11 10:49:05--  https://storage.googleapis.com/kaggle-data-sets/2243/9243/bundle/archive.zip?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=gcp-kaggle-com%40kaggle-161607.iam.gserviceaccount.com%2F20201011%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20201011T104838Z&X-Goog-Expires=259199&X-Goog-SignedHeaders=host&X-Goog-Signature=81a721a2b46bbb019329a0dafe9a2f8f4fb91c07f8880392a2ef5cdc5cd46fd8520c20dcf6a12170974cf4667bace6c6d1a3dfda81103e35906781e438bff3eed8a422cd9e37f8bab7c5f482b0edec6899a05b8112f4e9d30e29f291ccca48c858a5d1337afd0b2022e10f3aae33be6b956e43b7b20e7c3970dd9357e9702fa385adaf75ef6af6233c3b5695a76165a7eaeb694314a55287d889fe2bb82bc7a5e05421bd38a3bdea2d9a5ff03373ca234be5b522686913a1cd121555f6d151867954326a26928a46f8cee8af0189f22af0d6f5a8301ba76799dee69536b2eef4913b3877af11131693d99066a436a15d9dc30e52a453e1d0866e7df098734ff5
Resolving storage.googleapis.com (storage.googleapis.com)... 74.125.20.128, 74.125.28.128, 74.125.142.128, ...
Connecting to storage.googleapis.com (storage.googleapis.com)|74.125.20.128|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 72114846 (69M) [application/zip]
Saving to: ‘fashion.zip’

fashion.zip         100%[===================>]  68.77M   111MB/s    in 0.6s    

2020-10-11 10:49:05 (111 MB/s) - ‘fashion.zip’ saved [72114846/72114846]

In [138]:
! unzip -qq fashion.zip
In [140]:
x_train = pd.read_csv('fashion-mnist_train.csv')
x_test = pd.read_csv('fashion-mnist_test.csv')

y_train = x_train.pop('label')
y_test = x_test.pop('label')

x_train = np.array(x_train).reshape(-1, 28, 28) / 255.0
x_test = np.array(x_test).reshape(-1, 28, 28) / 255.0
In [141]:
labeldict = {
    0: 'T-shirt/top',
    1: 'Trouser',
    2: 'Pullover',
    3: 'Dress',
    4: 'Coat',
    5: 'Sandal',
    6: 'Shirt',
    7: 'Sneaker',
    8: 'Bag',
    9: 'Ankle boot'
}

fig, ax = plt.subplots(1, 10, figsize=(20, 2))
for i in range(10):
    ax[i].imshow(x_train[i], cmap='gray')
    ax[i].set_title(labeldict[y_train[i]])
In [142]:
x_train = x_train.reshape(-1, 28, 28, 1)
x_test = x_test.reshape(-1, 28, 28, 1)

def make_and_fit():
    inputs = Input(shape=(28, 28, 1))

    x = Conv2D(32, (3, 3), activation='relu', padding='same')(inputs)
    x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
    x = MaxPooling2D((2, 2))(x)
    x = BatchNormalization()(x)
    x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
    x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
    x = Conv2D(32, (2, 2), activation='relu', padding='same')(x)
    x = MaxPooling2D((2, 2))(x)
    x = BatchNormalization()(x)
    x = Conv2D(16, (2, 2), activation='relu', padding='same')(x)
    x = Conv2D(4, (2, 2), activation='relu', padding='same')(x)
    x = Conv2D(1, (2, 2), activation='relu', padding='same')(x)
    x = Flatten()(x)
    encoded = Dense(2, activation='relu')(x)

    encoder = Model(inputs=inputs, outputs=encoded)
    
    encoded_inputs = Input(shape=(2,))

    x = Dense(4, activation='relu')(encoded_inputs)
    x = Reshape((2, 2, 1))(x)
    x = Conv2D(4, (2, 2), activation='relu', padding='same')(x)
    x = Conv2D(16, (2, 2), activation='relu', padding='same')(x)
    x = BatchNormalization()(x)
    x = UpSampling2D((7, 7))(x)
    x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
    x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
    x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
    x = BatchNormalization()(x)
    x = UpSampling2D((2, 2))(x)
    x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
    x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
    decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)

    decoder = Model(inputs=encoded_inputs, outputs=decoded)
    
    x = encoder(inputs)
    x = decoder(x)
    model = Model(inputs=inputs, outputs=x)
    model.compile(optimizer=optimizers.Adam(1e-3), loss='binary_crossentropy', metrics=['accuracy', 'mse'])

    print(model.summary())
    
    clr = ReduceLROnPlateau(
        monitor='loss',
        factor=0.5,
        patience=3,
        min_delta=0.01,
        cooldown=0,
        min_lr=1e-7,
        verbose=1)

    model.fit(
        x_train,
        x_train,
        batch_size=256,
        epochs=50,
        shuffle=True,
        validation_data=(x_test, x_test),
        callbacks=[clr])

    return model, encoder, decoder

model, encoder, decoder = make_and_fit()
Model: "functional_17"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_34 (InputLayer)        [(None, 28, 28, 1)]       0         
_________________________________________________________________
functional_13 (Functional)   (None, 2)                 34889     
_________________________________________________________________
functional_15 (Functional)   (None, 28, 28, 1)         42417     
=================================================================
Total params: 77,306
Trainable params: 77,082
Non-trainable params: 224
_________________________________________________________________
None
Epoch 1/50
235/235 [==============================] - 5s 22ms/step - loss: 0.4073 - accuracy: 0.4891 - mse: 0.0558 - val_loss: 0.5230 - val_accuracy: 0.5026 - val_mse: 0.0972
Epoch 2/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3723 - accuracy: 0.4931 - mse: 0.0438 - val_loss: 0.4134 - val_accuracy: 0.4904 - val_mse: 0.0585
Epoch 3/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3634 - accuracy: 0.4935 - mse: 0.0411 - val_loss: 0.3654 - val_accuracy: 0.4921 - val_mse: 0.0422
Epoch 4/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3592 - accuracy: 0.4942 - mse: 0.0398 - val_loss: 0.3662 - val_accuracy: 0.4901 - val_mse: 0.0421
Epoch 5/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3558 - accuracy: 0.4951 - mse: 0.0386 - val_loss: 0.4130 - val_accuracy: 0.4972 - val_mse: 0.0521
Epoch 6/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3533 - accuracy: 0.4954 - mse: 0.0378 - val_loss: 0.3850 - val_accuracy: 0.4992 - val_mse: 0.0482
Epoch 7/50
232/235 [============================>.] - ETA: 0s - loss: 0.3511 - accuracy: 0.4958 - mse: 0.0372
Epoch 00007: ReduceLROnPlateau reducing learning rate to 0.0005000000237487257.
235/235 [==============================] - 5s 20ms/step - loss: 0.3511 - accuracy: 0.4957 - mse: 0.0372 - val_loss: 0.4056 - val_accuracy: 0.4751 - val_mse: 0.0573
Epoch 8/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3477 - accuracy: 0.4962 - mse: 0.0360 - val_loss: 0.3571 - val_accuracy: 0.5002 - val_mse: 0.0402
Epoch 9/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3460 - accuracy: 0.4965 - mse: 0.0355 - val_loss: 0.3457 - val_accuracy: 0.4986 - val_mse: 0.0356
Epoch 10/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3459 - accuracy: 0.4965 - mse: 0.0355 - val_loss: 0.3625 - val_accuracy: 0.4997 - val_mse: 0.0412
Epoch 11/50
232/235 [============================>.] - ETA: 0s - loss: 0.3442 - accuracy: 0.4969 - mse: 0.0350
Epoch 00011: ReduceLROnPlateau reducing learning rate to 0.0002500000118743628.
235/235 [==============================] - 5s 20ms/step - loss: 0.3443 - accuracy: 0.4968 - mse: 0.0350 - val_loss: 0.3605 - val_accuracy: 0.4881 - val_mse: 0.0410
Epoch 12/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3434 - accuracy: 0.4970 - mse: 0.0347 - val_loss: 0.3505 - val_accuracy: 0.5010 - val_mse: 0.0380
Epoch 13/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3419 - accuracy: 0.4973 - mse: 0.0342 - val_loss: 0.3419 - val_accuracy: 0.4961 - val_mse: 0.0346
Epoch 14/50
232/235 [============================>.] - ETA: 0s - loss: 0.3418 - accuracy: 0.4973 - mse: 0.0341
Epoch 00014: ReduceLROnPlateau reducing learning rate to 0.0001250000059371814.
235/235 [==============================] - 5s 20ms/step - loss: 0.3417 - accuracy: 0.4973 - mse: 0.0341 - val_loss: 0.3402 - val_accuracy: 0.4972 - val_mse: 0.0341
Epoch 15/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3406 - accuracy: 0.4974 - mse: 0.0338 - val_loss: 0.3421 - val_accuracy: 0.5000 - val_mse: 0.0347
Epoch 16/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3411 - accuracy: 0.4975 - mse: 0.0339 - val_loss: 0.3396 - val_accuracy: 0.4984 - val_mse: 0.0337
Epoch 17/50
232/235 [============================>.] - ETA: 0s - loss: 0.3407 - accuracy: 0.4976 - mse: 0.0338
Epoch 00017: ReduceLROnPlateau reducing learning rate to 6.25000029685907e-05.
235/235 [==============================] - 5s 20ms/step - loss: 0.3408 - accuracy: 0.4976 - mse: 0.0338 - val_loss: 0.3411 - val_accuracy: 0.4972 - val_mse: 0.0343
Epoch 18/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3397 - accuracy: 0.4977 - mse: 0.0335 - val_loss: 0.3381 - val_accuracy: 0.4985 - val_mse: 0.0333
Epoch 19/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3395 - accuracy: 0.4977 - mse: 0.0334 - val_loss: 0.3378 - val_accuracy: 0.4985 - val_mse: 0.0332
Epoch 20/50
232/235 [============================>.] - ETA: 0s - loss: 0.3394 - accuracy: 0.4976 - mse: 0.0334
Epoch 00020: ReduceLROnPlateau reducing learning rate to 3.125000148429535e-05.
235/235 [==============================] - 5s 20ms/step - loss: 0.3393 - accuracy: 0.4976 - mse: 0.0334 - val_loss: 0.3382 - val_accuracy: 0.4988 - val_mse: 0.0333
Epoch 21/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3390 - accuracy: 0.4977 - mse: 0.0333 - val_loss: 0.3375 - val_accuracy: 0.4986 - val_mse: 0.0331
Epoch 22/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3389 - accuracy: 0.4977 - mse: 0.0333 - val_loss: 0.3375 - val_accuracy: 0.4979 - val_mse: 0.0331
Epoch 23/50
232/235 [============================>.] - ETA: 0s - loss: 0.3390 - accuracy: 0.4977 - mse: 0.0333
Epoch 00023: ReduceLROnPlateau reducing learning rate to 1.5625000742147677e-05.
235/235 [==============================] - 5s 20ms/step - loss: 0.3390 - accuracy: 0.4977 - mse: 0.0333 - val_loss: 0.3374 - val_accuracy: 0.4984 - val_mse: 0.0331
Epoch 24/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3387 - accuracy: 0.4978 - mse: 0.0332 - val_loss: 0.3371 - val_accuracy: 0.4987 - val_mse: 0.0330
Epoch 25/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3386 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3371 - val_accuracy: 0.4986 - val_mse: 0.0330
Epoch 26/50
235/235 [==============================] - ETA: 0s - loss: 0.3384 - accuracy: 0.4978 - mse: 0.0331
Epoch 00026: ReduceLROnPlateau reducing learning rate to 7.812500371073838e-06.
235/235 [==============================] - 5s 20ms/step - loss: 0.3384 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3370 - val_accuracy: 0.4981 - val_mse: 0.0330
Epoch 27/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3385 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3370 - val_accuracy: 0.4988 - val_mse: 0.0330
Epoch 28/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3384 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 29/50
232/235 [============================>.] - ETA: 0s - loss: 0.3382 - accuracy: 0.4979 - mse: 0.0331
Epoch 00029: ReduceLROnPlateau reducing learning rate to 3.906250185536919e-06.
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3369 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 30/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3369 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 31/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3369 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 32/50
235/235 [==============================] - ETA: 0s - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0330
Epoch 00032: ReduceLROnPlateau reducing learning rate to 1.9531250927684596e-06.
235/235 [==============================] - 5s 20ms/step - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0330 - val_loss: 0.3369 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 33/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4987 - val_mse: 0.0329
Epoch 34/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4987 - val_mse: 0.0329
Epoch 35/50
232/235 [============================>.] - ETA: 0s - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0331
Epoch 00035: ReduceLROnPlateau reducing learning rate to 9.765625463842298e-07.
235/235 [==============================] - 5s 20ms/step - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 36/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4987 - val_mse: 0.0329
Epoch 37/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0330 - val_loss: 0.3368 - val_accuracy: 0.4987 - val_mse: 0.0329
Epoch 38/50
232/235 [============================>.] - ETA: 0s - loss: 0.3383 - accuracy: 0.4977 - mse: 0.0330
Epoch 00038: ReduceLROnPlateau reducing learning rate to 4.882812731921149e-07.
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 39/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 40/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0330 - val_loss: 0.3368 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 41/50
232/235 [============================>.] - ETA: 0s - loss: 0.3383 - accuracy: 0.4977 - mse: 0.0331
Epoch 00041: ReduceLROnPlateau reducing learning rate to 2.4414063659605745e-07.
235/235 [==============================] - 5s 20ms/step - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4987 - val_mse: 0.0329
Epoch 42/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0330 - val_loss: 0.3368 - val_accuracy: 0.4987 - val_mse: 0.0329
Epoch 43/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 44/50
234/235 [============================>.] - ETA: 0s - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331
Epoch 00044: ReduceLROnPlateau reducing learning rate to 1.2207031829802872e-07.
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4987 - val_mse: 0.0329
Epoch 45/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3385 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4987 - val_mse: 0.0329
Epoch 46/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0330 - val_loss: 0.3368 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 47/50
235/235 [==============================] - ETA: 0s - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0330
Epoch 00047: ReduceLROnPlateau reducing learning rate to 1e-07.
235/235 [==============================] - 5s 20ms/step - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0330 - val_loss: 0.3368 - val_accuracy: 0.4987 - val_mse: 0.0329
Epoch 48/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0331 - val_loss: 0.3368 - val_accuracy: 0.4988 - val_mse: 0.0329
Epoch 49/50
235/235 [==============================] - 5s 20ms/step - loss: 0.3382 - accuracy: 0.4978 - mse: 0.0330 - val_loss: 0.3368 - val_accuracy: 0.4987 - val_mse: 0.0329
Epoch 50/50
232/235 [============================>.] - ETA: 0s - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0330
Epoch 00050: ReduceLROnPlateau reducing learning rate to 1e-07.
235/235 [==============================] - 5s 20ms/step - loss: 0.3383 - accuracy: 0.4978 - mse: 0.0330 - val_loss: 0.3368 - val_accuracy: 0.4988 - val_mse: 0.0329
In [148]:
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA


def plot_latent(mode, count, technique):
    idx = np.random.choice(len(x_test), count)
    inputs = x_test[idx]
    fig, ax = plt.subplots(figsize=(10, 7))
    ax.set_title(technique)
    if technique == 'autoencoder':
        coords = encoder.predict(inputs)
    elif technique == 'pca':
        coords = PCA(n_components=2).fit_transform(inputs.reshape(count, -1))
    elif technique == 'tsne':
        coords = TSNE(n_components=2).fit_transform(inputs.reshape(count, -1))

    if mode == 'imgs':
        for image, (x, y) in zip(inputs, coords):
            im = OffsetImage(image.reshape(28, 28), zoom=1, cmap='gray')
            ab = AnnotationBbox(im, (x, y), xycoords='data', frameon=False)
            ax.add_artist(ab)
        ax.update_datalim(coords)
        ax.autoscale()
    elif mode == 'dots':
        classes = y_test[idx]
        plt.scatter(coords[:, 0], coords[:, 1], c=classes)
        plt.colorbar()
        for i in range(10):
            class_center = np.mean(coords[classes == i], axis=0)
            text = TextArea('{} ({})'.format(labeldict[i], i))
            ab = AnnotationBbox(text, class_center, xycoords='data', frameon=True)
            ax.add_artist(ab)
    plt.show()

plot_latent('dots', 10000, 'autoencoder')
plot_latent('dots', 10000, 'pca')
plot_latent('dots', 2000, 'tsne')

plot_latent('imgs', 300, 'autoencoder')
plot_latent('imgs', 300, 'pca')
plot_latent('imgs', 300, 'tsne')

Acknowledgements

  • Dripta Maharaj