Fix gradient penalty computation when empirical normalization is enabled - #58
Open
GiulioRomualdi wants to merge 1 commit into
Open
Fix gradient penalty computation when empirical normalization is enabled#58GiulioRomualdi wants to merge 1 commit into
GiulioRomualdi wants to merge 1 commit into
Conversation
…normalization is enabled The gradient penalty in compute_grad_pen was computed on pre-normalized inputs. The .detach().requires_grad_(True) call on already-normalized tensors excluded the normalizer from the autograd graph, causing the penalty to measure ||∂D/∂x_norm||² instead of ||∂D/∂x_raw||². Move normalization inside the gradient computation path via a new _forward_detached_std() helper so that autograd correctly accounts for the 1/σ Jacobian of the normalizer. When empirical_normalization=False the normalizer is nn.Identity and the behavior is unchanged.
Contributor
|
I guess this may also need to be tested by @gbionics/team-dexter . |
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.
Summary
The gradient penalty in
compute_grad_penwas computed on pre-normalized inputs, causing the autograd graph to miss the normalizer's Jacobian. This PR moves normalization inside the gradient computation path so the penalty correctly measures sensitivity in the raw input space.The bug
In
compute_loss, the expert/policy states were normalized before being passed tocompute_grad_pen:Then
compute_grad_penset up the autograd leaf on the already-normalized tensor:The
.detach().requires_grad_(True)call cuts the autograd graph — everything before it (including the normalizer) is invisible toautograd.grad. So the gradient was computed w.r.t. the normalized tensor, not the raw input.What the penalty actually measured
The empirical normalizer computes:
By the chain rule, the full gradient of the discriminator$D$ w.r.t. the raw input is:
The old code measured (per dimension$i$ ):
The new code correctly measures:
Impact on training
Overall penalty magnitude: The old code over-penalized by a factor of ~$\sigma^2$. With typical AMP observation ranges ($\sigma \approx 5$ ), the effective $\lambda$ was ~25x larger than configured, over-regularizing the discriminator.
Per-dimension weighting: Observation dimensions with large variance ($\sigma_i$ ) had their gradients over-penalized relative to those with small variance. The new code correctly penalizes each dimension proportionally to its actual sensitivity in raw input space.
Non-stationarity: Since$\sigma$ evolves during training (running statistics), the effective penalty strength was drifting — an unintended implicit schedule on $\lambda$ .
When
empirical_normalization=False: The normalizer isnn.Identity, so both old and new code produce identical results. This fix is a no-op in that case.Important
We need to test in a training loop
cc @gbionics/team-hermes