Keras
LSTM
sequence-to-sequence
nan
machine learning troubleshooting

Keras gives nan when training categorical LSTM sequence-to-sequence model

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

When a categorical seq2seq LSTM in Keras starts producing nan loss values, the problem is usually numerical instability or inconsistent training data rather than a mysterious LSTM bug. The fastest way to debug it is to check the target encoding, logits-versus-probabilities setup, gradient scale, and whether any NaN or Inf values already exist in the input pipeline. Seq2seq models amplify small mistakes because the decoder runs over many time steps.

Start With the Loss and Target Format

A categorical decoder usually ends with a softmax over the vocabulary at each output step. That implies a specific match between the output layer, the target tensor, and the loss function.

If your targets are one-hot encoded, use CategoricalCrossentropy. If your targets are integer token IDs, use SparseCategoricalCrossentropy.

python
1import tensorflow as tf
2from tensorflow import keras
3from tensorflow.keras import layers
4
5vocab_size = 20
6latent_dim = 32
7
8encoder_inputs = keras.Input(shape=(None, vocab_size))
9_, state_h, state_c = layers.LSTM(latent_dim, return_state=True)(encoder_inputs)
10encoder_state = [state_h, state_c]
11
12decoder_inputs = keras.Input(shape=(None, vocab_size))
13decoder_outputs, _, _ = layers.LSTM(
14    latent_dim,
15    return_sequences=True,
16    return_state=True,
17)(decoder_inputs, initial_state=encoder_state)
18decoder_outputs = layers.Dense(vocab_size, activation="softmax")(decoder_outputs)
19
20model = keras.Model([encoder_inputs, decoder_inputs], decoder_outputs)
21model.compile(
22    optimizer=keras.optimizers.Adam(learning_rate=1e-3, clipnorm=1.0),
23    loss=keras.losses.CategoricalCrossentropy(),
24)

A common mistake is using from_logits=True while the model already applies softmax, or using from_logits=False while the final layer emits raw scores. That mismatch can make the loss numerically unstable.

Check the Data Before Blaming the Model

Seq2seq training data has more moving parts than ordinary classification. You typically have:

  • encoder input sequence
  • decoder input sequence shifted right for teacher forcing
  • decoder target sequence shifted left

If any of those are misaligned, the model can train against nonsense targets. Also verify that the tensors contain only finite values.

python
1import numpy as np
2
3print(np.isnan(encoder_input_data).any())
4print(np.isnan(decoder_input_data).any())
5print(np.isnan(decoder_target_data).any())
6print(np.isinf(encoder_input_data).any())

If you use padded sequences, make sure the padding token is handled consistently. Bad masking or accidentally treating padding as a normal class can distort the loss badly, especially on long sequences.

Gradient Explosion Is Common in Seq2Seq LSTMs

Even though LSTMs help with vanishing gradients, they can still suffer from exploding gradients. That is one of the most common direct causes of nan during training.

The two simplest stabilizers are:

  • a smaller learning rate
  • gradient clipping
python
1optimizer = keras.optimizers.Adam(
2    learning_rate=1e-4,
3    clipnorm=1.0,
4)
5
6model.compile(
7    optimizer=optimizer,
8    loss=keras.losses.CategoricalCrossentropy(),
9)

If the loss becomes nan after a few batches rather than immediately, exploding updates are especially likely.

Keep the Output Scale Reasonable

Another common problem is feeding the model poorly scaled inputs or building an oversized decoder head. For one-hot token inputs this is less about normalization and more about architecture choices such as:

  • too large a learning rate
  • very deep recurrent stacks without regularization
  • long untrimmed sequences
  • extremely large vocabularies without careful optimization

A smaller baseline model is often the best debugging step. If a tiny encoder-decoder trains correctly, then the issue is probably in the training setup rather than the basic seq2seq idea.

Useful Debugging Habits

A practical sequence for diagnosing nan loss is:

  1. verify that all input and target tensors are finite
  2. check loss function and target encoding compatibility
  3. lower the learning rate
  4. enable gradient clipping
  5. overfit a tiny batch on purpose

If the model cannot overfit a tiny clean dataset, the configuration is wrong.

python
1history = model.fit(
2    [encoder_input_data[:32], decoder_input_data[:32]],
3    decoder_target_data[:32],
4    epochs=20,
5    batch_size=8,
6)

A tiny-batch sanity check often catches shape mismatches and bad target preparation much faster than staring at the full training loop.

Common Pitfalls

  • Mixing one-hot targets with SparseCategoricalCrossentropy, or integer targets with CategoricalCrossentropy.
  • Misusing the from_logits setting relative to the output activation.
  • Training with a learning rate that is too high for a recurrent decoder.
  • Forgetting gradient clipping in a long-sequence LSTM setup.
  • Feeding misaligned decoder input and decoder target sequences during teacher forcing.

Summary

  • 'nan loss in a categorical seq2seq LSTM is usually a setup problem, not an LSTM-specific mystery.'
  • First verify target encoding, output activation, and loss configuration.
  • Check the training tensors for existing NaN or Inf values.
  • Reduce the learning rate and add gradient clipping.
  • Use a tiny-batch overfit test to isolate bad data preparation quickly.

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.