Auto-Encoders are well known in dimensionality reduction and information retrieval. These are a special type of neural network architectures in which the output is same as the input. Autoencoders are trained in an unsupervised manner in order to learn the exteremely low level repersentations of the input data. These low level features are then deformed back to project the actual data
In this project, the objective is to reduce the noise in the images. Basically, it will take the noisy images as input and tries to reconstruct the images without noise. The plan will be load the data, apply noise factor into them and then apply the Auto-Encoder.
Differently from sparse autoencoders or undercomplete autoencoders that constrain representation, Denoising autoencoders (DAE) try to achieve a good representation by changing the reconstruction criterion.
Indeed, DAEs take a partially corrupted input and are trained to recover the original undistorted input. In practice, the objective of denoising autoencoders is that of cleaning the corrupted input, or denoising. Two underlying assumptions are inherent to this approach:
Higher level representations are relatively stable and robust to the corruption of the input; To perform denoising well, the model needs to extract features that capture useful structure in the distribution of the input.
In other words, denoising is advocated as a training criterion for learning to extract useful features that will constitute better higher level representations of the input.
Source: Wikipedia
# Import libraries
import tensorflow as tf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import random
# Load dataset
(X_train, y_train), (X_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()
# Check sample image
plt.imshow(X_train[0], cmap = 'gray')
plt.show()
# Check shape of the training data
X_train.shape, y_train.shape
# Check shape of the testing data
X_test.shape, y_test.shape
# Generate random number
i = random.randint(1,60000)
# Show random image
plt.imshow(X_train[i])
plt.show()
# Define the dimension of the plot grid
W_grid = 15
L_grid = 15
# Create subplots
fig, axes = plt.subplots(L_grid, W_grid, figsize = (17,17))
# Flaten the 15x15 matrix into 225 array
axes = axes.ravel()
# Get the length of the training dataset
n_training = len(X_train)
# Select a number from 0 to the number of training dataset
for i in np.arange(0, W_grid * L_grid):
index = np.random.randint(0, n_training)
axes[i].imshow(X_train[index])
axes[i].set_title(y_train[index], fontsize = 8)
axes[i].axis('off')
# Normalize the data
X_train = X_train/255
X_test = X_test/255
# Noise factor magnitude
noise_factor = 0.3
# Create empty label for training data
noise_dataset = []
# Add some noise
for img in X_train:
noisy_image = img + noise_factor * np.random.randn(*img.shape)
# Clip the image from range 0 to 1
noisy_image = np.clip(noisy_image, 0, 1)
noise_dataset.append(noisy_image)
# Show image
plt.imshow(noise_dataset[10], cmap = 'gray')
plt.show()
# Convert into array form
noise_dataset = np.array(noise_dataset)
# Noise factor magnitude
noise_factor = 0.1
# Create empty label for testing data
noise_test_dataset = []
# Add some noise
for img in X_test:
noisy_image = img + noise_factor * np.random.randn(*img.shape)
# Clip the image from range 0 to 1
noisy_image = np.clip(noisy_image, 0, 1)
noise_test_dataset.append(noisy_image)
# Show image
plt.imshow(noise_test_dataset[10], cmap = 'gray')
plt.show()
# Convert into array form
noise_test_dataset = np.array(noise_test_dataset)
# Build And Train Model
autoencoder = tf.keras.models.Sequential()
# first Encoder layer
autoencoder.add(tf.keras.layers.Conv2D(filters = 16, kernel_size = 3, strides = 2, padding = 'same', input_shape = (28, 28, 1)))
# Second Encoder layer
autoencoder.add(tf.keras.layers.Conv2D(filters = 8, kernel_size = 3, strides = 2, padding = 'same'))
# Third Encoder layer
autoencoder.add(tf.keras.layers.Conv2D(filters = 8, kernel_size = 3, strides = 1, padding = 'same'))
# First Decode layer
autoencoder.add(tf.keras.layers.Conv2DTranspose(filters = 16, kernel_size = 3, strides = 2, padding = 'same'))
# Second Decode layer
autoencoder.add(tf.keras.layers.Conv2DTranspose(filters = 1, kernel_size = 3, strides = 2, activation = 'sigmoid', padding = 'same'))
# Compile model
autoencoder.compile(loss = 'binary_crossentropy', optimizer = tf.keras.optimizers.Adam(lr = 0.001))
# Check summary
autoencoder.summary()
# Check train dataset dimension
noise_dataset.reshape(-1, 28, 28, 1).shape, X_train.reshape(-1, 28, 28, 1).shape
# Check test dataset dimension
noise_test_dataset.reshape(-1, 28, 28, 1).shape, X_test.reshape(-1, 28, 28, 1).shape
# Fit the model
autoencoder.fit(noise_dataset.reshape(-1, 28, 28, 1), X_train.reshape(-1, 28, 28, 1), epochs = 10, batch_size = 200, validation_data = (noise_test_dataset.reshape(-1, 28, 28, 1), X_test.reshape(-1, 28, 28, 1)))
# Evaualate model
evaluation = autoencoder.evaluate(noise_test_dataset.reshape(-1, 28, 28, 1), X_test.reshape(-1, 28, 28, 1))
# Check test accuracy
print('Test Accuracy : {:.3f}'.format(evaluation))
# Store prediction
predicted = autoencoder.predict(noise_test_dataset[:10].reshape(-1, 28, 28, 1))
fig, axes = plt.subplots(nrows = 2, ncols = 10, sharex = True, sharey = True, figsize = (20, 4))
for images, row in zip([noise_test_dataset[:10], predicted], axes):
for img, ax in zip(images, row):
ax.imshow(img.reshape((28, 28)), cmap = 'Greys_r')
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
The first row is the original image and the second row is the auto-encoder's prediction. The auto-encoder was able to remove the noise in the image but it can also be observed that the image's resolution became a little bit distorted. It is because of the encoding phase. It is like compressing the image and then reconstructing it again.This can be further improve by changing the model architecture and tuning some parameters.