Python
Gradient Descent
Overflow Error
Machine Learning
Debugging

Implementing Gradient Descent In Python and receiving an overflow error

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

Overflow during gradient descent usually means the optimization steps exploded numerically. The cause is rarely "gradient descent is broken." It is usually one of a few practical issues: a learning rate that is too large, input features on wildly different scales, unstable math such as exp on large numbers, or an unexpected data type.

Why Overflow Happens

Gradient descent updates parameters by repeatedly subtracting the gradient:

weights = weights - learning_rate * gradient

If learning_rate * gradient becomes huge, the next parameter values can jump to very large magnitudes. After that, later computations such as squaring errors or evaluating exponentials may overflow.

A common failure path looks like this:

  1. Features have large values.
  2. Gradients become large.
  3. A large learning rate amplifies them further.
  4. The loss becomes enormous.
  5. Python or NumPy emits overflow warnings.

A Stable Baseline Example

Here is a simple linear regression implementation that behaves well because the learning rate is moderate and the input is normalized:

python
1import numpy as np
2
3x = np.array([1.0, 2.0, 3.0, 4.0, 5.0], dtype=np.float64)
4y = np.array([3.0, 5.0, 7.0, 9.0, 11.0], dtype=np.float64)
5
6# Standardize the feature to reduce gradient scale.
7x_scaled = (x - x.mean()) / x.std()
8
9w = 0.0
10b = 0.0
11lr = 0.05
12n = len(x_scaled)
13
14for epoch in range(1000):
15    y_pred = w * x_scaled + b
16    error = y_pred - y
17
18    dw = (2 / n) * np.sum(error * x_scaled)
19    db = (2 / n) * np.sum(error)
20
21    w -= lr * dw
22    b -= lr * db
23
24print("w =", w)
25print("b =", b)

This uses float64, scaled features, and a learning rate that does not blow up immediately.

What Causes Exploding Updates

The most common issue is a learning rate that is too high:

python
lr = 10.0

That may look harmless in small examples, but with even moderately sized gradients it can throw the parameters far outside the stable region.

Feature scale is the next usual problem. If one feature is measured in millions and another in decimals, the loss surface becomes poorly conditioned and gradient steps can become erratic. Standardization or normalization often fixes this faster than changing the optimizer.

Logistic Regression And exp Overflow

Another common source of overflow is the sigmoid function:

python
1import numpy as np
2
3def sigmoid(z):
4    return 1 / (1 + np.exp(-z))

If z becomes very negative or very positive, np.exp can overflow. A numerically safer implementation clips the input:

python
1import numpy as np
2
3def stable_sigmoid(z):
4    z = np.clip(z, -500, 500)
5    return 1 / (1 + np.exp(-z))

Clipping is not a substitute for fixing the underlying optimization, but it prevents one unstable intermediate value from crashing the whole run.

Practical Fixes

When you hit overflow, try these in order:

  1. Reduce the learning rate.
  2. Scale or standardize the features.
  3. Confirm you are using floating-point arrays such as float64.
  4. Print loss and gradient norms every few iterations.
  5. Clip gradients or activations only if needed after the basics are fixed.

A debugging loop might look like this:

python
1for epoch in range(200):
2    y_pred = w * x_scaled + b
3    error = y_pred - y
4
5    dw = (2 / n) * np.sum(error * x_scaled)
6    db = (2 / n) * np.sum(error)
7
8    if epoch % 20 == 0:
9        loss = np.mean(error ** 2)
10        print(f"epoch={epoch} loss={loss:.6f} dw={dw:.6f} db={db:.6f}")
11
12    w -= lr * dw
13    b -= lr * db

If the loss is increasing rapidly instead of decreasing, your updates are probably too aggressive.

Gradient Clipping

For neural networks or more complex models, gradient clipping can help:

python
max_grad = 1.0
dw = np.clip(dw, -max_grad, max_grad)
db = np.clip(db, -max_grad, max_grad)

This is a useful stabilization tool, especially in recurrent models, but it should not hide a fundamentally bad learning-rate choice or broken loss implementation.

Common Pitfalls

The biggest mistake is trying to fix overflow only by adding clips everywhere. Clipping can reduce symptoms, but large learning rates and poor feature scaling are still the real problem most of the time.

Another common issue is using integer arrays by accident. NumPy may upcast in some operations, but mixed types make debugging harder and can hide precision problems.

Developers also often skip monitoring. If you never print the loss, gradients, or parameter values, you miss the early warning signs before overflow appears.

Finally, if your code uses exponentials or logarithms, make sure those operations are implemented in a numerically stable way. Overflow during gradient descent is often a math-stability problem, not just an optimizer problem.

Summary

  • Overflow usually means gradient updates became numerically too large.
  • Start by lowering the learning rate and scaling the features.
  • Use float64 and monitor loss and gradients during training.
  • For sigmoid-based models, protect exp from extreme inputs.
  • Gradient clipping can help, but it should not replace basic stability fixes.

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.