Convolutional Autoencoder

Sticking with the MNIST dataset, let's improve our autoencoder's performance using convolutional layers. Again, loading modules and the data.


In [1]:
%matplotlib inline

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

In [2]:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', validation_size=0)


Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz

In [3]:
img = mnist.train.images[2]
plt.imshow(img.reshape((28, 28)), cmap='Greys_r')


Out[3]:
<matplotlib.image.AxesImage at 0x116c5bb38>

Network Architecture

The encoder part of the network will be a typical convolutional pyramid. Each convolutional layer will be followed by a max-pooling layer to reduce the dimensions of the layers. The decoder though might be something new to you. The decoder needs to convert from a narrow representation to a wide reconstructed image. For example, the representation could be a 4x4x8 max-pool layer. This is the output of the encoder, but also the input to the decoder. We want to get a 28x28x1 image out from the decoder so we need to work our way back up from the narrow decoder input layer. A schematic of the network is shown below.

Here our final encoder layer has size 4x4x8 = 128. The original images have size 28x28 = 784, so the encoded vector is roughly 16% the size of the original image. These are just suggested sizes for each of the layers. Feel free to change the depths and sizes, but remember our goal here is to find a small representation of the input data.

What's going on with the decoder

Okay, so the decoder has these "Upsample" layers that you might not have seen before. First off, I'll discuss a bit what these layers aren't. Usually, you'll see deconvolutional layers used to increase the width and height of the layers. They work almost exactly the same as convolutional layers, but it reverse. A stride in the input layer results in a larger stride in the deconvolutional layer. For example, if you have a 3x3 kernel, a 3x3 patch in the input layer will be reduced to one unit in a convolutional layer. Comparatively, one unit in the input layer will be expanded to a 3x3 path in a deconvolutional layer. Deconvolution is often called "transpose convolution" which is what you'll find with the TensorFlow API, with tf.nn.conv2d_transpose.

However, deconvolutional layers can lead to artifacts in the final images, such as checkerboard patterns. This is due to overlap in the kernels which can be avoided by setting the stride and kernel size equal. In this Distill article from Augustus Odena, et al, the authors show that these checkerboard artifacts can be avoided by resizing the layers using nearest neighbor or bilinear interpolation (upsampling) followed by a convolutional layer. In TensorFlow, this is easily done with tf.image.resize_images, followed by a convolution. Be sure to read the Distill article to get a better understanding of deconvolutional layers and why we're using upsampling.

Exercise: Build the network shown above. Remember that a convolutional layer with strides of 1 and 'same' padding won't reduce the height and width. That is, if the input is 28x28 and the convolution layer has stride = 1 and 'same' padding, the convolutional layer will also be 28x28. The max-pool layers are used the reduce the width and height. A stride of 2 will reduce the size by 2. Odena et al claim that nearest neighbor interpolation works best for the upsampling, so make sure to include that as a parameter in tf.image.resize_images or use tf.image.resize_nearest_neighbor.


In [6]:
learning_rate = 0.001
n_elements = 28*28
inputs_ = tf.placeholder(tf.float32,(None,28,28,1))
targets_ = tf.placeholder(tf.float32,(None,28,28,1))

### Encoder
conv1 = tf.layers.conv2d(inputs_,16,(3,3),padding='same',activation=tf.nn.relu)
# Now 28x28x16
maxpool1 = tf.layers.max_pooling2d(conv1,(2,2),(2,2),padding='same')
# Now 14x14x16
conv2 = tf.layers.conv2d(maxpool1,8,(3,3),padding='same',activation=tf.nn.relu)
# Now 14x14x8
maxpool2 = tf.layers.max_pooling2d(conv2,(2,2),(2,2),padding='same')
# Now 7x7x8
conv3 = tf.layers.conv2d(maxpool2,8,(3,3),padding='same',activation=tf.nn.relu)
# Now 7x7x8
encoded = tf.layers.max_pooling2d(conv2,(2,2),(2,2),padding='same')
# Now 4x4x8

