wrapevofs 0.2.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.
- wrapevofs-0.2.0/CHANGELOG.md +27 -0
- wrapevofs-0.2.0/CITATION.cff +17 -0
- wrapevofs-0.2.0/LICENSE +29 -0
- wrapevofs-0.2.0/MANIFEST.in +10 -0
- wrapevofs-0.2.0/PKG-INFO +140 -0
- wrapevofs-0.2.0/README.md +96 -0
- wrapevofs-0.2.0/REPRODUCIBILITY.md +67 -0
- wrapevofs-0.2.0/configs/default.yaml +111 -0
- wrapevofs-0.2.0/configs/impute_mean_6_4.yaml +16 -0
- wrapevofs-0.2.0/configs/impute_zero_8_2.yaml +16 -0
- wrapevofs-0.2.0/configs/recommended_regret_constrained.yaml +29 -0
- wrapevofs-0.2.0/configs/sample_svm_fast.yaml +51 -0
- wrapevofs-0.2.0/configs/synthetic_regret_smoke.yaml +62 -0
- wrapevofs-0.2.0/docs/ARTIFACT_SCHEMA.md +68 -0
- wrapevofs-0.2.0/docs/CHECKPOINT_RESUME.md +40 -0
- wrapevofs-0.2.0/docs/CLI_AND_API.md +38 -0
- wrapevofs-0.2.0/docs/COMMON_ERRORS.md +13 -0
- wrapevofs-0.2.0/docs/CONFIGURATION.md +63 -0
- wrapevofs-0.2.0/docs/METHOD_AND_METRICS.md +42 -0
- wrapevofs-0.2.0/examples/quickstart.py +54 -0
- wrapevofs-0.2.0/examples/sample_radiomics.csv +81 -0
- wrapevofs-0.2.0/examples/toy_regret_locking.py +85 -0
- wrapevofs-0.2.0/pyproject.toml +60 -0
- wrapevofs-0.2.0/scripts/check_release_metadata.py +39 -0
- wrapevofs-0.2.0/scripts/run_development_only_smoke.py +33 -0
- wrapevofs-0.2.0/setup.cfg +4 -0
- wrapevofs-0.2.0/src/wrapevofs/__init__.py +63 -0
- wrapevofs-0.2.0/src/wrapevofs/_scoring.py +35 -0
- wrapevofs-0.2.0/src/wrapevofs/_version.py +5 -0
- wrapevofs-0.2.0/src/wrapevofs/artifacts.py +193 -0
- wrapevofs-0.2.0/src/wrapevofs/cli.py +158 -0
- wrapevofs-0.2.0/src/wrapevofs/config.py +306 -0
- wrapevofs-0.2.0/src/wrapevofs/locking.py +663 -0
- wrapevofs-0.2.0/src/wrapevofs/pipeline.py +360 -0
- wrapevofs-0.2.0/src/wrapevofs/preprocessing.py +153 -0
- wrapevofs-0.2.0/src/wrapevofs/selectors/__init__.py +16 -0
- wrapevofs-0.2.0/src/wrapevofs/selectors/_result.py +27 -0
- wrapevofs-0.2.0/src/wrapevofs/selectors/boruta_rf.py +70 -0
- wrapevofs-0.2.0/src/wrapevofs/selectors/genetic_rf.py +1348 -0
- wrapevofs-0.2.0/src/wrapevofs/selectors/rfecv_target.py +162 -0
- wrapevofs-0.2.0/src/wrapevofs/selectors/svm_l1_wrapper.py +112 -0
- wrapevofs-0.2.0/src/wrapevofs/selectors/xgboost_wrapper.py +105 -0
- wrapevofs-0.2.0/src/wrapevofs/split.py +115 -0
- wrapevofs-0.2.0/src/wrapevofs/validation.py +98 -0
- wrapevofs-0.2.0/src/wrapevofs.egg-info/PKG-INFO +140 -0
- wrapevofs-0.2.0/src/wrapevofs.egg-info/SOURCES.txt +61 -0
- wrapevofs-0.2.0/src/wrapevofs.egg-info/dependency_links.txt +1 -0
- wrapevofs-0.2.0/src/wrapevofs.egg-info/entry_points.txt +2 -0
- wrapevofs-0.2.0/src/wrapevofs.egg-info/requires.txt +31 -0
- wrapevofs-0.2.0/src/wrapevofs.egg-info/top_level.txt +1 -0
- wrapevofs-0.2.0/tests/test_artifacts.py +100 -0
- wrapevofs-0.2.0/tests/test_checkpoint_resume.py +167 -0
- wrapevofs-0.2.0/tests/test_cli_options.py +38 -0
- wrapevofs-0.2.0/tests/test_config_defaults.py +66 -0
- wrapevofs-0.2.0/tests/test_genetic_rf.py +437 -0
- wrapevofs-0.2.0/tests/test_locking.py +560 -0
- wrapevofs-0.2.0/tests/test_metric_alignment.py +44 -0
- wrapevofs-0.2.0/tests/test_preprocessing.py +64 -0
- wrapevofs-0.2.0/tests/test_release_contract.py +100 -0
- wrapevofs-0.2.0/tests/test_rfecv_target.py +69 -0
- wrapevofs-0.2.0/tests/test_split.py +23 -0
- wrapevofs-0.2.0/tests/test_svm_l1_wrapper.py +73 -0
- wrapevofs-0.2.0/tests/test_version.py +8 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
- Added development-only `regret_constrained_medoid` locking with absolute, relative, and best-run-SE-scaled eligibility.
|
|
6
|
+
- Enforced strict eligible-only pools, including singleton pools, without tolerance expansion.
|
|
7
|
+
- Added canonical-universe mask encoding and deterministic stable-mask-hash tie-breaking; source run IDs are provenance rather than scientific tie-breaks.
|
|
8
|
+
- Documented and audited the retained-multiplicity policy for duplicate masks.
|
|
9
|
+
- Added the recommended `untruncated_shifted_linear` GA mode with separate raw objective and sampling weights.
|
|
10
|
+
- Preserved explicit `top_k_jaccard_medoid` and `legacy_zero_truncated_linear` compatibility modes.
|
|
11
|
+
- Added GA flattening, sampling-fallback, target-deviation, and mask-diversity diagnostics.
|
|
12
|
+
- Added versioned locking and GA audit artifacts, configuration hashes, and aggregated warnings.
|
|
13
|
+
- Added atomic, fingerprint-validated GA checkpoint resume without silent restart.
|
|
14
|
+
- Added package, configuration, and artifact schema validation helpers.
|
|
15
|
+
- Added compatible unified metric support and mixed-development-metric warnings.
|
|
16
|
+
- Added CLI and Python API options, regression tests, a synthetic one-command example, and schema documentation.
|
|
17
|
+
- Added BSD-3-Clause licensing and release-ready package metadata.
|
|
18
|
+
|
|
19
|
+
## 0.1.0 - 2026-07-04
|
|
20
|
+
|
|
21
|
+
- Rebuilt the repository as an installable Python package.
|
|
22
|
+
- Added train/test split, preprocessing, first-stage wrappers, RFECV target discovery, and GA-RF feature selection.
|
|
23
|
+
- Added CSV and `.npy` artifact export for wrapper, RFECV target, GA, and final feature sets.
|
|
24
|
+
- Added configuration files, examples, tests, and procedure documentation.
|
|
25
|
+
- Added branch-specific RFECV compact caps: XGBoost <= 20, SVM-L1 <= 15, Boruta-RF <= 25.
|
|
26
|
+
- Added a synthetic tabular sample dataset for quick package validation.
|
|
27
|
+
- Added a compact de-identified radiomics demo CSV and notebook walkthrough.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this package, please cite the software and its associated manuscript when available."
|
|
3
|
+
title: "WrapEvoFS: Auditable Stochastic Feature Compression under Development-CV Regret Constraints"
|
|
4
|
+
type: software
|
|
5
|
+
version: "0.2.0"
|
|
6
|
+
authors:
|
|
7
|
+
- family-names: "Park"
|
|
8
|
+
given-names: "Junseo"
|
|
9
|
+
repository-code: "https://github.com/junseoparkX/wrapevofs-package"
|
|
10
|
+
license: BSD-3-Clause
|
|
11
|
+
keywords:
|
|
12
|
+
- tabular data
|
|
13
|
+
- feature selection
|
|
14
|
+
- stochastic compression
|
|
15
|
+
- development-CV regret
|
|
16
|
+
- genetic algorithm
|
|
17
|
+
- random forest
|
wrapevofs-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Junseo Park
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
10
|
+
this list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
include README.md
|
|
2
|
+
include LICENSE
|
|
3
|
+
include CHANGELOG.md
|
|
4
|
+
include CITATION.cff
|
|
5
|
+
include REPRODUCIBILITY.md
|
|
6
|
+
recursive-include configs *.yaml
|
|
7
|
+
recursive-include docs *.md
|
|
8
|
+
recursive-include examples *.py *.csv
|
|
9
|
+
recursive-include scripts *.py
|
|
10
|
+
recursive-include tests *.py
|
wrapevofs-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wrapevofs
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Auditable stochastic feature compression with regret-constrained representative locking.
|
|
5
|
+
Author: Junseo Park
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/junseoparkX/wrapevofs-package
|
|
8
|
+
Project-URL: Repository, https://github.com/junseoparkX/wrapevofs-package
|
|
9
|
+
Project-URL: Documentation, https://github.com/junseoparkX/wrapevofs-package#readme
|
|
10
|
+
Keywords: feature-selection,genetic-algorithm,machine-learning,reproducibility,stability
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Requires-Python: <3.13,>=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: joblib>=1.3
|
|
22
|
+
Requires-Dist: numpy>=1.24
|
|
23
|
+
Requires-Dist: pandas>=2.0
|
|
24
|
+
Requires-Dist: PyYAML>=6.0
|
|
25
|
+
Requires-Dist: scikit-learn>=1.3
|
|
26
|
+
Requires-Dist: scipy>=1.10
|
|
27
|
+
Provides-Extra: xgboost
|
|
28
|
+
Requires-Dist: xgboost>=2.0; extra == "xgboost"
|
|
29
|
+
Provides-Extra: boruta
|
|
30
|
+
Requires-Dist: boruta>=0.3; extra == "boruta"
|
|
31
|
+
Provides-Extra: gpu
|
|
32
|
+
Requires-Dist: cupy-cuda12x; platform_system == "Linux" and extra == "gpu"
|
|
33
|
+
Requires-Dist: cudf-cu12; platform_system == "Linux" and extra == "gpu"
|
|
34
|
+
Requires-Dist: cuml-cu12; platform_system == "Linux" and extra == "gpu"
|
|
35
|
+
Provides-Extra: all
|
|
36
|
+
Requires-Dist: xgboost>=2.0; extra == "all"
|
|
37
|
+
Requires-Dist: boruta>=0.3; extra == "all"
|
|
38
|
+
Provides-Extra: dev
|
|
39
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
41
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11" and extra == "dev"
|
|
42
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# WrapEvoFS
|
|
46
|
+
|
|
47
|
+
WrapEvoFS is a Python package for auditable stochastic feature compression. It combines branch-specific screening, RFECV-derived size guidance, repeated genetic searches, and deterministic regret-constrained representative locking for binary or multiclass tabular classification. Selection and locking use development data only; held-out outcomes are not inputs to the locking decision.
|
|
48
|
+
|
|
49
|
+
## Key features
|
|
50
|
+
|
|
51
|
+
- corrected untruncated genetic-search objective with separate nonnegative sampling weights;
|
|
52
|
+
- absolute, relative, and best-run-SE-scaled empirical regret modes;
|
|
53
|
+
- Jaccard-medoid locking within the eligible candidate pool;
|
|
54
|
+
- canonical feature-mask encoding and deterministic SHA-256 tie ordering;
|
|
55
|
+
- complete candidate, regret, agreement, seed, and configuration audits;
|
|
56
|
+
- checkpoint/resume support and explicit legacy-compatible modes;
|
|
57
|
+
- CPU execution, with optional supported GPU backends where available.
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
WrapEvoFS supports Python 3.10–3.12. Install from a source checkout:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
python -m venv .venv
|
|
65
|
+
python -m pip install --upgrade pip
|
|
66
|
+
python -m pip install -e .
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Install development tools or optional selectors with:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python -m pip install -e ".[dev]"
|
|
73
|
+
python -m pip install -e ".[all]"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Python API
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
import pandas as pd
|
|
80
|
+
|
|
81
|
+
from wrapevofs import PipelineConfig, WrapEvoPipeline
|
|
82
|
+
from wrapevofs.artifacts import save_pipeline_result
|
|
83
|
+
|
|
84
|
+
data = pd.read_csv("examples/sample_radiomics.csv")
|
|
85
|
+
config = PipelineConfig.from_yaml("configs/synthetic_regret_smoke.yaml")
|
|
86
|
+
result = WrapEvoPipeline(config).run_full(
|
|
87
|
+
data,
|
|
88
|
+
target_column="MGMT_binary",
|
|
89
|
+
drop_columns=["patient_id"],
|
|
90
|
+
methods=["svm_l1"],
|
|
91
|
+
)
|
|
92
|
+
save_pipeline_result(result, "runs/api_smoke")
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The bundled CSV is synthetic and contains no participant data.
|
|
96
|
+
|
|
97
|
+
## Command line
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
wrapevofs run \
|
|
101
|
+
--csv examples/sample_radiomics.csv \
|
|
102
|
+
--target MGMT_binary \
|
|
103
|
+
--drop-columns patient_id \
|
|
104
|
+
--out runs/cli_smoke \
|
|
105
|
+
--config configs/synthetic_regret_smoke.yaml \
|
|
106
|
+
--run-ga
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Run `wrapevofs run --help` for the complete interface.
|
|
110
|
+
Use `wrapevofs --version` to report the installed package version. A run with a
|
|
111
|
+
matching atomic GA state can be continued by repeating its original command
|
|
112
|
+
with `--resume`; mismatched or corrupt states are rejected rather than silently
|
|
113
|
+
starting a new search.
|
|
114
|
+
|
|
115
|
+
## Regret-constrained representative locking
|
|
116
|
+
|
|
117
|
+
For larger-is-better development scores, candidate regret is the gap from the highest candidate score. The recommended absolute rule first retains only candidates with regret at most the configured tolerance, then selects the candidate with greatest mean Jaccard similarity to the eligible pool. Ties are resolved by higher locking score, smaller feature count, and the stable hash of the canonical mask. The selected candidate therefore always satisfies the configured empirical score-gap constraint. This is an empirical development-score guarantee, not a guarantee of expected predictive risk or external validity.
|
|
118
|
+
|
|
119
|
+
See [`configs/recommended_regret_constrained.yaml`](configs/recommended_regret_constrained.yaml) for the recommended new-analysis settings. Archived configurations preserve the legacy zero-truncated objective and top-k medoid behavior when those modes are selected.
|
|
120
|
+
|
|
121
|
+
## Reproducibility and audit outputs
|
|
122
|
+
|
|
123
|
+
Locking exports a candidate audit, eligible-pool Jaccard matrix, selected features, and summary metadata under `locking/<branch>/`. The audit records canonical masks, stable hashes, duplicate multiplicity, scores, regrets, eligibility, agreement, seeds, metric orientation, and configuration hashes. Details are in [`docs/ARTIFACT_SCHEMA.md`](docs/ARTIFACT_SCHEMA.md), [`docs/CHECKPOINT_RESUME.md`](docs/CHECKPOINT_RESUME.md), and [`REPRODUCIBILITY.md`](REPRODUCIBILITY.md).
|
|
124
|
+
|
|
125
|
+
## Testing
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
python -m pytest -q
|
|
129
|
+
python scripts/run_development_only_smoke.py
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The continuous-integration workflow tests Python 3.10, 3.11, and 3.12, builds the wheel and source distribution, checks package metadata, and performs clean-install API and CLI smoke tests.
|
|
133
|
+
|
|
134
|
+
## Citation
|
|
135
|
+
|
|
136
|
+
Citation metadata are provided in [`CITATION.cff`](CITATION.cff). Please cite the associated manuscript when it becomes available.
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
WrapEvoFS is distributed under the [BSD 3-Clause License](LICENSE).
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# WrapEvoFS
|
|
2
|
+
|
|
3
|
+
WrapEvoFS is a Python package for auditable stochastic feature compression. It combines branch-specific screening, RFECV-derived size guidance, repeated genetic searches, and deterministic regret-constrained representative locking for binary or multiclass tabular classification. Selection and locking use development data only; held-out outcomes are not inputs to the locking decision.
|
|
4
|
+
|
|
5
|
+
## Key features
|
|
6
|
+
|
|
7
|
+
- corrected untruncated genetic-search objective with separate nonnegative sampling weights;
|
|
8
|
+
- absolute, relative, and best-run-SE-scaled empirical regret modes;
|
|
9
|
+
- Jaccard-medoid locking within the eligible candidate pool;
|
|
10
|
+
- canonical feature-mask encoding and deterministic SHA-256 tie ordering;
|
|
11
|
+
- complete candidate, regret, agreement, seed, and configuration audits;
|
|
12
|
+
- checkpoint/resume support and explicit legacy-compatible modes;
|
|
13
|
+
- CPU execution, with optional supported GPU backends where available.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
WrapEvoFS supports Python 3.10–3.12. Install from a source checkout:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python -m venv .venv
|
|
21
|
+
python -m pip install --upgrade pip
|
|
22
|
+
python -m pip install -e .
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Install development tools or optional selectors with:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python -m pip install -e ".[dev]"
|
|
29
|
+
python -m pip install -e ".[all]"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Python API
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import pandas as pd
|
|
36
|
+
|
|
37
|
+
from wrapevofs import PipelineConfig, WrapEvoPipeline
|
|
38
|
+
from wrapevofs.artifacts import save_pipeline_result
|
|
39
|
+
|
|
40
|
+
data = pd.read_csv("examples/sample_radiomics.csv")
|
|
41
|
+
config = PipelineConfig.from_yaml("configs/synthetic_regret_smoke.yaml")
|
|
42
|
+
result = WrapEvoPipeline(config).run_full(
|
|
43
|
+
data,
|
|
44
|
+
target_column="MGMT_binary",
|
|
45
|
+
drop_columns=["patient_id"],
|
|
46
|
+
methods=["svm_l1"],
|
|
47
|
+
)
|
|
48
|
+
save_pipeline_result(result, "runs/api_smoke")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The bundled CSV is synthetic and contains no participant data.
|
|
52
|
+
|
|
53
|
+
## Command line
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
wrapevofs run \
|
|
57
|
+
--csv examples/sample_radiomics.csv \
|
|
58
|
+
--target MGMT_binary \
|
|
59
|
+
--drop-columns patient_id \
|
|
60
|
+
--out runs/cli_smoke \
|
|
61
|
+
--config configs/synthetic_regret_smoke.yaml \
|
|
62
|
+
--run-ga
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Run `wrapevofs run --help` for the complete interface.
|
|
66
|
+
Use `wrapevofs --version` to report the installed package version. A run with a
|
|
67
|
+
matching atomic GA state can be continued by repeating its original command
|
|
68
|
+
with `--resume`; mismatched or corrupt states are rejected rather than silently
|
|
69
|
+
starting a new search.
|
|
70
|
+
|
|
71
|
+
## Regret-constrained representative locking
|
|
72
|
+
|
|
73
|
+
For larger-is-better development scores, candidate regret is the gap from the highest candidate score. The recommended absolute rule first retains only candidates with regret at most the configured tolerance, then selects the candidate with greatest mean Jaccard similarity to the eligible pool. Ties are resolved by higher locking score, smaller feature count, and the stable hash of the canonical mask. The selected candidate therefore always satisfies the configured empirical score-gap constraint. This is an empirical development-score guarantee, not a guarantee of expected predictive risk or external validity.
|
|
74
|
+
|
|
75
|
+
See [`configs/recommended_regret_constrained.yaml`](configs/recommended_regret_constrained.yaml) for the recommended new-analysis settings. Archived configurations preserve the legacy zero-truncated objective and top-k medoid behavior when those modes are selected.
|
|
76
|
+
|
|
77
|
+
## Reproducibility and audit outputs
|
|
78
|
+
|
|
79
|
+
Locking exports a candidate audit, eligible-pool Jaccard matrix, selected features, and summary metadata under `locking/<branch>/`. The audit records canonical masks, stable hashes, duplicate multiplicity, scores, regrets, eligibility, agreement, seeds, metric orientation, and configuration hashes. Details are in [`docs/ARTIFACT_SCHEMA.md`](docs/ARTIFACT_SCHEMA.md), [`docs/CHECKPOINT_RESUME.md`](docs/CHECKPOINT_RESUME.md), and [`REPRODUCIBILITY.md`](REPRODUCIBILITY.md).
|
|
80
|
+
|
|
81
|
+
## Testing
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
python -m pytest -q
|
|
85
|
+
python scripts/run_development_only_smoke.py
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The continuous-integration workflow tests Python 3.10, 3.11, and 3.12, builds the wheel and source distribution, checks package metadata, and performs clean-install API and CLI smoke tests.
|
|
89
|
+
|
|
90
|
+
## Citation
|
|
91
|
+
|
|
92
|
+
Citation metadata are provided in [`CITATION.cff`](CITATION.cff). Please cite the associated manuscript when it becomes available.
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
WrapEvoFS is distributed under the [BSD 3-Clause License](LICENSE).
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Reproducibility
|
|
2
|
+
|
|
3
|
+
## Environment
|
|
4
|
+
|
|
5
|
+
WrapEvoFS supports Python 3.10–3.12. Create an isolated environment and install the package with its test tools:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
python -m venv .venv
|
|
9
|
+
python -m pip install --upgrade pip
|
|
10
|
+
python -m pip install -e ".[dev]"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`pyproject.toml` is the authoritative compatibility and dependency specification.
|
|
14
|
+
|
|
15
|
+
## Tests
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
python -m pytest -q
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The locking tests cover nonempty eligibility, strict regret feasibility, zero-tolerance ties, the all-candidate limit, duplicate masks, feature-order canonicalization, process-stable hashing, deterministic audits, serialization, and candidate-order permutation invariance.
|
|
22
|
+
|
|
23
|
+
## Synthetic development-only execution
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python scripts/run_development_only_smoke.py --out runs/synthetic_regret_smoke
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This command uses the synthetic `examples/sample_radiomics.csv` input and `configs/synthetic_regret_smoke.yaml`. RFECV, genetic search, candidate rescoring, and locking use the development partition only.
|
|
30
|
+
|
|
31
|
+
## Recommended and legacy modes
|
|
32
|
+
|
|
33
|
+
New analyses should use `configs/recommended_regret_constrained.yaml`. Its core settings are:
|
|
34
|
+
|
|
35
|
+
- untruncated raw objective for genetic-search ranking and reporting;
|
|
36
|
+
- shifted nonnegative weights only for proportional parent sampling;
|
|
37
|
+
- absolute development-score regret tolerance of 0.01;
|
|
38
|
+
- strict eligible-only locking, with singleton pools allowed;
|
|
39
|
+
- deterministic Jaccard-medoid tie-breaking by score, feature count, and stable mask hash;
|
|
40
|
+
- compatible macro one-vs-rest AUROC scoring where applicable.
|
|
41
|
+
|
|
42
|
+
The 0.01 tolerance is a prespecified package operating default on the configured metric scale. It must not be selected by examining held-out results. Other datasets or metrics may require a separately justified, prospectively configured tolerance.
|
|
43
|
+
|
|
44
|
+
Archived configurations can explicitly retain:
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
ga:
|
|
48
|
+
fitness_mode: legacy_zero_truncated_linear
|
|
49
|
+
locking:
|
|
50
|
+
strategy: top_k_jaccard_medoid
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Legacy modes are retained to reproduce archived analyses. They are not silently replaced by the corrected objective or regret-constrained rule.
|
|
54
|
+
|
|
55
|
+
## Determinism and audit trail
|
|
56
|
+
|
|
57
|
+
Configuration objects record split, RFECV, genetic-search, and locking seeds. Canonical feature masks are encoded against one ordered candidate universe and hashed with SHA-256. Stable hashes order scientific ties; they are not probabilistic scores. Source run IDs are retained as provenance labels after feature-set selection.
|
|
58
|
+
|
|
59
|
+
When `ga.checkpoint_dir` is configured, `resume_state.npz` records the next population, random-generator state, completed history, and fingerprints of the package, configuration, ordered feature universe, and exact development inputs. Resume requires all fingerprints to match and never falls back to a fresh search. See `docs/CHECKPOINT_RESUME.md`.
|
|
60
|
+
|
|
61
|
+
When distinct source runs contain the same mask, the records remain separate voting candidates. Their multiplicity is part of the supplied candidate bank and is recorded in the locking audit.
|
|
62
|
+
|
|
63
|
+
See `docs/ARTIFACT_SCHEMA.md` for the complete output schema.
|
|
64
|
+
|
|
65
|
+
## Data boundary
|
|
66
|
+
|
|
67
|
+
Do not commit participant-level, controlled-access, or provider-restricted data to this repository. The bundled smoke-test CSV is synthetic. WrapEvoFS begins from already extracted tabular features and does not claim raw imaging or assay reconstruction.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
split:
|
|
2
|
+
ratio: "7:3"
|
|
3
|
+
random_state: 42
|
|
4
|
+
shuffle: true
|
|
5
|
+
stratify: true
|
|
6
|
+
stratify_columns: []
|
|
7
|
+
|
|
8
|
+
preprocessing:
|
|
9
|
+
numeric_only: true
|
|
10
|
+
missingness_threshold:
|
|
11
|
+
impute_strategy: "zero"
|
|
12
|
+
drop_zero_variance: false
|
|
13
|
+
scaling: "none"
|
|
14
|
+
correlation_threshold:
|
|
15
|
+
error_on_missing_features: true
|
|
16
|
+
|
|
17
|
+
first_stage:
|
|
18
|
+
enabled_methods: ["xgboost", "svm_l1", "boruta_rf"]
|
|
19
|
+
skip_missing_optional: true
|
|
20
|
+
xgboost:
|
|
21
|
+
importance_threshold: 0.0
|
|
22
|
+
top_k: 100
|
|
23
|
+
cv_folds: 5
|
|
24
|
+
scoring: "auto"
|
|
25
|
+
param_grid:
|
|
26
|
+
subsample: [0.6, 0.7, 0.8]
|
|
27
|
+
colsample_bytree: [0.7, 0.8, 1.0]
|
|
28
|
+
n_estimators: [80, 100, 120]
|
|
29
|
+
base_params:
|
|
30
|
+
learning_rate: 0.3
|
|
31
|
+
gamma: 0
|
|
32
|
+
max_depth: 6
|
|
33
|
+
reg_lambda: 1
|
|
34
|
+
reg_alpha: 0
|
|
35
|
+
svm_l1:
|
|
36
|
+
coefficient_threshold: 0.000001
|
|
37
|
+
standardize: true
|
|
38
|
+
cv_folds: 5
|
|
39
|
+
scoring: "auto"
|
|
40
|
+
c_grid: [0.001, 0.01, 0.1, 1.0, 10.0, 30.0, 100.0]
|
|
41
|
+
penalty: "l1"
|
|
42
|
+
dual: false
|
|
43
|
+
max_iter: 100000
|
|
44
|
+
tol: 0.0001
|
|
45
|
+
class_weight:
|
|
46
|
+
boruta_rf:
|
|
47
|
+
include_tentative: true
|
|
48
|
+
perc: 95
|
|
49
|
+
alpha: 0.05
|
|
50
|
+
max_iter: 150
|
|
51
|
+
|
|
52
|
+
rfecv:
|
|
53
|
+
estimator: "random_forest"
|
|
54
|
+
max_features_to_consider: 25
|
|
55
|
+
method_max_features_to_consider:
|
|
56
|
+
xgboost: 20
|
|
57
|
+
svm_l1: 20
|
|
58
|
+
boruta_rf: 25
|
|
59
|
+
cv_folds: 5
|
|
60
|
+
scoring: "auto"
|
|
61
|
+
step: 1
|
|
62
|
+
min_features_to_select: 1
|
|
63
|
+
n_jobs: 1
|
|
64
|
+
|
|
65
|
+
ga:
|
|
66
|
+
enabled: true
|
|
67
|
+
backend: "auto"
|
|
68
|
+
population_size: 50
|
|
69
|
+
n_generations: 50
|
|
70
|
+
n_runs: 5
|
|
71
|
+
crossover_rate: 0.8
|
|
72
|
+
mutation_rate: 0.05
|
|
73
|
+
elitism_count: 2
|
|
74
|
+
initial_off_ratio: 0.30
|
|
75
|
+
size_penalty_lambda: 0.015
|
|
76
|
+
fitness_mode: "legacy_zero_truncated_linear"
|
|
77
|
+
sampling_epsilon: 1.0e-12
|
|
78
|
+
legacy_zero_fraction_warning: 0.50
|
|
79
|
+
target_deviation_warning_threshold:
|
|
80
|
+
minimum_unique_masks_warning: 2
|
|
81
|
+
top_k: 5
|
|
82
|
+
cv_folds: 5
|
|
83
|
+
fitness_metric: "accuracy"
|
|
84
|
+
random_state: 42
|
|
85
|
+
n_jobs: 1
|
|
86
|
+
verbose: false
|
|
87
|
+
progress_interval: 10
|
|
88
|
+
checkpoint_dir:
|
|
89
|
+
gpu_rf_params:
|
|
90
|
+
n_bins: 16
|
|
91
|
+
|
|
92
|
+
locking:
|
|
93
|
+
enabled: false
|
|
94
|
+
strategy: "top_k_jaccard_medoid"
|
|
95
|
+
top_k: 3
|
|
96
|
+
tolerance_mode: "absolute"
|
|
97
|
+
regret_tolerance: 0.01
|
|
98
|
+
minimum_pool_size: 1
|
|
99
|
+
fallback_rule: "strict_eligible_only"
|
|
100
|
+
tie_breakers:
|
|
101
|
+
- "higher_locking_score"
|
|
102
|
+
- "smaller_feature_count"
|
|
103
|
+
- "stable_mask_hash"
|
|
104
|
+
epsilon: 1.0e-12
|
|
105
|
+
metric_orientation: "larger_is_better"
|
|
106
|
+
locking_metric: "auto"
|
|
107
|
+
cv_folds: 5
|
|
108
|
+
random_state: 42
|
|
109
|
+
|
|
110
|
+
scoring:
|
|
111
|
+
unified_metric:
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
split:
|
|
2
|
+
ratio: "6:4"
|
|
3
|
+
|
|
4
|
+
preprocessing:
|
|
5
|
+
impute_strategy: "mean"
|
|
6
|
+
missingness_threshold: 0.30
|
|
7
|
+
scaling: "standard"
|
|
8
|
+
correlation_threshold: 0.95
|
|
9
|
+
|
|
10
|
+
rfecv:
|
|
11
|
+
max_features_to_consider: 20
|
|
12
|
+
|
|
13
|
+
ga:
|
|
14
|
+
population_size: 50
|
|
15
|
+
size_penalty_lambda: 0.015
|
|
16
|
+
top_k: 5
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
split:
|
|
2
|
+
ratio: "8:2"
|
|
3
|
+
|
|
4
|
+
preprocessing:
|
|
5
|
+
impute_strategy: "zero"
|
|
6
|
+
missingness_threshold: 0.30
|
|
7
|
+
scaling: "standard"
|
|
8
|
+
correlation_threshold: 0.95
|
|
9
|
+
|
|
10
|
+
rfecv:
|
|
11
|
+
max_features_to_consider: 20
|
|
12
|
+
|
|
13
|
+
ga:
|
|
14
|
+
population_size: 50
|
|
15
|
+
size_penalty_lambda: 0.015
|
|
16
|
+
top_k: 5
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Recommended configuration for new analyses. Historical configurations that
|
|
2
|
+
# omit these fields continue to use the archived zero-truncated GA and locking
|
|
3
|
+
# behavior.
|
|
4
|
+
ga:
|
|
5
|
+
fitness_mode: "untruncated_shifted_linear"
|
|
6
|
+
sampling_epsilon: 1.0e-12
|
|
7
|
+
legacy_zero_fraction_warning: 0.50
|
|
8
|
+
target_deviation_warning_threshold: 10
|
|
9
|
+
minimum_unique_masks_warning: 2
|
|
10
|
+
top_k: 5
|
|
11
|
+
|
|
12
|
+
locking:
|
|
13
|
+
enabled: true
|
|
14
|
+
strategy: "regret_constrained_medoid"
|
|
15
|
+
tolerance_mode: "absolute"
|
|
16
|
+
regret_tolerance: 0.01
|
|
17
|
+
minimum_pool_size: 1
|
|
18
|
+
fallback_rule: "strict_eligible_only"
|
|
19
|
+
tie_breakers:
|
|
20
|
+
- "higher_locking_score"
|
|
21
|
+
- "smaller_feature_count"
|
|
22
|
+
- "stable_mask_hash"
|
|
23
|
+
metric_orientation: "larger_is_better"
|
|
24
|
+
locking_metric: "macro_ovr_auroc"
|
|
25
|
+
cv_folds: 5
|
|
26
|
+
random_state: 42
|
|
27
|
+
|
|
28
|
+
scoring:
|
|
29
|
+
unified_metric: "macro_ovr_auroc"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
split:
|
|
2
|
+
ratio: "7:3"
|
|
3
|
+
random_state: 42
|
|
4
|
+
stratify: true
|
|
5
|
+
|
|
6
|
+
preprocessing:
|
|
7
|
+
impute_strategy: "zero"
|
|
8
|
+
missingness_threshold:
|
|
9
|
+
drop_zero_variance: false
|
|
10
|
+
scaling: "none"
|
|
11
|
+
correlation_threshold:
|
|
12
|
+
|
|
13
|
+
first_stage:
|
|
14
|
+
enabled_methods: ["svm_l1"]
|
|
15
|
+
svm_l1:
|
|
16
|
+
standardize: true
|
|
17
|
+
c_grid: [0.01, 0.1, 1.0]
|
|
18
|
+
cv_folds: 3
|
|
19
|
+
n_jobs: 1
|
|
20
|
+
max_iter: 100000
|
|
21
|
+
|
|
22
|
+
rfecv:
|
|
23
|
+
method_max_features_to_consider:
|
|
24
|
+
svm_l1: 8
|
|
25
|
+
cv_folds: 3
|
|
26
|
+
step: 5
|
|
27
|
+
n_jobs: 1
|
|
28
|
+
rf_params:
|
|
29
|
+
n_estimators: 25
|
|
30
|
+
max_depth: 4
|
|
31
|
+
min_samples_leaf: 2
|
|
32
|
+
bootstrap: true
|
|
33
|
+
|
|
34
|
+
ga:
|
|
35
|
+
backend: "auto"
|
|
36
|
+
population_size: 12
|
|
37
|
+
n_generations: 2
|
|
38
|
+
n_runs: 1
|
|
39
|
+
top_k: 2
|
|
40
|
+
cv_folds: 3
|
|
41
|
+
n_jobs: 1
|
|
42
|
+
verbose: true
|
|
43
|
+
progress_interval: 10
|
|
44
|
+
checkpoint_dir:
|
|
45
|
+
rf_params:
|
|
46
|
+
n_estimators: 25
|
|
47
|
+
max_depth: 4
|
|
48
|
+
min_samples_leaf: 2
|
|
49
|
+
bootstrap: true
|
|
50
|
+
gpu_rf_params:
|
|
51
|
+
n_bins: 16
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
split:
|
|
2
|
+
ratio: "7:3"
|
|
3
|
+
random_state: 42
|
|
4
|
+
stratify: true
|
|
5
|
+
|
|
6
|
+
preprocessing:
|
|
7
|
+
impute_strategy: "zero"
|
|
8
|
+
drop_zero_variance: false
|
|
9
|
+
scaling: "none"
|
|
10
|
+
|
|
11
|
+
first_stage:
|
|
12
|
+
enabled_methods: ["svm_l1"]
|
|
13
|
+
svm_l1:
|
|
14
|
+
standardize: true
|
|
15
|
+
c_grid: [0.01, 0.1, 1.0]
|
|
16
|
+
cv_folds: 3
|
|
17
|
+
n_jobs: 1
|
|
18
|
+
max_iter: 100000
|
|
19
|
+
|
|
20
|
+
rfecv:
|
|
21
|
+
method_max_features_to_consider:
|
|
22
|
+
svm_l1: 8
|
|
23
|
+
cv_folds: 3
|
|
24
|
+
step: 5
|
|
25
|
+
n_jobs: 1
|
|
26
|
+
rf_params:
|
|
27
|
+
n_estimators: 20
|
|
28
|
+
max_depth: 4
|
|
29
|
+
min_samples_leaf: 2
|
|
30
|
+
bootstrap: true
|
|
31
|
+
|
|
32
|
+
ga:
|
|
33
|
+
enabled: true
|
|
34
|
+
backend: "cpu"
|
|
35
|
+
fitness_mode: "untruncated_shifted_linear"
|
|
36
|
+
population_size: 8
|
|
37
|
+
n_generations: 2
|
|
38
|
+
n_runs: 3
|
|
39
|
+
top_k: 3
|
|
40
|
+
cv_folds: 3
|
|
41
|
+
n_jobs: 1
|
|
42
|
+
random_state: 42
|
|
43
|
+
progress_interval: 1
|
|
44
|
+
rf_params:
|
|
45
|
+
n_estimators: 15
|
|
46
|
+
max_depth: 4
|
|
47
|
+
min_samples_leaf: 2
|
|
48
|
+
bootstrap: true
|
|
49
|
+
|
|
50
|
+
locking:
|
|
51
|
+
enabled: true
|
|
52
|
+
strategy: "regret_constrained_medoid"
|
|
53
|
+
tolerance_mode: "absolute"
|
|
54
|
+
regret_tolerance: 0.01
|
|
55
|
+
minimum_pool_size: 1
|
|
56
|
+
fallback_rule: "strict_eligible_only"
|
|
57
|
+
locking_metric: "macro_ovr_auroc"
|
|
58
|
+
cv_folds: 3
|
|
59
|
+
random_state: 42
|
|
60
|
+
|
|
61
|
+
scoring:
|
|
62
|
+
unified_metric: "macro_ovr_auroc"
|