Repository navigation
Raise a ValueError at trace time when eps underflows in the optimizer state dtype - #1835
Merged
Merged
Conversation
|
NP |
copybara-service
Bot
force-pushed
the
test_1002704127
branch
2 times, most recently
from
October 24, 2026 00:18
88af3ef to
336fa64
Compare
… state dtype Positive `eps` values smaller than the smallest normal number of the dtype they are added in (`jnp.finfo(dtype).tiny`) are flushed to zero. For example the default `eps=1e-8` is flushed to zero in float16 (smallest normal 2^-14 ~= 6.1e-5), which turns zero-gradient steps into `0 / 0 = NaN` (#1784, #1789). Rather than silently changing the requested `eps`, this change: - Adds `numerics.maybe_static_check_eps(eps, tree, name)`, which raises a `ValueError` when a concrete `eps` satisfies `0 < eps < jnp.finfo(dtype).tiny` for the dtype of `eps + leaf`. Traced `eps` (e.g. from `inject_hyperparams`) and `eps=0` are not checked. - Calls it on `eps` (and `eps_root`) in every transform that adds `eps` to a per-parameter gradient-statistics accumulator: - `optax/_src/transform.py`: `scale_by_rss`, `scale_by_rms`, `scale_by_stddev`, `scale_by_adam`, `scale_by_amsgrad`, `scale_by_adamax`, `scale_by_adadelta`, `scale_by_adan`, `scale_by_belief`, `scale_by_yogi`, `scale_by_radam`, `scale_by_sm3`, `scale_by_novograd`. `optax.sm3` gains an `eps` argument so the check is actionable. - `optax/_src/factorized.py`: `scale_by_factored_rms` (`epsilon`, used by `adafactor`). - `optax/contrib`: `acprop`, `ademamix`, `simplified_ademamix`, `adopt`, `dadapt_adamw`, `madgrad`, `momo_adam`, `sophia`. - Default `eps` values are unchanged. As a consequence, optimizers using these transforms with default `eps` now raise for float16 optimizer state; pass a larger `eps` (e.g. `eps=1e-4`) or keep the optimizer state in bfloat16/float32. float16 is removed from the dtype-stability test matrices and the sharding tests use bfloat16. Thanks to @vishesh9131 (#1785) and @Anu27n (#1790) for reporting and the initial fixes. PiperOrigin-RevId: 1005981980
copybara-service
Bot
force-pushed
the
test_1002704127
branch
from
October 24, 2026 00:31
336fa64 to
9a1f892
Compare
This was referenced Oct 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Raise a ValueError at trace time when eps underflows in the optimizer state dtype
Positive
epsvalues smaller than the smallest normal number of the dtype they are added in (jnp.finfo(dtype).tiny) are flushed to zero. For example the defaulteps=1e-8is flushed to zero in float16 (smallest normal 2^-14 ~= 6.1e-5), which turns zero-gradient steps into0 / 0 = NaN(#1784, #1789).Rather than silently changing the requested
eps, this change:numerics.maybe_static_check_eps(eps, tree, name), which raises aValueErrorwhen a concreteepssatisfies0 < eps < jnp.finfo(dtype).tinyfor the dtype ofeps + leaf. Tracedeps(e.g. frominject_hyperparams) andeps=0are not checked.eps(andeps_root) in every transform that addsepsto a per-parameter gradient-statistics accumulator:optax/_src/transform.py:scale_by_rss,scale_by_rms,scale_by_stddev,scale_by_adam,scale_by_amsgrad,scale_by_adamax,scale_by_adadelta,scale_by_adan,scale_by_belief,scale_by_yogi,scale_by_radam,scale_by_sm3,scale_by_novograd.optax.sm3gains anepsargument so the check is actionable.optax/_src/factorized.py:scale_by_factored_rms(epsilon, used byadafactor).optax/contrib:acprop,ademamix,simplified_ademamix,adopt,dadapt_adamw,madgrad,momo_adam,sophia.epsvalues are unchanged. As a consequence, optimizers using these transforms with defaultepsnow raise for float16 optimizer state; pass a largereps(e.g.eps=1e-4) or keep the optimizer state in bfloat16/float32. float16 is removed from the dtype-stability test matrices and the sharding tests use bfloat16.Thanks to @vishesh9131 (#1785) and @Anu27n (#1790) for reporting and the initial fixes.