InterviewPrepKit

Home / Coding / Machine Learning Coding / Numerical & Data / Numerically Stable Softmax

Numerically Stable Softmax

medium 00:00
Solving tips
  • Subtract the per-row max before exponentiating — it keeps the largest exponent at exp(0)=1 and never overflows, while leaving the result mathematically identical.
  • Work along axis=1 with keepdims=True so the max and sum broadcast back over each row cleanly.
  • Softmax is shift-invariant: subtracting any constant c from a row cancels in the numerator and denominator, so the output does not change.

Implement the softmax function over the rows of a 2-D array, using the max-subtraction trick so it does not overflow on large inputs. Softmax turns a row of raw scores (logits) into a probability distribution, and it sits at the output of nearly every classifier. Interviewers ask for the stable version because the naive formula silently breaks on large logits.

Definition

For a row of logits z = [z_1, ..., z_k], softmax is:

softmax(z)_i = exp(z_i) / sum_j exp(z_j)

The naive form overflows: exp(1000) is inf in float64, and inf / inf is nan. Because softmax is shift-invariant, subtracting the row maximum m = max(z) from every entry gives the identical result with no overflow:

softmax(z)_i = exp(z_i - m) / sum_j exp(z_j - m)

Now the largest exponent is exp(0) = 1, and every other term is in (0, 1].

Task

Complete softmax(logits) so it returns an array of the same shape where each row is a probability distribution over the k columns. Subtract the per-row maximum before exponentiating. Operate along the last axis (axis=1). Do not call scipy.special.softmax or any library softmax.

Example

logits = np.array([[1.0, 2.0, 3.0],
                   [1000.0, 1000.0, 1000.0]])
softmax(logits)
# -> array([[0.09003057, 0.24472847, 0.66524096],
#           [0.33333333, 0.33333333, 0.33333333]])

The first row is the ordinary softmax of [1, 2, 3]. The second row would overflow to nan without the max-subtraction, but stably resolves to a uniform distribution.

Constraints

  • logits is a 2-D array of shape (n, k) with 1 <= n, k.
  • Values may be large in magnitude (e.g. ±1000); the output must never contain inf or nan.
  • Use vectorized NumPy with broadcasting, not Python loops over rows.

Write your solution, then hit Run tests to check it — or get a mock grade from the AI coach.

The coach remembers this session — revise your code and ask again, and it grades your progress. It gives hints, not the answer.
Report a bug