{"article":{"slug":"a-fix-for-softmax-and-cross-entropy","title":"A Fix for Softmax and Cross-Entropy","subtitle":null,"summary":"Jonathan T. Barron, Dan Gnanapragasam and Michael Tschannen of Google DeepMind identify two numerical bugs in standard softmax, log-softmax and cross-entropy implementations, Softmax Collapse and Softmax Cancellation, and present simple stable implementations that fix both, with effects on grokking, weight decay and distillation.","content_type":"research","language":"en","canonical_url":"https://jonbarron.info/softmaxfix/","author":{"name":"Jonathan T. Barron","url":null,"person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"Jon Barron","url":"https://jonbarron.info/","listing_slug":null,"listing":null},"topics":[{"name":"Machine Learning","slug":"machine-learning","url":"https://listedarticles.com/topics/machine-learning"},{"name":"Research","slug":"research","url":"https://listedarticles.com/topics/research"},{"name":"AI","slug":"ai","url":"https://listedarticles.com/topics/ai"},{"name":"Mathematics","slug":"mathematics","url":"https://listedarticles.com/topics/mathematics"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":5999,"reading_minutes":26,"published_at":"2026-10-24T02:07:13.754Z","added_at":"2026-10-24T02:07:13.754Z","updated_at":"2026-10-24T02:07:13.754Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":true},"profile_url":"https://listedarticles.com/articles/a-fix-for-softmax-and-cross-entropy","markdown_url":"https://listedarticles.com/articles/a-fix-for-softmax-and-cross-entropy.md","example":false,"citation":"Jonathan T. Barron, Jon Barron. \"A Fix for Softmax and Cross-Entropy.\" 24 Oct 2026. https://jonbarron.info/softmaxfix/ (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://jonbarron.info/softmaxfix/"},"body_markdown":"# A Fix for Softmax and Cross-Entropy\n\nJonathan T. Barron\n\nGoogle DeepMind\n\n\nDan Gnanapragasam\n\nGoogle DeepMind\n\n\nMichael Tschannen\n\nGoogle DeepMind\n\n\nAbstract\n\nStandard implementations of softmax, log-softmax, and\ncross-entropy have two numerical bugs.\nThe first bug, *Softmax Collapse*, rounds the target logit's gradient to\nzero if that one logit is much larger than the others, resulting in\ngradients that no longer sum to zero.\nThe second bug, *Softmax Cancellation*,\noccurs when student logits are close to teacher logits,\nand produces non-zero gradients even when the student and teacher logits are\nequal.\nWe present simple implementations of log-softmax, softmax, and\ncross-entropy that fix both bugs.\nOur fix eliminates the previously observed “slingshot” phenomenon,\nspeeds up grokking with weight decay, prevents accuracy collapse without weight\ndecay, stops student networks from drifting away from the teacher during\ndistillation, and shows that after memorization, logit growth is bounded by an\nequilibrium between weight decay and Adam's \\(\\epsilon\\) hyperparameter.\n\n## 1. Introduction\n\n![paper_fig2_legend.png](https://jonbarron.info/softmaxfix/img/paper_fig2_legend.png)\n\n![paper_fig1a_hard_cliff.png](https://jonbarron.info/softmaxfix/img/paper_fig1a_hard_cliff.png)\n\n**(a)** Softmax Collapse: \\(|g\\_{t}|\\) vs. margin \\(m\\)\n\n![paper_fig4a_floor.png](https://jonbarron.info/softmaxfix/img/paper_fig4a_floor.png)\n\n**(b)** Softmax Cancellation: \\(\\|\\nabla\\_{\\mathbf{z}\\_{\\mathrm{S}}}\\mathcal{L}\\|\\_2\\) as \\(\\mathbf{z}\\_{\\mathrm{S}}\n\\to \\mathbf{z}\\_{\\mathrm{T}}\\)\n\n**Figure 1:** The two bugs in standard softmax and cross-entropy.\n**(a) Softmax Collapse:** As a model becomes more confident in the\ncorrect class (thereby increasing the logit margin \\(m\\)), the true\ngradient on the target logit shrinks exponentially, but standard\nimplementations incorrectly round that gradient to zero once \\(m\\)\ncrosses a precision cliff (\\(\\approx 5.5\\) in bf16, \\(16.6\\) in\nfp32, and \\(36.7\\) in fp64).\n**(b) Softmax Cancellation:** In soft-target distillation, as\nstudent logits \\(\\mathbf{z}\\_{\\mathrm{S}}\\) approach teacher logits \\(\\mathbf{z}\\_{\\mathrm{T}}\\), the true\ngradient shrinks toward zero, but standard implementations lose precision\nand plateau at a non-zero noise floor.\nOur fix eliminates both bugs and yields accurate gradients across all\nprecisions.\n\nNaively computing softmax or cross-entropy on logits \\(\\mathbf{z} \\in\n\\mathbb{R}^{K}\\) as \\(e^{z\\_k} / \\sum\\_j e^{z\\_j}\\) overflows if\nany logit exceeds the floating-point exponent limit (\\(\\approx 88\\) in\nfp32), which is why standard implementations in all deep learning\nframeworks (JAX, PyTorch, TensorFlow, etc.) shift the input logits by\nsubtracting their maximum value \\(z\\_{\\max} = \\max\\_j z\\_j\\)\n([Higham, 2002](#bib-higham2002accuracy); [Blanchard et al., 2021](#bib-blanchard2021accurately)):\n\n\\[\\tilde{z}\\_k = z\\_k - z\\_{\\max}\\,, \\quad\n\\operatorname{logsoftmax}(\\mathbf{z})\\_k\n= \\tilde{z}\\_k - \\log \\sum\\_j e^{\\tilde{z}\\_j}\\,,\n\\quad\nq\\_k = \\operatorname{softmax}(\\mathbf{z})\\_k\n= \\frac{e^{\\tilde{z}\\_k}}\n{\\sum\\_j e^{\\tilde{z}\\_j}}\\,.\\]\n\n(1)\n\nFor a target distribution \\(\\mathbf{p} \\in \\Delta^{K-1}\\),\ncross-entropy (CE) is \\(\\mathcal{L}(\\mathbf{z}, \\mathbf{p}) =\n-\\sum\\_k p\\_k\\,\\operatorname{logsoftmax}(\\mathbf{z})\\_k\\), with exact gradient\n\\(\\mathbf{g} = \\nabla\\_{\\mathbf{z}} \\mathcal{L}(\\mathbf{z}, \\mathbf{p}) = \\mathbf{q} -\n\\mathbf{p}\\).\nThough subtracting \\(z\\_{\\max}\\) prevents overflow, two numerical bugs remain.\n\nThe first bug, *Softmax Collapse* ([Figure 1a](#fig:fig1a),\n[Prieto et al., 2025](#bib-prieto2025grokking)), occurs when a\nmodel correctly predicts the target class \\(t \\in \\{1, \\dots,\nK\\}\\) with high confidence, so that \\(z\\_{t} = z\\_{\\max}\\) is\nmuch larger than all non-target logits \\(z\\_j\\) (\\(j \\neq t\\)).\nWe measure this confidence by the *logit margin*, which is how much larger\nthe target logit is than the log-sum-exp of all non-target logits:\n\n\\[m = z\\_{t}\n- \\log \\sum\\_{j \\neq t} e^{z\\_j}\\,.\\]\n\n(2)\n\nIn [Equation 1](#eq:std_softmax), subtracting \\(z\\_{\\max} = z\\_{t}\\) sets\nthe shifted target logit to \\(\\tilde{z}\\_{t} = 0\\) (so\n\\(e^{\\tilde{z}\\_{t}} = 1\\) in the denominator), while the \\(K\n- 1\\) non-target exponentials sum to a small positive number \\(e^{-m} =\n\\sum\\_{j \\neq t} e^{z\\_j - z\\_{t}} \\ll 1\\).\nFloating-point numbers have much finer precision near \\(0\\) than near \\(1\\): in\nfp32, values near \\(0\\) can be as small as \\({\\sim}10^{-38}\\), whereas\nvalues added to \\(1.0\\) are lost to rounding below \\({\\sim}10^{-7}\\).\nBecause standard implementations form the denominator \\(1 + e^{-m}\\) by\nadding \\(e^{-m}\\) to \\(1.0\\), the \\(e^{-m}\\) term is lost to rounding\nonce the margin \\(m\\) exceeds a threshold \\(c\\_{d}\\) that we call the\n*precision cliff* (\\(c\\_{16} \\approx 5.5\\) in bf16,\n\\(c\\_{32} \\approx 16.6\\) in fp32, and \\(c\\_{64} \\approx\n36.7\\) in fp64).\nWhen \\(m > c\\_{d}\\), the denominator \\(1 + e^{-m}\\) evaluates to\nexactly \\(1.0\\), which causes \\(q\\_{t} = 1/(1 + e^{-m})\\) to\nevaluate to \\(1.0\\) and zeroes out both the loss and the target gradient\n\\(\\tilde{g}\\_{t} = q\\_{t} - 1 = 0.0\\).\nHowever, the non-target gradients \\(\\tilde{g}\\_j = q\\_j = e^{z\\_j -\nz\\_{t}} / (1 + e^{-m})\\) (\\(j \\neq t\\)) are evaluated\nnear \\(0\\) without adding \\(1.0\\) to their numerators, so they remain positive all\nthe way down to exponent underflow (\\(m \\approx 88\\)).\nBecause the target gradient rounds to \\(0.0\\) while the non-target gradients do\nnot, the gradients no longer sum to zero (\\(\\sum\\_k \\tilde{g}\\_k > 0\\)).\nWhen training with adaptive optimizers such as Adam and AdamW\n([Kingma & Ba, 2015](#bib-kingma2015adam); [Loshchilov & Hutter, 2019](#bib-loshchilov2019decoupled)), which normalize each gradient\nby a moving average of its magnitude, this asymmetry causes the recurring\n“slingshot” loss spikes observed by [Thilak et al. (2022)](#bib-thilak2022slingshot) and the\ngrokking failures studied by [Prieto et al. (2025)](#bib-prieto2025grokking).\nWhile prior works used surrogate losses ([Prieto et al., 2025](#bib-prieto2025grokking)), gradient\nprojection ([Liu et al., 2026](#bib-liu2026grokking)), or fp64 casting\n([Nanda et al., 2023](#bib-nanda2023progress); [Varma et al., 2023](#bib-varma2023explaining)) to ameliorate these issues, we\ninstead fix log-softmax, softmax, and cross-entropy directly\n([Section 2](#sec:bug1)).\n\nThe second bug, *Softmax Cancellation* ([Figure 1b](#fig:fig4a)), occurs in\nknowledge distillation ([Hinton et al., 2015](#bib-hinton2015distilling)) and KL regularization,\nwhere the target \\(\\mathbf{p} = \\operatorname{softmax}(\\mathbf{z}\\_{\\mathrm{T}})\\) comes from teacher logits\n\\(\\mathbf{z}\\_{\\mathrm{T}}\\).\nStandard implementations compute \\(\\mathbf{q} = \\operatorname{softmax}(\\mathbf{z}\\_{\\mathrm{S}})\\) and\n\\(\\mathbf{p} = \\operatorname{softmax}(\\mathbf{z}\\_{\\mathrm{T}})\\) separately and subtract them to get\n\\(\\tilde{\\mathbf{g}} = \\mathbf{q} - \\mathbf{p}\\).\nThis means that if \\(\\mathbf{z}\\_{\\mathrm{S}}\\) is close to \\(\\mathbf{z}\\_{\\mathrm{T}}\\), subtracting these\nnearly equal probabilities loses precision, and slight differences between the\nforward-pass softmax and backward-pass log-softmax formulas leave a\nnon-zero gradient even when \\(\\mathbf{z}\\_{\\mathrm{S}} = \\mathbf{z}\\_{\\mathrm{T}}\\).\nWe fix this by computing \\(\\mathbf{q} - \\mathbf{p}\\) directly from \\(\\mathbf{z}\\_{\\mathrm{S}} -\n\\mathbf{z}\\_{\\mathrm{T}}\\) in log space ([Section 3](#sec:bug2)).\n\n## 2. Softmax Collapse\n\nWhen the target logit \\(z\\_{t} = z\\_{\\max}\\) is the largest logit,\nshifting by \\(z\\_{\\max}\\) in [Equation 1](#eq:std_softmax) sets\n\\(\\tilde{z}\\_{t} = 0\\) and \\(\\tilde{z}\\_j = z\\_j -\nz\\_{t} < 0\\) for \\(j \\neq t\\), so the denominator is\n\\(\\sum\\_i e^{\\tilde{z}\\_i} = 1 + \\sum\\_{j \\neq t} e^{z\\_j -\nz\\_{t}} = 1 + e^{-m}\\).\nMathematically, the hard-target loss is \\(\\mathcal{L}(\\mathbf{z}, t) =\n-\\operatorname{logsoftmax}(\\mathbf{z})\\_{t} = \\log(1 + e^{-m})\\), with gradients\n\n\\[g\\_{t}\n= \\underbrace{\\frac{1}{1 + e^{-m}} - 1}\\_{\\text{Standard}}\n= \\underbrace{-\\frac{e^{-m}}{1 + e^{-m}}}\\_{\\text{Fixed}}\\,,\n\\qquad\ng\\_j = \\frac{e^{z\\_j - z\\_{t}}}{1 + e^{-m}}\n\\quad \\text{for } j \\neq t\\,,\\]\n\n(3)\n\nwhich sum to zero (\\(\\sum\\_k g\\_k = 0\\)).\nIn floating point, however, the two expressions for \\(g\\_{t}\\) in\n[Equation 3](#eq:hard_exact) behave very differently once \\(m > c\\_{d}\\),\nwhere \\(e^{-m}\\) is too small to change \\(1.0\\) when added to it\n([Figure 1a](#fig:fig1a)).\nStandard implementations add \\(1\\) and \\(e^{-m}\\) to form the denominator \\(1 +\ne^{-m}\\), which rounds to \\(1\\) when \\(m > c\\_{d}\\).\nIn the forward pass, \\(\\log(1 + e^{-m})\\) then evaluates to \\(\\log(1) = 0\\),\nzeroing out both \\(\\operatorname{logsoftmax}(\\mathbf{z})\\_{t}\\) and \\(\\mathcal{L}(\\mathbf{z},\nt)\\).\nIn the backward pass, standard cross-entropy implementations compute\n\\(q\\_{t} = 1/(1 + e^{-m}) = 1\\) and subtract \\(1\\) to get\n\\(\\tilde{g}\\_{t} = q\\_{t} - 1 = 0\\).\nIn contrast, our fixed expression \\(-e^{-m}/(1 + e^{-m})\\) keeps\n\\(e^{-m}\\) in the numerator: even when the denominator \\(1 + e^{-m}\\)\nrounds to \\(1.0\\), dividing \\(-e^{-m}\\) by \\(1.0\\) preserves \\(g\\_{t}\n\\approx -e^{-m}\\) down to exponent underflow (\\(m \\approx 88\\)).\n\nWhile \\(\\tilde{g}\\_{t}\\) rounds to zero when \\(m > c\\_{d}\\), the\nnon-target gradients do not.\nFor each non-target class \\(j \\neq t\\), standard cross-entropy computes\n\\(\\tilde{g}\\_j = q\\_j = e^{z\\_j - z\\_{t}} / (1 +\ne^{-m})\\).\nBecause the numerator \\(e^{z\\_j - z\\_{t}}\\) is evaluated directly\nfrom the negative difference \\(z\\_j - z\\_{t}\\) without adding\n\\(1\\), it remains accurate down to exponent underflow while the denominator rounds\nto \\(1\\).\nWhen \\(m > c\\_{d}\\), standard cross-entropy therefore zeroes out only the\ntarget entry \\(t\\) while all \\(K - 1\\) non-target gradients\nremain positive:\n\n\\[\\tilde{g}\\_k = \\mathbf{1}{[k \\neq t]}\\,g\\_k\\,, \\qquad\n\\sum\\_k \\tilde{g}\\_k = -g\\_{t}\n= \\frac{e^{-m}}{1 + e^{-m}} > 0\n\\quad \\text{for } m > c\\_{d}\\,.\\]\n\n(4)\n\nThe same bug affects standalone \\(\\operatorname{softmax}(\\mathbf{z})\\) ([Qiu & Yao, 2026](#bib-qiu2026why)): once\n\\(m > c\\_{d}\\), its backward pass rounds \\(q\\_{i\\_{\\max}}\\) (\\(i\\_{\\max} =\n\\arg\\max\\_i z\\_i\\)) to \\(1\\) and zeroes \\(\\tilde{g}\\_{i\\_{\\max}}\\) while the other\ngradients stay non-zero.\n\nThis bug can be fixed by never adding \\(1\\) to \\(e^{-m}\\) directly.\nIn \\(\\operatorname{logsoftmax}(\\mathbf{z})\\) and \\(\\operatorname{softmax}(\\mathbf{z})\\), only the largest logit\n\\(z\\_{i\\_{\\max}}\\) is shifted to \\(0\\) (where \\(e^0 = 1\\) in the denominator).\nInstead of including \\(e^0 = 1\\) in the sum of exponentials, we set\n\\(\\tilde{z}\\_{i\\_{\\max}} = 0\\), compute the margin \\(m\\) by excluding \\(i\\_{\\max}\\)\nfrom the log-sum-exp ([Blanchard et al., 2021](#bib-blanchard2021accurately)), and combine them with a\nnumerically stable \\(\\operatorname{softplus}(x) = \\log(1 + e^x)\\) (with\n\\(\\operatorname{softmax}(\\mathbf{z})\\_k = \\exp(\\operatorname{logsoftmax}(\\mathbf{z})\\_k)\\)):\n\n\\[\\tilde{z}\\_k\n= \\mathbf{1}{[k \\neq i\\_{\\max}]}{(z\\_k - z\\_{i\\_{\\max}})}\\,,\n\\;\\;\nm = -\\operatorname\\*{LSE}\\_{j \\neq i\\_{\\max}} \\tilde{z}\\_j\\,,\n\\;\\;\n\\operatorname{logsoftmax}(\\mathbf{z})\\_k = \\tilde{z}\\_k - \\operatorname{softplus}(-m)\\,.\\]\n\n(5)\n\nFor hard-target cross-entropy with target \\(t\\), we can use\n\\(t\\) directly in place of \\(i\\_{\\max}\\) without an \\(\\arg\\max\\):\n\n\\[m = -\\operatorname\\*{LSE}\\_{j \\neq t}(z\\_j - z\\_{t})\\,,\n\\qquad\n\\mathcal{L}(\\mathbf{z}, t)\n= \\log(1 + e^{-m})\n= \\operatorname{softplus}(-m)\\,.\\]\n\n(6)\n\nBecause the \\(t\\)-th slot is replaced with the constant \\(0\\) rather than\n\\(z\\_{t} - z\\_{t}\\), \\(z\\_{t}\\) only appears in\n\\(\\mathcal{L}\\) through the \\(K - 1\\) differences \\(z\\_j -\nz\\_{t}\\) (\\(j \\neq t\\)), so autodiff correctly computes the\ntarget gradient as the negated sum of the non-target gradients:\n\n\\[g\\_j = e^{z\\_j - z\\_{t} - \\mathcal{L}}\n= \\frac{e^{z\\_j - z\\_{t}}}{1 + e^{-m}}\n\\quad \\text{for } j \\neq t\\,, \\qquad\ng\\_{t} = -\\sum\\_{j \\neq t} g\\_j\n= -\\frac{e^{-m}}{1 + e^{-m}}\\,.\\]\n\n(7)\n\nHere is a JAX implementation of log-softmax, softmax, and hard-target\ncross-entropy, which remains accurate down to exponent underflow and\nsatisfies \\(\\sum\\_k g\\_k = 0\\):\n\n```\nimport jax, jax.numpy as jnp, optax\n\ndef log_softmax(z):\n  i_max = jnp.argmax(z, axis=-1)\n  z_max = jnp.take_along_axis(z, i_max[..., None], axis=-1)  # Max logit.\n  is_max = jax.nn.one_hot(i_max, z.shape[-1], dtype=bool)    # Max mask.\n  shifted = jnp.where(is_max, 0.0, z - z_max)                # Exact 0 at argmax.\n  others = jnp.where(is_max, -jnp.inf, shifted)              # Exclude argmax from sum.\n  m = -jax.nn.logsumexp(others, axis=-1, keepdims=True)      # Logit margin.\n  return shifted - jax.nn.softplus(-m)                       # log_softmax(z).\n\nsoftmax = lambda z: jnp.exp(log_softmax(z))\n\ndef cross_entropy(z, t):\n  z_t = jnp.take_along_axis(z, t[..., None], axis=-1)        # Target logit.\n  is_t = jax.nn.one_hot(t, z.shape[-1], dtype=bool)          # Target mask.\n  others = jnp.where(is_t, -jnp.inf, z - z_t)                # Exclude target from sum.\n  m = -jax.nn.logsumexp(others, axis=-1)                     # Logit margin.\n  return jax.nn.softplus(-m)                                 # -log_softmax(z)_t.\n```\n\nAs an example, consider \\(\\mathbf{z} = [9.0, -9.0, -9.0]\\) and \\(t = 0\\).\nThe standard `jax.nn` and `optax` implementations return zero for\nthe target log-probability, loss, and target gradient, while our functions\nreturn accurate values whose gradients sum to zero:\n\n```\nz, t = jnp.array([9.0, -9.0, -9.0], dtype=jnp.float32), jnp.array(0)\nstd_ce = optax.softmax_cross_entropy_with_integer_labels\njax.nn.log_softmax(z)                       # ->           [ 0.0,      -18.0,     -18.0    ]\njax.grad(lambda z: jax.nn.softmax(z)[0])(z) # ->           [ 0.0,      -1.523e-8, -1.523e-8]\njax.value_and_grad(std_ce)(z, t)            # -> 0.0,      [ 0.0,       1.523e-8,  1.523e-8]\nlog_softmax(z)                              # ->           [-3.046e-8, -18.0,     -18.0    ]\njax.grad(lambda z: softmax(z)[0])(z)        # ->           [ 3.046e-8, -1.523e-8, -1.523e-8]\njax.value_and_grad(cross_entropy)(z, t)     # -> 3.046e-8, [-3.046e-8,  1.523e-8,  1.523e-8]\n```\n\n## 3. Softmax Cancellation\n\nGiven student logits \\(\\mathbf{z}\\_{\\mathrm{S}} \\in \\mathbb{R}^{K}\\) and teacher logits\n\\(\\mathbf{z}\\_{\\mathrm{T}} \\in \\mathbb{R}^{K}\\), standard soft-target cross-entropy\ncomputes \\(\\mathbf{p} = \\operatorname{softmax}(\\mathbf{z}\\_{\\mathrm{T}})\\) and evaluates\n\n\\[\\mathcal{L}(\\mathbf{z}\\_{\\mathrm{S}}, \\mathbf{z}\\_{\\mathrm{T}})\n= -\\sum\\_k p\\_k\\,\\operatorname{logsoftmax}(\\mathbf{z}\\_{\\mathrm{S}})\\_k\\,, \\quad\n\\mathbf{q} = \\operatorname{softmax}(\\mathbf{z}\\_{\\mathrm{S}})\\,, \\quad\n\\tilde{g}\\_k = \\frac{\\partial \\mathcal{L}}{\\partial z\\_{\\mathrm{S},k}}\n= q\\_k - p\\_k\\,.\\]\n\n(8)\n\nAs the student logits approach the teacher logits (\\(\\mathbf{z}\\_{\\mathrm{S}} \\to \\mathbf{z}\\_{\\mathrm{T}}\\)),\nthe true gradient \\(\\mathbf{g} = \\mathbf{q} - \\mathbf{p}\\) shrinks toward \\(\\mathbf{0}\\)\nand equals \\(\\mathbf{0}\\) when \\(\\mathbf{z}\\_{\\mathrm{S}} = \\mathbf{z}\\_{\\mathrm{T}}\\).\nIn floating point, however, computing \\(\\mathbf{q}\\) and \\(\\mathbf{p}\\) separately\nand subtracting them ([Equation 8](#eq:soft_buggy)) loses precision when\n\\(\\mathbf{z}\\_{\\mathrm{S}}\\) is close to \\(\\mathbf{z}\\_{\\mathrm{T}}\\), because the small logit difference\n\\(\\boldsymbol{\\delta} = \\mathbf{z}\\_{\\mathrm{S}} - \\mathbf{z}\\_{\\mathrm{T}}\\) is lost when \\(\\mathbf{q}\\) and\n\\(\\mathbf{p}\\) are rounded to probabilities before being subtracted\n([Figure 1b](#fig:fig4a)).\nFurthermore, because \\(\\mathbf{p} = \\operatorname{softmax}(\\mathbf{z}\\_{\\mathrm{T}})\\) in the forward pass\nand \\(\\mathbf{q} = \\exp(\\operatorname{logsoftmax}(\\mathbf{z}\\_{\\mathrm{S}}))\\) in the backward pass are\nevaluated using slightly different sequences of operations, \\(\\mathbf{q}\\) and\n\\(\\mathbf{p}\\) do not match to machine precision even when \\(\\mathbf{z}\\_{\\mathrm{S}} =\n\\mathbf{z}\\_{\\mathrm{T}}\\), leaving a non-zero gradient \\(\\tilde{\\mathbf{g}} = \\mathbf{q} - \\mathbf{p}\n\\neq \\mathbf{0}\\).\n\nTo avoid subtracting nearly equal probabilities, we pass \\(\\mathbf{z}\\_{\\mathrm{T}}\\) directly\nto our loss function and compute \\(\\mathbf{q} - \\mathbf{p}\\) in log space using\n\\(\\operatorname{expm1}(x) = e^x - 1\\) and \\(\\operatorname{log1p}(x) = \\log(1 + x)\\).\nGiven \\(\\boldsymbol{\\delta} = \\mathbf{z}\\_{\\mathrm{S}} - \\mathbf{z}\\_{\\mathrm{T}}\\), we center \\(\\boldsymbol{\\delta}\\) under\n\\(\\mathbf{p}\\) and write the log-ratio \\(s\\_k = \\log(q\\_k /\np\\_k)\\) and difference \\(u\\_k = q\\_k - p\\_k\\) as:\n\n\\[d\\_k = \\delta\\_k - \\sum\\_i p\\_i \\delta\\_i\\,,\n\\qquad\ns\\_k = d\\_k\n- \\operatorname{log1p}\\left(\\sum\\_i p\\_i \\operatorname{expm1}(d\\_i)\\right)\\,,\n\\qquad\nu\\_k = p\\_k \\operatorname{expm1}(s\\_k)\\,.\\]\n\n(9)\n\nBecause \\(\\sum\\_i p\\_i d\\_i = 0\\) and \\(\\operatorname{expm1}(x) \\ge x\\), the\ninput to \\(\\operatorname{log1p}\\) is always non-negative.\nWhen \\(|s\\_k| \\ge 1\\), we fall back to \\(u\\_k = q\\_k -\np\\_k\\) to avoid \\(0.0 \\times \\infty\\) if \\(p\\_k\\) rounds to \\(0.0\\)\nwhile \\(\\operatorname{expm1}\\) overflows, and we set \\(g\\_k = u\\_k - q\\_k\n\\sum\\_i u\\_i\\) so that \\(\\sum\\_k g\\_k = 0\\).\nBecause [Equation 9](#eq:soft_fix) avoids adding or subtracting \\(1\\), \\(\\mathbf{g}\\)\nremains accurate as \\(\\mathbf{z}\\_{\\mathrm{S}} \\to \\mathbf{z}\\_{\\mathrm{T}}\\) and is \\(\\mathbf{0}\\) when \\(\\mathbf{z}\\_{\\mathrm{S}} =\n\\mathbf{z}\\_{\\mathrm{T}}\\).\nHere is a JAX implementation of soft-target cross-entropy (using\n`log_softmax` and `softmax` from [Section 2](#sec:bug1)), which\nuses `jax.lax.stop_gradient` (`sg`) to return the forward loss\nwhile substituting \\(\\mathbf{g}\\) in the backward pass:\n\n```\ndef soft_target_cross_entropy(z_S, z_T):\n  log_q = log_softmax(z_S)\n  q, p = jnp.exp(log_q), softmax(z_T)\n  delta = z_S - z_T                                                    # Logit difference.\n  d = delta - jnp.sum(p * delta, axis=-1, keepdims=True)               # Center under p.\n  s = d - jnp.log1p(jnp.sum(p * jnp.expm1(d), axis=-1, keepdims=True)) # log(q / p).\n  u = jnp.where(jnp.abs(s) < 1, p * jnp.expm1(s), q - p)               # Difference q - p.\n  g = u - q * jnp.sum(u, axis=-1, keepdims=True)                       # Ensure sum(g) = 0.\n  sg = jax.lax.stop_gradient\n  loss = -jnp.sum(p * sg(log_q), axis=-1)                              # Forward loss.\n  return loss + jnp.sum(sg(g) * (z_S - sg(z_S)), axis=-1)              # Custom gradient g.\n```\n\nAs an example, let \\(\\mathbf{z}\\_{\\mathrm{S}}\\) be a small fp32 perturbation of\n\\(\\mathbf{z}\\_{\\mathrm{T}}\\).\nStandard soft-target cross-entropy shrinks the second gradient\nentry by nearly \\(3\\times\\), flips the sign of the third, and fails to sum to\nzero, while our implementation matches the exact fp64 gradient:\n\n```\nz_T = jnp.array([2.0, 1.0, 0.0], dtype=jnp.float32)\nz_S = z_T + jnp.array([-1e-7, 1e-7, 0.0], dtype=jnp.float32)\nstd_soft_ce = lambda z_S, z_T: -jnp.sum(jax.nn.softmax(z_T) * jax.nn.log_softmax(z_S))\njax.grad(std_soft_ce)(z_S, z_T)               # -> [-5.960e-8, 1.452e-8, -1.123e-9]\njax.grad(soft_target_cross_entropy)(z_S, z_T) # -> [-4.596e-8, 4.144e-8,  4.513e-9]\n# Exact (float64) gradient:                        [-4.596e-8, 4.144e-8,  4.513e-9]\n```\n\n## 4. The Slingshot Mechanism\n\nIn grokking ([Power et al., 2022](#bib-power2022grokking)), a network quickly memorizes the training\nset (\\(q\\_{t} \\to 1\\)) and generalizes much later.\nWhile studying grokking on modular addition with Adam\n([Kingma & Ba, 2015](#bib-kingma2015adam); [Loshchilov & Hutter, 2019](#bib-loshchilov2019decoupled)), [Thilak et al. (2022)](#bib-thilak2022slingshot)\nobserved the *slingshot mechanism*, where training after memorization\nalternates between flat loss plateaus near zero and sudden loss spikes that\ncoincide with jumps in test accuracy.\n\nThese slingshot spikes are a direct consequence of Softmax Collapse\n([Section 2](#sec:bug1)).\nRecall that AdamW updates parameters \\(\\boldsymbol{\\theta}\\) by subtracting\n\\(\\eta\\big(\\hat{\\mathbf{m}} / (\\sqrt{\\hat{\\mathbf{v}}} + \\epsilon) +\n\\lambda\\boldsymbol{\\theta}\\big)\\), where \\(\\hat{\\mathbf{m}}\\) and \\(\\hat{\\mathbf{v}}\\) are\nbias-corrected moving averages of the parameter gradient \\(\\mathbf{g} =\n\\nabla\\_{\\boldsymbol{\\theta}}\\mathcal{L}(\\boldsymbol{\\theta})\\) and its square (with decay rates \\(\\beta\\_1,\n\\beta\\_2\\)).\nAfter memorization, the logit margins \\(m\\) grow as the network pushes its\ntarget probabilities toward \\(1\\).\nOnce an example's margin exceeds the precision cliff \\(c\\_{d}\\), standard\ncross-entropy rounds its target gradient \\(\\tilde{g}\\_{t}\\) to zero while its\nnon-target gradients \\(\\tilde{g}\\_j > 0\\) (\\(j \\neq t\\)) remain positive.\nWhen all examples in a batch sit above \\(c\\_{d}\\), the parameter gradients nearly\nvanish and Adam's second moment \\(\\hat{v}\\_i\\) decays exponentially toward zero\nwhile weight decay slowly shrinks the parameters.\nEventually, weight decay or the residual non-target updates pull a few examples\nback below \\(c\\_{d}\\), where their target gradients \\(\\tilde{g}\\_{t} \\approx\n-e^{-m}\\) abruptly turn back on.\nBecause \\(\\sqrt{\\hat{v}\\_i}\\) decayed while those examples were above\n\\(c\\_{d}\\), Adam divides the restored gradients by a very small denominator\n\\(\\sqrt{\\hat{v}\\_i} + \\epsilon\\), producing a large parameter step that spikes\nthe training loss, resets \\(\\hat{v}\\_i\\), and repeats the cycle.\nWith our fixed cross-entropy, the target-logit gradient \\(g\\_{t} =\n-e^{-m}/(1 + e^{-m})\\) does not round to zero at \\(c\\_{d}\\), so\n\\(\\hat{m}\\_i\\) and \\(\\sqrt{\\hat{v}\\_i}\\) decay smoothly together and slingshot\nspikes disappear ([Figure 2](#fig:fig_slingshot)).\n\n![paper_fig_slingshot_legend.png](https://jonbarron.info/softmaxfix/img/paper_fig_slingshot_legend.png)\n\n![paper_fig_slingshot_a.png](https://jonbarron.info/softmaxfix/img/paper_fig_slingshot_a.png)\n\n**(a)** Mean logit margin \\(m\\)\n\n![paper_fig_slingshot_b.png](https://jonbarron.info/softmaxfix/img/paper_fig_slingshot_b.png)\n\n**(b)** Training loss\n\n![paper_fig_slingshot_c.png](https://jonbarron.info/softmaxfix/img/paper_fig_slingshot_c.png)\n\n**(c)** Test accuracy\n\n**Figure 2:** The slingshot mechanism ([Thilak et al., 2022](#bib-thilak2022slingshot)) with and without\nweight decay (5 random seeds, fp32).\n**Top row (\\(a + b \\bmod 31\\), \\(\\lambda = 1\\), \\(\\epsilon = 10^{-8}\\),\n[Varma et al., 2023](#bib-varma2023explaining)):** Standard cross-entropy hits the\nfp32 cliff (\\(m = c\\_{32} \\approx 16.6\\), where loss\nrounds to \\(0\\)) and repeatedly drops and rebounds, slowing and degrading\ngrokking; fixed cross-entropy crosses \\(c\\_{32}\\) smoothly, groks\nfaster on all 5 seeds, and saturates just above \\(c\\_{32}\\) near\n\\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}}) \\approx 18.4\\) ([Section 5](#sec:equilibria)).\n**Bottom row (\\(a^2 + b^2 \\bmod 97\\), \\(\\lambda = 0\\), \\(\\epsilon =\n10^{-16}\\), [Doshi et al., 2024](#bib-doshi2024grokking)):** Without weight decay, hitting\n\\(c\\_{32}\\) around step \\(1250\\) triggers a spike that drops standard\ncross-entropy test accuracy from \\(61\\%\\) to \\(23\\%\\), whereas fixed\ncross-entropy continues smoothly to \\(85\\%\\).\n\nWhether slingshot spikes appear to help or hurt generalization depends on how\nthe network's weight norm is controlled ([Figure 2](#fig:fig_slingshot)).\nWhen a network uses LayerNorm before the output layer and no weight decay\n([Thilak et al., 2022](#bib-thilak2022slingshot); [Prieto et al., 2025](#bib-prieto2025grokking)), growing the pre-LayerNorm\nweights does not change the logits, but it does shrink the effective step size\n\\(\\eta / \\|\\boldsymbol{\\theta}\\|\\_2\\); each slingshot spike inflates \\(\\|\\boldsymbol{\\theta}\\|\\_2\\) and\nacts as an accidental learning-rate decay.\nWhen weight norms are already controlled by weight decay\n([Varma et al., 2023](#bib-varma2023explaining)), slingshot spikes at \\(c\\_{32}\\) only slow\ndown and hurt grokking (\\(94 \\pm 5\\%\\) vs. \\(100 \\pm 0\\%\\) test accuracy on \\(a + b\n\\bmod 31\\); [Figure 2](#fig:fig_slingshot), top).\nAnd when neither LayerNorm nor weight decay is used ([Doshi et al., 2024](#bib-doshi2024grokking)), a\nsingle slingshot spike at \\(c\\_{32}\\) is destructive: on \\(a^2 + b^2 \\bmod\n97\\) (\\(\\lambda = 0\\), \\(\\epsilon = 10^{-16}\\)), standard cross-entropy tracks fixed\ncross-entropy up to \\(61\\%\\) test accuracy until \\(m\\) hits \\(c\\_{32}\\)\naround step \\(1250\\), where a spike drops test accuracy to \\(23\\%\\) (and from \\(60\\%\\)\nto \\(21\\%\\) on \\(a^3 + b \\bmod 97\\)), while fixed cross-entropy continues smoothly\nto \\(85\\%\\) ([Figure 2](#fig:fig_slingshot), bottom).\n\n## 5. Margin Equilibria\n\nIn [Figure 2a](#fig:fig_slingshot), our fixed cross-entropy eliminates the\nprecision cliff at \\(c\\_{32} \\approx 16.6\\), yet with weight decay\n(\\(\\lambda = 1\\), top) its margin still saturates just above \\(c\\_{32}\\)\nnear \\(18\\), whereas without weight decay (\\(\\lambda = 0\\), bottom) its margin\ncontinues to climb.\nThis plateau is the equilibrium where weight decay balances AdamW's normalized\ngradient step.\nAt a stationary point where the parameters stop changing, the moving averages\nconverge to \\(\\hat{m}\\_i = g\\_i\\) and \\(\\hat{v}\\_i = g\\_i^2\\) (so\n\\(\\sqrt{\\hat{v}\\_i} = |g\\_i|\\)), and setting the update to zero gives:\n\n\\[\\frac{\\hat{m}\\_i}{\\sqrt{\\hat{v}\\_i} + \\epsilon} + \\lambda\\theta\\_i = 0\n\\quad\\Longrightarrow\\quad\n\\frac{g\\_i}{|g\\_i| + \\epsilon} + \\lambda\\theta\\_i = 0\n\\quad \\forall i\\,.\\]\n\n(10)\n\nHere \\(\\eta\\), \\(\\beta\\_1\\), and \\(\\beta\\_2\\) cancel out, so RMSProp\n([Tieleman & Hinton, 2012](#bib-tieleman2012rmsprop)) and LaProp ([Ziyin et al., 2020](#bib-ziyin2020laprop)) share the same\nstationary point.\nAfter memorization, the gradients shrink exponentially with the margin\n(\\(|g\\_i| \\propto e^{-m}\\)).\nIf \\(\\epsilon = 0\\), the normalized gradient \\(g\\_i / |g\\_i| =\n\\mathrm{sign}(g\\_i)\\) has a magnitude of \\(1\\) no matter how small \\(|g\\_i|\\)\nbecomes, which causes the margin to grow until the gradients underflow.\nWhen \\(\\epsilon > 0\\), however, the normalized gradient has magnitude \\(\\approx 1\\)\nwhile \\(|g\\_i| \\gg \\epsilon\\), and shrinks as \\(g\\_i / \\epsilon \\propto\ne^{-m}\\) once \\(|g\\_i| \\ll \\epsilon\\) ([Figure 3](#fig:fig1b)).\nBalancing this shrinking step against weight decay \\(\\lambda\\theta\\_i\\) requires\n\\(|g\\_i| \\approx \\epsilon\\lambda|\\theta\\_i|\\)\n([Wortsman et al., 2024](#bib-wortsman2023small); [Molybog et al., 2023](#bib-molybog2023theory); [Everett et al., 2024](#bib-everett2024scaling); [Kosson et al., 2024](#bib-kosson2024rotational)), which acts like an \\(L\\_2\\) regularizer with weight\n\\(\\epsilon\\lambda\\) ([Rosset et al., 2004](#bib-rosset2004margin); [Soudry et al., 2018](#bib-soudry2018implicit)).\nSince \\(|g\\_i| \\propto e^{-m}\\), the margin stops growing at:\n\n\\[m^\\star(\\epsilon) \\approx \\log({{}^{1}\\!/\\!{}\\_{\\epsilon}})\\,.\\]\n\n(11)\n\n[Equation 11](#eq:margin_law) explains why the default \\(\\epsilon = 10^{-8}\\)\ncauses slingshot spikes in fp32: its equilibrium\n\\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}}) \\approx 18.4\\) sits just above \\(c\\_{32}\n\\approx 16.6\\) ([Figure 3](#fig:fig1b)), so standard cross-entropy hits the cliff\nbefore equilibrium (whereas for \\(\\epsilon \\ge 10^{-7}\\),\n\\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}}) \\le 16.1 < c\\_{32}\\) and standard\ncross-entropy settles without spiking).\nTo test [Equation 11](#eq:margin_law) across many orders of magnitude down to\n\\(\\epsilon = 0\\) in fp32 ([Figure 4](#fig:fig6)), we train with our\nfixed cross-entropy and LaProp on \\(a + b \\bmod 31\\), updating\n\\(\\sqrt{\\hat{\\mathbf{v}}}\\) directly without squaring \\(g\\_i\\) (which underflows in\nfp32 once \\(|g\\_i| < 2^{-63}\\), or \\(m \\approx 38\\)).\nWith weight decay (\\(\\lambda = 1\\), [Figure 4a](#fig:fig6a)), the margin for each\n\\(\\epsilon > 0\\) climbs along the \\(\\epsilon = 0\\) trajectory and levels off at\n\\(m^\\star(\\epsilon) = \\log({{}^{1}\\!/\\!{}\\_{\\epsilon}})\\), while \\(\\epsilon = 0\\) grows\nuntil the fp32 gradients underflow at \\(m \\approx 81.2\\).\nWithout weight decay (\\(\\lambda = 0\\), [Figure 4b](#fig:fig6b)), nothing balances\nthe \\(g\\_i / \\epsilon\\) step, so margins keep rising past\n\\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}})\\).\n\n![paper_fig1_legend.png](https://jonbarron.info/softmaxfix/img/paper_fig1_legend.png)\n\n**Figure 3:** Normalized Adam step\n\\(|g\\_{t}| / (|g\\_{t}| + \\epsilon)\\) vs. logit\nmargin \\(m\\) at \\(\\epsilon = 10^{-8}\\).\nWith our fixed cross-entropy, the step stays near \\(1\\) and decays\nsmoothly around \\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}}) \\approx 18.4\\), whereas\nstandard cross-entropy zeroes out \\(\\tilde{g}\\_{t}\\) at\n\\(c\\_{16} \\approx 5.5\\) and \\(c\\_{32} \\approx 16.6\\).\n\n![paper_fig1b_adam_eps.png](https://jonbarron.info/softmaxfix/img/paper_fig1b_adam_eps.png)\n\n![paper_fig6a.png](https://jonbarron.info/softmaxfix/img/paper_fig6a.png)\n\n**(a)** Weight decay (\\(\\lambda = 1\\))\n\n![paper_fig6b.png](https://jonbarron.info/softmaxfix/img/paper_fig6b.png)\n\n**(b)** No weight decay (\\(\\lambda = 0\\))\n\n**Figure 4:** Logit margins with our fixed cross-entropy and LaProp on \\(a + b \\bmod\n31\\) in fp32 (\\(\\beta\\_1 = 0.9\\), \\(\\beta\\_2 = 0.98\\); 3 seeds\nper setting as solid lines, analytical predictions\n\\(m^\\star(\\epsilon) = \\log({{}^{1}\\!/\\!{}\\_{\\epsilon}})\\) as dashed lines).\n**(a)** With weight decay (\\(\\lambda = 1\\)), margins level off at\n\\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}})\\).\n**(b)** Without weight decay (\\(\\lambda = 0\\)), margins overshoot\n\\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}})\\).\n\n## 6. Grokking Across Precisions and Benchmarks\n\nTo see how the precision cliff behaves across floating-point formats, we follow\n[Varma et al. (2023)](#bib-varma2023explaining) and [Lyle et al. (2025)](#bib-lyle2025grokking) and train a 1-layer\nwidth-\\(64\\) ReLU Transformer on \\(a + b \\bmod 31\\) (\\(50\\%\\) training split) for\n\\(10{,}000\\) epochs of full-batch AdamW (\\(\\eta = 10^{-3}\\), \\(\\beta\\_1 = 0.9\\),\n\\(\\beta\\_2 = 0.98\\), \\(\\lambda = 1\\)), varying the loss (standard vs. fixed\ncross-entropy), precision (bf16, fp32, fp64), and\n\\(\\epsilon \\in \\{10^{-8}, 10^{-12}, 10^{-16}\\}\\) ([Figure 5](#fig:fig2),\n[Table 1](#tab:baselines)).\nAt \\(\\epsilon = 10^{-8}\\) ([Figure 5](#fig:fig2), top), standard cross-entropy\nstalls at \\(c\\_{16} \\approx 5.5\\) in bf16 and repeatedly spikes at\n\\(c\\_{32} \\approx 16.6\\) in fp32, whereas fixed cross-entropy\ncrosses both cliffs smoothly to \\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}}) \\approx 18.4\\) and\nreaches \\(100\\%\\) test accuracy in all three precisions.\nReducing \\(\\epsilon\\) to \\(10^{-16}\\) ([Figure 5](#fig:fig2), bottom) raises the\nequilibrium to \\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}}) \\approx 36.8 > c\\_{64}\\),\nbreaking even fp64 standard cross-entropy at \\(c\\_{64} \\approx\n36.7\\) while fixed cross-entropy converges smoothly across all precisions.\n\nIn [Table 1](#tab:baselines) we summarize these results and compare against two\nrecent methods that modify the gradients or the loss to mitigate Softmax\nCollapse.\n[Liu et al. (2026)](#bib-liu2026grokking) subtract the mean logit gradient from each entry so the\ngradients sum to zero (“Zero-sum Proj.”).\nHowever, once \\(m > c\\_{32}\\) and \\(\\tilde{g}\\_{t} = 0\\),\nsubtracting the mean only gives the target logit \\(-{{}^{1}\\!/\\!{}\\_{K}}\\) of\nthe total non-target gradient, stalling \\(m\\) near \\(18\\) and dropping test\naccuracy below \\(50\\%\\) for \\(\\epsilon \\le 10^{-12}\\).\n[Prieto et al. (2025)](#bib-prieto2025grokking) propose “StableMax,” which replaces \\(\\exp(x)\\) in\nsoftmax with a piecewise rational function (\\(x + 1\\) for \\(x \\ge 0\\) and\n\\(1/(1 - x)\\) for \\(x < 0\\)).\nBecause this function grows linearly instead of exponentially, logit margins\nblow up to \\({\\sim}10^4\\) and test accuracy lags our fixed cross-entropy across\nall \\(\\epsilon\\).\n\nWe observe the same behavior across four grokking benchmarks at \\(\\epsilon =\n10^{-12}\\) ([Figure 6](#fig:fig3)): 1-layer Transformers on \\(a + b \\bmod 113\\)\n([Nanda et al., 2023](#bib-nanda2023progress)) and \\(a + b \\bmod 31\\) ([Varma et al., 2023](#bib-varma2023explaining)) with\n\\(\\lambda = 1\\), and 2-layer MLPs on \\(a^2 + b^2 \\bmod 97\\) and \\(a^3 + b \\bmod 97\\)\n([Doshi et al., 2024](#bib-doshi2024grokking)) with \\(\\lambda = 0.2\\).\nOn all four tasks, fp32 standard cross-entropy spikes once it hits\n\\(c\\_{32}\\), whereas fp32 fixed cross-entropy matches\nfp64 standard cross-entropy and reaches \\(100\\%\\) test accuracy.\n\n![paper_fig2_legend.png](https://jonbarron.info/softmaxfix/img/paper_fig2_legend.png)\n\n![paper_fig2a.png](https://jonbarron.info/softmaxfix/img/paper_fig2a.png)\n\n**(a)** Mean logit margin \\(m\\)\n\n![paper_fig2b.png](https://jonbarron.info/softmaxfix/img/paper_fig2b.png)\n\n**(b)** Training loss\n\n![paper_fig2c.png](https://jonbarron.info/softmaxfix/img/paper_fig2c.png)\n\n**(c)** Test accuracy\n\n**Figure 5:** Standard cross-entropy fails at the precision cliff \\(c\\_{d}\\) of its\nfloating-point format; fixed cross-entropy removes the cliff across all\nprecisions (\\(a + b \\bmod 31\\), \\(\\lambda = 1\\); 2 of 5 seeds shown).\nTop: \\(\\epsilon = 10^{-8}\\).\nBottom: \\(\\epsilon = 10^{-16}\\), where even fp64 standard\ncross-entropy fails at \\(c\\_{64}\\) while fixed cross-entropy\nconverges smoothly.\n\n|  |  | Test Accuracy (%) | | | | | | | | | Final Margin \\(m\\) | | |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n|  | Variant\\(\\epsilon =\\) | \\(10^{-8}\\) | | | \\(10^{-12}\\) | | | \\(10^{-16}\\) | | | \\(10^{-8}\\) | \\(10^{-12}\\) | \\(10^{-16}\\) |\n| fp32 | Fixed CE | 100.0 | \\(\\pm\\) | 0.0 | 99.6 | \\(\\pm\\) | 0.7 | 99.0 | \\(\\pm\\) | 2.3 | 17.9 | 27.4 | 36.8 |\n| fp32 | Standard CE | 94.3 | \\(\\pm\\) | 5.4 | 96.4 | \\(\\pm\\) | 5.1 | 96.5 | \\(\\pm\\) | 4.3 | 13.0 | 15.1 | 12.7 |\n| bf16 | Fixed CE | 100.0 | \\(\\pm\\) | 0.1 | 99.8 | \\(\\pm\\) | 0.2 | 98.9 | \\(\\pm\\) | 2.4 | 17.9 | 27.4 | 36.8 |\n| bf16 | Standard CE | 93.3 | \\(\\pm\\) | 7.4 | 94.9 | \\(\\pm\\) | 4.9 | 94.2 | \\(\\pm\\) | 8.3 | 5.1 | 5.6 | 5.8 |\n| fp64 | Fixed CE | 100.0 | \\(\\pm\\) | 0.0 | 99.5 | \\(\\pm\\) | 1.1 | 99.0 | \\(\\pm\\) | 2.0 | 17.9 | 27.4 | 36.8 |\n| fp64 | Standard CE | 100.0 | \\(\\pm\\) | 0.0 | 100.0 | \\(\\pm\\) | 0.1 | 97.2 | \\(\\pm\\) | 3.2 | 17.9 | 27.4 | 30.1 |\n| fp32 | Zero-sum Proj. ([Liu et al., 2026](#bib-liu2026grokking)) | 97.9 | \\(\\pm\\) | 3.2 | 48.9 | \\(\\pm\\) | 2.6 | 49.3 | \\(\\pm\\) | 2.5 | 17.0 | 18.9 | 18.9 |\n| fp32 | StableMax ([Prieto et al., 2025](#bib-prieto2025grokking)) | 97.3 | \\(\\pm\\) | 4.7 | 95.6 | \\(\\pm\\) | 2.0 | 97.3 | \\(\\pm\\) | 4.3 | 3200 | 5661 | 6313 |\n| fp64 | StableMax ([Prieto et al., 2025](#bib-prieto2025grokking)) | 97.4 | \\(\\pm\\) | 4.2 | 96.7 | \\(\\pm\\) | 5.3 | 95.6 | \\(\\pm\\) | 2.7 | 3170 | 21252 | 2322 |\n\n**Table 1:** Comparison of loss functions on modular addition (\\(a + b \\bmod 31\\), \\(\\lambda\n= 1\\), \\(3\\)–\\(5\\) seeds) across \\(\\epsilon \\in \\{10^{-8}, 10^{-12}, 10^{-16}\\}\\).\nFixed CE reaches the predicted equilibrium margin (\\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}})\n\\approx 18.4, 27.6, 36.8\\)) and \\({\\ge}98.9\\%\\) test accuracy across all\nprecisions, whereas Standard CE stalls once \\(m^\\star(\\epsilon)\\) exceeds the\ncliff \\(c\\_{d}\\) (\\(c\\_{16} \\approx 5.5\\) in bf16,\n\\(c\\_{32} \\approx 16.6\\) in fp32, and \\(c\\_{64}\n\\approx 36.7\\) in fp64).\n\n![paper_fig3_legend.png](https://jonbarron.info/softmaxfix/img/paper_fig3_legend.png)\n\n![paper_fig3a.png](https://jonbarron.info/softmaxfix/img/paper_fig3a.png)\n\n**(a)** \\(a{+}b \\bmod 113\\)   \n [Nanda et al. (2023)](#bib-nanda2023progress)\n\n![paper_fig3b.png](https://jonbarron.info/softmaxfix/img/paper_fig3b.png)\n\n**(b)** \\(a{+}b \\bmod 31\\)   \n [Varma et al. (2023)](#bib-varma2023explaining)\n\n![paper_fig3c.png](https://jonbarron.info/softmaxfix/img/paper_fig3c.png)\n\n**(c)** \\(a^2{+}b^2 \\bmod 97\\)   \n [Doshi et al. (2024)](#bib-doshi2024grokking)\n\n![paper_fig3d.png](https://jonbarron.info/softmaxfix/img/paper_fig3d.png)\n\n**(d)** \\(a^3{+}b \\bmod 97\\)   \n [Doshi et al. (2024)](#bib-doshi2024grokking)\n\n**Figure 6:** Results across four grokking tasks at \\(\\epsilon = 10^{-12}\\) (2 of 3–5\nseeds shown): 1-layer Transformers (a, b) and 2-layer MLPs (c, d).\nFixed cross-entropy in fp32 (blue) matches fp64\nstandard cross-entropy (red), while standard cross-entropy in\nfp32 (orange) breaks at \\(c\\_{32}\\).\n\n## 7. Soft-Target Distillation\n\nTo see how Softmax Cancellation ([Section 3](#sec:bug2)) affects optimization,\nwe initialize a student network with the weights of a teacher trained to \\(100\\%\\)\naccuracy on \\(a + b \\bmod 53\\) (\\(\\boldsymbol{\\theta}\\_{\\mathrm{S}}^{(0)} = \\boldsymbol{\\theta}\\_{\\mathrm{T}}\\)), and run\n\\(2{,}000\\) steps of Adam (\\(\\eta = 2\\times 10^{-3}\\), \\(\\lambda = 0\\),\n\\(\\epsilon = 10^{-8}\\)) at distillation temperature \\(T = 4\\)\n([Hinton et al., 2015](#bib-hinton2015distilling)), which keeps the scaled margin \\(m/T\\)\nbelow \\(c\\_{16}\\) so \\(\\mathbf{p}\\) does not round to one-hot.\nBecause \\(\\mathbf{z}\\_{\\mathrm{S}} = \\mathbf{z}\\_{\\mathrm{T}}\\) initially, the true gradient is zero and the\nstudent should not move.\nHowever, standard soft-target cross-entropy has a non-zero residual gradient at\n\\(\\mathbf{z}\\_{\\mathrm{S}} = \\mathbf{z}\\_{\\mathrm{T}}\\) due to the mismatch between its forward softmax\nand backward log-softmax ([Figure 1b](#fig:fig4a)).\nWhenever this residual gradient exceeds \\(\\epsilon\\), Adam normalizes it into\nsteps of size \\(\\eta\\) ([Figure 7](#fig:fig4)): in fp64 the residual\n(\\({\\sim}10^{-17}\\)) lies well below \\(\\epsilon = 10^{-8}\\) so the student stays\nnear \\(\\mathrm{KL} = 0\\), in fp32 (\\({\\sim}10^{-8}\\)) it causes an initial\n\\(\\mathrm{KL}\\) spike and a \\({\\sim}10^{-6}\\) floor, and in bf16\n(\\({\\sim}10^{-3}\\)) it drives the student away from the teacher and degrades test\naccuracy.\nOur fixed soft-target cross-entropy returns \\(\\mathbf{g} = \\mathbf{0}\\) at \\(\\mathbf{z}\\_{\\mathrm{S}} =\n\\mathbf{z}\\_{\\mathrm{T}}\\), so the student stays at \\(\\mathrm{KL} = 0\\) and \\(100\\%\\) accuracy\nacross all precisions.\n\n![paper_fig4_legend.png](https://jonbarron.info/softmaxfix/img/paper_fig4_legend.png)\n\n![paper_fig4b_kl.png](https://jonbarron.info/softmaxfix/img/paper_fig4b_kl.png)\n\n**(a)** Held-out \\(\\mathrm{KL}(\\mathbf{p}\\_{\\mathrm{T}} \\parallel \\mathbf{q}\\_{\\mathrm{S}})\\)\n\n![paper_fig4c_acc.png](https://jonbarron.info/softmaxfix/img/paper_fig4c_acc.png)\n\n**(b)** Test accuracy\n\n**Figure 7:** Soft-target distillation when the student is initialized with the\nteacher's weights (\\(\\boldsymbol{\\theta}\\_{\\mathrm{S}}^{(0)} = \\boldsymbol{\\theta}\\_{\\mathrm{T}}\\), \\(T = 4\\),\n\\(\\epsilon = 10^{-8}\\), 2 of 3 seeds shown).\nFixed soft-target cross-entropy stays at \\(\\mathrm{KL} = 0\\) and \\(100\\%\\)\naccuracy across all precisions; standard soft-target cross-entropy\namplifies rounding error into parameter drift in bf16 and an\ninitial \\(\\mathrm{KL}\\) spike and \\({\\sim}10^{-6}\\) floor in fp32.\n\n## 8. Conclusion\n\nWe have presented simple fixes for two numerical bugs in standard\nimplementations of softmax, log-softmax, and cross-entropy:\n*Softmax Collapse*, which zeroes out the dominant logit's gradient at high\nconfidence while leaving non-dominant gradients non-zero, and *Softmax\nCancellation*, which loses precision when student logits approach teacher logits\nin soft-target distillation.\nRewriting these functions in log space using \\(\\operatorname{softplus}\\), \\(\\operatorname{expm1}\\), and\n\\(\\operatorname{log1p}\\) restores accurate, zero-sum gradients across bf16,\nfp32, and fp64 without internally casting to higher\nprecision.\nFixing these bugs eliminates slingshot loss spikes during grokking, prevents\nstudent networks from drifting away from the teacher during distillation, and\nreveals that logit margins under AdamW and weight decay naturally converge to\n\\(\\log({{}^{1}\\!/\\!{}\\_{\\epsilon}})\\).\nThough the extreme margins and near-zero student–teacher gaps probed by our\nexperiments are uncommon in standard large-scale training, our fixed functions\nare easy drop-in replacements that can be implemented without meaningful\nslowdown, and may prove useful whenever models make high-confidence predictions\nor distill from close teachers.\n\n**Acknowledgments:**\nWe thank Jean-Baptiste Alayrac, Forrester Cole, Roy Frostig, Mark Hamilton, Miki\nRubinstein, Keith Rush, and Brandon Zhao for their helpful advice.\n\n## References\n\n1. [Blanchard et al., 2021] Pierre Blanchard, Desmond J. Higham, and Nicholas J. Higham. Accurately computing the log-sum-exp and softmax functions. *IMA Journal of Numerical Analysis*, 2021.\n2. [Doshi et al., 2024] Darshil Doshi, Tianyu He, Aritra Das, and Andrey Gromov. Grokking modular polynomials. *[arXiv:2406.03495](https://arxiv.org/abs/2406.03495)*, 2024.\n3. [Everett et al., 2024] Katie Everett, Lechao Xiao, Mitchell Wortsman, Alexander A. Alemi, Roman Novak, Peter J. Liu, Izzeddin Gur, Jascha Sohl-Dickstein, Leslie Pack Kaelbling, Jaehoon Lee, and Jeffrey Pennington. Scaling exponents across parameterizations and optimizers. *ICML*, 2024.\n4. [Higham, 2002] Nicholas J. Higham. *Accuracy and stability of numerical algorithms*. SIAM, 2nd edition, 2002.\n5. [Hinton et al., 2015] Geoffrey Hinton, Oriol Vinyals, and Jeff Dean. Distilling the knowledge in a neural network. *[arXiv:1503.02531](https://arxiv.org/abs/1503.02531)*, 2015.\n6. [Kingma & Ba, 2015] Diederik P. Kingma and Jimmy Ba. Adam: A method for stochastic optimization. *ICLR*, 2015.\n7. [Kosson et al., 2024] Atli Kosson, Bettina Messmer, and Martin Jaggi. Rotational equilibrium: How weight decay balances learning across neural networks. *ICML*, 2024.\n8. [Liu et al., 2026] Hanqing Liu, Jianjun Cao, Yuanze Li, and Zijian Zhou. Grokking or glitching? How low-precision drives Slingshot loss spikes. *[arXiv:2605.06152](https://arxiv.org/abs/2605.06152)*, 2026.\n9. [Loshchilov & Hutter, 2019] Ilya Loshchilov and Frank Hutter. Decoupled weight decay regularization. *ICLR*, 2019.\n10. [Lyle et al., 2025] Clare Lyle, Ghada Sokar, András György, and Razvan Pascanu. What can grokking teach us about learning under non-stationarity? *Conference on Lifelong Learning Agents*, 2025.\n11. [Molybog et al., 2023] Igor Molybog, Peter Albert, Moya Chen, Zachary DeVito, David Esiobu, Naman Goyal, Punit Singh Koura, Sharan Narang, Andrew Poulton, Ruan Silva, et al. A theory on Adam instability in large-scale machine learning. *[arXiv:2304.09871](https://arxiv.org/abs/2304.09871)*, 2023.\n12. [Nanda et al., 2023] Neel Nanda, Lawrence Chan, Tom Lieberum, Jess Smith, and Jacob Steinhardt. Progress measures for grokking via mechanistic interpretability. *ICLR*, 2023.\n13. [Power et al., 2022] Alethea Power, Yuri Burda, Harri Edwards, Igor Babuschkin, and Vedant Misra. Grokking: Generalization beyond overfitting on small algorithmic datasets. *[arXiv:2201.02177](https://arxiv.org/abs/2201.02177)*, 2022.\n14. [Prieto et al., 2025] Lucas Prieto, Melih Barsbey, Pedro A. M. Mediano, and Tolga Birdal. Grokking at the edge of numerical stability. *ICLR*, 2025.\n15. [Qiu & Yao, 2026] Haiquan Qiu and Quanming Yao. Why low-precision Transformer training fails: An analysis on Flash Attention. *ICLR*, 2026.\n16. [Rosset et al., 2004] Saharon Rosset, Ji Zhu, and Trevor Hastie. Margin maximizing loss functions. *NeurIPS*, 2004.\n17. [Soudry et al., 2018] Daniel Soudry, Elad Hoffer, Mor Shpigel Nacson, Suriya Gunasekar, and Nathan Srebro. The implicit bias of gradient descent on separable data. *JMLR*, 2018.\n18. [Thilak et al., 2022] Vimal Thilak, Etai Littwin, Shuangfei Zhai, Omid Saremi, Roni Paiss, and Joshua Susskind. The Slingshot mechanism: An empirical study of adaptive optimizers and the grokking phenomenon. *[arXiv:2206.04817](https://arxiv.org/abs/2206.04817)*, 2022.\n19. [Tieleman & Hinton, 2012] Tijmen Tieleman and Geoffrey Hinton. Lecture 6.5—RMSProp: Divide the gradient by a running average of its recent magnitude. *COURSERA: Neural Networks for Machine Learning*, 2012.\n20. [Varma et al., 2023] Vikrant Varma, Rohin Shah, Zachary Kenton, János Kramár, and Ramana Kumar. Explaining grokking through circuit efficiency. *[arXiv:2309.02390](https://arxiv.org/abs/2309.02390)*, 2023.\n21. [Wortsman et al., 2024] Mitchell Wortsman, Peter J. Liu, Lechao Xiao, Katie Everett, Alexander Alemi, Ben Adlam, John D. Co-Reyes, Izzeddin Gur, Abhishek Kumar, Roman Novak, et al. Small-scale proxies for large-scale Transformer training instabilities. *ICLR*, 2024.\n22. [Ziyin et al., 2020] Liu Ziyin, Zhikang T. Wang, and Masahito Ueda. LaProp: Separating momentum and adaptivity in Adam. *[arXiv:2002.04839](https://arxiv.org/abs/2002.04839)*, 2020.\n","body_html":"<h1 id=\"a-fix-for-softmax-and-cross-entropy\">A Fix for Softmax and Cross-Entropy</h1>\n<p>Jonathan T. Barron</p>\n<p>Google DeepMind</p>\n<p>Dan Gnanapragasam</p>\n<p>Google DeepMind</p>\n<p>Michael Tschannen</p>\n<p>Google DeepMind</p>\n<p>Abstract</p>\n<p>Standard implementations of softmax, log-softmax, and\ncross-entropy have two numerical bugs.\nThe first bug, <em>Softmax Collapse</em>, rounds the target logit&#39;s gradient to\nzero if that one logit is much larger than the others, resulting in\ngradients that no longer sum to zero.\nThe second bug, <em>Softmax Cancellation</em>,\noccurs when student logits are close to teacher logits,\nand produces non-zero gradients even when the student and teacher logits are\nequal.\nWe present simple implementations of log-softmax, softmax, and\ncross-entropy that fix both bugs.\nOur fix eliminates the previously observed “slingshot” phenomenon,\nspeeds up grokking with weight decay, prevents accuracy collapse without weight\ndecay, stops student networks from drifting away from the teacher during\ndistillation, and shows that after memorization, logit growth is bounded by an\nequilibrium between weight decay and Adam&#39;s (\\epsilon) hyperparameter.</p>\n<h2 id=\"1-introduction\">1. Introduction</h2>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig2_legend.png\" alt=\"paper_fig2_legend.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig1a_hard_cliff.png\" alt=\"paper_fig1a_hard_cliff.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(a)</strong> Softmax Collapse: (|g_{t}|) vs. margin (m)</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig4a_floor.png\" alt=\"paper_fig4a_floor.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(b)</strong> Softmax Cancellation: (|\\nabla_{\\mathbf{z}_{\\mathrm{S}}}\\mathcal{L}|<em>2) as (\\mathbf{z}</em>{\\mathrm{S}}\n\\to \\mathbf{z}_{\\mathrm{T}})</p>\n<p><strong>Figure 1:</strong> The two bugs in standard softmax and cross-entropy.\n<strong>(a) Softmax Collapse:</strong> As a model becomes more confident in the\ncorrect class (thereby increasing the logit margin (m)), the true\ngradient on the target logit shrinks exponentially, but standard\nimplementations incorrectly round that gradient to zero once (m)\ncrosses a precision cliff ((\\approx 5.5) in bf16, (16.6) in\nfp32, and (36.7) in fp64).\n<strong>(b) Softmax Cancellation:</strong> In soft-target distillation, as\nstudent logits (\\mathbf{z}<em>{\\mathrm{S}}) approach teacher logits (\\mathbf{z}</em>{\\mathrm{T}}), the true\ngradient shrinks toward zero, but standard implementations lose precision\nand plateau at a non-zero noise floor.\nOur fix eliminates both bugs and yields accurate gradients across all\nprecisions.</p>\n<p>Naively computing softmax or cross-entropy on logits (\\mathbf{z} \\in\n\\mathbb{R}^{K}) as (e^{z_k} / \\sum_j e^{z_j}) overflows if\nany logit exceeds the floating-point exponent limit ((\\approx 88) in\nfp32), which is why standard implementations in all deep learning\nframeworks (JAX, PyTorch, TensorFlow, etc.) shift the input logits by\nsubtracting their maximum value (z_{\\max} = \\max_j z_j)\n(<a href=\"#bib-higham2002accuracy\">Higham, 2002</a>; <a href=\"#bib-blanchard2021accurately\">Blanchard et al., 2021</a>):</p>\n<p>[\\tilde{z}_k = z_k - z_{\\max}\\,, \\quad\n\\operatorname{logsoftmax}(\\mathbf{z})_k\n= \\tilde{z}_k - \\log \\sum_j e^{\\tilde{z}_j}\\,,\n\\quad\nq_k = \\operatorname{softmax}(\\mathbf{z})_k\n= \\frac{e^{\\tilde{z}_k}}\n{\\sum_j e^{\\tilde{z}_j}}\\,.]</p>\n<p>(1)</p>\n<p>For a target distribution (\\mathbf{p} \\in \\Delta^{K-1}),\ncross-entropy (CE) is (\\mathcal{L}(\\mathbf{z}, \\mathbf{p}) =\n-\\sum_k p_k\\,\\operatorname{logsoftmax}(\\mathbf{z})_k), with exact gradient\n(\\mathbf{g} = \\nabla_{\\mathbf{z}} \\mathcal{L}(\\mathbf{z}, \\mathbf{p}) = \\mathbf{q} -\n\\mathbf{p}).\nThough subtracting (z_{\\max}) prevents overflow, two numerical bugs remain.</p>\n<p>The first bug, <em>Softmax Collapse</em> (<a href=\"#fig:fig1a\">Figure 1a</a>,\n<a href=\"#bib-prieto2025grokking\">Prieto et al., 2025</a>), occurs when a\nmodel correctly predicts the target class (t \\in {1, \\dots,\nK}) with high confidence, so that (z_{t} = z_{\\max}) is\nmuch larger than all non-target logits (z_j) ((j \\neq t)).\nWe measure this confidence by the <em>logit margin</em>, which is how much larger\nthe target logit is than the log-sum-exp of all non-target logits:</p>\n<p>[m = z_{t}</p>\n<ul><li>\\log \\sum_{j \\neq t} e^{z_j}\\,.]</li></ul>\n<p>(2)</p>\n<p>In <a href=\"#eq:std_softmax\">Equation 1</a>, subtracting (z_{\\max} = z_{t}) sets\nthe shifted target logit to (\\tilde{z}_{t} = 0) (so\n(e^{\\tilde{z}_{t}} = 1) in the denominator), while the (K</p>\n<ul><li><p>1) non-target exponentials sum to a small positive number (e^{-m} =</p><p>\\sum_{j \\neq t} e^{z_j - z_{t}} \\ll 1).\nFloating-point numbers have much finer precision near (0) than near (1): in\nfp32, values near (0) can be as small as ({\\sim}10^{-38}), whereas\nvalues added to (1.0) are lost to rounding below ({\\sim}10^{-7}).\nBecause standard implementations form the denominator (1 + e^{-m}) by\nadding (e^{-m}) to (1.0), the (e^{-m}) term is lost to rounding\nonce the margin (m) exceeds a threshold (c_{d}) that we call the\n<em>precision cliff</em> ((c_{16} \\approx 5.5) in bf16,\n(c_{32} \\approx 16.6) in fp32, and (c_{64} \\approx\n36.7) in fp64).\nWhen (m &gt; c_{d}), the denominator (1 + e^{-m}) evaluates to\nexactly (1.0), which causes (q_{t} = 1/(1 + e^{-m})) to\nevaluate to (1.0) and zeroes out both the loss and the target gradient\n(\\tilde{g}<em>{t} = q</em>{t} - 1 = 0.0).\nHowever, the non-target gradients (\\tilde{g}_j = q_j = e^{z_j -\nz_{t}} / (1 + e^{-m})) ((j \\neq t)) are evaluated\nnear (0) without adding (1.0) to their numerators, so they remain positive all\nthe way down to exponent underflow ((m \\approx 88)).\nBecause the target gradient rounds to (0.0) while the non-target gradients do\nnot, the gradients no longer sum to zero ((\\sum_k \\tilde{g}_k &gt; 0)).\nWhen training with adaptive optimizers such as Adam and AdamW\n(<a href=\"#bib-kingma2015adam\">Kingma &amp; Ba, 2015</a>; <a href=\"#bib-loshchilov2019decoupled\">Loshchilov &amp; Hutter, 2019</a>), which normalize each gradient\nby a moving average of its magnitude, this asymmetry causes the recurring\n“slingshot” loss spikes observed by <a href=\"#bib-thilak2022slingshot\">Thilak et al. (2022)</a> and the\ngrokking failures studied by <a href=\"#bib-prieto2025grokking\">Prieto et al. (2025)</a>.\nWhile prior works used surrogate losses (<a href=\"#bib-prieto2025grokking\">Prieto et al., 2025</a>), gradient\nprojection (<a href=\"#bib-liu2026grokking\">Liu et al., 2026</a>), or fp64 casting\n(<a href=\"#bib-nanda2023progress\">Nanda et al., 2023</a>; <a href=\"#bib-varma2023explaining\">Varma et al., 2023</a>) to ameliorate these issues, we\ninstead fix log-softmax, softmax, and cross-entropy directly\n(<a href=\"#sec:bug1\">Section 2</a>).</p></li></ul>\n<p>The second bug, <em>Softmax Cancellation</em> (<a href=\"#fig:fig4a\">Figure 1b</a>), occurs in\nknowledge distillation (<a href=\"#bib-hinton2015distilling\">Hinton et al., 2015</a>) and KL regularization,\nwhere the target (\\mathbf{p} = \\operatorname{softmax}(\\mathbf{z}_{\\mathrm{T}})) comes from teacher logits\n(\\mathbf{z}_{\\mathrm{T}}).\nStandard implementations compute (\\mathbf{q} = \\operatorname{softmax}(\\mathbf{z}_{\\mathrm{S}})) and\n(\\mathbf{p} = \\operatorname{softmax}(\\mathbf{z}_{\\mathrm{T}})) separately and subtract them to get\n(\\tilde{\\mathbf{g}} = \\mathbf{q} - \\mathbf{p}).\nThis means that if (\\mathbf{z}<em>{\\mathrm{S}}) is close to (\\mathbf{z}</em>{\\mathrm{T}}), subtracting these\nnearly equal probabilities loses precision, and slight differences between the\nforward-pass softmax and backward-pass log-softmax formulas leave a\nnon-zero gradient even when (\\mathbf{z}<em>{\\mathrm{S}} = \\mathbf{z}</em>{\\mathrm{T}}).\nWe fix this by computing (\\mathbf{q} - \\mathbf{p}) directly from (\\mathbf{z}_{\\mathrm{S}} -\n\\mathbf{z}_{\\mathrm{T}}) in log space (<a href=\"#sec:bug2\">Section 3</a>).</p>\n<h2 id=\"2-softmax-collapse\">2. Softmax Collapse</h2>\n<p>When the target logit (z_{t} = z_{\\max}) is the largest logit,\nshifting by (z_{\\max}) in <a href=\"#eq:std_softmax\">Equation 1</a> sets\n(\\tilde{z}_{t} = 0) and (\\tilde{z}_j = z_j -\nz_{t} &lt; 0) for (j \\neq t), so the denominator is\n(\\sum_i e^{\\tilde{z}<em>i} = 1 + \\sum</em>{j \\neq t} e^{z_j -\nz_{t}} = 1 + e^{-m}).\nMathematically, the hard-target loss is (\\mathcal{L}(\\mathbf{z}, t) =\n-\\operatorname{logsoftmax}(\\mathbf{z})_{t} = \\log(1 + e^{-m})), with gradients</p>\n<p>[g_{t}\n= \\underbrace{\\frac{1}{1 + e^{-m}} - 1}_{\\text{Standard}}\n= \\underbrace{-\\frac{e^{-m}}{1 + e^{-m}}}_{\\text{Fixed}}\\,,\n\\qquad\ng_j = \\frac{e^{z_j - z_{t}}}{1 + e^{-m}}\n\\quad \\text{for } j \\neq t\\,,]</p>\n<p>(3)</p>\n<p>which sum to zero ((\\sum_k g_k = 0)).\nIn floating point, however, the two expressions for (g_{t}) in\n<a href=\"#eq:hard_exact\">Equation 3</a> behave very differently once (m &gt; c_{d}),\nwhere (e^{-m}) is too small to change (1.0) when added to it\n(<a href=\"#fig:fig1a\">Figure 1a</a>).\nStandard implementations add (1) and (e^{-m}) to form the denominator (1 +\ne^{-m}), which rounds to (1) when (m &gt; c_{d}).\nIn the forward pass, (\\log(1 + e^{-m})) then evaluates to (\\log(1) = 0),\nzeroing out both (\\operatorname{logsoftmax}(\\mathbf{z})_{t}) and (\\mathcal{L}(\\mathbf{z},\nt)).\nIn the backward pass, standard cross-entropy implementations compute\n(q_{t} = 1/(1 + e^{-m}) = 1) and subtract (1) to get\n(\\tilde{g}<em>{t} = q</em>{t} - 1 = 0).\nIn contrast, our fixed expression (-e^{-m}/(1 + e^{-m})) keeps\n(e^{-m}) in the numerator: even when the denominator (1 + e^{-m})\nrounds to (1.0), dividing (-e^{-m}) by (1.0) preserves (g_{t}\n\\approx -e^{-m}) down to exponent underflow ((m \\approx 88)).</p>\n<p>While (\\tilde{g}<em>{t}) rounds to zero when (m &gt; c</em>{d}), the\nnon-target gradients do not.\nFor each non-target class (j \\neq t), standard cross-entropy computes\n(\\tilde{g}_j = q_j = e^{z_j - z_{t}} / (1 +\ne^{-m})).\nBecause the numerator (e^{z_j - z_{t}}) is evaluated directly\nfrom the negative difference (z_j - z_{t}) without adding\n(1), it remains accurate down to exponent underflow while the denominator rounds\nto (1).\nWhen (m &gt; c_{d}), standard cross-entropy therefore zeroes out only the\ntarget entry (t) while all (K - 1) non-target gradients\nremain positive:</p>\n<p>[\\tilde{g}_k = \\mathbf{1}{[k \\neq t]}\\,g_k\\,, \\qquad\n\\sum_k \\tilde{g}<em>k = -g</em>{t}\n= \\frac{e^{-m}}{1 + e^{-m}} &gt; 0\n\\quad \\text{for } m &gt; c_{d}\\,.]</p>\n<p>(4)</p>\n<p>The same bug affects standalone (\\operatorname{softmax}(\\mathbf{z})) (<a href=\"#bib-qiu2026why\">Qiu &amp; Yao, 2026</a>): once\n(m &gt; c_{d}), its backward pass rounds (q_{i_{\\max}}) ((i_{\\max} =\n\\arg\\max_i z_i)) to (1) and zeroes (\\tilde{g}<em>{i</em>{\\max}}) while the other\ngradients stay non-zero.</p>\n<p>This bug can be fixed by never adding (1) to (e^{-m}) directly.\nIn (\\operatorname{logsoftmax}(\\mathbf{z})) and (\\operatorname{softmax}(\\mathbf{z})), only the largest logit\n(z_{i_{\\max}}) is shifted to (0) (where (e^0 = 1) in the denominator).\nInstead of including (e^0 = 1) in the sum of exponentials, we set\n(\\tilde{z}<em>{i</em>{\\max}} = 0), compute the margin (m) by excluding (i_{\\max})\nfrom the log-sum-exp (<a href=\"#bib-blanchard2021accurately\">Blanchard et al., 2021</a>), and combine them with a\nnumerically stable (\\operatorname{softplus}(x) = \\log(1 + e^x)) (with\n(\\operatorname{softmax}(\\mathbf{z})_k = \\exp(\\operatorname{logsoftmax}(\\mathbf{z})_k))):</p>\n<p>[\\tilde{z}_k\n= \\mathbf{1}{[k \\neq i_{\\max}]}{(z_k - z_{i_{\\max}})}\\,,\n\\;\\;\nm = -\\operatorname*{LSE}<em>{j \\neq i</em>{\\max}} \\tilde{z}_j\\,,\n\\;\\;\n\\operatorname{logsoftmax}(\\mathbf{z})_k = \\tilde{z}_k - \\operatorname{softplus}(-m)\\,.]</p>\n<p>(5)</p>\n<p>For hard-target cross-entropy with target (t), we can use\n(t) directly in place of (i_{\\max}) without an (\\arg\\max):</p>\n<p>[m = -\\operatorname*{LSE}_{j \\neq t}(z_j - z_{t})\\,,\n\\qquad\n\\mathcal{L}(\\mathbf{z}, t)\n= \\log(1 + e^{-m})\n= \\operatorname{softplus}(-m)\\,.]</p>\n<p>(6)</p>\n<p>Because the (t)-th slot is replaced with the constant (0) rather than\n(z_{t} - z_{t}), (z_{t}) only appears in\n(\\mathcal{L}) through the (K - 1) differences (z_j -\nz_{t}) ((j \\neq t)), so autodiff correctly computes the\ntarget gradient as the negated sum of the non-target gradients:</p>\n<p>[g_j = e^{z_j - z_{t} - \\mathcal{L}}\n= \\frac{e^{z_j - z_{t}}}{1 + e^{-m}}\n\\quad \\text{for } j \\neq t\\,, \\qquad\ng_{t} = -\\sum_{j \\neq t} g_j\n= -\\frac{e^{-m}}{1 + e^{-m}}\\,.]</p>\n<p>(7)</p>\n<p>Here is a JAX implementation of log-softmax, softmax, and hard-target\ncross-entropy, which remains accurate down to exponent underflow and\nsatisfies (\\sum_k g_k = 0):</p>\n<pre><code>import jax, jax.numpy as jnp, optax\n\ndef log_softmax(z):\n  i_max = jnp.argmax(z, axis=-1)\n  z_max = jnp.take_along_axis(z, i_max[..., None], axis=-1)  # Max logit.\n  is_max = jax.nn.one_hot(i_max, z.shape[-1], dtype=bool)    # Max mask.\n  shifted = jnp.where(is_max, 0.0, z - z_max)                # Exact 0 at argmax.\n  others = jnp.where(is_max, -jnp.inf, shifted)              # Exclude argmax from sum.\n  m = -jax.nn.logsumexp(others, axis=-1, keepdims=True)      # Logit margin.\n  return shifted - jax.nn.softplus(-m)                       # log_softmax(z).\n\nsoftmax = lambda z: jnp.exp(log_softmax(z))\n\ndef cross_entropy(z, t):\n  z_t = jnp.take_along_axis(z, t[..., None], axis=-1)        # Target logit.\n  is_t = jax.nn.one_hot(t, z.shape[-1], dtype=bool)          # Target mask.\n  others = jnp.where(is_t, -jnp.inf, z - z_t)                # Exclude target from sum.\n  m = -jax.nn.logsumexp(others, axis=-1)                     # Logit margin.\n  return jax.nn.softplus(-m)                                 # -log_softmax(z)_t.</code></pre>\n<p>As an example, consider (\\mathbf{z} = [9.0, -9.0, -9.0]) and (t = 0).\nThe standard <code>jax.nn</code> and <code>optax</code> implementations return zero for\nthe target log-probability, loss, and target gradient, while our functions\nreturn accurate values whose gradients sum to zero:</p>\n<pre><code>z, t = jnp.array([9.0, -9.0, -9.0], dtype=jnp.float32), jnp.array(0)\nstd_ce = optax.softmax_cross_entropy_with_integer_labels\njax.nn.log_softmax(z)                       # -&gt;           [ 0.0,      -18.0,     -18.0    ]\njax.grad(lambda z: jax.nn.softmax(z)[0])(z) # -&gt;           [ 0.0,      -1.523e-8, -1.523e-8]\njax.value_and_grad(std_ce)(z, t)            # -&gt; 0.0,      [ 0.0,       1.523e-8,  1.523e-8]\nlog_softmax(z)                              # -&gt;           [-3.046e-8, -18.0,     -18.0    ]\njax.grad(lambda z: softmax(z)[0])(z)        # -&gt;           [ 3.046e-8, -1.523e-8, -1.523e-8]\njax.value_and_grad(cross_entropy)(z, t)     # -&gt; 3.046e-8, [-3.046e-8,  1.523e-8,  1.523e-8]</code></pre>\n<h2 id=\"3-softmax-cancellation\">3. Softmax Cancellation</h2>\n<p>Given student logits (\\mathbf{z}_{\\mathrm{S}} \\in \\mathbb{R}^{K}) and teacher logits\n(\\mathbf{z}_{\\mathrm{T}} \\in \\mathbb{R}^{K}), standard soft-target cross-entropy\ncomputes (\\mathbf{p} = \\operatorname{softmax}(\\mathbf{z}_{\\mathrm{T}})) and evaluates</p>\n<p>[\\mathcal{L}(\\mathbf{z}<em>{\\mathrm{S}}, \\mathbf{z}</em>{\\mathrm{T}})\n= -\\sum_k p_k\\,\\operatorname{logsoftmax}(\\mathbf{z}_{\\mathrm{S}})_k\\,, \\quad\n\\mathbf{q} = \\operatorname{softmax}(\\mathbf{z}_{\\mathrm{S}})\\,, \\quad\n\\tilde{g}<em>k = \\frac{\\partial \\mathcal{L}}{\\partial z</em>{\\mathrm{S},k}}\n= q_k - p_k\\,.]</p>\n<p>(8)</p>\n<p>As the student logits approach the teacher logits ((\\mathbf{z}<em>{\\mathrm{S}} \\to \\mathbf{z}</em>{\\mathrm{T}})),\nthe true gradient (\\mathbf{g} = \\mathbf{q} - \\mathbf{p}) shrinks toward (\\mathbf{0})\nand equals (\\mathbf{0}) when (\\mathbf{z}<em>{\\mathrm{S}} = \\mathbf{z}</em>{\\mathrm{T}}).\nIn floating point, however, computing (\\mathbf{q}) and (\\mathbf{p}) separately\nand subtracting them (<a href=\"#eq:soft_buggy\">Equation 8</a>) loses precision when\n(\\mathbf{z}<em>{\\mathrm{S}}) is close to (\\mathbf{z}</em>{\\mathrm{T}}), because the small logit difference\n(\\boldsymbol{\\delta} = \\mathbf{z}<em>{\\mathrm{S}} - \\mathbf{z}</em>{\\mathrm{T}}) is lost when (\\mathbf{q}) and\n(\\mathbf{p}) are rounded to probabilities before being subtracted\n(<a href=\"#fig:fig4a\">Figure 1b</a>).\nFurthermore, because (\\mathbf{p} = \\operatorname{softmax}(\\mathbf{z}_{\\mathrm{T}})) in the forward pass\nand (\\mathbf{q} = \\exp(\\operatorname{logsoftmax}(\\mathbf{z}_{\\mathrm{S}}))) in the backward pass are\nevaluated using slightly different sequences of operations, (\\mathbf{q}) and\n(\\mathbf{p}) do not match to machine precision even when (\\mathbf{z}_{\\mathrm{S}} =\n\\mathbf{z}_{\\mathrm{T}}), leaving a non-zero gradient (\\tilde{\\mathbf{g}} = \\mathbf{q} - \\mathbf{p}\n\\neq \\mathbf{0}).</p>\n<p>To avoid subtracting nearly equal probabilities, we pass (\\mathbf{z}_{\\mathrm{T}}) directly\nto our loss function and compute (\\mathbf{q} - \\mathbf{p}) in log space using\n(\\operatorname{expm1}(x) = e^x - 1) and (\\operatorname{log1p}(x) = \\log(1 + x)).\nGiven (\\boldsymbol{\\delta} = \\mathbf{z}<em>{\\mathrm{S}} - \\mathbf{z}</em>{\\mathrm{T}}), we center (\\boldsymbol{\\delta}) under\n(\\mathbf{p}) and write the log-ratio (s_k = \\log(q_k /\np_k)) and difference (u_k = q_k - p_k) as:</p>\n<p>[d_k = \\delta_k - \\sum_i p_i \\delta_i\\,,\n\\qquad\ns_k = d_k</p>\n<ul><li><p>\\operatorname{log1p}\\left(\\sum_i p_i \\operatorname{expm1}(d_i)\\right)\\,,</p><p>\\qquad\nu_k = p_k \\operatorname{expm1}(s_k)\\,.]</p></li></ul>\n<p>(9)</p>\n<p>Because (\\sum_i p_i d_i = 0) and (\\operatorname{expm1}(x) \\ge x), the\ninput to (\\operatorname{log1p}) is always non-negative.\nWhen (|s_k| \\ge 1), we fall back to (u_k = q_k -\np_k) to avoid (0.0 \\times \\infty) if (p_k) rounds to (0.0)\nwhile (\\operatorname{expm1}) overflows, and we set (g_k = u_k - q_k\n\\sum_i u_i) so that (\\sum_k g_k = 0).\nBecause <a href=\"#eq:soft_fix\">Equation 9</a> avoids adding or subtracting (1), (\\mathbf{g})\nremains accurate as (\\mathbf{z}<em>{\\mathrm{S}} \\to \\mathbf{z}</em>{\\mathrm{T}}) and is (\\mathbf{0}) when (\\mathbf{z}_{\\mathrm{S}} =\n\\mathbf{z}_{\\mathrm{T}}).\nHere is a JAX implementation of soft-target cross-entropy (using\n<code>log_softmax</code> and <code>softmax</code> from <a href=\"#sec:bug1\">Section 2</a>), which\nuses <code>jax.lax.stop_gradient</code> (<code>sg</code>) to return the forward loss\nwhile substituting (\\mathbf{g}) in the backward pass:</p>\n<pre><code>def soft_target_cross_entropy(z_S, z_T):\n  log_q = log_softmax(z_S)\n  q, p = jnp.exp(log_q), softmax(z_T)\n  delta = z_S - z_T                                                    # Logit difference.\n  d = delta - jnp.sum(p * delta, axis=-1, keepdims=True)               # Center under p.\n  s = d - jnp.log1p(jnp.sum(p * jnp.expm1(d), axis=-1, keepdims=True)) # log(q / p).\n  u = jnp.where(jnp.abs(s) &lt; 1, p * jnp.expm1(s), q - p)               # Difference q - p.\n  g = u - q * jnp.sum(u, axis=-1, keepdims=True)                       # Ensure sum(g) = 0.\n  sg = jax.lax.stop_gradient\n  loss = -jnp.sum(p * sg(log_q), axis=-1)                              # Forward loss.\n  return loss + jnp.sum(sg(g) * (z_S - sg(z_S)), axis=-1)              # Custom gradient g.</code></pre>\n<p>As an example, let (\\mathbf{z}_{\\mathrm{S}}) be a small fp32 perturbation of\n(\\mathbf{z}_{\\mathrm{T}}).\nStandard soft-target cross-entropy shrinks the second gradient\nentry by nearly (3\\times), flips the sign of the third, and fails to sum to\nzero, while our implementation matches the exact fp64 gradient:</p>\n<pre><code>z_T = jnp.array([2.0, 1.0, 0.0], dtype=jnp.float32)\nz_S = z_T + jnp.array([-1e-7, 1e-7, 0.0], dtype=jnp.float32)\nstd_soft_ce = lambda z_S, z_T: -jnp.sum(jax.nn.softmax(z_T) * jax.nn.log_softmax(z_S))\njax.grad(std_soft_ce)(z_S, z_T)               # -&gt; [-5.960e-8, 1.452e-8, -1.123e-9]\njax.grad(soft_target_cross_entropy)(z_S, z_T) # -&gt; [-4.596e-8, 4.144e-8,  4.513e-9]\n# Exact (float64) gradient:                        [-4.596e-8, 4.144e-8,  4.513e-9]</code></pre>\n<h2 id=\"4-the-slingshot-mechanism\">4. The Slingshot Mechanism</h2>\n<p>In grokking (<a href=\"#bib-power2022grokking\">Power et al., 2022</a>), a network quickly memorizes the training\nset ((q_{t} \\to 1)) and generalizes much later.\nWhile studying grokking on modular addition with Adam\n(<a href=\"#bib-kingma2015adam\">Kingma &amp; Ba, 2015</a>; <a href=\"#bib-loshchilov2019decoupled\">Loshchilov &amp; Hutter, 2019</a>), <a href=\"#bib-thilak2022slingshot\">Thilak et al. (2022)</a>\nobserved the <em>slingshot mechanism</em>, where training after memorization\nalternates between flat loss plateaus near zero and sudden loss spikes that\ncoincide with jumps in test accuracy.</p>\n<p>These slingshot spikes are a direct consequence of Softmax Collapse\n(<a href=\"#sec:bug1\">Section 2</a>).\nRecall that AdamW updates parameters (\\boldsymbol{\\theta}) by subtracting\n(\\eta\\big(\\hat{\\mathbf{m}} / (\\sqrt{\\hat{\\mathbf{v}}} + \\epsilon) +\n\\lambda\\boldsymbol{\\theta}\\big)), where (\\hat{\\mathbf{m}}) and (\\hat{\\mathbf{v}}) are\nbias-corrected moving averages of the parameter gradient (\\mathbf{g} =\n\\nabla_{\\boldsymbol{\\theta}}\\mathcal{L}(\\boldsymbol{\\theta})) and its square (with decay rates (\\beta_1,\n\\beta_2)).\nAfter memorization, the logit margins (m) grow as the network pushes its\ntarget probabilities toward (1).\nOnce an example&#39;s margin exceeds the precision cliff (c_{d}), standard\ncross-entropy rounds its target gradient (\\tilde{g}_{t}) to zero while its\nnon-target gradients (\\tilde{g}_j &gt; 0) ((j \\neq t)) remain positive.\nWhen all examples in a batch sit above (c_{d}), the parameter gradients nearly\nvanish and Adam&#39;s second moment (\\hat{v}_i) decays exponentially toward zero\nwhile weight decay slowly shrinks the parameters.\nEventually, weight decay or the residual non-target updates pull a few examples\nback below (c_{d}), where their target gradients (\\tilde{g}_{t} \\approx\n-e^{-m}) abruptly turn back on.\nBecause (\\sqrt{\\hat{v}_i}) decayed while those examples were above\n(c_{d}), Adam divides the restored gradients by a very small denominator\n(\\sqrt{\\hat{v}_i} + \\epsilon), producing a large parameter step that spikes\nthe training loss, resets (\\hat{v}_i), and repeats the cycle.\nWith our fixed cross-entropy, the target-logit gradient (g_{t} =\n-e^{-m}/(1 + e^{-m})) does not round to zero at (c_{d}), so\n(\\hat{m}_i) and (\\sqrt{\\hat{v}_i}) decay smoothly together and slingshot\nspikes disappear (<a href=\"#fig:fig_slingshot\">Figure 2</a>).</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig_slingshot_legend.png\" alt=\"paper_fig_slingshot_legend.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig_slingshot_a.png\" alt=\"paper_fig_slingshot_a.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(a)</strong> Mean logit margin (m)</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig_slingshot_b.png\" alt=\"paper_fig_slingshot_b.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(b)</strong> Training loss</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig_slingshot_c.png\" alt=\"paper_fig_slingshot_c.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(c)</strong> Test accuracy</p>\n<p><strong>Figure 2:</strong> The slingshot mechanism (<a href=\"#bib-thilak2022slingshot\">Thilak et al., 2022</a>) with and without\nweight decay (5 random seeds, fp32).\n<strong>Top row ((a + b \\bmod 31), (\\lambda = 1), (\\epsilon = 10^{-8}),\n<a href=\"#bib-varma2023explaining\">Varma et al., 2023</a>):</strong> Standard cross-entropy hits the\nfp32 cliff ((m = c_{32} \\approx 16.6), where loss\nrounds to (0)) and repeatedly drops and rebounds, slowing and degrading\ngrokking; fixed cross-entropy crosses (c_{32}) smoothly, groks\nfaster on all 5 seeds, and saturates just above (c_{32}) near\n(\\log({{}^{1}!/!{}_{\\epsilon}}) \\approx 18.4) (<a href=\"#sec:equilibria\">Section 5</a>).\n<strong>Bottom row ((a^2 + b^2 \\bmod 97), (\\lambda = 0), (\\epsilon =\n10^{-16}), <a href=\"#bib-doshi2024grokking\">Doshi et al., 2024</a>):</strong> Without weight decay, hitting\n(c_{32}) around step (1250) triggers a spike that drops standard\ncross-entropy test accuracy from (61\\%) to (23\\%), whereas fixed\ncross-entropy continues smoothly to (85\\%).</p>\n<p>Whether slingshot spikes appear to help or hurt generalization depends on how\nthe network&#39;s weight norm is controlled (<a href=\"#fig:fig_slingshot\">Figure 2</a>).\nWhen a network uses LayerNorm before the output layer and no weight decay\n(<a href=\"#bib-thilak2022slingshot\">Thilak et al., 2022</a>; <a href=\"#bib-prieto2025grokking\">Prieto et al., 2025</a>), growing the pre-LayerNorm\nweights does not change the logits, but it does shrink the effective step size\n(\\eta / |\\boldsymbol{\\theta}|_2); each slingshot spike inflates (|\\boldsymbol{\\theta}|_2) and\nacts as an accidental learning-rate decay.\nWhen weight norms are already controlled by weight decay\n(<a href=\"#bib-varma2023explaining\">Varma et al., 2023</a>), slingshot spikes at (c_{32}) only slow\ndown and hurt grokking ((94 \\pm 5\\%) vs. (100 \\pm 0\\%) test accuracy on (a + b\n\\bmod 31); <a href=\"#fig:fig_slingshot\">Figure 2</a>, top).\nAnd when neither LayerNorm nor weight decay is used (<a href=\"#bib-doshi2024grokking\">Doshi et al., 2024</a>), a\nsingle slingshot spike at (c_{32}) is destructive: on (a^2 + b^2 \\bmod\n97) ((\\lambda = 0), (\\epsilon = 10^{-16})), standard cross-entropy tracks fixed\ncross-entropy up to (61\\%) test accuracy until (m) hits (c_{32})\naround step (1250), where a spike drops test accuracy to (23\\%) (and from (60\\%)\nto (21\\%) on (a^3 + b \\bmod 97)), while fixed cross-entropy continues smoothly\nto (85\\%) (<a href=\"#fig:fig_slingshot\">Figure 2</a>, bottom).</p>\n<h2 id=\"5-margin-equilibria\">5. Margin Equilibria</h2>\n<p>In <a href=\"#fig:fig_slingshot\">Figure 2a</a>, our fixed cross-entropy eliminates the\nprecision cliff at (c_{32} \\approx 16.6), yet with weight decay\n((\\lambda = 1), top) its margin still saturates just above (c_{32})\nnear (18), whereas without weight decay ((\\lambda = 0), bottom) its margin\ncontinues to climb.\nThis plateau is the equilibrium where weight decay balances AdamW&#39;s normalized\ngradient step.\nAt a stationary point where the parameters stop changing, the moving averages\nconverge to (\\hat{m}_i = g_i) and (\\hat{v}_i = g_i^2) (so\n(\\sqrt{\\hat{v}_i} = |g_i|)), and setting the update to zero gives:</p>\n<p>[\\frac{\\hat{m}_i}{\\sqrt{\\hat{v}_i} + \\epsilon} + \\lambda\\theta_i = 0\n\\quad\\Longrightarrow\\quad\n\\frac{g_i}{|g_i| + \\epsilon} + \\lambda\\theta_i = 0\n\\quad \\forall i\\,.]</p>\n<p>(10)</p>\n<p>Here (\\eta), (\\beta_1), and (\\beta_2) cancel out, so RMSProp\n(<a href=\"#bib-tieleman2012rmsprop\">Tieleman &amp; Hinton, 2012</a>) and LaProp (<a href=\"#bib-ziyin2020laprop\">Ziyin et al., 2020</a>) share the same\nstationary point.\nAfter memorization, the gradients shrink exponentially with the margin\n((|g_i| \\propto e^{-m})).\nIf (\\epsilon = 0), the normalized gradient (g_i / |g_i| =\n\\mathrm{sign}(g_i)) has a magnitude of (1) no matter how small (|g_i|)\nbecomes, which causes the margin to grow until the gradients underflow.\nWhen (\\epsilon &gt; 0), however, the normalized gradient has magnitude (\\approx 1)\nwhile (|g_i| \\gg \\epsilon), and shrinks as (g_i / \\epsilon \\propto\ne^{-m}) once (|g_i| \\ll \\epsilon) (<a href=\"#fig:fig1b\">Figure 3</a>).\nBalancing this shrinking step against weight decay (\\lambda\\theta_i) requires\n(|g_i| \\approx \\epsilon\\lambda|\\theta_i|)\n(<a href=\"#bib-wortsman2023small\">Wortsman et al., 2024</a>; <a href=\"#bib-molybog2023theory\">Molybog et al., 2023</a>; <a href=\"#bib-everett2024scaling\">Everett et al., 2024</a>; <a href=\"#bib-kosson2024rotational\">Kosson et al., 2024</a>), which acts like an (L_2) regularizer with weight\n(\\epsilon\\lambda) (<a href=\"#bib-rosset2004margin\">Rosset et al., 2004</a>; <a href=\"#bib-soudry2018implicit\">Soudry et al., 2018</a>).\nSince (|g_i| \\propto e^{-m}), the margin stops growing at:</p>\n<p>[m^\\star(\\epsilon) \\approx \\log({{}^{1}!/!{}_{\\epsilon}})\\,.]</p>\n<p>(11)</p>\n<p><a href=\"#eq:margin_law\">Equation 11</a> explains why the default (\\epsilon = 10^{-8})\ncauses slingshot spikes in fp32: its equilibrium\n(\\log({{}^{1}!/!{}<em>{\\epsilon}}) \\approx 18.4) sits just above (c</em>{32}\n\\approx 16.6) (<a href=\"#fig:fig1b\">Figure 3</a>), so standard cross-entropy hits the cliff\nbefore equilibrium (whereas for (\\epsilon \\ge 10^{-7}),\n(\\log({{}^{1}!/!{}<em>{\\epsilon}}) \\le 16.1 &lt; c</em>{32}) and standard\ncross-entropy settles without spiking).\nTo test <a href=\"#eq:margin_law\">Equation 11</a> across many orders of magnitude down to\n(\\epsilon = 0) in fp32 (<a href=\"#fig:fig6\">Figure 4</a>), we train with our\nfixed cross-entropy and LaProp on (a + b \\bmod 31), updating\n(\\sqrt{\\hat{\\mathbf{v}}}) directly without squaring (g_i) (which underflows in\nfp32 once (|g_i| &lt; 2^{-63}), or (m \\approx 38)).\nWith weight decay ((\\lambda = 1), <a href=\"#fig:fig6a\">Figure 4a</a>), the margin for each\n(\\epsilon &gt; 0) climbs along the (\\epsilon = 0) trajectory and levels off at\n(m^\\star(\\epsilon) = \\log({{}^{1}!/!{}_{\\epsilon}})), while (\\epsilon = 0) grows\nuntil the fp32 gradients underflow at (m \\approx 81.2).\nWithout weight decay ((\\lambda = 0), <a href=\"#fig:fig6b\">Figure 4b</a>), nothing balances\nthe (g_i / \\epsilon) step, so margins keep rising past\n(\\log({{}^{1}!/!{}_{\\epsilon}})).</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig1_legend.png\" alt=\"paper_fig1_legend.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>Figure 3:</strong> Normalized Adam step\n(|g_{t}| / (|g_{t}| + \\epsilon)) vs. logit\nmargin (m) at (\\epsilon = 10^{-8}).\nWith our fixed cross-entropy, the step stays near (1) and decays\nsmoothly around (\\log({{}^{1}!/!{}_{\\epsilon}}) \\approx 18.4), whereas\nstandard cross-entropy zeroes out (\\tilde{g}_{t}) at\n(c_{16} \\approx 5.5) and (c_{32} \\approx 16.6).</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig1b_adam_eps.png\" alt=\"paper_fig1b_adam_eps.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig6a.png\" alt=\"paper_fig6a.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(a)</strong> Weight decay ((\\lambda = 1))</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig6b.png\" alt=\"paper_fig6b.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(b)</strong> No weight decay ((\\lambda = 0))</p>\n<p><strong>Figure 4:</strong> Logit margins with our fixed cross-entropy and LaProp on (a + b \\bmod\n31) in fp32 ((\\beta_1 = 0.9), (\\beta_2 = 0.98); 3 seeds\nper setting as solid lines, analytical predictions\n(m^\\star(\\epsilon) = \\log({{}^{1}!/!{}_{\\epsilon}})) as dashed lines).\n<strong>(a)</strong> With weight decay ((\\lambda = 1)), margins level off at\n(\\log({{}^{1}!/!{}_{\\epsilon}})).\n<strong>(b)</strong> Without weight decay ((\\lambda = 0)), margins overshoot\n(\\log({{}^{1}!/!{}_{\\epsilon}})).</p>\n<h2 id=\"6-grokking-across-precisions-and-benchmarks\">6. Grokking Across Precisions and Benchmarks</h2>\n<p>To see how the precision cliff behaves across floating-point formats, we follow\n<a href=\"#bib-varma2023explaining\">Varma et al. (2023)</a> and <a href=\"#bib-lyle2025grokking\">Lyle et al. (2025)</a> and train a 1-layer\nwidth-(64) ReLU Transformer on (a + b \\bmod 31) ((50\\%) training split) for\n(10{,}000) epochs of full-batch AdamW ((\\eta = 10^{-3}), (\\beta_1 = 0.9),\n(\\beta_2 = 0.98), (\\lambda = 1)), varying the loss (standard vs. fixed\ncross-entropy), precision (bf16, fp32, fp64), and\n(\\epsilon \\in {10^{-8}, 10^{-12}, 10^{-16}}) (<a href=\"#fig:fig2\">Figure 5</a>,\n<a href=\"#tab:baselines\">Table 1</a>).\nAt (\\epsilon = 10^{-8}) (<a href=\"#fig:fig2\">Figure 5</a>, top), standard cross-entropy\nstalls at (c_{16} \\approx 5.5) in bf16 and repeatedly spikes at\n(c_{32} \\approx 16.6) in fp32, whereas fixed cross-entropy\ncrosses both cliffs smoothly to (\\log({{}^{1}!/!{}_{\\epsilon}}) \\approx 18.4) and\nreaches (100\\%) test accuracy in all three precisions.\nReducing (\\epsilon) to (10^{-16}) (<a href=\"#fig:fig2\">Figure 5</a>, bottom) raises the\nequilibrium to (\\log({{}^{1}!/!{}<em>{\\epsilon}}) \\approx 36.8 &gt; c</em>{64}),\nbreaking even fp64 standard cross-entropy at (c_{64} \\approx\n36.7) while fixed cross-entropy converges smoothly across all precisions.</p>\n<p>In <a href=\"#tab:baselines\">Table 1</a> we summarize these results and compare against two\nrecent methods that modify the gradients or the loss to mitigate Softmax\nCollapse.\n<a href=\"#bib-liu2026grokking\">Liu et al. (2026)</a> subtract the mean logit gradient from each entry so the\ngradients sum to zero (“Zero-sum Proj.”).\nHowever, once (m &gt; c_{32}) and (\\tilde{g}_{t} = 0),\nsubtracting the mean only gives the target logit (-{{}^{1}!/!{}_{K}}) of\nthe total non-target gradient, stalling (m) near (18) and dropping test\naccuracy below (50\\%) for (\\epsilon \\le 10^{-12}).\n<a href=\"#bib-prieto2025grokking\">Prieto et al. (2025)</a> propose “StableMax,” which replaces (\\exp(x)) in\nsoftmax with a piecewise rational function ((x + 1) for (x \\ge 0) and\n(1/(1 - x)) for (x &lt; 0)).\nBecause this function grows linearly instead of exponentially, logit margins\nblow up to ({\\sim}10^4) and test accuracy lags our fixed cross-entropy across\nall (\\epsilon).</p>\n<p>We observe the same behavior across four grokking benchmarks at (\\epsilon =\n10^{-12}) (<a href=\"#fig:fig3\">Figure 6</a>): 1-layer Transformers on (a + b \\bmod 113)\n(<a href=\"#bib-nanda2023progress\">Nanda et al., 2023</a>) and (a + b \\bmod 31) (<a href=\"#bib-varma2023explaining\">Varma et al., 2023</a>) with\n(\\lambda = 1), and 2-layer MLPs on (a^2 + b^2 \\bmod 97) and (a^3 + b \\bmod 97)\n(<a href=\"#bib-doshi2024grokking\">Doshi et al., 2024</a>) with (\\lambda = 0.2).\nOn all four tasks, fp32 standard cross-entropy spikes once it hits\n(c_{32}), whereas fp32 fixed cross-entropy matches\nfp64 standard cross-entropy and reaches (100\\%) test accuracy.</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig2_legend.png\" alt=\"paper_fig2_legend.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig2a.png\" alt=\"paper_fig2a.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(a)</strong> Mean logit margin (m)</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig2b.png\" alt=\"paper_fig2b.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(b)</strong> Training loss</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig2c.png\" alt=\"paper_fig2c.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(c)</strong> Test accuracy</p>\n<p><strong>Figure 5:</strong> Standard cross-entropy fails at the precision cliff (c_{d}) of its\nfloating-point format; fixed cross-entropy removes the cliff across all\nprecisions ((a + b \\bmod 31), (\\lambda = 1); 2 of 5 seeds shown).\nTop: (\\epsilon = 10^{-8}).\nBottom: (\\epsilon = 10^{-16}), where even fp64 standard\ncross-entropy fails at (c_{64}) while fixed cross-entropy\nconverges smoothly.</p>\n<div class=\"table-wrap\"><table><thead><tr><th></th><th></th><th>Test Accuracy (%)</th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th>Final Margin (m)</th><th></th><th></th></tr></thead><tbody><tr><td></td><td>Variant(\\epsilon =)</td><td>(10^{-8})</td><td></td><td></td><td>(10^{-12})</td><td></td><td></td><td>(10^{-16})</td><td></td><td></td><td>(10^{-8})</td><td>(10^{-12})</td><td>(10^{-16})</td></tr><tr><td>fp32</td><td>Fixed CE</td><td>100.0</td><td>(\\pm)</td><td>0.0</td><td>99.6</td><td>(\\pm)</td><td>0.7</td><td>99.0</td><td>(\\pm)</td><td>2.3</td><td>17.9</td><td>27.4</td><td>36.8</td></tr><tr><td>fp32</td><td>Standard CE</td><td>94.3</td><td>(\\pm)</td><td>5.4</td><td>96.4</td><td>(\\pm)</td><td>5.1</td><td>96.5</td><td>(\\pm)</td><td>4.3</td><td>13.0</td><td>15.1</td><td>12.7</td></tr><tr><td>bf16</td><td>Fixed CE</td><td>100.0</td><td>(\\pm)</td><td>0.1</td><td>99.8</td><td>(\\pm)</td><td>0.2</td><td>98.9</td><td>(\\pm)</td><td>2.4</td><td>17.9</td><td>27.4</td><td>36.8</td></tr><tr><td>bf16</td><td>Standard CE</td><td>93.3</td><td>(\\pm)</td><td>7.4</td><td>94.9</td><td>(\\pm)</td><td>4.9</td><td>94.2</td><td>(\\pm)</td><td>8.3</td><td>5.1</td><td>5.6</td><td>5.8</td></tr><tr><td>fp64</td><td>Fixed CE</td><td>100.0</td><td>(\\pm)</td><td>0.0</td><td>99.5</td><td>(\\pm)</td><td>1.1</td><td>99.0</td><td>(\\pm)</td><td>2.0</td><td>17.9</td><td>27.4</td><td>36.8</td></tr><tr><td>fp64</td><td>Standard CE</td><td>100.0</td><td>(\\pm)</td><td>0.0</td><td>100.0</td><td>(\\pm)</td><td>0.1</td><td>97.2</td><td>(\\pm)</td><td>3.2</td><td>17.9</td><td>27.4</td><td>30.1</td></tr><tr><td>fp32</td><td>Zero-sum Proj. (<a href=\"#bib-liu2026grokking\">Liu et al., 2026</a>)</td><td>97.9</td><td>(\\pm)</td><td>3.2</td><td>48.9</td><td>(\\pm)</td><td>2.6</td><td>49.3</td><td>(\\pm)</td><td>2.5</td><td>17.0</td><td>18.9</td><td>18.9</td></tr><tr><td>fp32</td><td>StableMax (<a href=\"#bib-prieto2025grokking\">Prieto et al., 2025</a>)</td><td>97.3</td><td>(\\pm)</td><td>4.7</td><td>95.6</td><td>(\\pm)</td><td>2.0</td><td>97.3</td><td>(\\pm)</td><td>4.3</td><td>3200</td><td>5661</td><td>6313</td></tr><tr><td>fp64</td><td>StableMax (<a href=\"#bib-prieto2025grokking\">Prieto et al., 2025</a>)</td><td>97.4</td><td>(\\pm)</td><td>4.2</td><td>96.7</td><td>(\\pm)</td><td>5.3</td><td>95.6</td><td>(\\pm)</td><td>2.7</td><td>3170</td><td>21252</td><td>2322</td></tr></tbody></table></div>\n<p><strong>Table 1:</strong> Comparison of loss functions on modular addition ((a + b \\bmod 31), (\\lambda\n= 1), (3)–(5) seeds) across (\\epsilon \\in {10^{-8}, 10^{-12}, 10^{-16}}).\nFixed CE reaches the predicted equilibrium margin ((\\log({{}^{1}!/!{}_{\\epsilon}})\n\\approx 18.4, 27.6, 36.8)) and ({\\ge}98.9\\%) test accuracy across all\nprecisions, whereas Standard CE stalls once (m^\\star(\\epsilon)) exceeds the\ncliff (c_{d}) ((c_{16} \\approx 5.5) in bf16,\n(c_{32} \\approx 16.6) in fp32, and (c_{64}\n\\approx 36.7) in fp64).</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig3_legend.png\" alt=\"paper_fig3_legend.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig3a.png\" alt=\"paper_fig3a.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(a)</strong> (a{+}b \\bmod 113)<br />\n <a href=\"#bib-nanda2023progress\">Nanda et al. (2023)</a></p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig3b.png\" alt=\"paper_fig3b.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(b)</strong> (a{+}b \\bmod 31)<br />\n <a href=\"#bib-varma2023explaining\">Varma et al. (2023)</a></p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig3c.png\" alt=\"paper_fig3c.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(c)</strong> (a^2{+}b^2 \\bmod 97)<br />\n <a href=\"#bib-doshi2024grokking\">Doshi et al. (2024)</a></p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig3d.png\" alt=\"paper_fig3d.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(d)</strong> (a^3{+}b \\bmod 97)<br />\n <a href=\"#bib-doshi2024grokking\">Doshi et al. (2024)</a></p>\n<p><strong>Figure 6:</strong> Results across four grokking tasks at (\\epsilon = 10^{-12}) (2 of 3–5\nseeds shown): 1-layer Transformers (a, b) and 2-layer MLPs (c, d).\nFixed cross-entropy in fp32 (blue) matches fp64\nstandard cross-entropy (red), while standard cross-entropy in\nfp32 (orange) breaks at (c_{32}).</p>\n<h2 id=\"7-soft-target-distillation\">7. Soft-Target Distillation</h2>\n<p>To see how Softmax Cancellation (<a href=\"#sec:bug2\">Section 3</a>) affects optimization,\nwe initialize a student network with the weights of a teacher trained to (100\\%)\naccuracy on (a + b \\bmod 53) ((\\boldsymbol{\\theta}<em>{\\mathrm{S}}^{(0)} = \\boldsymbol{\\theta}</em>{\\mathrm{T}})), and run\n(2{,}000) steps of Adam ((\\eta = 2\\times 10^{-3}), (\\lambda = 0),\n(\\epsilon = 10^{-8})) at distillation temperature (T = 4)\n(<a href=\"#bib-hinton2015distilling\">Hinton et al., 2015</a>), which keeps the scaled margin (m/T)\nbelow (c_{16}) so (\\mathbf{p}) does not round to one-hot.\nBecause (\\mathbf{z}<em>{\\mathrm{S}} = \\mathbf{z}</em>{\\mathrm{T}}) initially, the true gradient is zero and the\nstudent should not move.\nHowever, standard soft-target cross-entropy has a non-zero residual gradient at\n(\\mathbf{z}<em>{\\mathrm{S}} = \\mathbf{z}</em>{\\mathrm{T}}) due to the mismatch between its forward softmax\nand backward log-softmax (<a href=\"#fig:fig4a\">Figure 1b</a>).\nWhenever this residual gradient exceeds (\\epsilon), Adam normalizes it into\nsteps of size (\\eta) (<a href=\"#fig:fig4\">Figure 7</a>): in fp64 the residual\n(({\\sim}10^{-17})) lies well below (\\epsilon = 10^{-8}) so the student stays\nnear (\\mathrm{KL} = 0), in fp32 (({\\sim}10^{-8})) it causes an initial\n(\\mathrm{KL}) spike and a ({\\sim}10^{-6}) floor, and in bf16\n(({\\sim}10^{-3})) it drives the student away from the teacher and degrades test\naccuracy.\nOur fixed soft-target cross-entropy returns (\\mathbf{g} = \\mathbf{0}) at (\\mathbf{z}_{\\mathrm{S}} =\n\\mathbf{z}_{\\mathrm{T}}), so the student stays at (\\mathrm{KL} = 0) and (100\\%) accuracy\nacross all precisions.</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig4_legend.png\" alt=\"paper_fig4_legend.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig4b_kl.png\" alt=\"paper_fig4b_kl.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(a)</strong> Held-out (\\mathrm{KL}(\\mathbf{p}<em>{\\mathrm{T}} \\parallel \\mathbf{q}</em>{\\mathrm{S}}))</p>\n<figure><img src=\"https://jonbarron.info/softmaxfix/img/paper_fig4c_acc.png\" alt=\"paper_fig4c_acc.png\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p><strong>(b)</strong> Test accuracy</p>\n<p><strong>Figure 7:</strong> Soft-target distillation when the student is initialized with the\nteacher&#39;s weights ((\\boldsymbol{\\theta}<em>{\\mathrm{S}}^{(0)} = \\boldsymbol{\\theta}</em>{\\mathrm{T}}), (T = 4),\n(\\epsilon = 10^{-8}), 2 of 3 seeds shown).\nFixed soft-target cross-entropy stays at (\\mathrm{KL} = 0) and (100\\%)\naccuracy across all precisions; standard soft-target cross-entropy\namplifies rounding error into parameter drift in bf16 and an\ninitial (\\mathrm{KL}) spike and ({\\sim}10^{-6}) floor in fp32.</p>\n<h2 id=\"8-conclusion\">8. Conclusion</h2>\n<p>We have presented simple fixes for two numerical bugs in standard\nimplementations of softmax, log-softmax, and cross-entropy:\n<em>Softmax Collapse</em>, which zeroes out the dominant logit&#39;s gradient at high\nconfidence while leaving non-dominant gradients non-zero, and *Softmax\nCancellation*, which loses precision when student logits approach teacher logits\nin soft-target distillation.\nRewriting these functions in log space using (\\operatorname{softplus}), (\\operatorname{expm1}), and\n(\\operatorname{log1p}) restores accurate, zero-sum gradients across bf16,\nfp32, and fp64 without internally casting to higher\nprecision.\nFixing these bugs eliminates slingshot loss spikes during grokking, prevents\nstudent networks from drifting away from the teacher during distillation, and\nreveals that logit margins under AdamW and weight decay naturally converge to\n(\\log({{}^{1}!/!{}_{\\epsilon}})).\nThough the extreme margins and near-zero student–teacher gaps probed by our\nexperiments are uncommon in standard large-scale training, our fixed functions\nare easy drop-in replacements that can be implemented without meaningful\nslowdown, and may prove useful whenever models make high-confidence predictions\nor distill from close teachers.</p>\n<p><strong>Acknowledgments:</strong>\nWe thank Jean-Baptiste Alayrac, Forrester Cole, Roy Frostig, Mark Hamilton, Miki\nRubinstein, Keith Rush, and Brandon Zhao for their helpful advice.</p>\n<h2 id=\"references\">References</h2>\n<ol><li>[Blanchard et al., 2021] Pierre Blanchard, Desmond J. Higham, and Nicholas J. Higham. Accurately computing the log-sum-exp and softmax functions. <em>IMA Journal of Numerical Analysis</em>, 2021.</li><li>[Doshi et al., 2024] Darshil Doshi, Tianyu He, Aritra Das, and Andrey Gromov. Grokking modular polynomials. <em><a href=\"https://arxiv.org/abs/2406.03495\" rel=\"nofollow ugc noopener\">arXiv:2406.03495</a></em>, 2024.</li><li>[Everett et al., 2024] Katie Everett, Lechao Xiao, Mitchell Wortsman, Alexander A. Alemi, Roman Novak, Peter J. Liu, Izzeddin Gur, Jascha Sohl-Dickstein, Leslie Pack Kaelbling, Jaehoon Lee, and Jeffrey Pennington. Scaling exponents across parameterizations and optimizers. <em>ICML</em>, 2024.</li><li>[Higham, 2002] Nicholas J. Higham. <em>Accuracy and stability of numerical algorithms</em>. SIAM, 2nd edition, 2002.</li><li>[Hinton et al., 2015] Geoffrey Hinton, Oriol Vinyals, and Jeff Dean. Distilling the knowledge in a neural network. <em><a href=\"https://arxiv.org/abs/1503.02531\" rel=\"nofollow ugc noopener\">arXiv:1503.02531</a></em>, 2015.</li><li>[Kingma &amp; Ba, 2015] Diederik P. Kingma and Jimmy Ba. Adam: A method for stochastic optimization. <em>ICLR</em>, 2015.</li><li>[Kosson et al., 2024] Atli Kosson, Bettina Messmer, and Martin Jaggi. Rotational equilibrium: How weight decay balances learning across neural networks. <em>ICML</em>, 2024.</li><li>[Liu et al., 2026] Hanqing Liu, Jianjun Cao, Yuanze Li, and Zijian Zhou. Grokking or glitching? How low-precision drives Slingshot loss spikes. <em><a href=\"https://arxiv.org/abs/2605.06152\" rel=\"nofollow ugc noopener\">arXiv:2605.06152</a></em>, 2026.</li><li>[Loshchilov &amp; Hutter, 2019] Ilya Loshchilov and Frank Hutter. Decoupled weight decay regularization. <em>ICLR</em>, 2019.</li><li>[Lyle et al., 2025] Clare Lyle, Ghada Sokar, András György, and Razvan Pascanu. What can grokking teach us about learning under non-stationarity? <em>Conference on Lifelong Learning Agents</em>, 2025.</li><li>[Molybog et al., 2023] Igor Molybog, Peter Albert, Moya Chen, Zachary DeVito, David Esiobu, Naman Goyal, Punit Singh Koura, Sharan Narang, Andrew Poulton, Ruan Silva, et al. A theory on Adam instability in large-scale machine learning. <em><a href=\"https://arxiv.org/abs/2304.09871\" rel=\"nofollow ugc noopener\">arXiv:2304.09871</a></em>, 2023.</li><li>[Nanda et al., 2023] Neel Nanda, Lawrence Chan, Tom Lieberum, Jess Smith, and Jacob Steinhardt. Progress measures for grokking via mechanistic interpretability. <em>ICLR</em>, 2023.</li><li>[Power et al., 2022] Alethea Power, Yuri Burda, Harri Edwards, Igor Babuschkin, and Vedant Misra. Grokking: Generalization beyond overfitting on small algorithmic datasets. <em><a href=\"https://arxiv.org/abs/2201.02177\" rel=\"nofollow ugc noopener\">arXiv:2201.02177</a></em>, 2022.</li><li>[Prieto et al., 2025] Lucas Prieto, Melih Barsbey, Pedro A. M. Mediano, and Tolga Birdal. Grokking at the edge of numerical stability. <em>ICLR</em>, 2025.</li><li>[Qiu &amp; Yao, 2026] Haiquan Qiu and Quanming Yao. Why low-precision Transformer training fails: An analysis on Flash Attention. <em>ICLR</em>, 2026.</li><li>[Rosset et al., 2004] Saharon Rosset, Ji Zhu, and Trevor Hastie. Margin maximizing loss functions. <em>NeurIPS</em>, 2004.</li><li>[Soudry et al., 2018] Daniel Soudry, Elad Hoffer, Mor Shpigel Nacson, Suriya Gunasekar, and Nathan Srebro. The implicit bias of gradient descent on separable data. <em>JMLR</em>, 2018.</li><li>[Thilak et al., 2022] Vimal Thilak, Etai Littwin, Shuangfei Zhai, Omid Saremi, Roni Paiss, and Joshua Susskind. The Slingshot mechanism: An empirical study of adaptive optimizers and the grokking phenomenon. <em><a href=\"https://arxiv.org/abs/2206.04817\" rel=\"nofollow ugc noopener\">arXiv:2206.04817</a></em>, 2022.</li><li>[Tieleman &amp; Hinton, 2012] Tijmen Tieleman and Geoffrey Hinton. Lecture 6.5—RMSProp: Divide the gradient by a running average of its recent magnitude. <em>COURSERA: Neural Networks for Machine Learning</em>, 2012.</li><li>[Varma et al., 2023] Vikrant Varma, Rohin Shah, Zachary Kenton, János Kramár, and Ramana Kumar. Explaining grokking through circuit efficiency. <em><a href=\"https://arxiv.org/abs/2309.02390\" rel=\"nofollow ugc noopener\">arXiv:2309.02390</a></em>, 2023.</li><li>[Wortsman et al., 2024] Mitchell Wortsman, Peter J. Liu, Lechao Xiao, Katie Everett, Alexander Alemi, Ben Adlam, John D. Co-Reyes, Izzeddin Gur, Abhishek Kumar, Roman Novak, et al. Small-scale proxies for large-scale Transformer training instabilities. <em>ICLR</em>, 2024.</li><li>[Ziyin et al., 2020] Liu Ziyin, Zhikang T. Wang, and Masahito Ueda. LaProp: Separating momentum and adaptivity in Adam. <em><a href=\"https://arxiv.org/abs/2002.04839\" rel=\"nofollow ugc noopener\">arXiv:2002.04839</a></em>, 2020.</li></ol>","headings":[{"level":1,"text":"A Fix for Softmax and Cross-Entropy","id":"a-fix-for-softmax-and-cross-entropy"},{"level":2,"text":"1. Introduction","id":"1-introduction"},{"level":2,"text":"2. Softmax Collapse","id":"2-softmax-collapse"},{"level":2,"text":"3. Softmax Cancellation","id":"3-softmax-cancellation"},{"level":2,"text":"4. The Slingshot Mechanism","id":"4-the-slingshot-mechanism"},{"level":2,"text":"5. Margin Equilibria","id":"5-margin-equilibria"},{"level":2,"text":"6. Grokking Across Precisions and Benchmarks","id":"6-grokking-across-precisions-and-benchmarks"},{"level":2,"text":"7. Soft-Target Distillation","id":"7-soft-target-distillation"},{"level":2,"text":"8. Conclusion","id":"8-conclusion"},{"level":2,"text":"References","id":"references"}]}}