svemnet 0.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.
- svemnet-0.1.0/.github/workflows/ci.yml +30 -0
- svemnet-0.1.0/.github/workflows/release.yml +39 -0
- svemnet-0.1.0/.gitignore +12 -0
- svemnet-0.1.0/CITATION.cff +47 -0
- svemnet-0.1.0/LICENSE +21 -0
- svemnet-0.1.0/PKG-INFO +168 -0
- svemnet-0.1.0/README.md +131 -0
- svemnet-0.1.0/RELEASING.md +66 -0
- svemnet-0.1.0/examples/01_quickstart.ipynb +185 -0
- svemnet-0.1.0/examples/02_coming_from_r_svemnet.ipynb +123 -0
- svemnet-0.1.0/pyproject.toml +74 -0
- svemnet-0.1.0/src/svemnet/__init__.py +89 -0
- svemnet-0.1.0/src/svemnet/core.py +858 -0
- svemnet-0.1.0/src/svemnet/estimator.py +206 -0
- svemnet-0.1.0/src/svemnet/expansion.py +81 -0
- svemnet-0.1.0/src/svemnet/formula.py +314 -0
- svemnet-0.1.0/src/svemnet/forward.py +884 -0
- svemnet-0.1.0/tests/test_core.py +221 -0
- svemnet-0.1.0/tests/test_estimator.py +126 -0
- svemnet-0.1.0/tests/test_expansion.py +57 -0
- svemnet-0.1.0/tests/test_formula.py +213 -0
- svemnet-0.1.0/tests/test_forward_select.py +203 -0
- svemnet-0.1.0/tests/test_svem_forward.py +184 -0
- svemnet-0.1.0/validation/compare_python.py +185 -0
- svemnet-0.1.0/validation/run_r_reference.R +154 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: "17 6 3 * *" # monthly canary against latest deps
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ${{ matrix.os }}
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
os: [ubuntu-latest]
|
|
18
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
19
|
+
include:
|
|
20
|
+
- os: windows-latest
|
|
21
|
+
python-version: "3.13"
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
- uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
- name: Install
|
|
28
|
+
run: python -m pip install -e ".[test]"
|
|
29
|
+
- name: Test
|
|
30
|
+
run: python -m pytest tests -q
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Release to PyPI
|
|
2
|
+
|
|
3
|
+
# Releasing is: git tag v0.1.0 && git push origin v0.1.0
|
|
4
|
+
# Requires a PyPI "trusted publisher" configured for this repository and a
|
|
5
|
+
# GitHub environment named "pypi" (see RELEASING.md).
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["v*"]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
- name: Build sdist and wheel
|
|
20
|
+
run: |
|
|
21
|
+
python -m pip install build
|
|
22
|
+
python -m build
|
|
23
|
+
- uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: dist
|
|
26
|
+
path: dist/
|
|
27
|
+
|
|
28
|
+
publish:
|
|
29
|
+
needs: build
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
environment: pypi
|
|
32
|
+
permissions:
|
|
33
|
+
id-token: write # PyPI trusted publishing
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/download-artifact@v4
|
|
36
|
+
with:
|
|
37
|
+
name: dist
|
|
38
|
+
path: dist/
|
|
39
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
svemnet-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: >-
|
|
3
|
+
If you use this software, please cite the SVEMnet paper (preferred
|
|
4
|
+
citation below) for the software and Lemkus et al. (2021) for the SVEM
|
|
5
|
+
method.
|
|
6
|
+
type: software
|
|
7
|
+
title: "svemnet: Self-Validated Ensemble Models (SVEM) for Python"
|
|
8
|
+
authors:
|
|
9
|
+
- family-names: Karl
|
|
10
|
+
given-names: Andrew T.
|
|
11
|
+
email: akarl@asu.edu
|
|
12
|
+
orcid: "https://orcid.org/0000-0002-5933-8706"
|
|
13
|
+
license: MIT
|
|
14
|
+
repository-code: "https://github.com/akarl46556/svemnet-python"
|
|
15
|
+
keywords:
|
|
16
|
+
- SVEM
|
|
17
|
+
- self-validated ensemble models
|
|
18
|
+
- design of experiments
|
|
19
|
+
- lasso
|
|
20
|
+
- elastic net
|
|
21
|
+
- forward selection
|
|
22
|
+
- chemometrics
|
|
23
|
+
preferred-citation:
|
|
24
|
+
type: article
|
|
25
|
+
title: "SVEMnet: Self-Validated Ensemble Models in R"
|
|
26
|
+
authors:
|
|
27
|
+
- family-names: Karl
|
|
28
|
+
given-names: Andrew T.
|
|
29
|
+
journal: "Chemometrics and Intelligent Laboratory Systems"
|
|
30
|
+
year: 2026
|
|
31
|
+
doi: 10.1016/j.chemolab.2026.105660
|
|
32
|
+
references:
|
|
33
|
+
- type: article
|
|
34
|
+
title: "Self-Validated Ensemble Models for design of experiments"
|
|
35
|
+
authors:
|
|
36
|
+
- family-names: Lemkus
|
|
37
|
+
given-names: Trent
|
|
38
|
+
- family-names: Gotwalt
|
|
39
|
+
given-names: Christopher
|
|
40
|
+
- family-names: Ramsey
|
|
41
|
+
given-names: Philip
|
|
42
|
+
- family-names: Weese
|
|
43
|
+
given-names: Maria L.
|
|
44
|
+
journal: "Chemometrics and Intelligent Laboratory Systems"
|
|
45
|
+
volume: 219
|
|
46
|
+
year: 2021
|
|
47
|
+
doi: 10.1016/j.chemolab.2021.104439
|
svemnet-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andrew T. Karl
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
svemnet-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: svemnet
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Self-Validated Ensemble Models (SVEM) for small-sample design-of-experiments regression: SVEM lasso / elastic net and SVEM forward selection with validation-weighted information criteria.
|
|
5
|
+
Project-URL: Homepage, https://github.com/akarl46556/svemnet-python
|
|
6
|
+
Project-URL: Source, https://github.com/akarl46556/svemnet-python
|
|
7
|
+
Project-URL: Issues, https://github.com/akarl46556/svemnet-python/issues
|
|
8
|
+
Project-URL: R package (CRAN), https://CRAN.R-project.org/package=SVEMnet
|
|
9
|
+
Project-URL: SVEMnet paper (Karl 2026), https://doi.org/10.1016/j.chemolab.2026.105660
|
|
10
|
+
Project-URL: SVEM method paper (Lemkus 2021), https://doi.org/10.1016/j.chemolab.2021.104439
|
|
11
|
+
Project-URL: Whole-model test (Karl 2024), https://doi.org/10.1016/j.chemolab.2024.105122
|
|
12
|
+
Author-email: "Andrew T. Karl" <akarl@asu.edu>
|
|
13
|
+
License-Expression: MIT
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Keywords: DOE,JMP,SVEM,SVEMnet,chemometrics,design of experiments,elastic net,forward selection,fractional random weights,lasso,self-validated ensemble,small sample
|
|
16
|
+
Classifier: Development Status :: 4 - Beta
|
|
17
|
+
Classifier: Intended Audience :: Science/Research
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Requires-Dist: numpy>=1.24
|
|
28
|
+
Requires-Dist: scikit-learn>=1.6
|
|
29
|
+
Provides-Extra: formula
|
|
30
|
+
Requires-Dist: formulaic>=1.1; extra == 'formula'
|
|
31
|
+
Requires-Dist: pandas>=2.0; extra == 'formula'
|
|
32
|
+
Provides-Extra: test
|
|
33
|
+
Requires-Dist: formulaic>=1.1; extra == 'test'
|
|
34
|
+
Requires-Dist: pandas>=2.0; extra == 'test'
|
|
35
|
+
Requires-Dist: pytest>=8; extra == 'test'
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
# svemnet — Self-Validated Ensemble Models (SVEM) for Python
|
|
39
|
+
|
|
40
|
+
**SVEM regression for small-sample design of experiments (DOE):** lasso /
|
|
41
|
+
elastic-net and forward-selection ensembles tuned by validation-weighted
|
|
42
|
+
information criteria, with bootstrap prediction intervals.
|
|
43
|
+
|
|
44
|
+
`svemnet` is the Python implementation of the Self-Validated Ensemble Model
|
|
45
|
+
method (Lemkus, Gotwalt, Ramsey, and Weese 2021) by the author of the
|
|
46
|
+
[R package SVEMnet](https://CRAN.R-project.org/package=SVEMnet). SVEM is
|
|
47
|
+
designed for the small-*n*, wide-model regime typical of designed
|
|
48
|
+
experiments — mixture formulations, process optimization, chemometrics —
|
|
49
|
+
where cross-validation is unstable: instead of holding data out, every run
|
|
50
|
+
appears in *both* the training and validation roles through anti-correlated
|
|
51
|
+
fractional random weights, and predictions are ensembled across bootstrap
|
|
52
|
+
replicates.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install svemnet # core: numpy + scikit-learn
|
|
58
|
+
pip install "svemnet[formula]" # + R-style formula interface (formulaic, pandas)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Quickstart (formula interface, closest to R / JMP)
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
import pandas as pd
|
|
65
|
+
import svemnet
|
|
66
|
+
|
|
67
|
+
df = pd.read_csv("experiment.csv") # columns: y, X1, X2, X3, ...
|
|
68
|
+
|
|
69
|
+
# SVEM with lasso / elastic-net base learners (the SVEMnet default)
|
|
70
|
+
model = svemnet.svem("y ~ (X1 + X2 + X3)**2 + I(X1**2)", df, seed=1)
|
|
71
|
+
preds = model.predict(new_df)
|
|
72
|
+
|
|
73
|
+
# SVEM with forward-selection base learners
|
|
74
|
+
model = svemnet.svem("y ~ (X1 + X2 + X3)**2", df, method="forward", seed=1)
|
|
75
|
+
model.selection_frequencies # per-term bootstrap selection rates
|
|
76
|
+
model.coef_table() # coefficients + % bootstraps nonzero
|
|
77
|
+
|
|
78
|
+
# Bootstrap percentile intervals
|
|
79
|
+
out = model.predict(new_df, interval=True, level=0.90)
|
|
80
|
+
out["fit"], out["lwr"], out["upr"]
|
|
81
|
+
|
|
82
|
+
# Deterministic forward selection by AICc (single-model benchmark)
|
|
83
|
+
bench = svemnet.forward_aicc("y ~ (X1 + X2 + X3)**2", df)
|
|
84
|
+
bench.selected_terms
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Categorical predictors: mark them as pandas `Categorical` (or leave them as
|
|
88
|
+
strings) and they are treatment-coded automatically, like R factors. Their
|
|
89
|
+
contrast columns enter and leave forward-selection paths **together** as
|
|
90
|
+
whole effects.
|
|
91
|
+
|
|
92
|
+
`(X1 + X2 + X3)**2` expands to main effects plus two-way interactions,
|
|
93
|
+
matching R's `(X1 + X2 + X3)^2`. The helper
|
|
94
|
+
`svemnet.response_surface_formula("y", continuous=["X1","X2"], nominal=["F"])`
|
|
95
|
+
builds standard response-surface formulas.
|
|
96
|
+
|
|
97
|
+
## Quickstart (scikit-learn interface)
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from svemnet import SVEMRegressor
|
|
101
|
+
|
|
102
|
+
est = SVEMRegressor(method="forward", n_boot=200, random_state=0)
|
|
103
|
+
est.fit(X, y) # numeric matrix, no intercept column
|
|
104
|
+
y_pred = est.predict(X_new)
|
|
105
|
+
y_pred, intervals = est.predict_interval(X_new, confidence_level=0.9)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`SVEMRegressor` is a conformant scikit-learn estimator: it works in
|
|
109
|
+
`Pipeline`, `cross_val_score`, and `GridSearchCV`, and handles categoricals
|
|
110
|
+
the scikit-learn way (`ColumnTransformer` / `OneHotEncoder`).
|
|
111
|
+
|
|
112
|
+
## Coming from R SVEMnet or JMP
|
|
113
|
+
|
|
114
|
+
| R SVEMnet | svemnet (Python) |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `SVEMnet(y ~ ..., data)` | `svemnet.svem("y ~ ...", df)` |
|
|
117
|
+
| `svem_forward(y ~ ..., data)` | `svemnet.svem("y ~ ...", df, method="forward")` |
|
|
118
|
+
| `forward_aicc(y ~ ..., data)` | `svemnet.forward_aicc("y ~ ...", df)` |
|
|
119
|
+
| `predict(fit, newdata, se.fit=, interval=)` | `model.predict(new_df, se_fit=, interval=)` |
|
|
120
|
+
| `coef(fit)` / `svem_nonzero(fit)` | `model.coef_table()` |
|
|
121
|
+
| `bigexp_terms(...)` | `svemnet.response_surface_formula(...)` |
|
|
122
|
+
| `objective = "wAIC"/"wBIC"/"wSSE"` | same |
|
|
123
|
+
| `weight_scheme = "SVEM"/"FRW_plain"/"Identity"` | same |
|
|
124
|
+
| `debias = TRUE` at predict | `debias=True` at fit or predict |
|
|
125
|
+
|
|
126
|
+
The Gaussian fitting mathematics match the published SVEM conventions used
|
|
127
|
+
by the R package: anti-correlated FRW train/validation weights rescaled to
|
|
128
|
+
mean one, validation-weighted wSSE/wAIC/wBIC path selection with the Kish
|
|
129
|
+
effective-sample-size admissibility guardrail, intercept-only fallback,
|
|
130
|
+
coefficient averaging across the ensemble, and optional linear debiasing.
|
|
131
|
+
The forward-selection engines here and the R functions `forward_aicc()` /
|
|
132
|
+
`svem_forward()` (SVEMnet ≥ 3.5.0) are ports of the same reference
|
|
133
|
+
implementation and validate against each other numerically. The lasso /
|
|
134
|
+
elastic-net base learners use scikit-learn's coordinate descent rather than
|
|
135
|
+
glmnet, so individual path fits can differ slightly in lambda gridding;
|
|
136
|
+
ensemble predictions agree closely in practice.
|
|
137
|
+
|
|
138
|
+
**Scope.** This package is intentionally minimal: Gaussian responses,
|
|
139
|
+
lasso/elastic-net and forward-selection base learners, prediction with
|
|
140
|
+
bootstrap uncertainty. For binomial responses, whole-model significance
|
|
141
|
+
testing, mixture-constrained random-search optimization, and
|
|
142
|
+
Thompson-sampling batch design, use the
|
|
143
|
+
[R package SVEMnet](https://CRAN.R-project.org/package=SVEMnet); JMP Pro
|
|
144
|
+
users have SVEM built into Generalized Regression.
|
|
145
|
+
|
|
146
|
+
## References
|
|
147
|
+
|
|
148
|
+
- Lemkus, T., Gotwalt, C., Ramsey, P., & Weese, M. L. (2021). Self-Validated
|
|
149
|
+
Ensemble Models for design of experiments. *Chemometrics and Intelligent
|
|
150
|
+
Laboratory Systems*, 219, 104439.
|
|
151
|
+
[doi:10.1016/j.chemolab.2021.104439](https://doi.org/10.1016/j.chemolab.2021.104439)
|
|
152
|
+
- Karl, A. T. (2024). A randomized permutation whole-model test for SVEM.
|
|
153
|
+
*Chemometrics and Intelligent Laboratory Systems*, 249, 105122.
|
|
154
|
+
[doi:10.1016/j.chemolab.2024.105122](https://doi.org/10.1016/j.chemolab.2024.105122)
|
|
155
|
+
- Karl, A. T. (2026). SVEMnet: Self-Validated Ensemble Models in R.
|
|
156
|
+
*Chemometrics and Intelligent Laboratory Systems*.
|
|
157
|
+
[doi:10.1016/j.chemolab.2026.105660](https://doi.org/10.1016/j.chemolab.2026.105660)
|
|
158
|
+
- Xu, L., Gotwalt, C., Hong, Y., King, C. B., & Meeker, W. Q. (2020).
|
|
159
|
+
Applications of the fractional-random-weight bootstrap. *The American
|
|
160
|
+
Statistician*, 74(4), 345–358.
|
|
161
|
+
[doi:10.1080/00031305.2020.1731599](https://doi.org/10.1080/00031305.2020.1731599)
|
|
162
|
+
|
|
163
|
+
If you use this package in published work, please cite Lemkus et al. (2021)
|
|
164
|
+
for the method and Karl (2026) for the software.
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
MIT. Copyright (c) 2026 Andrew T. Karl.
|
svemnet-0.1.0/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# svemnet — Self-Validated Ensemble Models (SVEM) for Python
|
|
2
|
+
|
|
3
|
+
**SVEM regression for small-sample design of experiments (DOE):** lasso /
|
|
4
|
+
elastic-net and forward-selection ensembles tuned by validation-weighted
|
|
5
|
+
information criteria, with bootstrap prediction intervals.
|
|
6
|
+
|
|
7
|
+
`svemnet` is the Python implementation of the Self-Validated Ensemble Model
|
|
8
|
+
method (Lemkus, Gotwalt, Ramsey, and Weese 2021) by the author of the
|
|
9
|
+
[R package SVEMnet](https://CRAN.R-project.org/package=SVEMnet). SVEM is
|
|
10
|
+
designed for the small-*n*, wide-model regime typical of designed
|
|
11
|
+
experiments — mixture formulations, process optimization, chemometrics —
|
|
12
|
+
where cross-validation is unstable: instead of holding data out, every run
|
|
13
|
+
appears in *both* the training and validation roles through anti-correlated
|
|
14
|
+
fractional random weights, and predictions are ensembled across bootstrap
|
|
15
|
+
replicates.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install svemnet # core: numpy + scikit-learn
|
|
21
|
+
pip install "svemnet[formula]" # + R-style formula interface (formulaic, pandas)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quickstart (formula interface, closest to R / JMP)
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
import pandas as pd
|
|
28
|
+
import svemnet
|
|
29
|
+
|
|
30
|
+
df = pd.read_csv("experiment.csv") # columns: y, X1, X2, X3, ...
|
|
31
|
+
|
|
32
|
+
# SVEM with lasso / elastic-net base learners (the SVEMnet default)
|
|
33
|
+
model = svemnet.svem("y ~ (X1 + X2 + X3)**2 + I(X1**2)", df, seed=1)
|
|
34
|
+
preds = model.predict(new_df)
|
|
35
|
+
|
|
36
|
+
# SVEM with forward-selection base learners
|
|
37
|
+
model = svemnet.svem("y ~ (X1 + X2 + X3)**2", df, method="forward", seed=1)
|
|
38
|
+
model.selection_frequencies # per-term bootstrap selection rates
|
|
39
|
+
model.coef_table() # coefficients + % bootstraps nonzero
|
|
40
|
+
|
|
41
|
+
# Bootstrap percentile intervals
|
|
42
|
+
out = model.predict(new_df, interval=True, level=0.90)
|
|
43
|
+
out["fit"], out["lwr"], out["upr"]
|
|
44
|
+
|
|
45
|
+
# Deterministic forward selection by AICc (single-model benchmark)
|
|
46
|
+
bench = svemnet.forward_aicc("y ~ (X1 + X2 + X3)**2", df)
|
|
47
|
+
bench.selected_terms
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Categorical predictors: mark them as pandas `Categorical` (or leave them as
|
|
51
|
+
strings) and they are treatment-coded automatically, like R factors. Their
|
|
52
|
+
contrast columns enter and leave forward-selection paths **together** as
|
|
53
|
+
whole effects.
|
|
54
|
+
|
|
55
|
+
`(X1 + X2 + X3)**2` expands to main effects plus two-way interactions,
|
|
56
|
+
matching R's `(X1 + X2 + X3)^2`. The helper
|
|
57
|
+
`svemnet.response_surface_formula("y", continuous=["X1","X2"], nominal=["F"])`
|
|
58
|
+
builds standard response-surface formulas.
|
|
59
|
+
|
|
60
|
+
## Quickstart (scikit-learn interface)
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from svemnet import SVEMRegressor
|
|
64
|
+
|
|
65
|
+
est = SVEMRegressor(method="forward", n_boot=200, random_state=0)
|
|
66
|
+
est.fit(X, y) # numeric matrix, no intercept column
|
|
67
|
+
y_pred = est.predict(X_new)
|
|
68
|
+
y_pred, intervals = est.predict_interval(X_new, confidence_level=0.9)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`SVEMRegressor` is a conformant scikit-learn estimator: it works in
|
|
72
|
+
`Pipeline`, `cross_val_score`, and `GridSearchCV`, and handles categoricals
|
|
73
|
+
the scikit-learn way (`ColumnTransformer` / `OneHotEncoder`).
|
|
74
|
+
|
|
75
|
+
## Coming from R SVEMnet or JMP
|
|
76
|
+
|
|
77
|
+
| R SVEMnet | svemnet (Python) |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `SVEMnet(y ~ ..., data)` | `svemnet.svem("y ~ ...", df)` |
|
|
80
|
+
| `svem_forward(y ~ ..., data)` | `svemnet.svem("y ~ ...", df, method="forward")` |
|
|
81
|
+
| `forward_aicc(y ~ ..., data)` | `svemnet.forward_aicc("y ~ ...", df)` |
|
|
82
|
+
| `predict(fit, newdata, se.fit=, interval=)` | `model.predict(new_df, se_fit=, interval=)` |
|
|
83
|
+
| `coef(fit)` / `svem_nonzero(fit)` | `model.coef_table()` |
|
|
84
|
+
| `bigexp_terms(...)` | `svemnet.response_surface_formula(...)` |
|
|
85
|
+
| `objective = "wAIC"/"wBIC"/"wSSE"` | same |
|
|
86
|
+
| `weight_scheme = "SVEM"/"FRW_plain"/"Identity"` | same |
|
|
87
|
+
| `debias = TRUE` at predict | `debias=True` at fit or predict |
|
|
88
|
+
|
|
89
|
+
The Gaussian fitting mathematics match the published SVEM conventions used
|
|
90
|
+
by the R package: anti-correlated FRW train/validation weights rescaled to
|
|
91
|
+
mean one, validation-weighted wSSE/wAIC/wBIC path selection with the Kish
|
|
92
|
+
effective-sample-size admissibility guardrail, intercept-only fallback,
|
|
93
|
+
coefficient averaging across the ensemble, and optional linear debiasing.
|
|
94
|
+
The forward-selection engines here and the R functions `forward_aicc()` /
|
|
95
|
+
`svem_forward()` (SVEMnet ≥ 3.5.0) are ports of the same reference
|
|
96
|
+
implementation and validate against each other numerically. The lasso /
|
|
97
|
+
elastic-net base learners use scikit-learn's coordinate descent rather than
|
|
98
|
+
glmnet, so individual path fits can differ slightly in lambda gridding;
|
|
99
|
+
ensemble predictions agree closely in practice.
|
|
100
|
+
|
|
101
|
+
**Scope.** This package is intentionally minimal: Gaussian responses,
|
|
102
|
+
lasso/elastic-net and forward-selection base learners, prediction with
|
|
103
|
+
bootstrap uncertainty. For binomial responses, whole-model significance
|
|
104
|
+
testing, mixture-constrained random-search optimization, and
|
|
105
|
+
Thompson-sampling batch design, use the
|
|
106
|
+
[R package SVEMnet](https://CRAN.R-project.org/package=SVEMnet); JMP Pro
|
|
107
|
+
users have SVEM built into Generalized Regression.
|
|
108
|
+
|
|
109
|
+
## References
|
|
110
|
+
|
|
111
|
+
- Lemkus, T., Gotwalt, C., Ramsey, P., & Weese, M. L. (2021). Self-Validated
|
|
112
|
+
Ensemble Models for design of experiments. *Chemometrics and Intelligent
|
|
113
|
+
Laboratory Systems*, 219, 104439.
|
|
114
|
+
[doi:10.1016/j.chemolab.2021.104439](https://doi.org/10.1016/j.chemolab.2021.104439)
|
|
115
|
+
- Karl, A. T. (2024). A randomized permutation whole-model test for SVEM.
|
|
116
|
+
*Chemometrics and Intelligent Laboratory Systems*, 249, 105122.
|
|
117
|
+
[doi:10.1016/j.chemolab.2024.105122](https://doi.org/10.1016/j.chemolab.2024.105122)
|
|
118
|
+
- Karl, A. T. (2026). SVEMnet: Self-Validated Ensemble Models in R.
|
|
119
|
+
*Chemometrics and Intelligent Laboratory Systems*.
|
|
120
|
+
[doi:10.1016/j.chemolab.2026.105660](https://doi.org/10.1016/j.chemolab.2026.105660)
|
|
121
|
+
- Xu, L., Gotwalt, C., Hong, Y., King, C. B., & Meeker, W. Q. (2020).
|
|
122
|
+
Applications of the fractional-random-weight bootstrap. *The American
|
|
123
|
+
Statistician*, 74(4), 345–358.
|
|
124
|
+
[doi:10.1080/00031305.2020.1731599](https://doi.org/10.1080/00031305.2020.1731599)
|
|
125
|
+
|
|
126
|
+
If you use this package in published work, please cite Lemkus et al. (2021)
|
|
127
|
+
for the method and Karl (2026) for the software.
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT. Copyright (c) 2026 Andrew T. Karl.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Release checklist (for Andrew)
|
|
2
|
+
|
|
3
|
+
One-time setup, then each release is just a git tag.
|
|
4
|
+
|
|
5
|
+
## One-time setup
|
|
6
|
+
|
|
7
|
+
1. **Create the GitHub repository** (suggested name: `svemnet-python`, owner:
|
|
8
|
+
your GitHub account). Then the URLs below already point at `akarl46556`:
|
|
9
|
+
- `pyproject.toml` (`[project.urls]`)
|
|
10
|
+
- `CITATION.cff` (`repository-code`)
|
|
11
|
+
2. **Push this repo**:
|
|
12
|
+
```bash
|
|
13
|
+
git remote add origin https://github.com/akarl46556/svemnet-python.git
|
|
14
|
+
git push -u origin main
|
|
15
|
+
```
|
|
16
|
+
CI (`.github/workflows/ci.yml`) runs the test suite on Python 3.10–3.13
|
|
17
|
+
(Linux) and 3.13 (Windows) on every push to `main` and on every pull
|
|
18
|
+
request, plus a monthly cron canary against the latest
|
|
19
|
+
numpy/scikit-learn.
|
|
20
|
+
3. **PyPI trusted publisher** (no API tokens needed):
|
|
21
|
+
- Create/log into your account on https://pypi.org.
|
|
22
|
+
- Go to *Your projects → Publishing → Add a new pending publisher* and
|
|
23
|
+
register: project name `svemnet`, owner `akarl46556`, repository
|
|
24
|
+
`svemnet-python`, workflow `release.yml`, environment `pypi`.
|
|
25
|
+
- In the GitHub repo: *Settings → Environments → New environment* named
|
|
26
|
+
`pypi` (optionally require your review before deployments).
|
|
27
|
+
4. **Cross-link from the R package** (optional but recommended): add a line
|
|
28
|
+
to the CRAN SVEMnet DESCRIPTION/README pointing to
|
|
29
|
+
`https://pypi.org/project/svemnet/`.
|
|
30
|
+
|
|
31
|
+
## Each release
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# bump version in pyproject.toml and src/svemnet/__init__.py, commit, then:
|
|
35
|
+
git tag v0.1.0
|
|
36
|
+
git push origin v0.1.0
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The `release.yml` workflow builds the sdist/wheel and publishes to PyPI via
|
|
40
|
+
trusted publishing.
|
|
41
|
+
|
|
42
|
+
## Re-running the R cross-validation
|
|
43
|
+
|
|
44
|
+
With the SVEMnet R package (>= 3.5.0) installed:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
Rscript validation/run_r_reference.R validation/output
|
|
48
|
+
python validation/compare_python.py validation/output
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Tier 1 (deterministic forward selection) and Tier 2 (SVEM forward with
|
|
52
|
+
injected FRW uniforms) must match R exactly; Tier 3 (lasso, cross-solver)
|
|
53
|
+
is statistical. See `validation/output/VALIDATION_REPORT.md`.
|
|
54
|
+
|
|
55
|
+
## Later milestones (optional, low urgency)
|
|
56
|
+
|
|
57
|
+
- **conda-forge** (once the API feels stable): submit a grayskull-generated
|
|
58
|
+
recipe to conda-forge/staged-recipes; afterwards maintenance is merging
|
|
59
|
+
autotick-bot PRs.
|
|
60
|
+
- **JOSS paper** (6–12 months out): JOSS requires ~6 months of public
|
|
61
|
+
development history and demonstrated reuse; a JOSS DOI gives Python users
|
|
62
|
+
a natural citation target.
|
|
63
|
+
- **Scope guard**: the package is deliberately minimal (Gaussian; lasso/enet
|
|
64
|
+
+ forward SVEM; prediction with bootstrap uncertainty). Point requests for
|
|
65
|
+
binomial, whole-model testing, optimization, etc. at the R package rather
|
|
66
|
+
than growing this one.
|