deep learning
autoencoder
keras
encoder-decoder
machine learning

Split autoencoder on encoder and decoder keras

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Keras, an autoencoder is just a model composed of two logical parts: an encoder that maps input to a latent representation, and a decoder that reconstructs from that latent space. Splitting the autoencoder means creating separate Keras models for those two parts while still allowing the combined autoencoder to train end to end. This is useful when you want to reuse the encoder for embeddings or reuse the decoder for generation and reconstruction experiments.

Build the Autoencoder with the Functional API

The easiest way to split an autoencoder is to name the latent boundary explicitly in the functional graph. Then the encoder and decoder can be defined as independent models that share layers with the full autoencoder.

python
1import tensorflow as tf
2from tensorflow import keras
3
4inputs = keras.Input(shape=(784,), name="input")
5x = keras.layers.Dense(256, activation="relu")(inputs)
6x = keras.layers.Dense(128, activation="relu")(x)
7latent = keras.layers.Dense(32, activation="relu", name="latent")(x)
8
9decoder_dense_1 = keras.layers.Dense(128, activation="relu")
10decoder_dense_2 = keras.layers.Dense(256, activation="relu")
11decoder_output = keras.layers.Dense(784, activation="sigmoid")
12
13x = decoder_dense_1(latent)
14x = decoder_dense_2(x)
15outputs = decoder_output(x)
16
17autoencoder = keras.Model(inputs, outputs, name="autoencoder")

This defines the whole network first, which makes the split much easier because the latent tensor is already identified.

Create the Encoder Model

The encoder is the submodel from the original input to the latent representation.

python
encoder = keras.Model(inputs, latent, name="encoder")

That is all you need if the latent layer already exists in the full graph. The encoder reuses the same trained weights as the autoencoder because it points to the same layers and tensors.

Create the Decoder Model

The decoder needs a new input that matches the latent shape, then it must reuse the decoder layers from the full autoencoder.

python
1latent_inputs = keras.Input(shape=(32,), name="decoder_input")
2x = decoder_dense_1(latent_inputs)
3x = decoder_dense_2(x)
4decoder_outputs = decoder_output(x)
5
6decoder = keras.Model(latent_inputs, decoder_outputs, name="decoder")

This pattern is more stable than rebuilding the decoder with copied layers or depending on raw layer indexes from the full model.

Train the Full Autoencoder, Then Reuse the Parts

Normally you compile and train the full autoencoder, not the encoder and decoder independently at first.

python
1autoencoder.compile(optimizer="adam", loss="binary_crossentropy")
2
3autoencoder.fit(
4    x_train,
5    x_train,
6    epochs=10,
7    batch_size=256,
8    validation_data=(x_test, x_test)
9)

After training:

python
1encoded = encoder.predict(x_test[:5])
2reconstructed = decoder.predict(encoded)
3
4print(encoded.shape)
5print(reconstructed.shape)

The encoder now produces embeddings, and the decoder can reconstruct from those embeddings without redefining the architecture.

Know When Separate Models Are Useful

Splitting the model is helpful when:

  1. You want latent vectors for clustering or retrieval.
  2. You want to feed custom latent vectors into the decoder.
  3. You want to inspect reconstruction quality separately from encoding quality.
  4. You want to save or deploy only the encoder.

This is especially common in anomaly detection and representation learning pipelines where the encoder becomes the real production artifact.

Keep Shapes Consistent at the Latent Boundary

Most split-autoencoder bugs are shape mismatches. The decoder input shape must exactly match the encoder output shape. If the latent representation is multidimensional, make that boundary explicit and inspect it before wiring the decoder model.

python
print(encoder.output_shape)
print(decoder.input_shape)

Those two shapes should match apart from the batch dimension. If they do not, the split is incorrect even if the full autoencoder trained successfully.

Common Pitfalls

  • Building the full autoencoder with Sequential and then struggling to expose a clean latent boundary.
  • Recreating encoder and decoder layers separately instead of reusing the trained layers from the autoencoder graph.
  • Splitting by raw layer indexes that later change when the model architecture is edited.
  • Forgetting that the decoder input shape must match the encoder output shape exactly.
  • Training encoder and decoder independently first when the real goal is an end-to-end reconstruction model.

Summary

  • A split autoencoder in Keras is easiest to build with the Functional API.
  • Define the latent boundary explicitly so the encoder and decoder become clean submodels.
  • Train the full autoencoder, then reuse the encoder for embeddings and the decoder for reconstruction.
  • Reuse the same layer objects when constructing the split models.
  • Validate shapes at the latent boundary to avoid subtle wiring mistakes.

Course illustration
Course illustration

All Rights Reserved.