I knew the log-sum-exp trick going in, so the first part felt okay.
First, explain the numerical stability issues with naive softmax entropy computation: overflow when exponentiating large logits and underflow when taking log of small probabilities. Then, present the log-sum-exp trick to compute log probabilities directly from logits, and derive the entropy formula using these log probabilities. Finally, discuss implementation details and potential pitfalls.
Pro tip: Mention that in practice, frameworks like PyTorch and TensorFlow have built-in numerically stable functions (e.g., log_softmax) that you should use, but understanding the underlying math is crucial for debugging and custom implementations.
Explain that directly exponentiating logits can overflow (for large values) and taking log of softmax probabilities can underflow (for small probabilities).
Describe how subtracting the maximum logit before exponentiation prevents overflow, and how log-sum-exp computes the log of the sum of exponentials stably.
Show that entropy H = -sum(p_i * log(p_i)) can be computed as H = logsumexp(logits) - sum(softmax(logits) * logits), using log probabilities.
Outline code steps: compute max logit, shifted logits, logsumexp, log probabilities, then entropy. Suggest testing with extreme values to ensure stability.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.
Explain that entropy can be maintained incrementally by tracking the running maximum logit and the sum of exponentials of shifted logits. When a new logit arrives, update the sum and adjust for a new maximum if necessary, then compute entropy using the current sum and maximum. Emphasize numerical stability and the need to avoid reprocessing previous logits.
Pro tip: Highlight that the shift by the maximum is crucial for numerical stability, and that when the maximum changes, the sum must be rescaled by exp(old_max - new_max). This shows you understand both the math and practical implementation concerns.
Maintain the current maximum logit (m) and the sum of exponentials of shifted logits (S = sum(exp(x_i - m))). Also track the count of logits (n) to compute the average.
When a new logit x arrives, if x > m, rescale S by exp(m - x) and set m = x; then add exp(x - m) to S. If x <= m, simply add exp(x - m) to S. Increment n.
The entropy (in nats) is log(S) + m - (sum of x_i * exp(x_i - m))/S. To compute this incrementally, also maintain the weighted sum T = sum(x_i * exp(x_i - m)), updating it similarly when a new logit arrives and rescaling when m changes.
Ensure that exp(m - x) does not underflow when m is much larger than x. Discuss the case of negative infinity or very large logits, and how to avoid overflow/underflow by using the shift.
The update is O(1) per logit, with O(1) memory. Discuss the trade-off between maintaining additional state (T) versus recomputing entropy from scratch, and the impact on precision.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.