Skip to content

Instantly share code, notes, and snippets.

@DiogenesAnalytics
Created December 5, 2023 07:42
Show Gist options
  • Save DiogenesAnalytics/399a96031ac360da5c34a000f3eae4ea to your computer and use it in GitHub Desktop.
Save DiogenesAnalytics/399a96031ac360da5c34a000f3eae4ea to your computer and use it in GitHub Desktop.
Keras Autoencoder Jupyter Notebook Tutorials
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "1b2cf03f-8eaf-4adf-80ab-0d5d5c661deb",
"metadata": {},
"source": [
"# Building Autoencoders in Keras\n",
"The following `Jupyter Notebook` has been *adapted* from the [Keras blog article](https://blog.keras.io/building-autoencoders-in-keras.html) written by *F. Chollet* on [autoencoders](https://en.wikipedia.org/wiki/Autoencoder)."
]
},
{
"cell_type": "markdown",
"id": "6ca7604f-90e7-4a2a-aec5-a6fbab7e8e78",
"metadata": {},
"source": [
"## Minimal Autoencoder\n",
"We'll start simple, with a single fully-connected neural layer as encoder and as decoder:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ec50fb59-56cc-4b44-80b4-e1937ef41132",
"metadata": {},
"outputs": [],
"source": [
"# get initial libs\n",
"import keras\n",
"from keras import layers\n",
"from keras.datasets import mnist\n",
"import numpy as np\n",
"import visualization.image"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8519277f-72b8-474c-8087-98b49046c3e1",
"metadata": {},
"outputs": [],
"source": [
"# 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",
"\n",
"# \"encoded\" is the encoded representation of the input\n",
"encoded = layers.Dense(encoding_dim, activation='relu')(input_img)\n",
"\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",
"id": "19ad5b79-bd89-4869-897e-1b8b08806121",
"metadata": {},
"source": [
"Let's also create a separate encoder model:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "43287e48-2e9c-4162-af83-fc3e83d67427",
"metadata": {},
"outputs": [],
"source": [
"# This model maps an input to its encoded representation\n",
"encoder = keras.Model(input_img, encoded)"
]
},
{
"cell_type": "markdown",
"id": "d188c22f-f273-42f7-8db9-bc21b2b29ffa",
"metadata": {},
"source": [
"As well as the decoder model:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "23b8667f-5545-4cd7-810d-7e301de4441d",
"metadata": {},
"outputs": [],
"source": [
"# This is our encoded (32-dimensional) input\n",
"encoded_input = keras.Input(shape=(encoding_dim,))\n",
"\n",
"# Retrieve the last layer of the autoencoder model\n",
"decoder_layer = autoencoder.layers[-1]\n",
"\n",
"# Create the decoder model\n",
"decoder = keras.Model(encoded_input, decoder_layer(encoded_input))"
]
},
{
"cell_type": "markdown",
"id": "4918684b-b71e-4bf0-9fbf-3cef1d6fa693",
"metadata": {},
"source": [
"Now let's train our autoencoder to reconstruct MNIST digits.\n",
"First, we'll configure our model to use a per-pixel binary crossentropy loss, and the Adam optimizer:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5d64f688-279c-4a92-99ad-593e4a78e3d3",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"autoencoder.compile(optimizer='adam', loss='binary_crossentropy')"
]
},
{
"cell_type": "markdown",
"id": "002b5507-0be8-4fe3-b75d-3bc16d80fa22",
"metadata": {},
"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)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "db702b19-0dc6-482e-8315-01643d23e304",
"metadata": {},
"outputs": [],
"source": [
"from keras.datasets import mnist\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ad955852-5d3b-489e-8424-8d1f71a9b66b",
"metadata": {},
"outputs": [],
"source": [
"(x_train, _), (x_test, _) = mnist.load_data()"
]
},
{
"cell_type": "markdown",
"id": "51130aed-4cf0-4631-9f48-166af984a1a5",
"metadata": {},
"source": [
"We will normalize all values between 0 and 1 and we will flatten the 28x28 images into vectors of size 784."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "244dfd57-b9a6-403b-82f2-17f9efad4e75",
"metadata": {},
"outputs": [],
"source": [
"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)"
]
},
{
"cell_type": "markdown",
"id": "8eb69dc1-a2cf-4de7-ad6f-52629b867c54",
"metadata": {},
"source": [
"Now let's train our autoencoder for 50 epochs:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b222e0d1-e77d-4905-8f7a-018cb6665613",
"metadata": {},
"outputs": [],
"source": [
"autoencoder.fit(x_train, x_train,\n",
" epochs=50,\n",
" batch_size=256,\n",
" shuffle=True,\n",
" validation_data=(x_test, x_test))"
]
},
{
"cell_type": "markdown",
"id": "df683b6d-1c0f-4f62-8e04-d7fc1af5af80",
"metadata": {},
"source": [
"After 50 epochs, the autoencoder seems to reach a stable train/validation loss value of about 0.09. We can try to visualize the reconstructed inputs and the encoded representations. We will use Matplotlib."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "aedb1dc7-6196-45c7-954a-e45d311b7979",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# now get predicted and compare\n",
"visualization.image.compare_results(x_test, autoencoder.predict(x_test));"
]
},
{
"cell_type": "markdown",
"id": "f63ee2e8-2771-4c62-94ae-6943d34a9e85",
"metadata": {},
"source": [
"Here's what we get. The top row is the original digits, and the bottom row is the reconstructed digits. We are losing quite a bit of detail with this basic approach."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment