polystep 0.13.0__tar.gz → 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {polystep-0.13.0 → polystep-1.0.0}/CHANGELOG.md +32 -0
- {polystep-0.13.0 → polystep-1.0.0}/CITATION.cff +4 -4
- polystep-1.0.0/CONTRIBUTING.md +65 -0
- {polystep-0.13.0 → polystep-1.0.0}/LIMITATIONS.md +49 -25
- {polystep-0.13.0 → polystep-1.0.0}/PKG-INFO +46 -33
- {polystep-0.13.0 → polystep-1.0.0}/README.md +43 -28
- polystep-1.0.0/docs/api_overview.md +390 -0
- polystep-1.0.0/docs/determinism.md +61 -0
- polystep-1.0.0/docs/performance.md +237 -0
- polystep-1.0.0/docs/reproducibility.md +152 -0
- {polystep-0.13.0 → polystep-1.0.0}/pyproject.toml +4 -9
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/__init__.py +5 -48
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/_compiled.py +17 -54
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/_serialization.py +30 -77
- polystep-1.0.0/src/polystep/_step_blockwise.py +360 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/_step_core.py +74 -15
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/_step_momentum.py +1 -9
- polystep-1.0.0/src/polystep/_step_monolithic.py +1084 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/adaptive_subspace.py +42 -59
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/api.py +15 -26
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/ask_tell.py +7 -6
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/baselines/core.py +9 -13
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/baselines/methods.py +22 -32
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/benchmarks/__init__.py +0 -2
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/benchmarks/rl/cartpole.py +8 -59
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/benchmarks/rl/gym_evaluator.py +46 -49
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/benchmarks/rl/policies.py +0 -2
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/benchmarks/utils.py +15 -26
- polystep-1.0.0/src/polystep/blockwise.py +135 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/cost_nn.py +608 -287
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/costs.py +15 -14
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/dynamics.py +0 -2
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/epsilon.py +23 -7
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/factored_subspace.py +9 -19
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/geometry.py +16 -36
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/hybrid_subspace.py +89 -178
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/layers/attention.py +9 -8
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/optimizer.py +275 -542
- polystep-1.0.0/src/polystep/projection/sparse.py +249 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/solver.py +52 -94
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/solvers/__init__.py +0 -2
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/solvers/_shared.py +35 -41
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/solvers/base.py +8 -2
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/solvers/greedy.py +11 -31
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/solvers/kl_softmax.py +19 -19
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/solvers/sinkhorn.py +29 -62
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/solvers/softmax.py +16 -3
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/subspace.py +21 -2
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/transform.py +4 -13
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep.egg-info/PKG-INFO +46 -33
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep.egg-info/SOURCES.txt +1 -10
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep.egg-info/requires.txt +1 -3
- {polystep-0.13.0 → polystep-1.0.0}/tests/conftest.py +17 -97
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_ablation_solvers.py +71 -98
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_adaptive_subspace.py +297 -37
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_amortization.py +98 -41
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_api.py +91 -68
- polystep-1.0.0/tests/test_ask_tell.py +172 -0
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_baseline_fairness.py +68 -55
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_baselines.py +71 -6
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_benchmarks.py +2 -2
- polystep-1.0.0/tests/test_biased_rotation.py +145 -0
- polystep-1.0.0/tests/test_blockwise.py +330 -0
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_candidate_autocast.py +5 -7
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_checkpoint_resume.py +94 -91
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_compiled.py +47 -16
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_controlled.py +1 -6
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_cost_nn.py +124 -34
- polystep-1.0.0/tests/test_costs.py +134 -0
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_determinism.py +15 -14
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_dfo.py +403 -91
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_diagnostics.py +6 -6
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_dynamics.py +1 -1
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_end_to_end_learning.py +2 -2
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_epsilon.py +73 -22
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_evaluator_compile_forward.py +14 -1
- polystep-1.0.0/tests/test_factored_subspace.py +226 -0
- polystep-1.0.0/tests/test_fastpath_parity.py +426 -0
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_fused_projection.py +13 -17
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_geometry.py +40 -41
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_hybrid_subspace.py +237 -120
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_input_validation.py +65 -28
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_integration.py +44 -48
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_kl_softmax.py +52 -9
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_layers.py +159 -14
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_math_guards.py +87 -47
- polystep-1.0.0/tests/test_mixed_precision.py +779 -0
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_mnist.py +52 -38
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_no_test_set_leakage.py +5 -9
- polystep-1.0.0/tests/test_nondiff_data.py +86 -0
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_nondiff_models.py +2 -145
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_numerical_stress.py +5 -56
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_objectives.py +16 -42
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_optimizer.py +369 -303
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_per_sample.py +2 -2
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_practical.py +0 -8
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_probe_jitter.py +79 -33
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_quadratic_model.py +101 -83
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_rl_benchmarks.py +156 -4
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_search_experiments.py +23 -4
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_sequential_fast_path.py +30 -34
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_sinkhorn.py +124 -94
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_sinkhorn_numerics.py +19 -8
- polystep-1.0.0/tests/test_site_vmap.py +1192 -0
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_softmax.py +38 -21
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_softmax_integration.py +18 -46
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_sparse_delta_evaluator.py +127 -31
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_sparse_projection.py +115 -30
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_subspace_blockwise.py +132 -190
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_subspace_contract.py +5 -9
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_subspace_delta.py +66 -64
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_subspace_gain.py +2 -2
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_timeseries_val_selection.py +4 -8
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_transform.py +112 -12
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_trust_region.py +110 -55
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_tuning_sweep.py +21 -26
- polystep-0.13.0/CONTRIBUTING.md +0 -54
- polystep-0.13.0/docs/api_overview.md +0 -217
- polystep-0.13.0/docs/determinism.md +0 -31
- polystep-0.13.0/docs/performance.md +0 -133
- polystep-0.13.0/docs/reproducibility.md +0 -80
- polystep-0.13.0/src/polystep/_step_blockwise.py +0 -648
- polystep-0.13.0/src/polystep/_step_monolithic.py +0 -1295
- polystep-0.13.0/src/polystep/blockwise.py +0 -276
- polystep-0.13.0/src/polystep/cma.py +0 -117
- polystep-0.13.0/src/polystep/cma_subspace.py +0 -95
- polystep-0.13.0/src/polystep/projection/sparse.py +0 -208
- polystep-0.13.0/src/polystep/solvers/tempered_softmax.py +0 -31
- polystep-0.13.0/tests/test_ask_tell.py +0 -100
- polystep-0.13.0/tests/test_biased_rotation.py +0 -82
- polystep-0.13.0/tests/test_blockwise.py +0 -219
- polystep-0.13.0/tests/test_cma.py +0 -319
- polystep-0.13.0/tests/test_cma_subspace.py +0 -380
- polystep-0.13.0/tests/test_costs.py +0 -63
- polystep-0.13.0/tests/test_evaluator_regressions.py +0 -367
- polystep-0.13.0/tests/test_factored_subspace.py +0 -107
- polystep-0.13.0/tests/test_fastpath_parity.py +0 -168
- polystep-0.13.0/tests/test_mixed_precision.py +0 -496
- polystep-0.13.0/tests/test_nondiff_data.py +0 -151
- polystep-0.13.0/tests/test_regressions.py +0 -1105
- polystep-0.13.0/tests/test_silent_failures.py +0 -748
- polystep-0.13.0/tests/test_site_vmap.py +0 -382
- polystep-0.13.0/tests/test_vmap_layer_compatibility.py +0 -239
- {polystep-0.13.0 → polystep-1.0.0}/LICENSE +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/MANIFEST.in +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/setup.cfg +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/baselines/__init__.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/benchmarks/rl/__init__.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/benchmarks/rl/metrics.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/benchmarks/threads.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/layers/__init__.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/layers/rnn.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/objectives/__init__.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/objectives/base.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/objectives/synthetic.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/projection/__init__.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/py.typed +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep/quadratic_model.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep.egg-info/dependency_links.txt +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/src/polystep.egg-info/top_level.txt +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/tests/__init__.py +0 -0
- {polystep-0.13.0 → polystep-1.0.0}/tests/test_sparse_integration.py +0 -0
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.0 - 2026-10-13
|
|
4
|
+
|
|
5
|
+
### Upgrade notes
|
|
6
|
+
|
|
7
|
+
- Use `PolyStepOptimizer` for neural networks and `PolyStep` for standalone objectives.
|
|
8
|
+
- Replace diagonal CMA with `AdaptiveSubspace`, tempered softmax with `SoftmaxSolver`,
|
|
9
|
+
and `auto_epsilon` with `ProgressiveEpsilon`. Probe reuse has been removed.
|
|
10
|
+
- Checkpoints use format 6. Rebuild the optimizer from saved model weights when
|
|
11
|
+
upgrading from 0.13; older optimizer checkpoints cannot be loaded.
|
|
12
|
+
- Some low-level exports and experiment helpers moved or were removed. The
|
|
13
|
+
[migration guide](docs/api_overview.md#upgrading-from-013) lists replacements and
|
|
14
|
+
changes to evaluation, configuration, and callbacks.
|
|
15
|
+
|
|
16
|
+
### Fixes
|
|
17
|
+
|
|
18
|
+
- Preserve live model weights, buffers, momentum, and trust-region state across
|
|
19
|
+
evaluation, subspace updates, and checkpoint restoration.
|
|
20
|
+
- Handle nonfinite costs, tiny transport rows, integer losses, and half-precision
|
|
21
|
+
reductions consistently. Sparse CUDA projections repeat in deterministic mode.
|
|
22
|
+
- Accept device strings in rotation sampling and float32 masks in half-precision
|
|
23
|
+
CUDA attention.
|
|
24
|
+
- Correct baseline budgets, tied ranks, rollout accounting, and download handling.
|
|
25
|
+
|
|
26
|
+
### Performance and examples
|
|
27
|
+
|
|
28
|
+
- Reuse unchanged forward work, update only affected weights, and size candidate
|
|
29
|
+
chunks from measured activations. Speed up blockwise, factored, and adaptive steps.
|
|
30
|
+
- Reduce sparse projection storage and host synchronization; compile Sinkhorn loops.
|
|
31
|
+
- Refresh all 11 examples, their evaluation paths, and their documented settings.
|
|
32
|
+
See [performance](docs/performance.md) for measurements and tradeoffs.
|
|
33
|
+
- Consolidate redundant tests and keep release validation focused on the built wheel.
|
|
34
|
+
|
|
3
35
|
## 0.13.0 - 2026-09-22
|
|
4
36
|
|
|
5
37
|
- Fix KL row mass, nonfinite inputs, evaluator hooks, and chunk handling.
|
|
@@ -6,8 +6,8 @@ authors:
|
|
|
6
6
|
- family-names: Le
|
|
7
7
|
given-names: An T.
|
|
8
8
|
license: Apache-2.0
|
|
9
|
-
version: 0.
|
|
10
|
-
date-released: "2026-
|
|
9
|
+
version: 1.0.0
|
|
10
|
+
date-released: "2026-10-13"
|
|
11
11
|
repository-code: "https://github.com/anindex/polystep"
|
|
12
12
|
keywords:
|
|
13
13
|
- gradient-free optimization
|
|
@@ -22,9 +22,9 @@ preferred-citation:
|
|
|
22
22
|
authors:
|
|
23
23
|
- family-names: Le
|
|
24
24
|
given-names: An T.
|
|
25
|
-
journal: "
|
|
25
|
+
journal: "Transactions on Machine Learning Research"
|
|
26
26
|
year: 2026
|
|
27
|
-
url: "https://
|
|
27
|
+
url: "https://openreview.net/forum?id=8mlcqTTMuU"
|
|
28
28
|
references:
|
|
29
29
|
- type: conference-paper
|
|
30
30
|
title: "Accelerating Motion Planning via Optimal Transport"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Install the development dependencies. Then run the CI checks:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install -e ".[dev]"
|
|
7
|
+
ruff check .
|
|
8
|
+
ruff format --check .
|
|
9
|
+
pytest tests/ -q -n auto
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Work on a branch. Add a regression test when the change needs one.
|
|
13
|
+
Open a pull request after the checks pass. Test observable behavior.
|
|
14
|
+
Keep one small regression test per bug.
|
|
15
|
+
Extend an existing case when it already covers the same path; avoid separate tests
|
|
16
|
+
for trivial defaults, getters, or repeated shapes. Keep comments specific and public
|
|
17
|
+
APIs typed.
|
|
18
|
+
|
|
19
|
+
## Tests
|
|
20
|
+
|
|
21
|
+
The default suite excludes `slow` and `gpu` tests. To select them:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pytest tests/ -m slow
|
|
25
|
+
pytest tests/ -m gpu
|
|
26
|
+
pytest tests/ -m ""
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The fast suite uses one CPU thread; `POLYSTEP_TEST_THREADS` overrides it. Slow tests
|
|
30
|
+
use `ncpu - 8` threads, clamped to 2-16, and may download datasets. Keep downloads
|
|
31
|
+
and training-quality checks in the slow suite; use synthetic inputs for unit tests.
|
|
32
|
+
Tests importing `experiments/` must skip when that directory is absent, since it is
|
|
33
|
+
excluded from distributions.
|
|
34
|
+
|
|
35
|
+
Pushes and pull requests test Python 3.11 with PyTorch 2.8 and Python 3.14 with
|
|
36
|
+
current PyTorch. Scheduled and manual runs add Python 3.12/3.13, coverage, real-data
|
|
37
|
+
learning checks, and the shipped tests against the installed wheel. Every run
|
|
38
|
+
builds both distributions and checks the wheel's imports and type marker.
|
|
39
|
+
|
|
40
|
+
## Releases
|
|
41
|
+
|
|
42
|
+
Update `polystep.__version__`. Set the same version and the release date in
|
|
43
|
+
`CITATION.cff`. Add a `CHANGELOG.md` entry with the heading `## X.Y.Z - YYYY-MM-DD`.
|
|
44
|
+
`pyproject.toml` reads the package version automatically.
|
|
45
|
+
If the project's maturity changes, update its `Development Status` classifier.
|
|
46
|
+
|
|
47
|
+
Build the distributions. Then check their metadata:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
uv build
|
|
51
|
+
uvx twine check --strict dist/*
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Run the full manual CI workflow on the release commit.
|
|
55
|
+
This covers the Python matrix and repository-only experiment tests.
|
|
56
|
+
After CI passes, publish a GitHub Release with the tag `vX.Y.Z`.
|
|
57
|
+
This triggers the PyPI workflow. The workflow checks version consistency, lint, and
|
|
58
|
+
package metadata. It tests the installed wheel before it publishes the package.
|
|
59
|
+
Only the separate publish job has OIDC permission; it uses the `pypi` environment
|
|
60
|
+
and PyPI Trusted Publishing.
|
|
61
|
+
|
|
62
|
+
## Issues
|
|
63
|
+
|
|
64
|
+
Include a minimal reproduction, the traceback, Python and PyTorch versions, and
|
|
65
|
+
hardware details relevant to the failure.
|
|
@@ -13,33 +13,46 @@ projection do not apply to those columns.
|
|
|
13
13
|
`FactoredSubspace` restricts perturbations to the input directions in its fixed
|
|
14
14
|
factor. Rotation changes those directions. Retune radii when switching subspaces.
|
|
15
15
|
|
|
16
|
-
Momentum
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
`trace(C) = n`. Its default `mu_eff=1` gives rank-one adaptation only. Cumulative
|
|
23
|
-
step-size adaptation is not implemented.
|
|
16
|
+
Momentum, the `amortize_steps` coasting direction, and the `biased_rotation`
|
|
17
|
+
direction are cleared when the basis changes. `AdaptiveSubspace` rotates every step
|
|
18
|
+
by default. These options need a longer rotation interval to take effect.
|
|
19
|
+
The optimizer warns when you combine them with rotation on every step.
|
|
20
|
+
Heavy-ball momentum can amplify the barycentric displacement.
|
|
21
|
+
`step_radius` bounds the displacement before momentum.
|
|
24
22
|
|
|
25
23
|
## Evaluation
|
|
26
24
|
|
|
27
25
|
- `step()` expects `closure(batched_params) -> losses` with shape `(N,)`.
|
|
26
|
+
The candidate tensors may share storage that the next chunk overwrites, so clone
|
|
27
|
+
any you keep after the closure returns.
|
|
28
28
|
- Manual loops must register the evaluator and current batch to enable fast paths.
|
|
29
29
|
The evaluator and closure must compute the same objective.
|
|
30
|
+
- `NNCostEvaluator` and `train()` score candidates in eval mode: dropout is off and
|
|
31
|
+
batch-norm running statistics never update. A custom closure that runs the model in
|
|
32
|
+
train mode compares candidates under different dropout masks.
|
|
30
33
|
- Mixed-dtype models require `HybridSubspace` or `FactoredSubspace`. Full-space and
|
|
31
34
|
global-subspace coordinates use one dtype and reject mixed parameter dtypes.
|
|
32
35
|
- `mixed_precision=True` uses BF16 geometry and forwards; solver costs use FP32.
|
|
33
|
-
Models needing autocast internally must provide it.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
36
|
+
Models needing autocast internally must provide it. Half-precision candidate outputs
|
|
37
|
+
reduce in FP32 only under the builtin cross-entropy, MSE and L1 losses at their
|
|
38
|
+
defaults apart from `reduction`. Other losses may round nearby candidate scores
|
|
39
|
+
to the same value. With FP16 or BF16 parameters, `FactoredSubspace` materializes
|
|
40
|
+
every candidate and runs slower. See
|
|
41
|
+
[precision](docs/performance.md#compilation-and-precision).
|
|
42
|
+
- `train()` rejects `trust_region`. See
|
|
43
|
+
[radius control](docs/api_overview.md#quadratic-model-and-radius-control) for its
|
|
44
|
+
manual-step use.
|
|
45
|
+
- `trust_region` and `use_adaptive_radius` both scale the step. Choose one; the
|
|
46
|
+
optimizer warns when both are on.
|
|
39
47
|
- Multi-fidelity screening imputes dropped costs using an additive offset. This can
|
|
40
|
-
bias the full-fidelity cost estimate
|
|
41
|
-
-
|
|
42
|
-
options warn at construction.
|
|
48
|
+
bias the full-fidelity cost estimate.
|
|
49
|
+
- Full-space blockwise mode does not support every monolithic adaptation option;
|
|
50
|
+
unsupported options warn at construction.
|
|
51
|
+
- Automatic chunk sizing counts outputs of layers with parameters. On a site-local
|
|
52
|
+
path, it counts all module outputs from the perturbed layer onward, provided the
|
|
53
|
+
forward neither draws random numbers nor reads the perturbed parameter before
|
|
54
|
+
calling its layer. Attention scores and other temporary tensors inside a module's
|
|
55
|
+
forward are not counted. Set `chunk_size` by hand if such a model runs out of memory.
|
|
43
56
|
- The library does not distribute optimizer state across multiple GPUs.
|
|
44
57
|
|
|
45
58
|
## Attention and recurrent layers
|
|
@@ -53,9 +66,7 @@ Boolean masks use `True` for masked positions; float masks are additive. Attenti
|
|
|
53
66
|
masks accept `(query, key)`, `(batch * heads, query, key)`, and broadcastable 4D shapes.
|
|
54
67
|
The wrapper also accepts `(batch, query, key)` masks.
|
|
55
68
|
|
|
56
|
-
CPU
|
|
57
|
-
may emit a batching-fallback warning. Evaluate dropout layers in `model.eval()` mode
|
|
58
|
-
for deterministic candidate comparisons.
|
|
69
|
+
CPU vmap may emit a batching-fallback warning.
|
|
59
70
|
|
|
60
71
|
[`VmapSafeLSTM`](src/polystep/layers/rnn.py) requires batch-first dense inputs. It does
|
|
61
72
|
not support bidirectional recurrence, projection, or `PackedSequence`. Its explicit
|
|
@@ -70,10 +81,22 @@ a common direction across particles.
|
|
|
70
81
|
|
|
71
82
|
Sinkhorn requires `omega` in `[0.5, 1.95]`. Anderson acceleration and adaptive omega
|
|
72
83
|
are inactive in fixed-iteration mode (`threshold <= 0`). Both solver families promote
|
|
73
|
-
FP16/BF16 costs to FP32.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
84
|
+
FP16/BF16 costs to FP32. Cost differences and reductions must also fit the solver's
|
|
85
|
+
dtype: finite FP32 inputs near its limits can still overflow when recentered or
|
|
86
|
+
averaged. Rescale the objective before evaluation or return FP64 costs in that case.
|
|
87
|
+
|
|
88
|
+
All nonfinite costs are invalid. `min_cost_greedy` and `top_k_mean` skip a vertex
|
|
89
|
+
with any nonfinite probe, and the solve leaves a particle with no feasible vertex
|
|
90
|
+
where it is. The weighted solvers replace each nonfinite cost with twice the largest
|
|
91
|
+
finite magnitude plus one, clamped to the dtype limit. An infeasible candidate can
|
|
92
|
+
therefore retain weight, depending on epsilon. With `scale_cost='mean'` or
|
|
93
|
+
`'max_cost'`, the solvers compute the penalty after scaling. Otherwise, that weight
|
|
94
|
+
also depends on the cost offset.
|
|
95
|
+
Balanced Sinkhorn sends every column its prescribed mass, even when all of that
|
|
96
|
+
column's candidates are infeasible. The monolithic step records a vertex's cost as
|
|
97
|
+
the mean of its probes with each nonfinite probe already penalized, so with several
|
|
98
|
+
probes a vertex with only some nonfinite probes can still set the best-vertex
|
|
99
|
+
progress that drives the adaptive radius.
|
|
77
100
|
|
|
78
101
|
Quadratic fits are finite-radius models. Simplex gradients can be biased on
|
|
79
102
|
anisotropic quadratics, and block models omit cross-block curvature. A fit does not
|
|
@@ -89,4 +112,5 @@ The SNN surrogate-gradient baseline has substantial variation across seeds. MAX-
|
|
|
89
112
|
search heuristics use flip budgets, which are not equivalent to neural candidate
|
|
90
113
|
budgets. Head-only GPT-2 experiments do not establish full-model fine-tuning results.
|
|
91
114
|
|
|
92
|
-
|
|
115
|
+
The [reproducibility guide](docs/reproducibility.md#protocol) gives the protocols, and the
|
|
116
|
+
[experiment index](experiments/EXPERIMENT_INDEX.md) has the results.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: polystep
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: PyTorch PolyStep Optimizer - gradient-free neural network training via entropic optimal transport
|
|
5
5
|
Author: An T. Le
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -10,7 +10,7 @@ Project-URL: Documentation, https://github.com/anindex/polystep/blob/main/docs/a
|
|
|
10
10
|
Project-URL: Changelog, https://github.com/anindex/polystep/blob/main/CHANGELOG.md
|
|
11
11
|
Project-URL: Issues, https://github.com/anindex/polystep/issues
|
|
12
12
|
Keywords: pytorch,optimal-transport,gradient-free,sinkhorn,polystep,optimization,neural-network
|
|
13
|
-
Classifier: Development Status ::
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
14
|
Classifier: Intended Audience :: Science/Research
|
|
15
15
|
Classifier: Intended Audience :: Developers
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
@@ -45,14 +45,12 @@ Requires-Dist: pandas>=2.0; extra == "experiments"
|
|
|
45
45
|
Requires-Dist: python-sat; extra == "experiments"
|
|
46
46
|
Requires-Dist: torchvision>=0.25; extra == "experiments"
|
|
47
47
|
Requires-Dist: cma>=3.3; extra == "experiments"
|
|
48
|
-
Requires-Dist: snntorch>=0.7; extra == "experiments"
|
|
49
48
|
Requires-Dist: datasets>=2.14; extra == "experiments"
|
|
50
49
|
Requires-Dist: transformers>=4.40; extra == "experiments"
|
|
51
50
|
Requires-Dist: gymnasium>=0.29; extra == "experiments"
|
|
52
51
|
Provides-Extra: rl
|
|
53
|
-
Requires-Dist: gymnasium
|
|
52
|
+
Requires-Dist: gymnasium>=0.29; extra == "rl"
|
|
54
53
|
Requires-Dist: stable-baselines3>=2.3; extra == "rl"
|
|
55
|
-
Requires-Dist: swig>=4.2; extra == "rl"
|
|
56
54
|
Dynamic: license-file
|
|
57
55
|
|
|
58
56
|
# polystep
|
|
@@ -74,7 +72,8 @@ backpropagation is usually faster.
|
|
|
74
72
|
|
|
75
73
|
[Paper](https://arxiv.org/abs/2605.01928) ·
|
|
76
74
|
[Interactive visualization](https://vietngth.github.io/polystep-visualization/) ·
|
|
77
|
-
[API reference](docs/api_overview.md)
|
|
75
|
+
[API reference](https://github.com/anindex/polystep/blob/main/docs/api_overview.md) ·
|
|
76
|
+
[Julia package](https://github.com/anindex/PolyStep.jl)
|
|
78
77
|
|
|
79
78
|
<p align="center">
|
|
80
79
|
<img src="https://raw.githubusercontent.com/anindex/polystep/main/docs/figures/method_diagram.png" width="840"
|
|
@@ -85,7 +84,7 @@ backpropagation is usually faster.
|
|
|
85
84
|
|
|
86
85
|
```bash
|
|
87
86
|
pip install polystep
|
|
88
|
-
pip install "polystep[examples]" #
|
|
87
|
+
pip install "polystep[examples]" # dependencies for the repository's examples
|
|
89
88
|
```
|
|
90
89
|
|
|
91
90
|
Python 3.11+ and PyTorch 2.8+ are required. Choose a CUDA build compatible with your
|
|
@@ -98,8 +97,7 @@ For development, install `pip install -e ".[dev]"` from a checkout.
|
|
|
98
97
|
import torch
|
|
99
98
|
from torch import nn
|
|
100
99
|
from torch.utils.data import DataLoader, TensorDataset
|
|
101
|
-
from polystep import HybridSubspace, PolyStepOptimizer, TrainConfig, train
|
|
102
|
-
from polystep.transform import ParamLayout
|
|
100
|
+
from polystep import HybridSubspace, ParamLayout, PolyStepOptimizer, TrainConfig, train
|
|
103
101
|
|
|
104
102
|
model = nn.Sequential(nn.Linear(16, 32), nn.ReLU(), nn.Linear(32, 3))
|
|
105
103
|
loader = DataLoader(
|
|
@@ -113,10 +111,11 @@ optimizer = PolyStepOptimizer(model, subspace=subspace, solver="softmax")
|
|
|
113
111
|
train(model, loader, nn.CrossEntropyLoss(), optimizer, TrainConfig(epochs=5))
|
|
114
112
|
```
|
|
115
113
|
|
|
116
|
-
Replace the generated data with your dataset.
|
|
117
|
-
|
|
118
|
-
`train()` does this automatically. See
|
|
119
|
-
|
|
114
|
+
Replace the generated data with your dataset. `max_subspace_dim=128` caps the search
|
|
115
|
+
at 128 coordinates, so each step scores 144 candidates. In manual loops, call
|
|
116
|
+
`register_evaluator()` before each batch; `train()` does this automatically. See
|
|
117
|
+
[performance](https://github.com/anindex/polystep/blob/main/docs/performance.md)
|
|
118
|
+
for candidate paths, thread counts, compilation, and memory settings.
|
|
120
119
|
|
|
121
120
|
### Ask/tell
|
|
122
121
|
|
|
@@ -133,6 +132,7 @@ print(es.best_fitness, es.best_solution)
|
|
|
133
132
|
### Synthetic objectives
|
|
134
133
|
|
|
135
134
|
```python
|
|
135
|
+
import torch
|
|
136
136
|
from polystep import Ackley
|
|
137
137
|
from polystep.solver import PolyStep
|
|
138
138
|
|
|
@@ -144,7 +144,8 @@ state = solver.run(torch.randn(100, 10))
|
|
|
144
144
|
|
|
145
145
|
Each step samples a rotated polytope, evaluates its vertices, computes transport
|
|
146
146
|
weights, and moves to their barycenter. Subspaces reduce the number of coordinates
|
|
147
|
-
searched. Softmax
|
|
147
|
+
searched. Softmax normalizes each particle's vertex weights; Sinkhorn also enforces
|
|
148
|
+
the target marginal.
|
|
148
149
|
|
|
149
150
|
Finite-radius probes can cross flat regions of discontinuous losses. Performance
|
|
150
151
|
depends on the radius, representation, and evaluation budget. PolyStep's optional
|
|
@@ -154,8 +155,8 @@ inherit classical direct-search or trust-region guarantees.
|
|
|
154
155
|
## Baselines
|
|
155
156
|
|
|
156
157
|
`polystep.baselines` provides `openai_es`, `spsa`, `mezo`, `random_search`, `eggroll`,
|
|
157
|
-
and `cma_es`. One evaluation means one candidate
|
|
158
|
-
batched:
|
|
158
|
+
and `cma_es`, which needs `pip install cma`. One evaluation means one candidate
|
|
159
|
+
scored, even when candidates are batched:
|
|
159
160
|
|
|
160
161
|
```python
|
|
161
162
|
from polystep.baselines import Objective, openai_es
|
|
@@ -164,20 +165,30 @@ objective = Objective(lambda x: x.square().sum(1), dim=64, budget=10_000)
|
|
|
164
165
|
result = openai_es(objective, sigma=0.05, lr=0.1, popsize=32)
|
|
165
166
|
```
|
|
166
167
|
|
|
167
|
-
The paper runners
|
|
168
|
-
|
|
169
|
-
[reproduction protocol](docs/reproducibility.md) for tuning and budget details.
|
|
168
|
+
The paper runners match search spaces, budgets and tuning as the
|
|
169
|
+
[reproducibility guide](https://github.com/anindex/polystep/blob/main/docs/reproducibility.md#protocol) describes.
|
|
170
170
|
|
|
171
171
|
## Benchmarks
|
|
172
172
|
|
|
173
|
-
Five-seed mean ± sample standard deviation
|
|
174
|
-
validation
|
|
175
|
-
|
|
173
|
+
Five-seed mean ± sample standard deviation, with configurations and checkpoints
|
|
174
|
+
selected on validation data; the probSAT and RC2 columns are single runs. In the
|
|
175
|
+
architecture tables, OpenAI-ES, CMA-ES and EGGROLL get PolyStep's candidate-evaluation
|
|
176
|
+
budget, and SPSA, MeZO and random search get its step count. On argmax attention, hard
|
|
177
|
+
MoE and ETTh1, the population methods instead get 32 evaluations per PolyStep step,
|
|
178
|
+
spent at their own population size, and Adam trains for PolyStep's 30 epochs, except
|
|
179
|
+
50 on ETTh1. On MAX-SAT, CMA-ES and OpenAI-ES get 50 evaluations per PolyStep step.
|
|
180
|
+
OpenAI-ES scores 50 candidates at each of PolyStep's steps, while CMA-ES doubles its
|
|
181
|
+
population at each restart and takes fewer generations. The tables were recorded
|
|
182
|
+
before 1.0; the
|
|
183
|
+
[reproducibility guide](https://github.com/anindex/polystep/blob/main/docs/reproducibility.md#changes-since-the-published-tables)
|
|
184
|
+
lists the rows that 1.0 changes. The
|
|
185
|
+
[experiment index](https://github.com/anindex/polystep/blob/main/experiments/EXPERIMENT_INDEX.md)
|
|
186
|
+
has the full tables.
|
|
176
187
|
|
|
177
188
|
<!-- BENCH:START -->
|
|
178
189
|
### Non-differentiable tasks
|
|
179
190
|
|
|
180
|
-
Test accuracy %. A dash means the
|
|
191
|
+
Test accuracy %. A dash means the method was not run on that task.
|
|
181
192
|
|
|
182
193
|
| Task | PolyStep | CMA-ES | OpenAI-ES | SPSA | Adam (surrogate) | Non-diff op |
|
|
183
194
|
|---|---|---|---|---|---|---|
|
|
@@ -205,16 +216,17 @@ Test accuracy %. A dash means the result is not in this release.
|
|
|
205
216
|
|
|
206
217
|
The SNN surrogate-gradient baseline varies substantially across seeds. Adam leads
|
|
207
218
|
on the differentiable tasks, and specialized solvers lead on MAX-SAT. See
|
|
208
|
-
[limitations](LIMITATIONS.md)
|
|
219
|
+
[limitations](https://github.com/anindex/polystep/blob/main/LIMITATIONS.md)
|
|
220
|
+
for unsupported configurations and comparison limits.
|
|
209
221
|
|
|
210
222
|
## Documentation
|
|
211
223
|
|
|
212
|
-
- [API reference](docs/api_overview.md)
|
|
213
|
-
- [Performance](docs/performance.md)
|
|
214
|
-
- [Examples](examples/README.md)
|
|
215
|
-
- [Experiments](experiments/README.md) and [reproduction](docs/reproducibility.md)
|
|
216
|
-
- [Determinism](docs/determinism.md)
|
|
217
|
-
- [Contributing](CONTRIBUTING.md) and [changelog](CHANGELOG.md)
|
|
224
|
+
- [API reference](https://github.com/anindex/polystep/blob/main/docs/api_overview.md)
|
|
225
|
+
- [Performance](https://github.com/anindex/polystep/blob/main/docs/performance.md)
|
|
226
|
+
- [Examples](https://github.com/anindex/polystep/blob/main/examples/README.md)
|
|
227
|
+
- [Experiments](https://github.com/anindex/polystep/blob/main/experiments/README.md) and [reproduction](https://github.com/anindex/polystep/blob/main/docs/reproducibility.md)
|
|
228
|
+
- [Determinism](https://github.com/anindex/polystep/blob/main/docs/determinism.md)
|
|
229
|
+
- [Contributing](https://github.com/anindex/polystep/blob/main/CONTRIBUTING.md) and [changelog](https://github.com/anindex/polystep/blob/main/CHANGELOG.md)
|
|
218
230
|
|
|
219
231
|
## Citation
|
|
220
232
|
|
|
@@ -222,8 +234,9 @@ on the differentiable tasks, and specialized solvers lead on MAX-SAT. See
|
|
|
222
234
|
@article{le2026training,
|
|
223
235
|
title={Training Non-Differentiable Networks via Optimal Transport},
|
|
224
236
|
author={Le, An T},
|
|
225
|
-
journal={
|
|
226
|
-
year={2026}
|
|
237
|
+
journal={Transactions on Machine Learning Research},
|
|
238
|
+
year={2026},
|
|
239
|
+
url={https://openreview.net/forum?id=8mlcqTTMuU}
|
|
227
240
|
}
|
|
228
241
|
```
|
|
229
242
|
|
|
@@ -234,4 +247,4 @@ Thanks to [Viet T. Nguyen](https://vietngth.github.io/) for the
|
|
|
234
247
|
|
|
235
248
|
## License
|
|
236
249
|
|
|
237
|
-
[Apache-2.0](LICENSE).
|
|
250
|
+
[Apache-2.0](https://github.com/anindex/polystep/blob/main/LICENSE).
|
|
@@ -17,7 +17,8 @@ backpropagation is usually faster.
|
|
|
17
17
|
|
|
18
18
|
[Paper](https://arxiv.org/abs/2605.01928) ·
|
|
19
19
|
[Interactive visualization](https://vietngth.github.io/polystep-visualization/) ·
|
|
20
|
-
[API reference](docs/api_overview.md)
|
|
20
|
+
[API reference](https://github.com/anindex/polystep/blob/main/docs/api_overview.md) ·
|
|
21
|
+
[Julia package](https://github.com/anindex/PolyStep.jl)
|
|
21
22
|
|
|
22
23
|
<p align="center">
|
|
23
24
|
<img src="https://raw.githubusercontent.com/anindex/polystep/main/docs/figures/method_diagram.png" width="840"
|
|
@@ -28,7 +29,7 @@ backpropagation is usually faster.
|
|
|
28
29
|
|
|
29
30
|
```bash
|
|
30
31
|
pip install polystep
|
|
31
|
-
pip install "polystep[examples]" #
|
|
32
|
+
pip install "polystep[examples]" # dependencies for the repository's examples
|
|
32
33
|
```
|
|
33
34
|
|
|
34
35
|
Python 3.11+ and PyTorch 2.8+ are required. Choose a CUDA build compatible with your
|
|
@@ -41,8 +42,7 @@ For development, install `pip install -e ".[dev]"` from a checkout.
|
|
|
41
42
|
import torch
|
|
42
43
|
from torch import nn
|
|
43
44
|
from torch.utils.data import DataLoader, TensorDataset
|
|
44
|
-
from polystep import HybridSubspace, PolyStepOptimizer, TrainConfig, train
|
|
45
|
-
from polystep.transform import ParamLayout
|
|
45
|
+
from polystep import HybridSubspace, ParamLayout, PolyStepOptimizer, TrainConfig, train
|
|
46
46
|
|
|
47
47
|
model = nn.Sequential(nn.Linear(16, 32), nn.ReLU(), nn.Linear(32, 3))
|
|
48
48
|
loader = DataLoader(
|
|
@@ -56,10 +56,11 @@ optimizer = PolyStepOptimizer(model, subspace=subspace, solver="softmax")
|
|
|
56
56
|
train(model, loader, nn.CrossEntropyLoss(), optimizer, TrainConfig(epochs=5))
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Replace the generated data with your dataset.
|
|
60
|
-
|
|
61
|
-
`train()` does this automatically. See
|
|
62
|
-
|
|
59
|
+
Replace the generated data with your dataset. `max_subspace_dim=128` caps the search
|
|
60
|
+
at 128 coordinates, so each step scores 144 candidates. In manual loops, call
|
|
61
|
+
`register_evaluator()` before each batch; `train()` does this automatically. See
|
|
62
|
+
[performance](https://github.com/anindex/polystep/blob/main/docs/performance.md)
|
|
63
|
+
for candidate paths, thread counts, compilation, and memory settings.
|
|
63
64
|
|
|
64
65
|
### Ask/tell
|
|
65
66
|
|
|
@@ -76,6 +77,7 @@ print(es.best_fitness, es.best_solution)
|
|
|
76
77
|
### Synthetic objectives
|
|
77
78
|
|
|
78
79
|
```python
|
|
80
|
+
import torch
|
|
79
81
|
from polystep import Ackley
|
|
80
82
|
from polystep.solver import PolyStep
|
|
81
83
|
|
|
@@ -87,7 +89,8 @@ state = solver.run(torch.randn(100, 10))
|
|
|
87
89
|
|
|
88
90
|
Each step samples a rotated polytope, evaluates its vertices, computes transport
|
|
89
91
|
weights, and moves to their barycenter. Subspaces reduce the number of coordinates
|
|
90
|
-
searched. Softmax
|
|
92
|
+
searched. Softmax normalizes each particle's vertex weights; Sinkhorn also enforces
|
|
93
|
+
the target marginal.
|
|
91
94
|
|
|
92
95
|
Finite-radius probes can cross flat regions of discontinuous losses. Performance
|
|
93
96
|
depends on the radius, representation, and evaluation budget. PolyStep's optional
|
|
@@ -97,8 +100,8 @@ inherit classical direct-search or trust-region guarantees.
|
|
|
97
100
|
## Baselines
|
|
98
101
|
|
|
99
102
|
`polystep.baselines` provides `openai_es`, `spsa`, `mezo`, `random_search`, `eggroll`,
|
|
100
|
-
and `cma_es`. One evaluation means one candidate
|
|
101
|
-
batched:
|
|
103
|
+
and `cma_es`, which needs `pip install cma`. One evaluation means one candidate
|
|
104
|
+
scored, even when candidates are batched:
|
|
102
105
|
|
|
103
106
|
```python
|
|
104
107
|
from polystep.baselines import Objective, openai_es
|
|
@@ -107,20 +110,30 @@ objective = Objective(lambda x: x.square().sum(1), dim=64, budget=10_000)
|
|
|
107
110
|
result = openai_es(objective, sigma=0.05, lr=0.1, popsize=32)
|
|
108
111
|
```
|
|
109
112
|
|
|
110
|
-
The paper runners
|
|
111
|
-
|
|
112
|
-
[reproduction protocol](docs/reproducibility.md) for tuning and budget details.
|
|
113
|
+
The paper runners match search spaces, budgets and tuning as the
|
|
114
|
+
[reproducibility guide](https://github.com/anindex/polystep/blob/main/docs/reproducibility.md#protocol) describes.
|
|
113
115
|
|
|
114
116
|
## Benchmarks
|
|
115
117
|
|
|
116
|
-
Five-seed mean ± sample standard deviation
|
|
117
|
-
validation
|
|
118
|
-
|
|
118
|
+
Five-seed mean ± sample standard deviation, with configurations and checkpoints
|
|
119
|
+
selected on validation data; the probSAT and RC2 columns are single runs. In the
|
|
120
|
+
architecture tables, OpenAI-ES, CMA-ES and EGGROLL get PolyStep's candidate-evaluation
|
|
121
|
+
budget, and SPSA, MeZO and random search get its step count. On argmax attention, hard
|
|
122
|
+
MoE and ETTh1, the population methods instead get 32 evaluations per PolyStep step,
|
|
123
|
+
spent at their own population size, and Adam trains for PolyStep's 30 epochs, except
|
|
124
|
+
50 on ETTh1. On MAX-SAT, CMA-ES and OpenAI-ES get 50 evaluations per PolyStep step.
|
|
125
|
+
OpenAI-ES scores 50 candidates at each of PolyStep's steps, while CMA-ES doubles its
|
|
126
|
+
population at each restart and takes fewer generations. The tables were recorded
|
|
127
|
+
before 1.0; the
|
|
128
|
+
[reproducibility guide](https://github.com/anindex/polystep/blob/main/docs/reproducibility.md#changes-since-the-published-tables)
|
|
129
|
+
lists the rows that 1.0 changes. The
|
|
130
|
+
[experiment index](https://github.com/anindex/polystep/blob/main/experiments/EXPERIMENT_INDEX.md)
|
|
131
|
+
has the full tables.
|
|
119
132
|
|
|
120
133
|
<!-- BENCH:START -->
|
|
121
134
|
### Non-differentiable tasks
|
|
122
135
|
|
|
123
|
-
Test accuracy %. A dash means the
|
|
136
|
+
Test accuracy %. A dash means the method was not run on that task.
|
|
124
137
|
|
|
125
138
|
| Task | PolyStep | CMA-ES | OpenAI-ES | SPSA | Adam (surrogate) | Non-diff op |
|
|
126
139
|
|---|---|---|---|---|---|---|
|
|
@@ -148,16 +161,17 @@ Test accuracy %. A dash means the result is not in this release.
|
|
|
148
161
|
|
|
149
162
|
The SNN surrogate-gradient baseline varies substantially across seeds. Adam leads
|
|
150
163
|
on the differentiable tasks, and specialized solvers lead on MAX-SAT. See
|
|
151
|
-
[limitations](LIMITATIONS.md)
|
|
164
|
+
[limitations](https://github.com/anindex/polystep/blob/main/LIMITATIONS.md)
|
|
165
|
+
for unsupported configurations and comparison limits.
|
|
152
166
|
|
|
153
167
|
## Documentation
|
|
154
168
|
|
|
155
|
-
- [API reference](docs/api_overview.md)
|
|
156
|
-
- [Performance](docs/performance.md)
|
|
157
|
-
- [Examples](examples/README.md)
|
|
158
|
-
- [Experiments](experiments/README.md) and [reproduction](docs/reproducibility.md)
|
|
159
|
-
- [Determinism](docs/determinism.md)
|
|
160
|
-
- [Contributing](CONTRIBUTING.md) and [changelog](CHANGELOG.md)
|
|
169
|
+
- [API reference](https://github.com/anindex/polystep/blob/main/docs/api_overview.md)
|
|
170
|
+
- [Performance](https://github.com/anindex/polystep/blob/main/docs/performance.md)
|
|
171
|
+
- [Examples](https://github.com/anindex/polystep/blob/main/examples/README.md)
|
|
172
|
+
- [Experiments](https://github.com/anindex/polystep/blob/main/experiments/README.md) and [reproduction](https://github.com/anindex/polystep/blob/main/docs/reproducibility.md)
|
|
173
|
+
- [Determinism](https://github.com/anindex/polystep/blob/main/docs/determinism.md)
|
|
174
|
+
- [Contributing](https://github.com/anindex/polystep/blob/main/CONTRIBUTING.md) and [changelog](https://github.com/anindex/polystep/blob/main/CHANGELOG.md)
|
|
161
175
|
|
|
162
176
|
## Citation
|
|
163
177
|
|
|
@@ -165,8 +179,9 @@ on the differentiable tasks, and specialized solvers lead on MAX-SAT. See
|
|
|
165
179
|
@article{le2026training,
|
|
166
180
|
title={Training Non-Differentiable Networks via Optimal Transport},
|
|
167
181
|
author={Le, An T},
|
|
168
|
-
journal={
|
|
169
|
-
year={2026}
|
|
182
|
+
journal={Transactions on Machine Learning Research},
|
|
183
|
+
year={2026},
|
|
184
|
+
url={https://openreview.net/forum?id=8mlcqTTMuU}
|
|
170
185
|
}
|
|
171
186
|
```
|
|
172
187
|
|
|
@@ -177,4 +192,4 @@ Thanks to [Viet T. Nguyen](https://vietngth.github.io/) for the
|
|
|
177
192
|
|
|
178
193
|
## License
|
|
179
194
|
|
|
180
|
-
[Apache-2.0](LICENSE).
|
|
195
|
+
[Apache-2.0](https://github.com/anindex/polystep/blob/main/LICENSE).
|