Skip to content
C.W.K.
Stream
Lesson 04 of 05 · published

Log-Space Computing: The Underrated AI Skill

~8 min · log-likelihood, stability, logsumexp

Level 0Math Novice
0 XP0/59 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete

Combining Values in Log Space

Sometimes you need the log of a sum of probabilities while storing each probability as a log. Directly computing can underflow for very negative inputs and overflow for large positive inputs. The stable form is log-sum-exp:

Subtracting the maximum makes every exponent nonpositive, then adding it back preserves the exact algebra. Use scipy.special.logsumexp or torch.logsumexp.

Stable Softmax Uses the Same Shift

Softmax is . A naive implementation can overflow on large logits and underflow on very negative ones. Subtracting changes neither the normalized probabilities nor their ordering and keeps exponentials in range.

When you need log-probabilities, use a library's log_softmax rather than computing softmax and then taking a log. PyTorch provides torch.nn.functional.log_softmax, and SciPy provides scipy.special.log_softmax.

Use a library logsumexp or log-softmax whenever the formula contains a log of summed exponentials. The naive algebra is correct over real numbers and fragile in floating point.

Code

logsumexp earns its name·python
import numpy as np
from scipy.special import logsumexp

# Numerically dangerous: very negative log-probs
log_probs = np.array([-1000., -1001., -1002.])

# Naive: log(sum(exp(...)))
naive = np.log(np.sum(np.exp(log_probs)))   # -inf — underflow

# Stable: logsumexp
stable = logsumexp(log_probs)
print(stable)                                # ~-999.59 — correct

External links

Exercise

Implement logsumexp yourself: take an array of log-probabilities, subtract the max, exp, sum, log, add the max back. Compare with scipy.special.logsumexp on [-1000, -1001, -1002].
Hint
`` m = log_probs.max() stable = m + np.log(np.sum(np.exp(log_probs - m))) ``

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 2

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.
  1. Elechemist
    Elechemist

    import numpy as np from scipy.special import logsumexp

    logs = np.array([-1000, -1001, -1002])

    m = np.max(logs) shifted = logs - m exp_terms = np.exp(shifted) s = np.sum(exp_terms) manual = m + np.log(s)

    scipy_result = logsumexp(logs)

    print("manual :", manual) print("scipy :", scipy_result) print("diff :", abs(manual - scipy_result))

    출력

    manual : -999.5923940355556

    scipy : -999.5923940355556

    diff : 0.0

    언더플로우를 방지하려고 하는 기법인가보다. 에러값이 점점 작아질수록 중요한작업인듯,, 잘못하면 에러가있는데도 0으로 처리해버릴수있으니

    1. Pippa
      Pippa· warmElechemistElechemist

      네, 정확해요. logsumexp는 “언더플로우를 피하면서 로그 확률들을 안전하게 합치는 기법”이라고 보면 돼요.

      핵심은 m = np.max(logs)로 제일 큰 값을 기준점으로 잡고, 나머지를 logs - m처럼 상대값으로 옮긴다는 점이에요. 그러면 exp(-1000)처럼 바로 0에 가까워지는 계산 대신 exp(0), exp(-1), exp(-2)처럼 안전한 범위에서 계산할 수 있거든요.

      말씀하신 것처럼 에러나 확률이 아주 작아지는 작업일수록 중요해요. 그냥 0으로 뭉개지면 “아주 작다”와 “진짜 없다”를 구분하지 못하니까요.