Fix: reuse training obs normalization stats in ppo_continuous_action eval - #556
Open
discobot wants to merge 1 commit into
Open
Fix: reuse training obs normalization stats in ppo_continuous_action eval#556discobot wants to merge 1 commit into
discobot wants to merge 1 commit into
Conversation
…eval ppo_continuous_action.py trains on NormalizeObservation-wrapped envs but only saved the agent state_dict, so evaluate() rebuilt the envs with a fresh RunningMeanStd and the policy received observations on a completely different scale than it was trained on. Save the obs_rms mean/var/count alongside the model weights and restore them, frozen, onto the evaluation envs. Checkpoints saved as a plain state_dict, e.g. the existing hub models, still load through the legacy path. Adds regression tests and a save+eval smoke test.
|
@discobot is attempting to deploy a commit to the Costa Huang's projects Team on Vercel. A member of the Team first needs to authorize it. |
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.
Description
Fixes #532.
This is the observation-normalization gap @noahfarr and @pseudo-rnd-thoughts identified in the issue, confirmed at the code level: the save block in
ppo_continuous_action.pywrites onlyagent.state_dict(), andcleanrl_utils.evals.ppo_eval.evaluate()rebuilds the envs throughmake_envwith a freshRunningMeanStd(mean=0, var=1). After a 300k-step HalfCheetah-v4 run the trainingobs_rms.varreaches ~119 on some dimensions, so the policy evaluates on a completely different observation scale than it trained on. Same root cause as #425.The fix saves the
obs_rmsmean/var/count alongside the weights (samemodel_datadict layout asc51.py), andevaluate()restores them onto the eval envs and freezes updates, so eval uses exactly the training-time scaling. Old checkpoints that are a plainstate_dict— including the existing hub models — still load through a legacy path, and training behavior is unchanged (identical training logs before/after on the same seed).One detail that explains the seed-dependent severity in the issue: gymnasium 0.29.1's
NormalizeObservationkeeps updating the fresh eval statistics during evaluation, so the error partially self-corrects over long episodes — the wildly negative returns mostly show up on longer (1M+ step) runs.Validation: A/B on the same HalfCheetah-v4 checkpoint (stats stripped vs restored, 10 episodes) gives eval mean ~822 vs ~872, with the fixed eval matching the run's final training returns (~870 vs ~860). Added to
tests/test_classic_control_gymnasium.py(already run by CI): a save+eval smoke test mirroringtest_c51_eval, a regression test that synthetic stats round-trip through the checkpoint into the eval wrapper, and a legacy-checkpoint test.Types of changes
Checklist:
pre-commit run --all-filespasses (required).mkdocs serve.If you need to run benchmark experiments for a performance-impacting changes:
--capture_video.python -m openrlbenchmark.rlops.python -m openrlbenchmark.rlopsutility to the documentation.python -m openrlbenchmark.rlops ....your_args... --report, to the documentation.