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

Living in Log Space

Once you start summing log-probabilities, you sometimes need to combine log-probabilities — for example, the log of a sum of probabilities. The naive way () hits underflow when are very negative. The fix: log-sum-exp.

Subtracting the max keeps the exponentials in a sane range. Adding it back at the end recovers the right answer. scipy.special.logsumexp and torch.logsumexp handle it for you.

Why Softmax Is Really Log-Softmax in Disguise

Softmax: . Naive implementation underflows when is very negative. Modern frameworks subtract first — same trick as log-sum-exp.

If you ever need log(softmax(x)), never compute it as np.log(softmax(x)). Use log_softmax(x) directly — it's numerically stable. PyTorch and NumPy/SciPy provide it.

Whenever your math involves "log of a sum of exponentials," use the library's logsumexp. The naive version is correct in theory and wrong in float32.

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으로 뭉개지면 “아주 작다”와 “진짜 없다”를 구분하지 못하니까요.