### Decoder
upsample1 = tf.image.resize_images(encoded,(7,7))
# Now 7x7x8
conv4 = tf.layers.conv2d_transpose(upsample1,8,(3,3), padding='same')
# Now 7x7x8
upsample2 = tf.image.resize_images(conv4,(14,14))
# Now 14x14x8
conv5 = tf.layers.conv2d_transpose(upsample2,8,(3,3), padding='same')
# Now 14x14x8
upsample3 = tf.image.resize_images(conv5,(28,28))
# Now 28x28x8
conv6 = tf.layers.conv2d_transpose(upsample3,16,(3,3), padding='same')
# Now 28x28x16

logits = tf.layers.conv2d(conv6,1,(3,3),padding='same')
#Now 28x28x1

# Pass logits through sigmoid to get reconstructed image
decoded = tf.sigmoid(logits)

# Pass logits through sigmoid and calculate the cross-entropy loss
loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=logits,labels=targets_)

# Get cost and define the optimizer
cost = tf.reduce_mean(loss)
opt = tf.train.AdamOptimizer(learning_rate).minimize(cost)

Training

As before, here wi'll train the network. Instead of flattening the images though, we can pass them in as 28x28x1 arrays.


In [7]:
sess = tf.Session()

In [9]:
epochs = 1
batch_size = 200
sess.run(tf.global_variables_initializer())
for e in range(epochs):
    for ii in range(mnist.train.num_examples//batch_size):
        batch = mnist.train.next_batch(batch_size)
        imgs = batch[0].reshape((-1, 28, 28, 1))
        batch_cost, _ = sess.run([cost, opt], feed_dict={inputs_: imgs,
                                                         targets_: imgs})

        print("Epoch: {}/{}...".format(e+1, epochs),
              "Training loss: {:.4f}".format(batch_cost))


Epoch: 1/1... Training loss: 0.6986
Epoch: 1/1... Training loss: 0.6870
Epoch: 1/1... Training loss: 0.6750
Epoch: 1/1... Training loss: 0.6622
Epoch: 1/1... Training loss: 0.6468
Epoch: 1/1... Training loss: 0.6297
Epoch: 1/1... Training loss: 0.6149
Epoch: 1/1... Training loss: 0.6050
Epoch: 1/1... Training loss: 0.5999
Epoch: 1/1... Training loss: 0.5927
Epoch: 1/1... Training loss: 0.5547
Epoch: 1/1... Training loss: 0.5612
Epoch: 1/1... Training loss: 0.5928
Epoch: 1/1... Training loss: 0.5616
Epoch: 1/1... Training loss: 0.5215
Epoch: 1/1... Training loss: 0.5310
Epoch: 1/1... Training loss: 0.5425
Epoch: 1/1... Training loss: 0.5146
Epoch: 1/1... Training loss: 0.5097
Epoch: 1/1... Training loss: 0.5129
Epoch: 1/1... Training loss: 0.5011
Epoch: 1/1... Training loss: 0.4951
Epoch: 1/1... Training loss: 0.4838
Epoch: 1/1... Training loss: 0.4674
Epoch: 1/1... Training loss: 0.4685
Epoch: 1/1... Training loss: 0.4493
Epoch: 1/1... Training loss: 0.4298
Epoch: 1/1... Training loss: 0.4299
Epoch: 1/1... Training loss: 0.4390
Epoch: 1/1... Training loss: 0.4140
Epoch: 1/1... Training loss: 0.4286
Epoch: 1/1... Training loss: 0.3789
Epoch: 1/1... Training loss: 0.3684
Epoch: 1/1... Training loss: 0.3561
Epoch: 1/1... Training loss: 0.3439
Epoch: 1/1... Training loss: 0.3304
Epoch: 1/1... Training loss: 0.3074
Epoch: 1/1... Training loss: 0.2915
Epoch: 1/1... Training loss: 0.2790
Epoch: 1/1... Training loss: 0.2669
Epoch: 1/1... Training loss: 0.2740
Epoch: 1/1... Training loss: 0.2543
Epoch: 1/1... Training loss: 0.2414
Epoch: 1/1... Training loss: 0.2412
Epoch: 1/1... Training loss: 0.2208
Epoch: 1/1... Training loss: 0.2252
Epoch: 1/1... Training loss: 0.2334
Epoch: 1/1... Training loss: 0.2213
Epoch: 1/1... Training loss: 0.2187
Epoch: 1/1... Training loss: 0.2194
Epoch: 1/1... Training loss: 0.2138
Epoch: 1/1... Training loss: 0.2078
Epoch: 1/1... Training loss: 0.2081
Epoch: 1/1... Training loss: 0.2086
Epoch: 1/1... Training loss: 0.1947
Epoch: 1/1... Training loss: 0.1938
Epoch: 1/1... Training loss: 0.1886
Epoch: 1/1... Training loss: 0.1822
Epoch: 1/1... Training loss: 0.1894
Epoch: 1/1... Training loss: 0.1906
Epoch: 1/1... Training loss: 0.1852
Epoch: 1/1... Training loss: 0.1871
Epoch: 1/1... Training loss: 0.1733
Epoch: 1/1... Training loss: 0.1834
Epoch: 1/1... Training loss: 0.1854
Epoch: 1/1... Training loss: 0.1736
Epoch: 1/1... Training loss: 0.1778
Epoch: 1/1... Training loss: 0.1856
Epoch: 1/1... Training loss: 0.1812
Epoch: 1/1... Training loss: 0.1784
Epoch: 1/1... Training loss: 0.1797
Epoch: 1/1... Training loss: 0.1739
Epoch: 1/1... Training loss: 0.1710
Epoch: 1/1... Training loss: 0.1803
Epoch: 1/1... Training loss: 0.1736
Epoch: 1/1... Training loss: 0.1731
Epoch: 1/1... Training loss: 0.1743
Epoch: 1/1... Training loss: 0.1685
Epoch: 1/1... Training loss: 0.1734
Epoch: 1/1... Training loss: 0.1708
Epoch: 1/1... Training loss: 0.1704
Epoch: 1/1... Training loss: 0.1714
Epoch: 1/1... Training loss: 0.1658
Epoch: 1/1... Training loss: 0.1598
Epoch: 1/1... Training loss: 0.1680
Epoch: 1/1... Training loss: 0.1655
Epoch: 1/1... Training loss: 0.1603
Epoch: 1/1... Training loss: 0.1597
Epoch: 1/1... Training loss: 0.1570
Epoch: 1/1... Training loss: 0.1606
Epoch: 1/1... Training loss: 0.1664
Epoch: 1/1... Training loss: 0.1545
Epoch: 1/1... Training loss: 0.1661
Epoch: 1/1... Training loss: 0.1616
Epoch: 1/1... Training loss: 0.1679
Epoch: 1/1... Training loss: 0.1680
Epoch: 1/1... Training loss: 0.1612
Epoch: 1/1... Training loss: 0.1566
Epoch: 1/1... Training loss: 0.1619
Epoch: 1/1... Training loss: 0.1611
Epoch: 1/1... Training loss: 0.1588
Epoch: 1/1... Training loss: 0.1521
Epoch: 1/1... Training loss: 0.1547
Epoch: 1/1... Training loss: 0.1540
Epoch: 1/1... Training loss: 0.1621
Epoch: 1/1... Training loss: 0.1618
Epoch: 1/1... Training loss: 0.1592
Epoch: 1/1... Training loss: 0.1551
Epoch: 1/1... Training loss: 0.1484
Epoch: 1/1... Training loss: 0.1555
Epoch: 1/1... Training loss: 0.1492
Epoch: 1/1... Training loss: 0.1548
Epoch: 1/1... Training loss: 0.1529
Epoch: 1/1... Training loss: 0.1552
Epoch: 1/1... Training loss: 0.1492
Epoch: 1/1... Training loss: 0.1569
Epoch: 1/1... Training loss: 0.1575
Epoch: 1/1... Training loss: 0.1572
Epoch: 1/1... Training loss: 0.1485
Epoch: 1/1... Training loss: 0.1502
Epoch: 1/1... Training loss: 0.1439
Epoch: 1/1... Training loss: 0.1495
Epoch: 1/1... Training loss: 0.1491
Epoch: 1/1... Training loss: 0.1451
Epoch: 1/1... Training loss: 0.1442
Epoch: 1/1... Training loss: 0.1481
Epoch: 1/1... Training loss: 0.1510
Epoch: 1/1... Training loss: 0.1461
Epoch: 1/1... Training loss: 0.1429
Epoch: 1/1... Training loss: 0.1489
Epoch: 1/1... Training loss: 0.1428
Epoch: 1/1... Training loss: 0.1435
Epoch: 1/1... Training loss: 0.1455
Epoch: 1/1... Training loss: 0.1487
Epoch: 1/1... Training loss: 0.1494
Epoch: 1/1... Training loss: 0.1440
Epoch: 1/1... Training loss: 0.1477
Epoch: 1/1... Training loss: 0.1446
Epoch: 1/1... Training loss: 0.1509
Epoch: 1/1... Training loss: 0.1440
Epoch: 1/1... Training loss: 0.1443
Epoch: 1/1... Training loss: 0.1533
Epoch: 1/1... Training loss: 0.1463
Epoch: 1/1... Training loss: 0.1491
Epoch: 1/1... Training loss: 0.1410
Epoch: 1/1... Training loss: 0.1451
Epoch: 1/1... Training loss: 0.1400
Epoch: 1/1... Training loss: 0.1414
Epoch: 1/1... Training loss: 0.1401
Epoch: 1/1... Training loss: 0.1393
Epoch: 1/1... Training loss: 0.1428
Epoch: 1/1... Training loss: 0.1339
Epoch: 1/1... Training loss: 0.1416
Epoch: 1/1... Training loss: 0.1360
Epoch: 1/1... Training loss: 0.1305
Epoch: 1/1... Training loss: 0.1403
Epoch: 1/1... Training loss: 0.1420
Epoch: 1/1... Training loss: 0.1339
Epoch: 1/1... Training loss: 0.1339
Epoch: 1/1... Training loss: 0.1389
Epoch: 1/1... Training loss: 0.1394
Epoch: 1/1... Training loss: 0.1346
Epoch: 1/1... Training loss: 0.1304
Epoch: 1/1... Training loss: 0.1321
Epoch: 1/1... Training loss: 0.1361
Epoch: 1/1... Training loss: 0.1328
Epoch: 1/1... Training loss: 0.1297
Epoch: 1/1... Training loss: 0.1335
Epoch: 1/1... Training loss: 0.1323
Epoch: 1/1... Training loss: 0.1313
Epoch: 1/1... Training loss: 0.1283
Epoch: 1/1... Training loss: 0.1351
Epoch: 1/1... Training loss: 0.1317
Epoch: 1/1... Training loss: 0.1348
Epoch: 1/1... Training loss: 0.1355
Epoch: 1/1... Training loss: 0.1301
Epoch: 1/1... Training loss: 0.1330
Epoch: 1/1... Training loss: 0.1320
Epoch: 1/1... Training loss: 0.1285
Epoch: 1/1... Training loss: 0.1304
Epoch: 1/1... Training loss: 0.1286
Epoch: 1/1... Training loss: 0.1284
Epoch: 1/1... Training loss: 0.1316
Epoch: 1/1... Training loss: 0.1315
Epoch: 1/1... Training loss: 0.1237
Epoch: 1/1... Training loss: 0.1279
Epoch: 1/1... Training loss: 0.1274
Epoch: 1/1... Training loss: 0.1277
Epoch: 1/1... Training loss: 0.1295
Epoch: 1/1... Training loss: 0.1294
Epoch: 1/1... Training loss: 0.1257
Epoch: 1/1... Training loss: 0.1244
Epoch: 1/1... Training loss: 0.1238
Epoch: 1/1... Training loss: 0.1260
Epoch: 1/1... Training loss: 0.1211
Epoch: 1/1... Training loss: 0.1256
Epoch: 1/1... Training loss: 0.1219
Epoch: 1/1... Training loss: 0.1270
Epoch: 1/1... Training loss: 0.1271
Epoch: 1/1... Training loss: 0.1254
Epoch: 1/1... Training loss: 0.1202
Epoch: 1/1... Training loss: 0.1240
Epoch: 1/1... Training loss: 0.1227
Epoch: 1/1... Training loss: 0.1270
Epoch: 1/1... Training loss: 0.1264
Epoch: 1/1... Training loss: 0.1238
Epoch: 1/1... Training loss: 0.1199
Epoch: 1/1... Training loss: 0.1225
Epoch: 1/1... Training loss: 0.1260
Epoch: 1/1... Training loss: 0.1205
Epoch: 1/1... Training loss: 0.1240
Epoch: 1/1... Training loss: 0.1198
Epoch: 1/1... Training loss: 0.1248
Epoch: 1/1... Training loss: 0.1255
Epoch: 1/1... Training loss: 0.1204
Epoch: 1/1... Training loss: 0.1211
Epoch: 1/1... Training loss: 0.1237
Epoch: 1/1... Training loss: 0.1228
Epoch: 1/1... Training loss: 0.1216
Epoch: 1/1... Training loss: 0.1204
Epoch: 1/1... Training loss: 0.1194
Epoch: 1/1... Training loss: 0.1215
Epoch: 1/1... Training loss: 0.1193
Epoch: 1/1... Training loss: 0.1227
Epoch: 1/1... Training loss: 0.1195
Epoch: 1/1... Training loss: 0.1200
Epoch: 1/1... Training loss: 0.1207
Epoch: 1/1... Training loss: 0.1202
Epoch: 1/1... Training loss: 0.1184
Epoch: 1/1... Training loss: 0.1181
Epoch: 1/1... Training loss: 0.1191
Epoch: 1/1... Training loss: 0.1161
Epoch: 1/1... Training loss: 0.1233
Epoch: 1/1... Training loss: 0.1200
Epoch: 1/1... Training loss: 0.1168
Epoch: 1/1... Training loss: 0.1196
Epoch: 1/1... Training loss: 0.1168
Epoch: 1/1... Training loss: 0.1193
Epoch: 1/1... Training loss: 0.1195
Epoch: 1/1... Training loss: 0.1176
Epoch: 1/1... Training loss: 0.1176
Epoch: 1/1... Training loss: 0.1185
Epoch: 1/1... Training loss: 0.1210
Epoch: 1/1... Training loss: 0.1169
Epoch: 1/1... Training loss: 0.1181
Epoch: 1/1... Training loss: 0.1196
Epoch: 1/1... Training loss: 0.1144
Epoch: 1/1... Training loss: 0.1199
Epoch: 1/1... Training loss: 0.1223
Epoch: 1/1... Training loss: 0.1172
Epoch: 1/1... Training loss: 0.1176
Epoch: 1/1... Training loss: 0.1178
Epoch: 1/1... Training loss: 0.1189
Epoch: 1/1... Training loss: 0.1152
Epoch: 1/1... Training loss: 0.1176
Epoch: 1/1... Training loss: 0.1150
Epoch: 1/1... Training loss: 0.1187
Epoch: 1/1... Training loss: 0.1121
Epoch: 1/1... Training loss: 0.1152
Epoch: 1/1... Training loss: 0.1152
Epoch: 1/1... Training loss: 0.1117
Epoch: 1/1... Training loss: 0.1177
Epoch: 1/1... Training loss: 0.1130
Epoch: 1/1... Training loss: 0.1129
Epoch: 1/1... Training loss: 0.1100
Epoch: 1/1... Training loss: 0.1149
Epoch: 1/1... Training loss: 0.1134
Epoch: 1/1... Training loss: 0.1178
Epoch: 1/1... Training loss: 0.1112
Epoch: 1/1... Training loss: 0.1134
Epoch: 1/1... Training loss: 0.1155
Epoch: 1/1... Training loss: 0.1101
Epoch: 1/1... Training loss: 0.1140
Epoch: 1/1... Training loss: 0.1162
Epoch: 1/1... Training loss: 0.1115
Epoch: 1/1... Training loss: 0.1130
Epoch: 1/1... Training loss: 0.1145
Epoch: 1/1... Training loss: 0.1157
Epoch: 1/1... Training loss: 0.1112
Epoch: 1/1... Training loss: 0.1125
Epoch: 1/1... Training loss: 0.1108
Epoch: 1/1... Training loss: 0.1158
Epoch: 1/1... Training loss: 0.1160
Epoch: 1/1... Training loss: 0.1146
Epoch: 1/1... Training loss: 0.1153
Epoch: 1/1... Training loss: 0.1116
Epoch: 1/1... Training loss: 0.1176
Epoch: 1/1... Training loss: 0.1153
Epoch: 1/1... Training loss: 0.1134
Epoch: 1/1... Training loss: 0.1135
Epoch: 1/1... Training loss: 0.1134
Epoch: 1/1... Training loss: 0.1117
Epoch: 1/1... Training loss: 0.1118
Epoch: 1/1... Training loss: 0.1162
Epoch: 1/1... Training loss: 0.1107
Epoch: 1/1... Training loss: 0.1101
Epoch: 1/1... Training loss: 0.1112
Epoch: 1/1... Training loss: 0.1103
Epoch: 1/1... Training loss: 0.1134
Epoch: 1/1... Training loss: 0.1144

In [13]:
fig, axes = plt.subplots(nrows=2, ncols=10, sharex=True, sharey=True, figsize=(20,4))
in_imgs = mnist.test.images[:10]
reconstructed = sess.run(decoded, feed_dict={inputs_: in_imgs.reshape((10, 28, 28, 1))})

for images, row in zip([in_imgs, reconstructed], 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)


fig.tight_layout(pad=0.1)



In [19]:
sess.close()

Denoising

As I've mentioned before, autoencoders like the ones you've built so far aren't too useful in practive. However, they can be used to denoise images quite successfully just by training the network on noisy images. We can create the noisy images ourselves by adding Gaussian noise to the training images, then clipping the values to be between 0 and 1. We'll use noisy images as input and the original, clean images as targets. Here's an example of the noisy images I generated and the denoised images.

Since this is a harder problem for the network, we'll want to use deeper convolutional layers here, more feature maps. I suggest something like 32-32-16 for the depths of the convolutional layers in the encoder, and the same depths going backward through the decoder. Otherwise the architecture is the same as before.

Exercise: Build the network for the denoising autoencoder. It's the same as before, but with deeper layers. I suggest 32-32-16 for the depths, but you can play with these numbers, or add more layers.


In [21]:
learning_rate = 0.001
inputs_ = tf.placeholder(tf.float32, (None, 28, 28, 1), name='inputs')
targets_ = tf.placeholder(tf.float32, (None, 28, 28, 1), name='targets')

### Encoder
conv1 = 
# Now 28x28x32
maxpool1 = 
# Now 14x14x32
conv2 = 
# Now 14x14x32
maxpool2 = 
# Now 7x7x32
conv3 = 
# Now 7x7x16
encoded = 
# Now 4x4x16

### Decoder
upsample1 = 
# Now 7x7x16
conv4 = 
# Now 7x7x16
upsample2 = 
# Now 14x14x16
conv5 = 
# Now 14x14x32
upsample3 = 
# Now 28x28x32
conv6 = 
# Now 28x28x32

logits = 
#Now 28x28x1

# Pass logits through sigmoid to get reconstructed image
decoded =

# Pass logits through sigmoid and calculate the cross-entropy loss
loss = 

# Get cost and define the optimizer
cost = tf.reduce_mean(loss)
opt = tf.train.AdamOptimizer(learning_rate).minimize(cost)

In [22]:
sess = tf.Session()

In [ ]:
epochs = 100
batch_size = 200
# Set's how much noise we're adding to the MNIST images
noise_factor = 0.5
sess.run(tf.global_variables_initializer())
for e in range(epochs):
    for ii in range(mnist.train.num_examples//batch_size):
        batch = mnist.train.next_batch(batch_size)
        # Get images from the batch
        imgs = batch[0].reshape((-1, 28, 28, 1))
        
        # Add random noise to the input images
        noisy_imgs = imgs + noise_factor * np.random.randn(*imgs.shape)
        # Clip the images to be between 0 and 1
        noisy_imgs = np.clip(noisy_imgs, 0., 1.)
        
        # Noisy images as inputs, original images as targets
        batch_cost, _ = sess.run([cost, opt], feed_dict={inputs_: noisy_imgs,
                                                         targets_: imgs})

        print("Epoch: {}/{}...".format(e+1, epochs),
              "Training loss: {:.4f}".format(batch_cost))

Checking out the performance

Here I'm adding noise to the test images and passing them through the autoencoder. It does a suprisingly great job of removing the noise, even though it's sometimes difficult to tell what the original number is.


In [29]:
fig, axes = plt.subplots(nrows=2, ncols=10, sharex=True, sharey=True, figsize=(20,4))
in_imgs = mnist.test.images[:10]
noisy_imgs = in_imgs + noise_factor * np.random.randn(*in_imgs.shape)
noisy_imgs = np.clip(noisy_imgs, 0., 1.)

reconstructed = sess.run(decoded, feed_dict={inputs_: noisy_imgs.reshape((10, 28, 28, 1))})

for images, row in zip([noisy_imgs, reconstructed], 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)

fig.tight_layout(pad=0.1)