Machine Learning
Neural Networks
Model Chaining
Intermediate Layers
Deep Learning

How can I use the output of intermediate layer of one model as input to another model?

Master System Design with Codemia

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

Introduction

Using the output of an intermediate layer as input to another model is a standard feature-extraction pattern in Keras and TensorFlow. The main idea is simple: expose the hidden tensor you care about, then either feed it into a second model as precomputed features or connect both stages into one larger graph.

Build a model that exposes the intermediate tensor

The cleanest approach is to create a new model whose output is the layer you want from the original network.

python
1from tensorflow import keras
2from tensorflow.keras import layers
3import numpy as np
4
5inputs = keras.Input(shape=(32,))
6x = layers.Dense(64, activation="relu", name="hidden_1")(inputs)
7embedding = layers.Dense(16, activation="relu", name="embedding")(x)
8classifier = layers.Dense(3, activation="softmax", name="classifier")(embedding)
9
10base_model = keras.Model(inputs=inputs, outputs=classifier)
11
12feature_extractor = keras.Model(
13    inputs=base_model.input,
14    outputs=base_model.get_layer("embedding").output
15)

Now feature_extractor returns a tensor with shape (batch_size, 16) instead of the final class probabilities. That tensor is often called an embedding or latent representation.

Feed those features into a second model

Once the intermediate output is available, the second model can be trained on those features like any other input.

python
1x_train = np.random.random((100, 32)).astype("float32")
2y_train = np.random.randint(0, 2, size=(100, 1)).astype("float32")
3
4features = feature_extractor.predict(x_train, verbose=0)
5
6second_model = keras.Sequential([
7    layers.Input(shape=(16,)),
8    layers.Dense(8, activation="relu"),
9    layers.Dense(1, activation="sigmoid")
10])
11
12second_model.compile(optimizer="adam", loss="binary_crossentropy")
13second_model.fit(features, y_train, epochs=2, verbose=0)

This pattern is useful when the first model is already trained and you want to reuse its learned representation for classification, ranking, clustering, or anomaly detection.

Freeze the first model when features should stay fixed

If the first model is acting purely as a feature generator, freeze it. That makes the training behavior explicit and prevents accidental updates.

python
base_model.trainable = False

A frozen first stage is common in transfer learning. You compute embeddings once or on demand and train the second stage independently. This is operationally simple and easy to debug because the features are stable.

Build one end-to-end model when both stages should learn together

Sometimes you do not want fixed features. You want the downstream loss to shape the intermediate representation. In that case, attach the second stage directly to the intermediate tensor instead of running a separate prediction step.

python
1base_model.trainable = True
2
3intermediate = base_model.get_layer("embedding").output
4downstream_output = layers.Dense(1, activation="sigmoid")(intermediate)
5
6combined_model = keras.Model(
7    inputs=base_model.input,
8    outputs=downstream_output
9)
10
11combined_model.compile(optimizer="adam", loss="binary_crossentropy")
12combined_model.fit(x_train, y_train, epochs=2, verbose=0)

The combined model keeps gradients flowing through the first model. That is a very different workflow from offline feature extraction, so decide which behavior you actually want before writing the training code.

Shape management is the main integration issue

The second model must accept exactly the shape produced by the intermediate layer. Dense embeddings are easy. Sequence tensors and image feature maps usually need more thought.

For example, if an intermediate layer returns a three-dimensional sequence tensor, a dense classifier may require pooling first:

python
sequence_features = layers.GlobalAveragePooling1D()(some_sequence_tensor)

Always inspect the shape rather than guessing:

python
print(feature_extractor.output_shape)

That one line often saves a lot of confusion.

Choose the intermediate layer deliberately

Earlier layers usually encode generic patterns. Later layers encode more task-specific abstractions. If the second model needs broadly reusable features, a middle layer is often better than the final classifier-adjacent layer. The best choice depends on what information the downstream task needs to preserve.

Common Pitfalls

  • Pulling the wrong layer output and training on features that do not match the downstream task.
  • Forgetting to freeze the first model when only fixed feature extraction is intended.
  • Precomputing features once, then changing the first model and accidentally using stale embeddings.
  • Feeding sequence or image tensors into a dense model without pooling or reshaping.
  • Mixing end-to-end training and offline feature extraction in the same experiment without being explicit about the difference.

Summary

  • Create a feature extractor model whose output is the intermediate layer you want.
  • Feed those intermediate features into a second model with a matching input shape.
  • Freeze the first model for fixed embeddings, or connect both stages into one graph for joint training.
  • Check tensor shapes early, especially for sequence and image features.
  • The layer you choose affects feature quality, not just wiring convenience.

Course illustration
Course illustration

All Rights Reserved.