python-somax 1.0.1__tar.gz → 1.1.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.
Files changed (68) hide show
  1. python_somax-1.1.0/PKG-INFO +182 -0
  2. python_somax-1.1.0/README.md +138 -0
  3. {python_somax-1.0.1 → python_somax-1.1.0}/pyproject.toml +6 -5
  4. python_somax-1.1.0/src/python_somax.egg-info/PKG-INFO +182 -0
  5. {python_somax-1.0.1 → python_somax-1.1.0}/src/python_somax.egg-info/SOURCES.txt +6 -1
  6. {python_somax-1.0.1 → python_somax-1.1.0}/src/python_somax.egg-info/requires.txt +6 -1
  7. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/__init__.py +6 -0
  8. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/assembler.py +17 -7
  9. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/curvature/__init__.py +2 -0
  10. python_somax-1.1.0/src/somax/curvature/base.py +140 -0
  11. python_somax-1.1.0/src/somax/curvature/fgnha_ce.py +338 -0
  12. python_somax-1.1.0/src/somax/curvature/ggn_ce.py +281 -0
  13. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/curvature/ggn_mse.py +57 -16
  14. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/curvature/hessian.py +24 -4
  15. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/curvature/with_estimators.py +29 -4
  16. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/damping/__init__.py +4 -1
  17. python_somax-1.1.0/src/somax/damping/scheduled.py +63 -0
  18. python_somax-1.1.0/src/somax/damping/trust_region.py +162 -0
  19. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/estimators/__init__.py +6 -0
  20. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/estimators/base.py +4 -2
  21. python_somax-1.1.0/src/somax/estimators/diagpp.py +251 -0
  22. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/estimators/gnb_ce.py +8 -7
  23. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/estimators/hutchinson.py +8 -16
  24. python_somax-1.1.0/src/somax/estimators/lanczos.py +94 -0
  25. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/executor.py +239 -145
  26. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/methods/__init__.py +6 -1
  27. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/methods/adahessian.py +0 -1
  28. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/methods/direct_methods.py +55 -8
  29. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/methods/egn.py +118 -24
  30. python_somax-1.1.0/src/somax/methods/fgn.py +168 -0
  31. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/methods/newton_cg.py +7 -7
  32. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/methods/sgn.py +21 -17
  33. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/methods/sophia_g.py +5 -4
  34. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/methods/sophia_h.py +0 -1
  35. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/metrics.py +11 -7
  36. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/optax.py +3 -3
  37. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/planner.py +47 -52
  38. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/preconditioners/__init__.py +1 -1
  39. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/preconditioners/base.py +1 -0
  40. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/preconditioners/diag_ema.py +6 -4
  41. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/solvers/__init__.py +2 -2
  42. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/solvers/base.py +1 -1
  43. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/solvers/cg.py +100 -52
  44. python_somax-1.1.0/src/somax/solvers/direct.py +204 -0
  45. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/solvers/row_cg.py +14 -38
  46. python_somax-1.1.0/src/somax/solvers/row_cg_lifted.py +183 -0
  47. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/solvers/row_common.py +9 -6
  48. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/specs.py +60 -26
  49. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/types.py +21 -2
  50. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/utils.py +3 -10
  51. python_somax-1.0.1/PKG-INFO +0 -202
  52. python_somax-1.0.1/README.md +0 -162
  53. python_somax-1.0.1/src/python_somax.egg-info/PKG-INFO +0 -202
  54. python_somax-1.0.1/src/somax/curvature/base.py +0 -56
  55. python_somax-1.0.1/src/somax/curvature/ggn_ce.py +0 -183
  56. python_somax-1.0.1/src/somax/damping/trust_region.py +0 -115
  57. python_somax-1.0.1/src/somax/solvers/direct.py +0 -55
  58. python_somax-1.0.1/src/somax/solvers/row_cholesky.py +0 -78
  59. {python_somax-1.0.1 → python_somax-1.1.0}/LICENSE +0 -0
  60. {python_somax-1.0.1 → python_somax-1.1.0}/setup.cfg +0 -0
  61. {python_somax-1.0.1 → python_somax-1.1.0}/src/python_somax.egg-info/dependency_links.txt +0 -0
  62. {python_somax-1.0.1 → python_somax-1.1.0}/src/python_somax.egg-info/top_level.txt +0 -0
  63. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/damping/base.py +0 -0
  64. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/damping/constant.py +0 -0
  65. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/preconditioners/diag_direct.py +0 -0
  66. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/preconditioners/identity.py +0 -0
  67. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/presets.py +0 -0
  68. {python_somax-1.0.1 → python_somax-1.1.0}/src/somax/solvers/identity.py +0 -0
