How to implement Tensorflow batch normalization in LSTM
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
Batch normalization is a technique that normalizes the inputs to each layer, stabilizing training and often allowing higher learning rates. Applying it to LSTM networks is not as straightforward as inserting a layer into a feedforward model because LNNs process sequential data across time steps. This article covers practical approaches to adding normalization between LSTM layers in TensorFlow/Keras, explores Layer Normalization as a recurrence-friendly alternative, and demonstrates a custom LSTM cell with built-in normalization.
Batch Normalization Between LSTM Layers
The simplest approach is to place a BatchNormalization layer between stacked LSTM layers. When you stack multiple LSTM layers, you can normalize the output of one LSTM before feeding it into the next. The key requirement is that the first LSTM must return full sequences so the next LSTM receives input at every time step.
The BatchNormalization layer computes statistics across the batch dimension. During training it uses the current mini-batch mean and variance, while during inference it uses running averages accumulated during training.
Why Layer Normalization Is Often Better for RNNs
Batch normalization computes statistics across samples in a mini-batch. In recurrent networks, this creates problems because batch statistics can vary significantly across time steps, and small batch sizes lead to noisy estimates. Layer Normalization computes statistics across the feature dimension for each individual sample, making it independent of batch size and more stable for sequential models.
Layer Normalization works well with variable-length sequences and batch size of 1, which are common scenarios in RNN applications such as text generation and time-series forecasting.
Custom LSTM Cell with Normalization
For finer control, you can create a custom LSTM cell that applies normalization inside the recurrence, normalizing the gate activations at every time step rather than only between layers.
You can then use this cell with the RNN wrapper layer.
Training Example
Here is a complete training example that uses batch normalization between LSTM layers on synthetic time-series data.
Combine BatchNormalization with Dropout for regularization. Place batch normalization before dropout so that the normalization statistics are computed on the full output before units are randomly zeroed out.
Common Pitfalls
- Using small batch sizes with BatchNormalization: Batch norm estimates become noisy with very small batches, leading to unstable training. Use Layer Normalization instead when batch sizes are below 16.
- Forgetting return_sequences on intermediate LSTMs: Stacking LSTM layers requires
return_sequences=Trueon all layers except the last, otherwise the subsequent LSTM receives a single vector instead of a sequence. - Ignoring training vs inference mode: BatchNormalization behaves differently during training and inference. Always pass
training=Trueortraining=Falsecorrectly when using custom training loops. - Applying BN after activation in LSTM gates: Inside a custom cell, normalize before the activation functions, not after. Normalizing after sigmoid or tanh compresses the distribution and reduces the normalization benefit.
- Not freezing BN layers during fine-tuning: When fine-tuning a pretrained model with very few samples, freeze BatchNormalization layers by setting
layer.trainable = Falseto prevent running statistics from being corrupted by the small fine-tuning dataset.
Summary
- Place
BatchNormalizationbetween stacked LSTM layers for a quick improvement in training stability. - Prefer
LayerNormalizationover batch normalization for recurrent networks, especially with small or variable batch sizes. - Build a custom LSTM cell with normalization inside the recurrence for gate-level control.
- Always set
return_sequences=Trueon LSTM layers that feed into another recurrent or normalization layer. - Combine normalization with dropout for regularization, placing normalization before dropout in the layer order.
Related reading
- how to implement tensorflow session configuration
- How to import keras.engine.topology in Tensorflow?
- HOW TO Import TensorFlow in Jupyter Notebook from Conda with GPU support?
- How to improve digit recognition of a model trained on MNIST?
- How to implement tensorflow Estimator with multiple models for GAN?
- how to implement tensorflow's next_batch for own data
- How to include batch size in pytorch basic example?
- How to initialise only optimizer variables in Tensorflow?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack 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.