The logarithm of Softmax computed in one stable pass via logsumexp; the input to NLL loss, KL divergence, and any log-probability computation.

Equation

Gradient (with and upstream ):

From scratch

import torch
 
def log_softmax(x, dim=-1):
    m = x.max(dim, keepdim=True).values
    z = x - m
    return z - torch.log(torch.exp(z).sum(dim, keepdim=True))
 
def log_softmax_grad(out, g, dim=-1):
    # out = log_softmax(x) from forward, g = dL/dout
    return g - out.exp() * g.sum(dim, keepdim=True)

Notes

  • Strictly better than softmax().log(): the latter underflows to whenever a probability rounds to 0.
  • Gradients stay bounded even for very confident predictions, which is why Cross-Entropy Loss fuses the two.
  • is the smoothed by the temperature-1 Softmax; its gradient is the softmax.
  • Handle masks by setting masked logits to a large negative finite value, not -inf, or an all-masked row yields nan.