Keras
Cell Class
Machine Learning
Neural Networks
Deep Learning

What is a cell class in Keras?

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 Keras, a cell class is the unit of computation used inside a recurrent layer. It defines what happens at a single time step: given the current input and previous state, it returns the next output and next state. The surrounding keras.layers.RNN layer is what applies that cell repeatedly across a sequence.

Cell Versus Layer

This distinction is the part many people miss.

A recurrent layer such as keras.layers.LSTM is a full sequence-processing layer. A cell such as keras.layers.LSTMCell is only the step function for one time step.

You usually interact with cells through the generic RNN wrapper:

python
1import tensorflow as tf
2from tensorflow import keras
3
4cell = keras.layers.SimpleRNNCell(8)
5layer = keras.layers.RNN(cell)
6
7x = tf.random.normal((4, 10, 3))
8y = layer(x)
9print(y.shape)

The input shape is (batch, timesteps, features). The RNN layer loops over the timesteps dimension and calls the cell once per step.

What a Cell Must Provide

A custom Keras RNN cell generally defines:

  • 'state_size'
  • optionally output_size
  • a call(inputs, states) method

The method receives the current step's input plus a list of previous states. It returns the current output and the updated state list.

Here is a minimal custom cell:

python
1import tensorflow as tf
2from tensorflow import keras
3
4class AdditiveCell(keras.layers.Layer):
5    def __init__(self, units, **kwargs):
6        super().__init__(**kwargs)
7        self.units = units
8        self.state_size = units
9        self.output_size = units
10
11    def build(self, input_shape):
12        self.kernel = self.add_weight(
13            shape=(input_shape[-1], self.units),
14            initializer='glorot_uniform',
15            name='kernel'
16        )
17        self.recurrent_kernel = self.add_weight(
18            shape=(self.units, self.units),
19            initializer='orthogonal',
20            name='recurrent_kernel'
21        )
22        self.bias = self.add_weight(
23            shape=(self.units,),
24            initializer='zeros',
25            name='bias'
26        )
27
28    def call(self, inputs, states):
29        prev = states[0]
30        output = tf.nn.tanh(
31            tf.matmul(inputs, self.kernel) +
32            tf.matmul(prev, self.recurrent_kernel) +
33            self.bias
34        )
35        return output, [output]
36
37
38cell = AdditiveCell(16)
39layer = keras.layers.RNN(cell)
40x = tf.random.normal((2, 5, 4))
41y = layer(x)
42print(y.shape)

This example shows the cell's real role: it is the recurrence logic, not the loop.

Built-In Cell Classes

Keras provides several built-in cells:

  • 'SimpleRNNCell'
  • 'LSTMCell'
  • 'GRUCell'

These correspond to the well-known recurrent architectures. They can be wrapped in keras.layers.RNN directly, or you can use higher-level layers such as keras.layers.LSTM, which package the same idea in a more convenient form.

python
cell = keras.layers.GRUCell(32)
layer = keras.layers.RNN(cell, return_sequences=True)

Using the explicit cell form is helpful when you want custom behavior, stacked cells, or a mixed recurrent architecture.

Why Cells Exist as Separate Classes

Separating the cell from the looping layer makes the API flexible.

  • the same RNN wrapper can drive many cell types
  • you can write custom recurrent logic without reimplementing sequence handling
  • you can stack cells more easily

For example, Keras can run multiple cells in sequence inside one recurrent layer.

python
cells = [keras.layers.LSTMCell(16), keras.layers.LSTMCell(16)]
layer = keras.layers.RNN(cells, return_sequences=True)

That creates a stacked recurrent computation while still relying on the generic RNN wrapper.

When You Need a Custom Cell

Most projects do not need one. Built-in LSTM, GRU, and SimpleRNN layers are enough for standard sequence tasks.

A custom cell becomes useful when you need to:

  • add special state variables
  • inject custom gating logic
  • combine learned recurrence with external memory or constraints
  • reproduce a research paper's recurrence exactly

In those cases, writing a cell is much cleaner than rewriting an entire recurrent layer from scratch.

Common Pitfalls

A common mistake is treating a cell like a standalone sequence layer. A cell processes one step; keras.layers.RNN handles the full sequence loop.

Another mistake is forgetting to define state_size, which prevents Keras from knowing how to manage recurrent state.

Developers also sometimes return the wrong structure from call. The method must return both the output and a list of next states, even when output and state are the same tensor.

Summary

  • A Keras cell defines the computation for one recurrent time step.
  • 'keras.layers.RNN applies that cell across a sequence.'
  • Built-in cells include SimpleRNNCell, LSTMCell, and GRUCell.
  • Custom cells expose state_size and implement call(inputs, states).
  • Use a custom cell when the recurrence itself needs to be specialized.

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.