Keras
TensorFlow
Custom Layer
Deep Learning
Neural Networks

Initialize keras placeholder as Input to a Custom Layer

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

In modern Keras, you normally do not initialize a raw placeholder and feed it into a custom layer directly. The standard approach is to define a symbolic Keras input with keras.Input(...) and let your custom layer operate on that tensor inside the Functional API.

Use keras.Input, Not a Raw Placeholder

The clean modern pattern looks like this:

python
1import keras
2from keras import layers
3
4
5class ScalingLayer(layers.Layer):
6    def build(self, input_shape):
7        self.scale = self.add_weight(
8            name="scale",
9            shape=(1,),
10            initializer="ones",
11            trainable=True,
12        )
13
14    def call(self, inputs):
15        return inputs * self.scale
16
17
18inputs = keras.Input(shape=(32,))
19outputs = ScalingLayer()(inputs)
20model = keras.Model(inputs=inputs, outputs=outputs)
21
22model.summary()

keras.Input creates the symbolic input tensor Keras expects. Your custom layer then receives that symbolic tensor naturally during model construction.

Why Raw Placeholders Are the Wrong Abstraction

Older TensorFlow graph-mode examples often use placeholders. That reflected the TensorFlow 1 execution model, where users built graphs manually and fed values at runtime.

Keras sits at a higher level. It wants:

  • symbolic model inputs
  • layers with build and call
  • shape inference through the model graph

Using keras.Input keeps you inside that contract. Dropping a raw placeholder into the middle of a Keras model usually makes the code harder to reason about and less portable across Keras and TensorFlow versions.

Write the Custom Layer Properly

Your layer should focus on layer behavior, not on how input placeholders are created. The minimum shape-aware custom layer usually implements:

  • 'build(self, input_shape) for weights'
  • 'call(self, inputs) for forward computation'

For example, a layer that adds a trainable bias:

python
1import keras
2from keras import layers
3
4
5class BiasLayer(layers.Layer):
6    def build(self, input_shape):
7        self.bias = self.add_weight(
8            name="bias",
9            shape=(input_shape[-1],),
10            initializer="zeros",
11            trainable=True,
12        )
13
14    def call(self, inputs):
15        return inputs + self.bias

Then use it in the same way:

python
inputs = keras.Input(shape=(16,))
outputs = BiasLayer()(inputs)
model = keras.Model(inputs, outputs)

If You Are in Legacy TensorFlow 1 Code

If you are maintaining old graph-mode code, you may still encounter tf.compat.v1.placeholder. In that world, the safer long-term move is usually to migrate the model boundary to Keras inputs instead of trying to thread placeholders through custom layers indefinitely.

A legacy placeholder belongs at the TensorFlow graph boundary:

python
import tensorflow as tf

x = tf.compat.v1.placeholder(tf.float32, shape=[None, 32])

But for Keras model construction, use Keras symbols. Mixing the two models of abstraction too casually is where confusion usually starts.

Think About Shape, Not Placeholder Mechanics

Most questions that sound like “how do I initialize the placeholder?” are actually shape questions:

  • what is the input rank
  • does the batch dimension stay dynamic
  • what feature shape should the custom layer expect

Once those are clear, keras.Input(shape=(...)) is usually all you need.

Build the Model Boundary Once

Another good habit is to keep the model boundary in one place:

  • define the input tensor once
  • pass it through normal layers and custom layers
  • create the model from that graph

That keeps the custom layer reusable. A well-written layer should work with any compatible Keras input tensor, not just one manually prepared placeholder from a specific script.

Common Pitfalls

  • Starting from old placeholder-based TensorFlow examples and applying them directly to modern Keras code.
  • Putting input-creation logic inside the custom layer instead of at the model boundary.
  • Forgetting that shape in keras.Input excludes the batch dimension.
  • Writing custom layers that depend on manual placeholder feeding instead of ordinary Keras model inputs.
  • Mixing legacy graph-mode tensors and Keras symbols without a clear migration boundary.

Summary

  • In modern Keras, use keras.Input(...) as the input to a custom layer.
  • Keep custom layers responsible for computation and weights, not placeholder management.
  • Implement build and call cleanly so Keras can infer shapes and create weights properly.
  • Treat raw placeholders as legacy TensorFlow graph-mode constructs.
  • If the code feels placeholder-heavy, the real fix is often to move fully into the Keras Functional API.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.