From e2efe305c87caaa1cf40d51e3c3526413eea68a6 Mon Sep 17 00:00:00 2001 From: mushroomfire <934313174@qq.com> Date: Thu, 6 Aug 2026 19:35:09 +0300 Subject: [PATCH] Default use_gpumd_qscaler to False 600-epoch, 4-seed PdCuNiP benchmark (stage2, 10% validation, V100): the default torch init with the self-consistent q_scaler reaches clearly better minima than the GPUMD-style start on every metric and every seed - ~12% lower E and V RMSE, ~3% lower F, on train and validation alike. Swapping only the NN init while keeping the c=1 scaler + uniform(-1,1) coefficients changes nothing, so the gap comes from the c=1-scaler/large-coefficient combination itself. True (the old default) is unchanged and remains available for GPUMD-comparison runs. The saved nep.txt is GPUMD-compatible either way - the q_scaler is stored in the file. --- README.md | 2 +- releaseNotes.md | 9 +++++++++ torchnep/train.py | 22 +++++++++++++--------- torchnep/train_sharded.py | 2 +- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 3075c89..1162b28 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ function (`train_nep` / `train_nep_sharded`): | `recompute_q_scaler` | `False` | only with `finetune_from`: recompute the descriptor scaler on the new data instead of keeping the source model's | | `slim_types` | `False` | drop element types absent from the dataset | | `energy_key` | `"energy"` | comment-line tag read as reference energy (e.g. `"atomization_energy"`) | -| `use_gpumd_qscaler` | `True` | reproduce GPUMD's init (SNES `mu`): re-init every parameter — descriptor coeffs **and** NN weights — uniform(−1,1), and compute `q_scaler` with coeffs `c=1`. Fresh training only | +| `use_gpumd_qscaler` | `False` | `False`: torch's default init + self-consistent `q_scaler` — converges to better minima (600-epoch 4-seed benchmark: ~12% lower E/V RMSE, ~3% lower F). `True`: reproduce GPUMD's init (SNES `mu`, all parameters uniform(−1,1)) with the `c=1` `q_scaler` — for GPUMD-comparison runs. The saved `nep.txt` is GPUMD-compatible either way. Fresh training only | | `run_seed` | `None` | master RNG seed. `None` = random each run; an int makes the run reproducible (weight init + batch shuffle). Saved in `checkpoint.pt`, restored on resume | | `valid_file` | `None` | validation `.xyz`, `nep_best` and the plateau LR schedule follow the validation loss; writes GPUMD-style `*_test.out` | | `valid_ratio` | `None` | hold out this fraction (e.g. `0.1`) of `data_file` as the validation set; the split is drawn from `run_seed` and preserved on resume. Mutually exclusive with `valid_file` | diff --git a/releaseNotes.md b/releaseNotes.md index 7510f72..39f542c 100644 --- a/releaseNotes.md +++ b/releaseNotes.md @@ -1,5 +1,14 @@ # Release Notes +## Unreleased + +- **`use_gpumd_qscaler` now defaults to `False`**: torch's default init + with the self-consistent q_scaler converges to clearly better minima + than the GPUMD-style start (600-epoch 4-seed PdCuNiP benchmark: ~12% + lower E/V RMSE, ~3% lower F, on train and validation alike). `True` + (the old default) remains available for GPUMD-comparison runs; the + saved nep.txt is GPUMD-compatible either way. + ## 1.0.2a1 - **Streaming-only data path**: the preloaded GPU data store and the diff --git a/torchnep/train.py b/torchnep/train.py index 781c4eb..1b7d1fe 100644 --- a/torchnep/train.py +++ b/torchnep/train.py @@ -1126,7 +1126,7 @@ def train_nep( recompute_q_scaler: bool = False, slim_types: bool = False, energy_key: str = "energy", - use_gpumd_qscaler: bool = True, + use_gpumd_qscaler: bool = False, run_seed: int = None, valid_file: str = None, valid_ratio: float = None, @@ -1180,14 +1180,18 @@ def train_nep( energy_key : name of the comment-line tag read as the reference energy (default ``"energy"``). Set to ``"atomization_energy"`` to train against atomization energies instead of totals. - use_gpumd_qscaler : Default True — reproduce GPUMD's initialization: every - parameter is re-initialised uniform(-1, 1) — the descriptor - coefficients AND the NN weights (w0/b0/w1), matching SNES's mu init — - and the q_scaler is computed with all coefficients = 1.0 (GPUMD's - generation-0 ``initial_para``). False leaves torch's default NN init in - place and uses the self-consistent q_scaler (computed from the model's - actual init coefficients). Only applies to fresh training (ignored - under finetune_from). + use_gpumd_qscaler : Default False — torch's default init with the + self-consistent q_scaler (computed from the model's actual init + coefficients). On a 600-epoch 4-seed PdCuNiP benchmark this + converges to clearly better minima than the GPUMD-style start + (~12% lower E/V RMSE, ~3% lower F, train and validation alike). + True reproduces GPUMD's initialization instead: every parameter + re-initialised uniform(-1, 1) (SNES mu init) and the q_scaler + computed with all coefficients = 1.0 (GPUMD's generation-0 + ``initial_para``) — useful for GPUMD-comparison runs. Either way + the saved nep.txt is fully GPUMD-compatible (the scaler is stored + in the file). Only applies to fresh training (ignored under + finetune_from). run_seed : master RNG seed for this run. None (default) -> a fresh random seed each run, so repeated runs differ (independent weight init AND per-epoch batch shuffle) — the stochastic-testing behaviour. Pass an diff --git a/torchnep/train_sharded.py b/torchnep/train_sharded.py index 08d48aa..d209cc4 100644 --- a/torchnep/train_sharded.py +++ b/torchnep/train_sharded.py @@ -215,7 +215,7 @@ def train_nep_sharded( recompute_q_scaler: bool = False, slim_types: bool = False, energy_key: str = "energy", - use_gpumd_qscaler: bool = True, + use_gpumd_qscaler: bool = False, run_seed: int = None, valid_file: str = None, valid_ratio: float = None,