@@ -0,0 +1,182 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-somax
3
+ Version: 1.1.0
4
+ Summary: Composable Second-Order Optimization for JAX and Optax.
5
+ Author: Nick Korbit
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/cor3bit/somax
8
+ Project-URL: Repository, https://github.com/cor3bit/somax
9
+ Project-URL: Issues, https://github.com/cor3bit/somax/issues
10
+ Project-URL: Releases, https://github.com/cor3bit/somax/releases
11
+ Project-URL: Documentation, https://github.com/cor3bit/somax/tree/main/docs
12
+ Project-URL: Paper, https://arxiv.org/abs/2603.25976
13
+ Keywords: jax,optax,optimization,second-order,gauss-newton,hessian,machine-learning
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
21
+ Requires-Python: >=3.11
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: jax>=0.4.20
25
+ Requires-Dist: optax>=0.1.7
26
+ Requires-Dist: flax>=0.7.5
27
+ Provides-Extra: dev
28
+ Requires-Dist: build>=1.2; extra == "dev"
29
+ Requires-Dist: twine>=5; extra == "dev"
30
+ Requires-Dist: pytest>=8; extra == "dev"
31
+ Requires-Dist: pytest-cov>=5; extra == "dev"
32
+ Requires-Dist: ruff>=0.5; extra == "dev"
33
+ Requires-Dist: pyright>=1.1; extra == "dev"
34
+ Requires-Dist: pre-commit>=3; extra == "dev"
35
+ Requires-Dist: chex>=0.1.8; extra == "dev"
36
+ Provides-Extra: docs
37
+ Requires-Dist: mkdocs>=1.5; extra == "docs"
38
+ Requires-Dist: mkdocs-material>=9; extra == "docs"
39
+ Provides-Extra: matfree
40
+ Requires-Dist: matfree; extra == "matfree"
41
+ Provides-Extra: lineax
42
+ Requires-Dist: lineax; extra == "lineax"
43
+ Dynamic: license-file
44
+
45
+ <h1 align="center">Somax</h1>
46
+
47
+ <p align="center">
48
+ <img src="assets/somax_logo_mini.png" alt="Somax logo" width="250" />
49
+ </p>
50
+
51
+ <p align="center">
52
+ <strong>Second-Order Methods in JAX</strong>
53
+ </p>
54
+
55
+
56
+
57
+ Somax is a JAX-native library for composable second-order optimization.
58
+ It combines curvature operators, solvers, damping, preconditioners,
59
+ and update transforms into flexible optimization methods.
60
+
61
+
62
+ Features:
63
+ - **Composable:** combine curvature, solvers, damping, preconditioners, and update rules.
64
+ - **Matrix-free:** compute curvature products without forming dense matrices.
65
+ - **JAX-first:** JIT-compiled steps with explicit control over execution.
66
+ - **Optax integration:** apply standard Optax transformations to computed directions.
67
+ - **Research-friendly:** swap components, run ablations, and prototype new methods.
68
+
69
+
70
+
71
+
72
+ > The catfish in the logo is a small nod to *som*, the Belarusian word for catfish.
73
+ > A quiet bottom-dweller, but not a first-order creature.
74
+
75
+
76
+
77
+
78
+
79
+
80
+ ## Installation
81
+
82
+ Install [JAX](https://docs.jax.dev/en/latest/installation.html) for your hardware, then:
83
+
84
+ ```bash
85
+ pip install python-somax
86
+ ```
87
+
88
+ For development:
89
+
90
+ ```bash
91
+ git clone https://github.com/cor3bit/somax.git
92
+ cd somax
93
+ pip install -e ".[dev]"
94
+ ```
95
+
96
+ The `lineax` package is optional and needed only for CG with `backend="lineax"`.
97
+
98
+
99
+
100
+
101
+
102
+
103
+ ## Quickstart
104
+
105
+
106
+ A minimal stochastic Gauss-Newton training loop for multiclass classification:
107
+
108
+ ```python
109
+ import jax
110
+ import jax.numpy as jnp
111
+ import somax
112
+
113
+
114
+ def predict_fn(params, x):
115
+ h = jnp.tanh(x @ params["W1"] + params["b1"])
116
+ return h @ params["W2"] + params["b2"]
117
+
118
+
119
+ rng = jax.random.PRNGKey(0)
120
+ k1, k2, k3, k4 = jax.random.split(rng, 4)
121
+
122
+ params = {
123
+ "W1": 0.1 * jax.random.normal(k1, (16, 32)),
124
+ "b1": jnp.zeros((32,)),
125
+ "W2": 0.1 * jax.random.normal(k2, (32, 10)),
126
+ "b2": jnp.zeros((10,)),
127
+ }
128
+
129
+ batch = {
130
+ "x": jax.random.normal(k3, (64, 16)),
131
+ "y": jax.random.randint(k4, (64,), 0, 10),
132
+ }
133
+
134
+ method = somax.sgn_ce(
135
+ predict_fn=predict_fn,
136
+ learning_rate=0.1,
137
+ lam0=1.0,
138
+ maxiter=10,
139
+ tol=1e-4,
140
+ )
141
+
142
+ state = method.init(params)
143
+
144
+
145
+ @jax.jit
146
+ def train_step(params, batch, state, rng):
147
+ return method.step(params, batch, state, rng)
148
+
149
+
150
+ for step in range(10):
151
+ step_rng = jax.random.fold_in(rng, step)
152
+ params, state, info = train_step(params, batch, state, step_rng)
153
+ ```
154
+
155
+ For more examples, see [Usage: A paper in a few lines](docs/USAGE.md).
156
+
157
+
158
+
159
+
160
+ ## Citation
161
+
162
+ Mikalai Korbit and Mario Zanon,
163
+ "Second-Order, First-Class: A Composable Stack for Curvature-Aware Training",
164
+ ECML PKDD 2026, [arXiv](https://arxiv.org/abs/2603.25976).
165
+
166
+ ```bibtex
167
+ @inproceedings{korbit2026second,
168
+ title={Second-Order, First-Class: A Composable Stack for Curvature-Aware Training},
169
+ author={Korbit, Mikalai and Zanon, Mario},
170
+ booktitle={Joint European Conference on Machine Learning and Knowledge Discovery in Databases},
171
+ pages={90--105},
172
+ year={2026},
173
+ organization={Springer}
174
+ }
175
+ ```
176
+
177
+
178
+
179
+ ## License
180
+
181
+ Apache-2.0
182
+
@@ -0,0 +1,138 @@
1
+ <h1 align="center">Somax</h1>
2
+
3
+ <p align="center">
4
+ <img src="assets/somax_logo_mini.png" alt="Somax logo" width="250" />
5
+ </p>
6
+
7
+ <p align="center">
8
+ <strong>Second-Order Methods in JAX</strong>
9
+ </p>
10
+
11
+
12
+
13
+ Somax is a JAX-native library for composable second-order optimization.
14
+ It combines curvature operators, solvers, damping, preconditioners,
15
+ and update transforms into flexible optimization methods.
16
+
17
+
18
+ Features:
19
+ - **Composable:** combine curvature, solvers, damping, preconditioners, and update rules.
20
+ - **Matrix-free:** compute curvature products without forming dense matrices.
21
+ - **JAX-first:** JIT-compiled steps with explicit control over execution.
22
+ - **Optax integration:** apply standard Optax transformations to computed directions.
23
+ - **Research-friendly:** swap components, run ablations, and prototype new methods.
24
+
25
+
26
+
27
+
28
+ > The catfish in the logo is a small nod to *som*, the Belarusian word for catfish.
29
+ > A quiet bottom-dweller, but not a first-order creature.
30
+
31
+
32
+
33
+
34
+
35
+
36
+ ## Installation
37
+
38
+ Install [JAX](https://docs.jax.dev/en/latest/installation.html) for your hardware, then:
39
+
40
+ ```bash
41
+ pip install python-somax
42
+ ```
43
+
44
+ For development:
45
+
46
+ ```bash
47
+ git clone https://github.com/cor3bit/somax.git
48
+ cd somax
49
+ pip install -e ".[dev]"
50
+ ```
51
+
52
+ The `lineax` package is optional and needed only for CG with `backend="lineax"`.
53
+
54
+
55
+
56
+
57
+
58
+
59
+ ## Quickstart
60
+
61
+
62
+ A minimal stochastic Gauss-Newton training loop for multiclass classification:
63
+
64
+ ```python
65
+ import jax
66
+ import jax.numpy as jnp
67
+ import somax
68
+
69
+
70
+ def predict_fn(params, x):
71
+ h = jnp.tanh(x @ params["W1"] + params["b1"])
72
+ return h @ params["W2"] + params["b2"]
73
+
74
+
75
+ rng = jax.random.PRNGKey(0)
76
+ k1, k2, k3, k4 = jax.random.split(rng, 4)
77
+
78
+ params = {
79
+ "W1": 0.1 * jax.random.normal(k1, (16, 32)),
80
+ "b1": jnp.zeros((32,)),
81
+ "W2": 0.1 * jax.random.normal(k2, (32, 10)),
82
+ "b2": jnp.zeros((10,)),
83
+ }
84
+
85
+ batch = {
86
+ "x": jax.random.normal(k3, (64, 16)),
87
+ "y": jax.random.randint(k4, (64,), 0, 10),
88
+ }
89
+
90
+ method = somax.sgn_ce(
91
+ predict_fn=predict_fn,
92
+ learning_rate=0.1,
93
+ lam0=1.0,
94
+ maxiter=10,
95
+ tol=1e-4,
96
+ )
97
+
98
+ state = method.init(params)
99
+
100
+
101
+ @jax.jit
102
+ def train_step(params, batch, state, rng):
103
+ return method.step(params, batch, state, rng)
104
+
105
+
106
+ for step in range(10):
107
+ step_rng = jax.random.fold_in(rng, step)
108
+ params, state, info = train_step(params, batch, state, step_rng)
109
+ ```
110
+
111
+ For more examples, see [Usage: A paper in a few lines](docs/USAGE.md).
112
+
113
+
114
+
115
+
116
+ ## Citation
117
+
118
+ Mikalai Korbit and Mario Zanon,
119
+ "Second-Order, First-Class: A Composable Stack for Curvature-Aware Training",
120
+ ECML PKDD 2026, [arXiv](https://arxiv.org/abs/2603.25976).
121
+
122
+ ```bibtex
123
+ @inproceedings{korbit2026second,
124
+ title={Second-Order, First-Class: A Composable Stack for Curvature-Aware Training},
125
+ author={Korbit, Mikalai and Zanon, Mario},
126
+ booktitle={Joint European Conference on Machine Learning and Knowledge Discovery in Databases},
127
+ pages={90--105},
128
+ year={2026},
129
+ organization={Springer}
130
+ }
131
+ ```
132
+
133
+
134
+
135
+ ## License
136
+
137
+ Apache-2.0
138
+
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-somax"
7
- version = "1.0.1"
7
+ version = "1.1.0"
8
8
  description = "Composable Second-Order Optimization for JAX and Optax."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -17,7 +17,6 @@ dependencies = [
17
17
  "jax>=0.4.20",
18
18
  "optax>=0.1.7",
19
19
  "flax>=0.7.5",
20
- "numpy>=1.23",
21
20
  ]
22
21
  keywords = [
23
22
  "jax",
@@ -29,7 +28,7 @@ keywords = [
29
28
  "machine-learning",
30
29
  ]
31
30
  classifiers = [
32
- "Development Status :: 3 - Alpha",
31
+ "Development Status :: 4 - Beta",
33
32
  "Intended Audience :: Science/Research",
34
33
  "Programming Language :: Python :: 3",
35
34
  "Programming Language :: Python :: 3.11",
@@ -43,7 +42,7 @@ Homepage = "https://github.com/cor3bit/somax"
43
42
  Repository = "https://github.com/cor3bit/somax"
44
43
  Issues = "https://github.com/cor3bit/somax/issues"
45
44
  Releases = "https://github.com/cor3bit/somax/releases"
46
- #Documentation = "https://github.com/cor3bit/somax/tree/main/docs"
45
+ Documentation = "https://github.com/cor3bit/somax/tree/main/docs"
47
46
  Paper = "https://arxiv.org/abs/2603.25976"
48
47
 
49
48
  [project.optional-dependencies]
@@ -61,6 +60,8 @@ docs = [
61
60
  "mkdocs>=1.5",
62
61
  "mkdocs-material>=9",
63
62
  ]
63
+ matfree = ["matfree"]
64
+ lineax = ["lineax"]
64
65
 
65
66
  [tool.setuptools.packages.find]
66
67
  where = ["src"]
@@ -90,4 +91,4 @@ typeCheckingMode = "basic"
90
91
  [tool.pytest.ini_options]
91
92
  testpaths = ["tests"]
92
93
  addopts = "-q --strict-markers"
93
- xfail_strict = true
94
+ xfail_strict = true
@@ -0,0 +1,182 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-somax
3
+ Version: 1.1.0
4
+ Summary: Composable Second-Order Optimization for JAX and Optax.
5
+ Author: Nick Korbit
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/cor3bit/somax
8
+ Project-URL: Repository, https://github.com/cor3bit/somax
9
+ Project-URL: Issues, https://github.com/cor3bit/somax/issues
10
+ Project-URL: Releases, https://github.com/cor3bit/somax/releases
11
+ Project-URL: Documentation, https://github.com/cor3bit/somax/tree/main/docs
12
+ Project-URL: Paper, https://arxiv.org/abs/2603.25976
13
+ Keywords: jax,optax,optimization,second-order,gauss-newton,hessian,machine-learning
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
21
+ Requires-Python: >=3.11
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: jax>=0.4.20
25
+ Requires-Dist: optax>=0.1.7
26
+ Requires-Dist: flax>=0.7.5
27
+ Provides-Extra: dev
28
+ Requires-Dist: build>=1.2; extra == "dev"
29
+ Requires-Dist: twine>=5; extra == "dev"
30
+ Requires-Dist: pytest>=8; extra == "dev"
31
+ Requires-Dist: pytest-cov>=5; extra == "dev"
32
+ Requires-Dist: ruff>=0.5; extra == "dev"
33
+ Requires-Dist: pyright>=1.1; extra == "dev"
34
+ Requires-Dist: pre-commit>=3; extra == "dev"
35
+ Requires-Dist: chex>=0.1.8; extra == "dev"
36
+ Provides-Extra: docs
37
+ Requires-Dist: mkdocs>=1.5; extra == "docs"
38
+ Requires-Dist: mkdocs-material>=9; extra == "docs"
39
+ Provides-Extra: matfree
40
+ Requires-Dist: matfree; extra == "matfree"
41
+ Provides-Extra: lineax
42
+ Requires-Dist: lineax; extra == "lineax"
43
+ Dynamic: license-file
44
+
45
+ <h1 align="center">Somax</h1>
46
+
47
+ <p align="center">
48
+ <img src="assets/somax_logo_mini.png" alt="Somax logo" width="250" />
49
+ </p>
50
+
51
+ <p align="center">
52
+ <strong>Second-Order Methods in JAX</strong>
53
+ </p>
54
+
55
+
56
+
57
+ Somax is a JAX-native library for composable second-order optimization.
58
+ It combines curvature operators, solvers, damping, preconditioners,
59
+ and update transforms into flexible optimization methods.
60
+
61
+
62
+ Features:
63
+ - **Composable:** combine curvature, solvers, damping, preconditioners, and update rules.
64
+ - **Matrix-free:** compute curvature products without forming dense matrices.
65
+ - **JAX-first:** JIT-compiled steps with explicit control over execution.
66
+ - **Optax integration:** apply standard Optax transformations to computed directions.
67
+ - **Research-friendly:** swap components, run ablations, and prototype new methods.
68
+
69
+
70
+
71
+
72
+ > The catfish in the logo is a small nod to *som*, the Belarusian word for catfish.
73
+ > A quiet bottom-dweller, but not a first-order creature.
74
+
75
+
76
+
77
+
78
+
79
+
80
+ ## Installation
81
+
82
+ Install [JAX](https://docs.jax.dev/en/latest/installation.html) for your hardware, then:
83
+
84
+ ```bash
85
+ pip install python-somax
86
+ ```
87
+
88
+ For development:
89
+
90
+ ```bash
91
+ git clone https://github.com/cor3bit/somax.git
92
+ cd somax
93
+ pip install -e ".[dev]"
94
+ ```
95
+
96
+ The `lineax` package is optional and needed only for CG with `backend="lineax"`.
97
+
98
+
99
+
100
+
101
+
102
+
103
+ ## Quickstart
104
+
105
+
106
+ A minimal stochastic Gauss-Newton training loop for multiclass classification:
107
+
108
+ ```python
109
+ import jax
110
+ import jax.numpy as jnp
111
+ import somax
112
+
113
+
114
+ def predict_fn(params, x):
115
+ h = jnp.tanh(x @ params["W1"] + params["b1"])
116
+ return h @ params["W2"] + params["b2"]
117
+
118
+
119
+ rng = jax.random.PRNGKey(0)
120
+ k1, k2, k3, k4 = jax.random.split(rng, 4)
121
+
122
+ params = {
123
+ "W1": 0.1 * jax.random.normal(k1, (16, 32)),
124
+ "b1": jnp.zeros((32,)),
125
+ "W2": 0.1 * jax.random.normal(k2, (32, 10)),
126
+ "b2": jnp.zeros((10,)),
127
+ }
128
+
129
+ batch = {
130
+ "x": jax.random.normal(k3, (64, 16)),
131
+ "y": jax.random.randint(k4, (64,), 0, 10),
132
+ }
133
+
134
+ method = somax.sgn_ce(
135
+ predict_fn=predict_fn,
136
+ learning_rate=0.1,
137
+ lam0=1.0,
138
+ maxiter=10,
139
+ tol=1e-4,
140
+ )
141
+
142
+ state = method.init(params)
143
+
144
+
145
+ @jax.jit
146
+ def train_step(params, batch, state, rng):
147
+ return method.step(params, batch, state, rng)
148
+
149
+
150
+ for step in range(10):
151
+ step_rng = jax.random.fold_in(rng, step)
152
+ params, state, info = train_step(params, batch, state, step_rng)
153
+ ```
154
+
155
+ For more examples, see [Usage: A paper in a few lines](docs/USAGE.md).
156
+
157
+
158
+
159
+
160
+ ## Citation
161
+
162
+ Mikalai Korbit and Mario Zanon,
163
+ "Second-Order, First-Class: A Composable Stack for Curvature-Aware Training",
164
+ ECML PKDD 2026, [arXiv](https://arxiv.org/abs/2603.25976).
165
+
166
+ ```bibtex
167
+ @inproceedings{korbit2026second,
168
+ title={Second-Order, First-Class: A Composable Stack for Curvature-Aware Training},
169
+ author={Korbit, Mikalai and Zanon, Mario},
170
+ booktitle={Joint European Conference on Machine Learning and Knowledge Discovery in Databases},
171
+ pages={90--105},
172
+ year={2026},
173
+ organization={Springer}
174
+ }
175
+ ```
176
+
177
+
178
+
179
+ ## License
180
+
181
+ Apache-2.0
182
+
@@ -18,6 +18,7 @@ src/somax/types.py
18
18
  src/somax/utils.py
19
19
  src/somax/curvature/__init__.py
20
20
  src/somax/curvature/base.py
21
+ src/somax/curvature/fgnha_ce.py
21
22
  src/somax/curvature/ggn_ce.py
22
23
  src/somax/curvature/ggn_mse.py
23
24
  src/somax/curvature/hessian.py
@@ -25,15 +26,19 @@ src/somax/curvature/with_estimators.py
25
26
  src/somax/damping/__init__.py
26
27
  src/somax/damping/base.py
27
28
  src/somax/damping/constant.py
29
+ src/somax/damping/scheduled.py
28
30
  src/somax/damping/trust_region.py
29
31
  src/somax/estimators/__init__.py
30
32
  src/somax/estimators/base.py
33
+ src/somax/estimators/diagpp.py
31
34
  src/somax/estimators/gnb_ce.py
32
35
  src/somax/estimators/hutchinson.py
36
+ src/somax/estimators/lanczos.py
33
37
  src/somax/methods/__init__.py
34
38
  src/somax/methods/adahessian.py
35
39
  src/somax/methods/direct_methods.py
36
40
  src/somax/methods/egn.py
41
+ src/somax/methods/fgn.py
37
42
  src/somax/methods/newton_cg.py
38
43
  src/somax/methods/sgn.py
39
44
  src/somax/methods/sophia_g.py
@@ -49,5 +54,5 @@ src/somax/solvers/cg.py
49
54
  src/somax/solvers/direct.py
50
55
  src/somax/solvers/identity.py
51
56
  src/somax/solvers/row_cg.py
52
- src/somax/solvers/row_cholesky.py
57
+ src/somax/solvers/row_cg_lifted.py
53
58
  src/somax/solvers/row_common.py
@@ -1,7 +1,6 @@
1
1
  jax>=0.4.20
2
2
  optax>=0.1.7
3
3
  flax>=0.7.5
4
- numpy>=1.23
5
4
 
6
5
  [dev]
7
6
  build>=1.2
@@ -16,3 +15,9 @@ chex>=0.1.8
16
15
  [docs]
17
16
  mkdocs>=1.5
18
17
  mkdocs-material>=9
18
+
19
+ [lineax]
20
+ lineax
21
+
22
+ [matfree]
23
+ matfree
@@ -20,9 +20,12 @@ from .methods import (
20
20
  adahessian,
21
21
  ggn_direct_mse,
22
22
  ggn_direct_ce,
23
+ fgn_direct_ce,
23
24
  newton_direct,
24
25
  egn_ce,
25
26
  egn_mse,
27
+ fgn_ce,
28
+ fgn_ce_exact,
26
29
  newton_cg,
27
30
  sgn_mse,
28
31
  sgn_ce,
@@ -47,9 +50,12 @@ __all__ = [
47
50
  "adahessian",
48
51
  "ggn_direct_mse",
49
52
  "ggn_direct_ce",
53
+ "fgn_direct_ce",
50
54
  "newton_direct",
51
55
  "egn_ce",
52
56
  "egn_mse",
57
+ "fgn_ce",
58
+ "fgn_ce_exact",
53
59
  "newton_cg",
54
60
  "sgn_mse",
55
61
  "sgn_ce",
@@ -33,6 +33,8 @@ from .types import Array, Batch, Params, PRNGKey, StepInfo, ScalarOrSchedule, Gr
33
33
  class SecondOrderState:
34
34
  """Single state tree owned by Somax.
35
35
 
36
+ model_state: optional non-parameter model state, such as BatchNorm running
37
+ statistics. It is updated once by the curvature primal each outer step.
36
38
  opt_state: post-direction tx state (Optax state or custom).
37
39
  method_state: optional extra state for method-specific algorithms (eg AdaHessian EMAs).
38
40
  """
@@ -42,13 +44,14 @@ class SecondOrderState:
42
44
  solver_state: Any
43
45
  opt_state: Any
44
46
  method_state: Any # optional extension point (eg AdaHessian)
47
+ model_state: Any = ()
45
48
 
46
49
 
47
50
  class SecondOrderMethod:
48
- """Runnable Somax method: init/update.
51
+ """Runnable Somax method: init/step.
49
52
 
50
- update(...) performs one fused step:
51
- init cstate -> grad/row_op -> solve direction -> tx.update -> apply -> (optional rho) -> damping.update
53
+ step(...) performs one fused step:
54
+ init cstate -> grad/row_op -> solve direction -> tx.update -> apply -> (optional gain ratio) -> damping.update
52
55
  """
53
56
 
54
57
  def __init__(
@@ -68,11 +71,18 @@ class SecondOrderMethod:
68
71
  self.plan = plan
69
72
  self.tx = tx
70
73
 
71
- def init(self, params: Params) -> SecondOrderState:
74
+ def init(
75
+ self,
76
+ params: Params,
77
+ *,
78
+ model_state: Any = (),
79
+ ) -> SecondOrderState:
80
+ """Initialize optimizer and optional non-parameter model state."""
72
81
  m_t = jax.tree_util.tree_map(jnp.zeros_like, params) if self.plan.want.want_m else ()
73
82
 
74
83
  return SecondOrderState(
75
84
  step=jnp.asarray(0, jnp.int32),
85
+ model_state=model_state,
76
86
  damp_state=self.damping.init(),
77
87
  precond_state=self.precond.init(params),
78
88
  solver_state=self.solver.init(params),
@@ -118,8 +128,8 @@ def assemble(
118
128
  estimator: Optional[EstimatorSpec] = None,
119
129
  telemetry: Optional[TelemetrySpec] = None,
120
130
 
121
- # post-direction application
122
- tx: GradientTransformation | None = None, # full optax chain, if None, we build from knobs below
131
+ # post-direction application (owned)
132
+ tx: GradientTransformation | None = None, # full optax chain (expert); if None, we build from knobs below
123
133
  learning_rate: ScalarOrSchedule = 1.0,
124
134
  clip_norm: float | None = None,
125
135
  weight_decay: float | None = None,
@@ -137,7 +147,7 @@ def assemble(
137
147
  # Build plan from components
138
148
  plan = build_plan(damping=dp, solver=slv, precond=pp, telemetry_reqs=tlm_reqs)
139
149
 
140
- # Build owned post-direction tx
150
+ # Build owned post-direction tx (identity/sign+lr/clip/wd), unless user provided a full tx.
141
151
  optax_chain = build_optax_tx(
142
152
  tx=tx,
143
153
  learning_rate=learning_rate,