{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"ex6 - autoencoder.ipynb","provenance":[],"collapsed_sections":[],"toc_visible":true},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["## Autoencoder\n","\n","

\n"," \n","

\n","\n","\"Autoencoding\" is a data compression algorithm where the compression and decompression functions are 1) data-specific, 2) lossy, and 3) learned automatically from examples rather than engineered by a human. Additionally, in almost all contexts where the term \"autoencoder\" is used, the compression and decompression functions are implemented with neural networks.\n","\n","1) Autoencoders are data-specific, which means that they will only be able to compress data similar to what they have been trained on. This is different from, say, the MPEG-2 Audio Layer III (MP3) compression algorithm, which only holds assumptions about \"sound\" in general, but not about specific types of sounds. An autoencoder trained on pictures of faces would do a rather poor job of compressing pictures of trees, because the features it would learn would be face-specific.\n","\n","2) Autoencoders are lossy, which means that the decompressed outputs will be degraded compared to the original inputs (similar to MP3 or JPEG compression). This differs from lossless arithmetic compression.\n","\n","3) Autoencoders are learned automatically from data examples, which is a useful property: it means that it is easy to train specialized instances of the algorithm that will perform well on a specific type of input. It doesn't require any new engineering, just appropriate training data.\n","\n","To build an autoencoder, you need three things: an encoding function, a decoding function, and a distance function between the amount of information loss between the compressed representation of your data and the decompressed representation (i.e. a \"loss\" function). The encoder and decoder will be chosen to be parametric functions (typically neural networks), and to be differentiable with respect to the distance function, so the parameters of the encoding/decoding functions can be optimize to minimize the reconstruction loss, using Stochastic Gradient Descent. It's simple! And you don't even need to understand any of these words to start using autoencoders in practice.\n","\n","A more detailed illustration is below\n","\n","

\n"," \n","

\n","\n","The loss function to train such a neural network is the following\n","$$\\mathcal{L}(\\theta, \\phi) = \\frac{1}{n} \\sum_{i=1}^n (x_i - f_{\\theta}(g_{\\phi}(x_i)))^2$$\n","\n","As seen above, the loss function depends on $\\theta$ and $\\phi$ which are the parameters that define the encoder and the decoder. From the autoencoder image above, the encoder is represented by $G_{\\phi}$, while the decoder is represented by $f_{\\theta}$ and they simply mean the weights and bias of the neural network. So in the equation, we are summing up the difference between the original image, $x$, and the reconstructed image $f_{\\theta}(g_{\\phi}(x'))$.\n","\n","\n","The original paper is [here](https://arxiv.org/abs/1312.6114).\n","\n","\n"],"metadata":{"id":"iGhCxXl5o-ja"}},{"cell_type":"markdown","source":["### Setup\n","\n","We'll start simple, with a single fully-connected neural layer as encoder and as decoder:"],"metadata":{"id":"0BJO-ehH00As"}},{"cell_type":"markdown","source":["### Encoder"],"metadata":{"id":"P3RSyGCFmRD0"}},{"cell_type":"code","execution_count":null,"metadata":{"id":"w7hyJnu60USA"},"outputs":[],"source":["# import\n","import keras\n","from keras import layers\n","\n","# This is the size of our encoded representations\n","encoding_dim = 32 # 32 floats -> compression of factor 24.5, assuming the input is 784 floats\n","\n","# This is our input image\n","input_img = keras.Input(shape=(784,))\n","# \"encoded\" is the encoded representation of the input\n","encoded = layers.Dense(encoding_dim, activation='relu')(input_img)\n","# \"decoded\" is the lossy reconstruction of the input\n","decoded = layers.Dense(784, activation='sigmoid')(encoded)\n","\n","# This model maps an input to its reconstruction\n","autoencoder = keras.Model(input_img, decoded)"]},{"cell_type":"markdown","source":["Let's also create a separate encoder model:"],"metadata":{"id":"w4yjtNJq01uQ"}},{"cell_type":"code","source":["# This model maps an input to its encoded representation\n","encoder = keras.Model(input_img, encoded)"],"metadata":{"id":"7VaRBrMF0jqL"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Decoder\n","\n","As well as the decoder model:"],"metadata":{"id":"BzxN6brP03Q2"}},{"cell_type":"code","source":["# This is our encoded (32-dimensional) input\n","encoded_input = keras.Input(shape=(encoding_dim,))\n","# Retrieve the last layer of the autoencoder model\n","decoder_layer = autoencoder.layers[-1]\n","# Create the decoder model\n","decoder = keras.Model(encoded_input, decoder_layer(encoded_input))"],"metadata":{"id":"sdBJPGHI0kIj"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Now let's train our autoencoder to reconstruct MNIST digits.\n","\n","First, we'll configure our model to use a per-pixel binary crossentropy loss, and the Adam optimizer:"],"metadata":{"id":"YiOx-Qtr05Fj"}},{"cell_type":"code","source":["# configure\n","autoencoder.compile(optimizer='adam', loss='binary_crossentropy')"],"metadata":{"id":"O6hXTm7q0lZr"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Let's prepare our input data. We're using MNIST digits, and we're discarding the labels (since we're only interested in encoding/decoding the input images)."],"metadata":{"id":"V2EjeX1v06r4"}},{"cell_type":"code","source":["# data\n","from keras.datasets import mnist\n","import numpy as np\n","(x_train, _), (x_test, _) = mnist.load_data()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"chD4cZ6q0mzq","executionInfo":{"status":"ok","timestamp":1655991591052,"user_tz":240,"elapsed":1177,"user":{"displayName":"Yiqiao Yin","userId":"17143243938280119775"}},"outputId":"89c94647-d3c7-40b3-8bc1-092044332202"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz\n","11493376/11490434 [==============================] - 0s 0us/step\n","11501568/11490434 [==============================] - 0s 0us/step\n"]}]},{"cell_type":"markdown","source":["### Rescale\n","\n","We will normalize all values between 0 and 1 and we will flatten the 28x28 images into vectors of size 784."],"metadata":{"id":"WSoOnASB08RV"}},{"cell_type":"code","source":["# process and normalize\n","x_train = x_train.astype('float32') / 255.\n","x_test = x_test.astype('float32') / 255.\n","x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:])))\n","x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:])))\n","print(x_train.shape)\n","print(x_test.shape)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"zZUHQNHE0oPS","executionInfo":{"status":"ok","timestamp":1655991591052,"user_tz":240,"elapsed":5,"user":{"displayName":"Yiqiao Yin","userId":"17143243938280119775"}},"outputId":"5ccc534e-76f6-4b37-a08f-6c93e6c8307e"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["(60000, 784)\n","(10000, 784)\n"]}]},{"cell_type":"markdown","source":["### Train"],"metadata":{"id":"sl5auPekmbf0"}},{"cell_type":"code","source":["# model\n","autoencoder.fit(x_train, x_train,\n"," epochs=50,\n"," batch_size=256,\n"," shuffle=True,\n"," validation_data=(x_test, x_test))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"rpKoyIGA0qPe","executionInfo":{"status":"ok","timestamp":1655991694931,"user_tz":240,"elapsed":103882,"user":{"displayName":"Yiqiao Yin","userId":"17143243938280119775"}},"outputId":"0e8f0886-787f-4d93-e414-e8f2f209eb9d"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Epoch 1/50\n","235/235 [==============================] - 4s 15ms/step - loss: 0.2766 - val_loss: 0.1889\n","Epoch 2/50\n","235/235 [==============================] - 3s 14ms/step - loss: 0.1703 - val_loss: 0.1534\n","Epoch 3/50\n","235/235 [==============================] - 3s 13ms/step - loss: 0.1441 - val_loss: 0.1334\n","Epoch 4/50\n","235/235 [==============================] - 2s 9ms/step - loss: 0.1282 - val_loss: 0.1210\n","Epoch 5/50\n","235/235 [==============================] - 2s 9ms/step - loss: 0.1182 - val_loss: 0.1128\n","Epoch 6/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.1112 - val_loss: 0.1071\n","Epoch 7/50\n","235/235 [==============================] - 2s 9ms/step - loss: 0.1061 - val_loss: 0.1026\n","Epoch 8/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.1023 - val_loss: 0.0995\n","Epoch 9/50\n","235/235 [==============================] - 2s 10ms/step - loss: 0.0995 - val_loss: 0.0971\n","Epoch 10/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0976 - val_loss: 0.0955\n","Epoch 11/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0962 - val_loss: 0.0945\n","Epoch 12/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0954 - val_loss: 0.0939\n","Epoch 13/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0948 - val_loss: 0.0933\n","Epoch 14/50\n","235/235 [==============================] - 2s 9ms/step - loss: 0.0944 - val_loss: 0.0931\n","Epoch 15/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0942 - val_loss: 0.0928\n","Epoch 16/50\n","235/235 [==============================] - 2s 9ms/step - loss: 0.0940 - val_loss: 0.0927\n","Epoch 17/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0938 - val_loss: 0.0924\n","Epoch 18/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0937 - val_loss: 0.0923\n","Epoch 19/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0935 - val_loss: 0.0923\n","Epoch 20/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0934 - val_loss: 0.0922\n","Epoch 21/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0934 - val_loss: 0.0921\n","Epoch 22/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0933 - val_loss: 0.0921\n","Epoch 23/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0932 - val_loss: 0.0920\n","Epoch 24/50\n","235/235 [==============================] - 2s 9ms/step - loss: 0.0932 - val_loss: 0.0920\n","Epoch 25/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0931 - val_loss: 0.0919\n","Epoch 26/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0931 - val_loss: 0.0920\n","Epoch 27/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0931 - val_loss: 0.0919\n","Epoch 28/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0930 - val_loss: 0.0919\n","Epoch 29/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0930 - val_loss: 0.0919\n","Epoch 30/50\n","235/235 [==============================] - 2s 9ms/step - loss: 0.0930 - val_loss: 0.0918\n","Epoch 31/50\n","235/235 [==============================] - 2s 9ms/step - loss: 0.0929 - val_loss: 0.0917\n","Epoch 32/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0929 - val_loss: 0.0917\n","Epoch 33/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0929 - val_loss: 0.0917\n","Epoch 34/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0929 - val_loss: 0.0917\n","Epoch 35/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0928 - val_loss: 0.0918\n","Epoch 36/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0928 - val_loss: 0.0917\n","Epoch 37/50\n","235/235 [==============================] - 2s 9ms/step - loss: 0.0928 - val_loss: 0.0917\n","Epoch 38/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0928 - val_loss: 0.0917\n","Epoch 39/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0928 - val_loss: 0.0917\n","Epoch 40/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0927 - val_loss: 0.0916\n","Epoch 41/50\n","235/235 [==============================] - 2s 10ms/step - loss: 0.0927 - val_loss: 0.0917\n","Epoch 42/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0927 - val_loss: 0.0916\n","Epoch 43/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0927 - val_loss: 0.0916\n","Epoch 44/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0927 - val_loss: 0.0916\n","Epoch 45/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0927 - val_loss: 0.0916\n","Epoch 46/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0927 - val_loss: 0.0916\n","Epoch 47/50\n","235/235 [==============================] - 2s 9ms/step - loss: 0.0926 - val_loss: 0.0916\n","Epoch 48/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0926 - val_loss: 0.0915\n","Epoch 49/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0926 - val_loss: 0.0915\n","Epoch 50/50\n","235/235 [==============================] - 2s 8ms/step - loss: 0.0926 - val_loss: 0.0916\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":7}]},{"cell_type":"code","source":["# Encode and decode some digits\n","# Note that we take them from the *test* set\n","encoded_imgs = encoder.predict(x_test)\n","decoded_imgs = decoder.predict(encoded_imgs)"],"metadata":{"id":"TUhxIQ0n0seA"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# Use Matplotlib (don't ask)\n","import matplotlib.pyplot as plt\n","\n","n = 10 # How many digits we will display\n","plt.figure(figsize=(20, 4))\n","for i in range(n):\n"," # Display original\n"," ax = plt.subplot(2, n, i + 1)\n"," plt.imshow(x_test[i].reshape(28, 28))\n"," plt.gray()\n"," ax.get_xaxis().set_visible(False)\n"," ax.get_yaxis().set_visible(False)\n","\n"," # Display reconstruction\n"," ax = plt.subplot(2, n, i + 1 + n)\n"," plt.imshow(decoded_imgs[i].reshape(28, 28))\n"," plt.gray()\n"," ax.get_xaxis().set_visible(False)\n"," ax.get_yaxis().set_visible(False)\n","plt.show()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"822iBWbp0wEs","executionInfo":{"status":"ok","timestamp":1655991697069,"user_tz":240,"elapsed":13,"user":{"displayName":"Yiqiao Yin","userId":"17143243938280119775"}},"outputId":"463d581d-d245-4af8-9a74-faa93088fe24"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAABG0AAADnCAYAAACkCqtqAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3dZ7wURdbH8WJVFBMIAio5mBFRUFHRFcUEmHFFMWEOa3oQc467sLJrQMKaMwZUUNBVFF2zAoIg4IIECZJFUcR0nxf78ey/DneGucPM3L4zv++r01bdmWZ6qrunrVOnWllZWQAAAAAAAECy/KGydwAAAAAAAACr46ENAAAAAABAAvHQBgAAAAAAIIF4aAMAAAAAAJBAPLQBAAAAAABIIB7aAAAAAAAAJNC6FelcrVo16oNXkrKysmq5eB2OYaVaXFZWVjcXL8RxrDyMxaLAWCwCjMWiwFgsAozFosBYLAKMxaJQ7lhkpg1QOLMqewcAhBAYi0BSMBaBZGAsAslQ7ljkoQ0AAAAAAEAC8dAGAAAAAAAggXhoAwAAAAAAkEA8tAEAAAAAAEggHtoAAAAAAAAkEA9tAAAAAAAAEoiHNgAAAAAAAAnEQxsAAAAAAIAEWreydwCl6dJLL7W4Ro0aUVvr1q0t7tatW8rXGDBggMXvv/9+1Pboo4+u7S4CAAAAAFCpmGkDAAAAAACQQDy0AQAAAAAASCAe2gAAAAAAACQQa9qgYIYMGWJxurVq1G+//Zay7eyzz7a4U6dOUdtbb71l8ezZszPdRVSybbbZJtqeMmWKxRdddJHFd999d8H2qZRttNFGFvft29diHXshhDBmzBiLjz322Kht1qxZedo7AACAyrHZZptZ3Lhx44z+xt8TXXLJJRZPnDjR4i+++CLqN378+Gx2EUWEmTYAAAAAAAAJxEMbAAAAAACABCI9Cnmj6VAhZJ4SpSkxr776qsXNmzeP+h122GEWt2jRImrr0aOHxbfffntG74vKt8suu0Tbmh43Z86cQu9Oydtyyy0tPvPMMy32aYtt27a1uGvXrlFb//7987R3ULvuuqvFQ4cOjdqaNm2at/c96KCDou3Jkydb/NVXX+XtfbFmeo0MIYRhw4ZZ/Oc//9nigQMHRv1+/fXX/O5YEapXr57FTz/9tMXvvfde1G/w4MEWz5w5M+/79buaNWtG2/vuu6/Fr7zyisU///xzwfYJqAq6dOli8eGHHx617bfffha3bNkyo9fzaU9NmjSxeP3110/5d+uss05Gr4/ixUwbAAAAAACABOKhDQAAAAAAQAKRHoWcateuncVHHXVUyn6TJk2y2E83XLx4scUrVqywuHr16lG/Dz74wOKdd945aqtTp06Ge4wkadOmTbT9/fffW/z8888XendKTt26daPthx9+uJL2BBV18MEHW5xuinWu+RSc0047zeLu3bsXbD/wX3rtu/fee1P2u+eeeyx+4IEHoraVK1fmfseKjFaNCSG+p9FUpAULFkT9KislSiv8hRCf6zW9ddq0afnfsSpm0003jbY15b5Vq1YW+yqmpJolmy6rcP7551usqeAhhFCjRg2Lq1Wrttbv66ukAplipg0AAAAAAEAC8dAGAAAAAAAggXhoAwAAAAAAkECVuqaNLwGteYTz5s2L2n788UeLH3/8cYu//vrrqB/5uJVLSwT73E/N+db1F+bPn5/Ra/fq1Sva3mGHHVL2ffnllzN6TVQ+zQnXMrQhhPDoo48WendKzoUXXmjxkUceGbXtvvvuFX49LSUbQgh/+MP//t/A+PHjLX777bcr/NqIrbvu/y7hnTt3rpR98Gtl/N///Z/FG220UdSma1QhP3T8NWzYMGW/J5980mK9v0Jqm2++ucVDhgyJ2mrXrm2xriV0wQUX5H/HUrjmmmssbtasWdR29tlnW8x98+p69Ohh8a233hq1NWrUqNy/8WvfLFmyJPc7hpzR8+NFF12U1/eaMmWKxfpbCLmjJdf1XB1CvMaqlmkPIYTffvvN4oEDB1r87rvvRv2ScJ5kpg0AAAAAAEAC8dAGAAAAAAAggSo1PapPnz7RdtOmTTP6O53W+d1330VthZx2NmfOHIv9v+WTTz4p2H4kyfDhwy3WqWohxMdq6dKlFX5tXz52vfXWq/BrIHm22247i306hZ+Cjtz7+9//brFOE83W0UcfnXJ71qxZFh933HFRP59mgzXr2LGjxXvuuafF/nqUT770saatbrjhhlEb6VG558u7X3311Rn9naaelpWV5XSfitWuu+5qsZ9ir2666aYC7M3qdtxxx2hbU8qff/75qI1r6+o0XeYf//iHxXXq1In6pRovd999d7St6d7Z3PMiMz4VRlOdNMXllVdeifqtWrXK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H1OlOOo537f583emqSGM58z5NAE9n3br1i1q22233SwePny4xaNGjYr6abop/kfHVe3ataM2HX8bbLCBxYsXL476LV261OLvv//eYn9uzOZexX8XNF190003Tfl3en7Q0sQhMBZDSJ+Ko3LxWaV7DX/+13OtHjc/fovxupvrY6Jj24+VAw880OJzzz03att1110t1nHvr8F6fPw54b333rP4/vvvt3jSpElRP71281umNDHTBgAAAAAAIIF4aAMAAAAAAJBAlZoe5aeP6TRrrRoTQrxquk7p/uGHH6J+fmpnofipeqUypdT/uzfaaFAyT3QAACAASURBVCOLfdrT+PHjLR45cqTFL730UtTv888/L/c1dtppp6jf5ZdfbvHmm28etel3pFSORVXhp3XqMdZKUiHEx3H27Nnl/vcQOMa54sdY9+7dLdZj48/dmqZzzDHHRG0jRoywWNMBkBk9x+r06xDitLS99trLYn9dfPXVVy3W1MJsq0elSxPRqeWaChJCCMuWLbM4XYUT3a9iG9v+mplqmn+m09/932+77bYW33jjjVGbpjXqcXr77bejfqRH/Zc/zzVt2tRiraYXQggNGza0ePLkyRb7+xufGvE7X5VGj2u6car9fHqrVrBp165d1KbVGEePHm3x8uXLy92/UqPH3v8e0eqJOlZ8FdNc3IdqapP/Huj1QF/fp6wW4/lU/03pUqW0zY9n/b3SpUsXi2+77baon6bp+wpeqao2pqsC5qtvdu7c2WKtQPXpp59G/S666CKLNe0ca6bHyacZ6pjQ8ebTCpMwdphpAwAAAAAAkEA8tAEAAAAAAEggHtoAAAAAAAAkUF7WtPG5fJpLpjnV2223XdRv7733tlhzh0OISxfOnz/f4jFjxkT9vvjiC4u11LPPRdNcUJ8HrLn2mofo19vQMom+BPG3335rsebFJSEnLpd87mzjxo0t1s8nhBAefPBBi7UssF9/IRX/Ge+8884W16tXL2o79dRTLe7Vq5fF+S59WAprG6XKH87235qqbHEIIYwbN87iuXPnWpxuPQxUTP369S0eOHBg1Ka53Klyt0OIc4S1PGYIIVxyySUW33vvvRb78wMlLMun482Pj+OOO87ibbbZxmJdRyiEeOxoGe5cnJ/8Pu24444W6/gNIT7m+t5+P4rtvKnHMN39US7KPB9//PEW6/j1ffW+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p926dWuLv/nmG4v92jd6PtRj6r8zun3EEUdEbbrmhq5p89JLL0X9cl16PMn0HJqubG826xv412vZsqXFO+20U7n7EEKcW69xCKV7bsyWPx/q+hjnnntu1KbrKejx9q+h66josfNr2my11VYW67U0hBAWL15s8TXXXGMx96Rrpp+5L+97yCGHWKxrW9arVy/qp+drPd/59Wg+//xzi/2x0fc6+OCDLX744Yejfo8//njK1yhGet7bY489LPbnOd3295Q6Jq644gqLlyxZEvXTdXKOOeYYi/0aRkOHDrVYfxP6/fjuu+8s1jEaQumucaPru/jx0atXL4sPPfTQqE2PgY5TXzZc1y/Sc7C/v9Rtf23VY6PrWl177bVRv+eff95if0+dz3VsFDNtAAAAAAAAEoiHNgAAAAAAAAlUZUp+67TtVFMTQ0g9/den6nTv3t3iU089NWrT6at9+/a1eOHChZnvMKLp3CGEsO+++1qsx1PToUII4eyzz7ZYy6pXZPpZPqeB57pUdiHpvueidLK+hk+10BKo2267bcr30jLT2ZbDxepThDXNxqcXzZw50+J0U65TpdL4866OTT/1VFOizjrrLIt9qo8eey1bvKZ9LAY6PXfGjBlRm5bQ3nHHHaO2448/3uLOnTtb7D8vPcdqatPcuXOjfvp35513XtS20UYbWaxTg3VKeAjJPwfmi46PbKfCp5vyf/jhh1vsU+iUTt/3aXKoGP9d1vOev2/x2xXly4trWpWms4YQl3KfMmWKxZmWNE6nlMbvhhtuGG3vsssuFmt6mr+30XPe7bffbvGTTz6Z8vWPPvroqK1jx44W16xZ02JdOiCEED788EOLJ02aFLUV47HS7+n8+fMt9tc0/Wz9b4MddtjB4v79+1usS1+EEEKzZs0s1uubp6lyb7/9dtSm41TH4p133hn18/c0pULPSf4+VNN3Bw8eHLXdd999Fuu9oqZAhRCXCj/hhBMsPuWUU6J+mlblvy96P6z3UdOnT4/6FSoFKh1m2gAAAAAAACQQD20AAAAAAAASiIc2AAAAAAAACVRl1rTRXDJdcybTnE7NTw0hhN69e1vsy/lpCdNPPvmk3H1A+TT38Oqrr47aateubbHmp2rOaQghjBw50uJMP3Ofr52LXF9dm0NLzvkykbpugM+7rSo5x34/M91v7efXMmnVqpXFmn/sy/7N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\n"},"metadata":{"needs_background":"light"}}]},{"cell_type":"markdown","source":["## Deep autoencoder\n","\n","We do not have to limit ourselves to a single layer as encoder or decoder, we could instead use a stack of layers, such as:"],"metadata":{"id":"vfdgxg8rpiLh"}},{"cell_type":"code","source":["model = tf.keras.models.Sequential()\n","model.add()"],"metadata":{"id":"cO2BHVdDqgtZ"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# functional form\n","output = name_of_function(input_arg)"],"metadata":{"id":"KE1VZK1Pq41R"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# model\n","input_img = keras.Input(shape=(784,))\n","\n","# encode\n","encoded = layers.Dense(128, activation='relu')(input_img)\n","encoded = layers.Dense(64, activation='relu')(encoded)\n","encoded = layers.Dense(32, activation='relu')(encoded)\n","\n","# decode\n","decoded = layers.Dense(64, activation='relu')(encoded)\n","decoded = layers.Dense(128, activation='relu')(decoded)\n","decoded = layers.Dense(784, activation='sigmoid')(decoded)"],"metadata":{"id":"hFfQ3o8n0x9Z"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# build model\n","autoencoder = keras.Model(input_img, decoded)"],"metadata":{"id":"7uf1vqItps8i"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# compile\n","autoencoder.compile(optimizer='adam', loss='binary_crossentropy')"],"metadata":{"id":"ZSNdxBQopwtx"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# train\n","autoencoder.fit(x=x_train, y=x_train,\n"," epochs=100,\n"," batch_size=256,\n"," shuffle=True,\n"," validation_data=(x_test, x_test))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Qg0uFw9op8Kh","executionInfo":{"status":"ok","timestamp":1655992021948,"user_tz":240,"elapsed":324889,"user":{"displayName":"Yiqiao Yin","userId":"17143243938280119775"}},"outputId":"0fb4578a-95b4-430e-934f-870b96061ec8"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Epoch 1/100\n","235/235 [==============================] - 4s 14ms/step - loss: 0.2522 - val_loss: 0.1726\n","Epoch 2/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.1554 - val_loss: 0.1388\n","Epoch 3/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.1327 - val_loss: 0.1257\n","Epoch 4/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.1231 - val_loss: 0.1180\n","Epoch 5/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.1171 - val_loss: 0.1133\n","Epoch 6/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.1128 - val_loss: 0.1092\n","Epoch 7/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.1089 - val_loss: 0.1062\n","Epoch 8/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.1061 - val_loss: 0.1038\n","Epoch 9/100\n","235/235 [==============================] - 3s 12ms/step - loss: 0.1039 - val_loss: 0.1017\n","Epoch 10/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.1019 - val_loss: 0.0998\n","Epoch 11/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.1002 - val_loss: 0.0987\n","Epoch 12/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0989 - val_loss: 0.0971\n","Epoch 13/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0977 - val_loss: 0.0965\n","Epoch 14/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0968 - val_loss: 0.0955\n","Epoch 15/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0959 - val_loss: 0.0945\n","Epoch 16/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0951 - val_loss: 0.0940\n","Epoch 17/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0944 - val_loss: 0.0930\n","Epoch 18/100\n","235/235 [==============================] - 3s 15ms/step - loss: 0.0937 - val_loss: 0.0923\n","Epoch 19/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0932 - val_loss: 0.0919\n","Epoch 20/100\n","235/235 [==============================] - 4s 15ms/step - loss: 0.0925 - val_loss: 0.0915\n","Epoch 21/100\n","235/235 [==============================] - 4s 16ms/step - loss: 0.0920 - val_loss: 0.0909\n","Epoch 22/100\n","235/235 [==============================] - 3s 15ms/step - loss: 0.0916 - val_loss: 0.0905\n","Epoch 23/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0911 - val_loss: 0.0899\n","Epoch 24/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0906 - val_loss: 0.0899\n","Epoch 25/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0903 - val_loss: 0.0893\n","Epoch 26/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0898 - val_loss: 0.0887\n","Epoch 27/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0895 - val_loss: 0.0886\n","Epoch 28/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0891 - val_loss: 0.0883\n","Epoch 29/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0888 - val_loss: 0.0879\n","Epoch 30/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0885 - val_loss: 0.0877\n","Epoch 31/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0882 - val_loss: 0.0875\n","Epoch 32/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0880 - val_loss: 0.0869\n","Epoch 33/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0877 - val_loss: 0.0869\n","Epoch 34/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0874 - val_loss: 0.0868\n","Epoch 35/100\n","235/235 [==============================] - 4s 17ms/step - loss: 0.0872 - val_loss: 0.0867\n","Epoch 36/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0870 - val_loss: 0.0864\n","Epoch 37/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0868 - val_loss: 0.0864\n","Epoch 38/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0865 - val_loss: 0.0862\n","Epoch 39/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0863 - val_loss: 0.0857\n","Epoch 40/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0861 - val_loss: 0.0858\n","Epoch 41/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0860 - val_loss: 0.0854\n","Epoch 42/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0858 - val_loss: 0.0852\n","Epoch 43/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0856 - val_loss: 0.0848\n","Epoch 44/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0854 - val_loss: 0.0847\n","Epoch 45/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0853 - val_loss: 0.0847\n","Epoch 46/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0851 - val_loss: 0.0847\n","Epoch 47/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0850 - val_loss: 0.0844\n","Epoch 48/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0849 - val_loss: 0.0847\n","Epoch 49/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0848 - val_loss: 0.0843\n","Epoch 50/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0847 - val_loss: 0.0841\n","Epoch 51/100\n","235/235 [==============================] - 4s 15ms/step - loss: 0.0846 - val_loss: 0.0841\n","Epoch 52/100\n","235/235 [==============================] - 3s 15ms/step - loss: 0.0844 - val_loss: 0.0841\n","Epoch 53/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0844 - val_loss: 0.0837\n","Epoch 54/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0843 - val_loss: 0.0838\n","Epoch 55/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0841 - val_loss: 0.0837\n","Epoch 56/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0840 - val_loss: 0.0838\n","Epoch 57/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0840 - val_loss: 0.0836\n","Epoch 58/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0839 - val_loss: 0.0836\n","Epoch 59/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0838 - val_loss: 0.0834\n","Epoch 60/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0837 - val_loss: 0.0833\n","Epoch 61/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0836 - val_loss: 0.0832\n","Epoch 62/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0836 - val_loss: 0.0834\n","Epoch 63/100\n","235/235 [==============================] - 3s 15ms/step - loss: 0.0835 - val_loss: 0.0830\n","Epoch 64/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0835 - val_loss: 0.0829\n","Epoch 65/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0834 - val_loss: 0.0830\n","Epoch 66/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0834 - val_loss: 0.0829\n","Epoch 67/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0833 - val_loss: 0.0827\n","Epoch 68/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0832 - val_loss: 0.0828\n","Epoch 69/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0832 - val_loss: 0.0831\n","Epoch 70/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0831 - val_loss: 0.0827\n","Epoch 71/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0830 - val_loss: 0.0829\n","Epoch 72/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0830 - val_loss: 0.0827\n","Epoch 73/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0830 - val_loss: 0.0827\n","Epoch 74/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0829 - val_loss: 0.0825\n","Epoch 75/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0829 - val_loss: 0.0828\n","Epoch 76/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0828 - val_loss: 0.0824\n","Epoch 77/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0827 - val_loss: 0.0823\n","Epoch 78/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0827 - val_loss: 0.0822\n","Epoch 79/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0827 - val_loss: 0.0827\n","Epoch 80/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0827 - val_loss: 0.0828\n","Epoch 81/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0826 - val_loss: 0.0823\n","Epoch 82/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0826 - val_loss: 0.0824\n","Epoch 83/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0825 - val_loss: 0.0822\n","Epoch 84/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0825 - val_loss: 0.0820\n","Epoch 85/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0824 - val_loss: 0.0822\n","Epoch 86/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0824 - val_loss: 0.0822\n","Epoch 87/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0823 - val_loss: 0.0825\n","Epoch 88/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0823 - val_loss: 0.0818\n","Epoch 89/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0823 - val_loss: 0.0822\n","Epoch 90/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0823 - val_loss: 0.0821\n","Epoch 91/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0823 - val_loss: 0.0822\n","Epoch 92/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0822 - val_loss: 0.0820\n","Epoch 93/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0822 - val_loss: 0.0820\n","Epoch 94/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0821 - val_loss: 0.0817\n","Epoch 95/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0821 - val_loss: 0.0821\n","Epoch 96/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0820 - val_loss: 0.0817\n","Epoch 97/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0820 - val_loss: 0.0818\n","Epoch 98/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0820 - val_loss: 0.0816\n","Epoch 99/100\n","235/235 [==============================] - 3s 14ms/step - loss: 0.0820 - val_loss: 0.0818\n","Epoch 100/100\n","235/235 [==============================] - 3s 13ms/step - loss: 0.0819 - val_loss: 0.0819\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":13}]},{"cell_type":"code","source":["# predict\n","decoded_imgs = autoencoder.predict(x_test)\n","decoded_imgs.shape"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"YRK1UsZ5qdJw","executionInfo":{"status":"ok","timestamp":1655992022783,"user_tz":240,"elapsed":839,"user":{"displayName":"Yiqiao Yin","userId":"17143243938280119775"}},"outputId":"1f4c7147-78dd-42f8-adda-525bafa910a4"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["(10000, 784)"]},"metadata":{},"execution_count":14}]},{"cell_type":"code","source":["# Use Matplotlib (don't ask)\n","n = 10 # How many digits we will display\n","plt.figure(figsize=(20, 4))\n","for i in range(n):\n"," # Display original\n"," ax = plt.subplot(2, n, i + 1)\n"," plt.imshow(x_test[i].reshape(28, 28))\n"," plt.gray()\n"," ax.get_xaxis().set_visible(False)\n"," ax.get_yaxis().set_visible(False)\n","\n"," # Display reconstruction\n"," ax = plt.subplot(2, n, i + 1 + n)\n"," plt.imshow(decoded_imgs[i].reshape(28, 28))\n"," plt.gray()\n"," ax.get_xaxis().set_visible(False)\n"," ax.get_yaxis().set_visible(False)\n","plt.show()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":248},"id":"iDhpfRK7p9mQ","executionInfo":{"status":"ok","timestamp":1655992023511,"user_tz":240,"elapsed":524,"user":{"displayName":"Yiqiao Yin","userId":"17143243938280119775"}},"outputId":"9b181857-243a-46fc-b529-af6aa8d65aff"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"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z522FStWaP722281L1682Ol35MiRsK+P6NnpFETcc8zea/rviWg1bNhQ82+//ea0rV27VvOcOXOcNvue+/XXX7P0u6PBSBsAAAAAAIAA4qENAAAAAABAAPHQBgAAAAAAIICydU4bu8S3iEjNmjU1r1692mmrWrWq5kh1xY0aNdL8448/ag63RF8oto5t586dmu1y1r7Nmzc726k6p41l56/Iql69emmuXLly2H62ljTUNoKrd+/emv33DOdRfEyZMkWzXZI7q+zSpgcPHnTaypcvr9kuO7tgwQKnX65cuU55P5KdX89tl21ev3695n/+858J26frr78+Yb8LJ6pRo4azXbdu3bB97b3N1KlT47ZPyaJ48eLO9k033RS2b+fOnTXb+8Z4s/PYfPHFF2H7+XPa+PNBQuSRRx7RbJdwj5Y/T9u1116r2V823M5/E885MJJVpHlmatWqpdku9eybP3++Zvu9cuPGjU6/cuXKabZzmYrEZh5AnMg+D+jRo4dm/xwrVKhQyJ//6aefnO2vv/5a8w8//OC02e8gdm7FBg0aOP3sNaFly5ZO29KlSzXbZcNjjZE2AAAAAAAAAcRDGwAAAAAAgADK1vKoGTNmRNy2/KXa/uQvN1q7dm3NdphT/fr1o96vo0ePav7uu+80+yVbdqiUHZqOU3Pddddptktn5smTx+m3Y8cOzY8++qjTdvjw4TjtHU5VhQoVnO169epptuebCEsjxsqVV17pbFepUkWzHd4b7VBff/inHZ5sl84UEWnWrJnmSMsR/9///Z/mESNGRLUfqebxxx93tu0QcTsU3y9RizX72ee/txgunliRSnZ8fhkBInv++eed7dtuu02zvb8UEfnwww8Tsk++xo0bay5RooTT9vbbb2t+9913E7VLOYYt3RURufvuu0P2W7ZsmbO9fft2zc2bNw/7+oULF9ZsS69ERMaMGaN527ZtJ9/ZFOff/7/33nuabTmUiFseHKlk0PJLoix/+gvE3quvvups27K2SMt32+cGy5cv1/zYY485/ez3et+ll16q2d6Hvvnmm04/+3zBXgNERIYNG6Z5woQJmmNdKstIGwAAAAAAgADioQ0AAAAAAEAAZWt5VCzs3bvX2Z45c2bIfpFKryKxQ4/9Uiw7FGvcuHFZen2cyJbL+EMiLfs3nz17dlz3CbHjl1NYiVx1I9nZMrT333/faYs03NSyq3nZIZ9PPfWU0y9SOaJ9jW7dumkuVqyY02/gwIGa8+XL57QNHTpU87Fjx06220mlXbt2mv0VC9atW6c5kSut2TI3vxxq1qxZmvft25eoXUpZV1xxRdg2f1WaSOWJOFFGRoazbd/rW7ZscdriuQLQGWec4Wzbof9//etfNfv7e88998Rtn5KBLXcQETnzzDM129Vm/HsW+/l06623avZLMipVqqS5ZMmSTtu///1vzS1atNC8Z8+eqPY9FRQsWFCzPwWCnUZh165dTttzzz2nmakSgsO/r7OrNnXp0sVpS0tL02y/F/il84MGDdKc1ekUihYtqtmuYtqvXz+nn52mxS+tTBRG2gAAAAAAAAQQD20AAAAAAAACiIc2AAAAAAAAAZTj57SJh+LFi2sePny45tNOc59x2eWoqUPNuo8//tjZ/stf/hKy3zvvvONs+8vfImeoUaNG2DY7rwlOzemn/+/yHu0cNv7cULfccotmv248WnZOm2effVbz4MGDnX758+fX7L8PJk2apHn9+vVZ2o+cqn379prt30jE/XyKNztHUqdOnTT//vvvTr8BAwZoTrX5hxLFLlFqs8+v8V+yZEnc9inVtGrVytm2y6nbuZz8ORiiZedRadKkidPWqFGjkD8zfvz4LP2uVJU3b15n284J9MILL4T9Obt88FtvvaXZXqtFRCpWrBj2NexcK/GcDykna9u2rea+ffs6bXYZbrvsvYjI/v3747tjyBL/OtarVy/Ndg4bEZGffvpJs51bdsGCBVn63XaumrJlyzpt9rvllClTNPvz2Fr+/o4ePVpzPOfyY6QNAAAAAABAAPHQBgAAAAAAIIAojwqhR48emu2ytP7y4mvXrk3YPiWbUqVKafaHd9shq7Ykww67FxE5ePBgnPYOsWaHc999991O2+LFizVPnz49YfuEP9ilov0lYrNaEhWOLXOyJTYiIvXr14/p78qpChcu7GyHK4UQyXrpRVbY5dptud3q1audfjNnzkzYPqWqaM+VRL4/ktGLL77obDdt2lRz6dKlnTa79LodOt+mTZss/W77Gv5S3taGDRs0+0tOIzK7XLfPlr/5Jfzh1KtXL+rfPX/+fM3cy4YWqfTT3jemp6cnYndwimyJksiJpdXWb7/9prlhw4aa27Vr5/S78MILQ/78kSNHnO2qVauGzCLufW6J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\n"},"metadata":{"needs_background":"light"}}]}]}