TensorFlow
Gradient Computation
Machine Learning
TensorFlow 2.0
Deep Learning Debugging

Tensorflow 2.0 doesn't compute the gradient

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 TensorFlow returns None gradients, the cause is usually graph disconnection, non-trainable values, or operations outside GradientTape. This is one of the most common debugging issues in custom training loops. A systematic check of watched tensors, differentiable operations, and variable types usually resolves it quickly.

Minimal Working Gradient Example

Start from a known-good baseline.

python
1import tensorflow as tf
2
3w = tf.Variable(3.0)
4
5with tf.GradientTape() as tape:
6    loss = (w - 5.0) ** 2
7
8grad = tape.gradient(loss, w)
9print("grad:", grad.numpy())

If this works but your real model fails, the issue is in model wiring rather than TensorFlow installation.

Common Cause 1: Not Using tf.Variable

Gradients are computed for watched tensors, usually trainable variables. If you use Python numbers or constant tensors where trainable variables are expected, gradients can be missing.

Bad pattern:

python
w = tf.constant(3.0)  # not trainable by default

Correct pattern:

python
w = tf.Variable(3.0)

Common Cause 2: Operations Outside Tape Scope

Only operations executed inside the active tape context are recorded.

python
1x = tf.Variable(2.0)
2
3with tf.GradientTape() as tape:
4    y = x * x
5
6# recorded and differentiable
7grad = tape.gradient(y, x)
8print(grad.numpy())

If part of the forward pass runs before entering GradientTape, gradient flow breaks.

Common Cause 3: Non-Differentiable Ops

Some operations are not differentiable or behave poorly for gradient-based learning, such as hard indexing patterns, casts to integer, or string operations in the loss path.

If you must use such operations, keep them out of the trainable path or redesign the objective.

Common Cause 4: Numpy Break in the Middle

Using NumPy operations inside the forward pass can detach tensors from TensorFlow autodiff.

Problematic pattern:

python
1import numpy as np
2
3with tf.GradientTape() as tape:
4    x = tf.Variable([1.0, 2.0])
5    y = np.sum(x.numpy())  # breaks gradient path

Keep calculations in TensorFlow ops:

python
with tf.GradientTape() as tape:
    x = tf.Variable([1.0, 2.0])
    y = tf.reduce_sum(x)

Watching Non-Variable Tensors Manually

If you need gradients with respect to non-variable tensors, watch them explicitly.

python
1x = tf.constant(3.0)
2
3with tf.GradientTape() as tape:
4    tape.watch(x)
5    y = x ** 2
6
7grad = tape.gradient(y, x)
8print(grad.numpy())

This is useful for input-gradient methods and saliency techniques.

Multi-Variable Model Debug Pattern

In model training, inspect gradient list before applying optimizer updates.

python
1optimizer = tf.keras.optimizers.Adam(1e-3)
2
3with tf.GradientTape() as tape:
4    preds = model(batch_x, training=True)
5    loss = tf.reduce_mean(tf.keras.losses.mse(batch_y, preds))
6
7grads = tape.gradient(loss, model.trainable_variables)
8for v, g in zip(model.trainable_variables, grads):
9    if g is None:
10        print("missing grad for", v.name)
11
12optimizer.apply_gradients(zip(grads, model.trainable_variables))

This quickly identifies disconnected layers.

tf.function and Shape Issues

tf.function can hide debugging signals by tracing graphs. During debugging, run eagerly first, verify gradients, then add tf.function for performance.

Also check shape and dtype consistency. Integer tensors in loss paths can silently block useful gradients.

Practical Debug Checklist

Use this order:

  1. verify trainable values are tf.Variable
  2. ensure forward pass is inside tape scope
  3. remove NumPy operations from differentiable path
  4. check for non-differentiable ops
  5. print missing gradient variable names

This sequence resolves most cases quickly.

Common Pitfalls

  • Defining trainable parameters as constants instead of variables.
  • Computing part of the forward pass outside GradientTape scope.
  • Mixing NumPy operations into TensorFlow gradient path.
  • Expecting gradients through non-differentiable integer or indexing logic.
  • Applying optimizer without checking whether any gradients are None.

Summary

  • Missing gradients in TensorFlow usually come from graph disconnection, not random failure.
  • Keep trainable computations inside GradientTape and in TensorFlow ops.
  • Use tf.Variable for trainable parameters and tape.watch for custom cases.
  • Print gradient diagnostics before optimizer steps.
  • Debug eagerly first, then reintroduce tracing and performance optimizations.

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.