arvore 0.0.5__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.
- arvore-0.0.5/LICENSE +21 -0
- arvore-0.0.5/PKG-INFO +650 -0
- arvore-0.0.5/README.md +579 -0
- arvore-0.0.5/arvore/__init__.py +11 -0
- arvore-0.0.5/arvore/box/__init__.py +1 -0
- arvore-0.0.5/arvore/box/base.py +877 -0
- arvore-0.0.5/arvore/cli/__init__.py +0 -0
- arvore-0.0.5/arvore/cli/cli.py +207 -0
- arvore-0.0.5/arvore/cli/predict.py +79 -0
- arvore-0.0.5/arvore/cli/scoring.py +193 -0
- arvore-0.0.5/arvore/cli/train.py +68 -0
- arvore-0.0.5/arvore/config/__init__.py +2 -0
- arvore-0.0.5/arvore/config/configs.py +401 -0
- arvore-0.0.5/arvore/config/instantiate.py +226 -0
- arvore-0.0.5/arvore/metrics/__init__.py +1 -0
- arvore-0.0.5/arvore/metrics/base.py +136 -0
- arvore-0.0.5/arvore/models/__init__.py +1 -0
- arvore-0.0.5/arvore/models/adapters.py +694 -0
- arvore-0.0.5/arvore/models/ensemble.py +353 -0
- arvore-0.0.5/arvore/prediction.py +146 -0
- arvore-0.0.5/arvore/scorers/__init__.py +28 -0
- arvore-0.0.5/arvore/scorers/base.py +41 -0
- arvore-0.0.5/arvore/scorers/distances.py +142 -0
- arvore-0.0.5/arvore/scorers/ensemble.py +211 -0
- arvore-0.0.5/arvore/scorers/leaves.py +377 -0
- arvore-0.0.5/arvore/scorers/persistence.py +247 -0
- arvore-0.0.5/arvore/scorers/reference.py +53 -0
- arvore-0.0.5/arvore/scorers/references.py +87 -0
- arvore-0.0.5/arvore/scorers/registry.py +123 -0
- arvore-0.0.5/arvore/scorers/runner.py +269 -0
- arvore-0.0.5/arvore/scorers/tanimoto.py +504 -0
- arvore-0.0.5/arvore/typing.py +43 -0
- arvore-0.0.5/arvore/utils/__init__.py +0 -0
- arvore-0.0.5/arvore/utils/plotting.py +70 -0
- arvore-0.0.5/arvore.egg-info/PKG-INFO +650 -0
- arvore-0.0.5/arvore.egg-info/SOURCES.txt +61 -0
- arvore-0.0.5/arvore.egg-info/dependency_links.txt +1 -0
- arvore-0.0.5/arvore.egg-info/entry_points.txt +2 -0
- arvore-0.0.5/arvore.egg-info/requires.txt +36 -0
- arvore-0.0.5/arvore.egg-info/top_level.txt +1 -0
- arvore-0.0.5/pyproject.toml +81 -0
- arvore-0.0.5/setup.cfg +4 -0
- arvore-0.0.5/test/test_adapters.py +154 -0
- arvore-0.0.5/test/test_checkpoint_training_config.py +205 -0
- arvore-0.0.5/test/test_cli_scoring.py +137 -0
- arvore-0.0.5/test/test_config.py +177 -0
- arvore-0.0.5/test/test_ensemble.py +283 -0
- arvore-0.0.5/test/test_euclidean_distance.py +176 -0
- arvore-0.0.5/test/test_evaluation.py +39 -0
- arvore-0.0.5/test/test_fitting.py +149 -0
- arvore-0.0.5/test/test_leaf_indices.py +210 -0
- arvore-0.0.5/test/test_leaf_occupancy.py +260 -0
- arvore-0.0.5/test/test_reference_distances.py +570 -0
- arvore-0.0.5/test/test_reference_percentile.py +201 -0
- arvore-0.0.5/test/test_scorer_architecture.py +250 -0
- arvore-0.0.5/test/test_scorer_cache.py +551 -0
- arvore-0.0.5/test/test_scorer_registry.py +144 -0
- arvore-0.0.5/test/test_scorers.py +303 -0
- arvore-0.0.5/test/test_tanimoto_distance.py +268 -0
- arvore-0.0.5/test/test_tree_box.py +254 -0
- arvore-0.0.5/test/test_tree_capabilities.py +91 -0
- arvore-0.0.5/test/test_tree_scoring.py +358 -0
- arvore-0.0.5/test/test_typed_config.py +162 -0
arvore-0.0.5/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [year] [fullname]
|
|
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.
|
arvore-0.0.5/PKG-INFO
ADDED
|
@@ -0,0 +1,650 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: arvore
|
|
3
|
+
Version: 0.0.5
|
|
4
|
+
Summary: Reproducible tree-based machine learning.
|
|
5
|
+
Author-email: Eachan Johnson <eachan.johnson@crick.ac.uk>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) [year] [fullname]
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
Project-URL: Homepage, https://__PRESERVE_ARVORE_REPO_URL__
|
|
28
|
+
Project-URL: Bug Tracker, https://__PRESERVE_ARVORE_REPO_URL__/issues
|
|
29
|
+
Keywords: ai,active-learning,bayesian-optimization,data,deep-learning,machine-learning
|
|
30
|
+
Classifier: Development Status :: 3 - Alpha
|
|
31
|
+
Classifier: Intended Audience :: Science/Research
|
|
32
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
39
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
40
|
+
Requires-Python: >=3.11
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: aspect-data>=0.0.7
|
|
44
|
+
Requires-Dist: carabiner-tools>=0.0.5.post3
|
|
45
|
+
Requires-Dist: datasets>=3.5.0
|
|
46
|
+
Requires-Dist: joblib>=1.3
|
|
47
|
+
Requires-Dist: numpy>=2.0
|
|
48
|
+
Requires-Dist: scikit-learn>=1.7
|
|
49
|
+
Requires-Dist: skops>=0.12
|
|
50
|
+
Provides-Extra: chem
|
|
51
|
+
Requires-Dist: schemist>=0.0.7; extra == "chem"
|
|
52
|
+
Provides-Extra: bio
|
|
53
|
+
Requires-Dist: vectome>=0.0.7; extra == "bio"
|
|
54
|
+
Provides-Extra: cat
|
|
55
|
+
Requires-Dist: catboost>=1.2; extra == "cat"
|
|
56
|
+
Provides-Extra: lgbm
|
|
57
|
+
Requires-Dist: lightgbm[arrow,plotting,scikit-learn]>=4.0; extra == "lgbm"
|
|
58
|
+
Provides-Extra: xgb
|
|
59
|
+
Requires-Dist: xgboost_cpu; extra == "xgb"
|
|
60
|
+
Provides-Extra: xgb-cuda12
|
|
61
|
+
Requires-Dist: xgboost-cu12; extra == "xgb-cuda12"
|
|
62
|
+
Provides-Extra: xgb-cuda13
|
|
63
|
+
Requires-Dist: xgboost>=3.0; extra == "xgb-cuda13"
|
|
64
|
+
Provides-Extra: trees
|
|
65
|
+
Requires-Dist: arvore[lgbm,xgb]; extra == "trees"
|
|
66
|
+
Provides-Extra: dev
|
|
67
|
+
Requires-Dist: arvore[bio,chem,trees]; extra == "dev"
|
|
68
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
69
|
+
Requires-Dist: flake8; extra == "dev"
|
|
70
|
+
Dynamic: license-file
|
|
71
|
+
|
|
72
|
+
# 🌳 Arvore
|
|
73
|
+
|
|
74
|
+

|
|
75
|
+

|
|
76
|
+

|
|
77
|
+
|
|
78
|
+
**Arvore makes tree-based machine learning simple, reproducible and shareable.**
|
|
79
|
+
|
|
80
|
+
Train random forests, XGBoost, LightGBM, CatBoost and other scikit-learn-compatible estimators through a consistent interface. Combine models into ensembles, evaluate predictions, measure uncertainty and novelty, and share complete experiments as portable checkpoints.
|
|
81
|
+
|
|
82
|
+
Arvore brings together model training, feature preprocessing, data provenance and prediction diagnostics without imposing a particular modelling workflow. Its composable scoring interface makes it straightforward to compare uncertainty measures or integrate methods from other packages.
|
|
83
|
+
|
|
84
|
+
Use it interactively from Python or through a reproducible command-line interface, from a laptop to an HPC cluster.
|
|
85
|
+
|
|
86
|
+
Arvore currently focuses on regression and is under active alpha development.
|
|
87
|
+
|
|
88
|
+
## Installation
|
|
89
|
+
|
|
90
|
+
Python 3.11 or later is required.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
pip install arvore
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Install optional model backends as needed:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install "arvore[trees]" # XGBoost and LightGBM
|
|
100
|
+
pip install "arvore[cat]" # CatBoost
|
|
101
|
+
pip install "arvore[chem]" # Molecular fingerprints and descriptors
|
|
102
|
+
pip install "arvore[bio]" # Biological feature tools
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
For the latest development version:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
pip install "git+https://github.com/scbirlab/treeton.git@dev"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Quick start
|
|
112
|
+
|
|
113
|
+
### Command-line interface
|
|
114
|
+
|
|
115
|
+
Train and save a model using a simple JSON configuration.
|
|
116
|
+
|
|
117
|
+
Create `experiment.json`:
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"box": {
|
|
122
|
+
"model": {
|
|
123
|
+
"class_path": "sklearn.ensemble.RandomForestRegressor",
|
|
124
|
+
"init_args": {
|
|
125
|
+
"n_estimators": 200,
|
|
126
|
+
"random_state": 42
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"features": ["x1", "x2"],
|
|
130
|
+
"target": "y",
|
|
131
|
+
"pipeline": {}
|
|
132
|
+
},
|
|
133
|
+
"fit": {
|
|
134
|
+
"skip_eval": true
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Train a model from a CSV file:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
arvore train train.csv \
|
|
143
|
+
--config experiment.json \
|
|
144
|
+
--checkpoint model.ao
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Make predictions on new data:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
arvore predict model.ao \
|
|
151
|
+
--trust-sklearn-trees \
|
|
152
|
+
--data candidates.csv \
|
|
153
|
+
--output predictions.csv
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Add uncertainty and novelty diagnostics with one argument:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
arvore predict model.ao \
|
|
160
|
+
--trust-sklearn-trees \
|
|
161
|
+
--data candidates.csv \
|
|
162
|
+
--score tree_sd feature_distance \
|
|
163
|
+
--output scored.csv
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The resulting table retains the input columns and adds predictions and requested scores:
|
|
167
|
+
|
|
168
|
+
| x1 | x2 | prediction:y | score:tree_sd:y | score:feature_distance |
|
|
169
|
+
| --- | --- | --- | --- | --- |
|
|
170
|
+
| ... | ... | ... | ... | ... |
|
|
171
|
+
|
|
172
|
+
The same configuration can be reused across datasets and overridden from the command line.
|
|
173
|
+
|
|
174
|
+
### Python API
|
|
175
|
+
|
|
176
|
+
The equivalent workflow takes only a few lines:
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from arvore import Box
|
|
180
|
+
|
|
181
|
+
box = Box.from_config({
|
|
182
|
+
"model": {
|
|
183
|
+
"class_path": "sklearn.ensemble.RandomForestRegressor",
|
|
184
|
+
"init_args": {
|
|
185
|
+
"n_estimators": 200,
|
|
186
|
+
"random_state": 42
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"features": ["x1", "x2"],
|
|
190
|
+
"target": "y",
|
|
191
|
+
"pipeline": {}
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
box.fit("train.csv", skip_eval=True)
|
|
195
|
+
|
|
196
|
+
results = box.predict(
|
|
197
|
+
"candidates.csv",
|
|
198
|
+
score=["tree_sd", "feature_distance"]
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
box.save("model.ao")
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Restore the complete fitted experiment elsewhere:
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
from arvore import Box
|
|
208
|
+
|
|
209
|
+
box = Box.load(
|
|
210
|
+
"model.ao",
|
|
211
|
+
trusted_types=("sklearn.tree._tree.Tree",)
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
predictions = box.predict("new_data.csv")
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The checkpoint preserves the trained estimator, its configuration, fitted preprocessing and training-data provenance. Prepared reference resources for uncertainty and novelty scoring can also be checkpointed and reused.
|
|
218
|
+
|
|
219
|
+
## Models and ensembles
|
|
220
|
+
|
|
221
|
+
Arvore supports scikit-learn-compatible estimators through a common training, prediction and persistence interface.
|
|
222
|
+
|
|
223
|
+
Supported backends include:
|
|
224
|
+
|
|
225
|
+
- Random forests and other scikit-learn estimators
|
|
226
|
+
- XGBoost
|
|
227
|
+
- LightGBM
|
|
228
|
+
- CatBoost
|
|
229
|
+
- Homogeneous and heterogeneous ensembles
|
|
230
|
+
|
|
231
|
+
Additional estimators can be integrated through model adapters.
|
|
232
|
+
|
|
233
|
+
### Ensembles
|
|
234
|
+
|
|
235
|
+
Combine estimators directly through the Python API:
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
from arvore import Ensemble
|
|
239
|
+
|
|
240
|
+
from sklearn.ensemble import RandomForestRegressor
|
|
241
|
+
from xgboost import XGBRegressor
|
|
242
|
+
|
|
243
|
+
model = Ensemble(
|
|
244
|
+
{
|
|
245
|
+
"rf": RandomForestRegressor(
|
|
246
|
+
n_estimators=200,
|
|
247
|
+
random_state=42
|
|
248
|
+
),
|
|
249
|
+
"xgb": XGBRegressor(
|
|
250
|
+
n_estimators=300,
|
|
251
|
+
random_state=43
|
|
252
|
+
)
|
|
253
|
+
},
|
|
254
|
+
weights=[1, 2]
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
model.fit(X_train, y_train)
|
|
258
|
+
|
|
259
|
+
predictions = model.predict(X_test)
|
|
260
|
+
members = model.predict_members(X_test)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Arvore also supports ensembles of repeated estimators defined through JSON configurations.
|
|
264
|
+
|
|
265
|
+
Individual member predictions can be inspected alongside aggregate predictions, including through the CLI's `--disaggregate` option.
|
|
266
|
+
|
|
267
|
+
## Prediction scoring
|
|
268
|
+
|
|
269
|
+
Arvore supports composable prediction diagnostics through the `score` argument of `Box.predict()`.
|
|
270
|
+
|
|
271
|
+
Scores can quantify model disagreement, variability between trees, or distance from observations in the training dataset.
|
|
272
|
+
|
|
273
|
+
| Scorer | Description |
|
|
274
|
+
| --- | --- |
|
|
275
|
+
| `ensemble_sd` | Standard deviation of predictions across ensemble members |
|
|
276
|
+
| `tree_sd` | Variation in predictions across individual trees |
|
|
277
|
+
| `inverse_leaf_occupancy` | Sparsity of training observations in the leaves reached by a candidate |
|
|
278
|
+
| `feature_distance` | Distance to nearest training observations in transformed feature space |
|
|
279
|
+
| `tanimoto_distance` | Distance to training compounds using molecular fingerprints |
|
|
280
|
+
|
|
281
|
+
Scores are diagnostics with different scales and interpretations. They should not automatically be interpreted as calibrated prediction errors.
|
|
282
|
+
|
|
283
|
+
### Composing scorers
|
|
284
|
+
|
|
285
|
+
Request several scores in the same prediction:
|
|
286
|
+
|
|
287
|
+
```python
|
|
288
|
+
results = box.predict(
|
|
289
|
+
"candidates.csv",
|
|
290
|
+
score=[
|
|
291
|
+
"tree_sd",
|
|
292
|
+
"feature_distance",
|
|
293
|
+
"inverse_leaf_occupancy"
|
|
294
|
+
]
|
|
295
|
+
)
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Scorers can also be configured as objects:
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
from arvore.scorers import (
|
|
302
|
+
FeatureDistance,
|
|
303
|
+
InverseLeafOccupancy
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
results = box.predict(
|
|
307
|
+
"candidates.csv",
|
|
308
|
+
score={
|
|
309
|
+
"nearest": FeatureDistance(n_neighbors=1),
|
|
310
|
+
"neighbourhood": FeatureDistance(n_neighbors=10),
|
|
311
|
+
"leaf_percentile": InverseLeafOccupancy(
|
|
312
|
+
normalization="reference_percentile"
|
|
313
|
+
)
|
|
314
|
+
}
|
|
315
|
+
)
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Using a dictionary assigns each scorer a custom output name, allowing different configurations of the same method to be evaluated together.
|
|
319
|
+
|
|
320
|
+
### Molecular novelty
|
|
321
|
+
|
|
322
|
+
Chemical novelty can be evaluated independently of the features used by a predictive model.
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
from arvore.scorers import TanimotoDistance
|
|
326
|
+
|
|
327
|
+
results = box.predict(
|
|
328
|
+
"compounds.csv",
|
|
329
|
+
score=TanimotoDistance(
|
|
330
|
+
structure_column="smiles",
|
|
331
|
+
column="fingerprint"
|
|
332
|
+
)
|
|
333
|
+
)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Arvore can reuse existing molecular fingerprints or generate them from molecular structures through its preprocessing integrations.
|
|
337
|
+
|
|
338
|
+
### External scoring methods
|
|
339
|
+
|
|
340
|
+
**Any callable accepting an Arvore `ScoreContext` can be used as a scorer.** This allows existing uncertainty estimators, distance metrics or custom diagnostics to be integrated without modifying Arvore.
|
|
341
|
+
|
|
342
|
+
For example, to use a function from another package:
|
|
343
|
+
|
|
344
|
+
```python
|
|
345
|
+
import numpy as np
|
|
346
|
+
|
|
347
|
+
from external_package import novelty_score
|
|
348
|
+
|
|
349
|
+
def external_novelty(context):
|
|
350
|
+
return np.asarray(
|
|
351
|
+
novelty_score(context.X)
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
results = box.predict(
|
|
355
|
+
"candidates.csv",
|
|
356
|
+
score={"novelty": external_novelty}
|
|
357
|
+
)
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
The callable receives the transformed feature matrix and can access the fitted model, predictions, candidate data and other available context.
|
|
361
|
+
|
|
362
|
+
For methods requiring training-set references, calibration data or additional model capabilities, Arvore provides a more structured scorer interface described under [Extending Arvore](#extending-arvore).
|
|
363
|
+
|
|
364
|
+
### Reference-based scoring
|
|
365
|
+
|
|
366
|
+
Some diagnostics require information from the fitted training dataset, such as nearest-neighbour indices, molecular fingerprints or tree-leaf occupancy distributions.
|
|
367
|
+
|
|
368
|
+
Arvore prepares these resources lazily and caches them on the fitted `Box`. Repeated scoring requests reuse compatible references rather than recomputing them.
|
|
369
|
+
|
|
370
|
+
```python
|
|
371
|
+
box.predict(
|
|
372
|
+
candidates,
|
|
373
|
+
score="feature_distance"
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
# Reuses the same prepared training reference.
|
|
377
|
+
box.predict(
|
|
378
|
+
more_candidates,
|
|
379
|
+
score="feature_distance"
|
|
380
|
+
)
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Prepared references can be retained in checkpoints:
|
|
384
|
+
|
|
385
|
+
```python
|
|
386
|
+
box.save(
|
|
387
|
+
"model.ao",
|
|
388
|
+
score=[
|
|
389
|
+
"feature_distance",
|
|
390
|
+
"inverse_leaf_occupancy",
|
|
391
|
+
"tanimoto_distance"
|
|
392
|
+
]
|
|
393
|
+
)
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
References are identified by deterministic specifications, allowing compatible scorers and repeated predictions to share resources.
|
|
397
|
+
|
|
398
|
+
## Data and preprocessing
|
|
399
|
+
|
|
400
|
+
Arvore works with datasets resolved through [Providence](https://github.com/scbirlab/providence), including CSV, Parquet and Hugging Face datasets.
|
|
401
|
+
|
|
402
|
+
Feature transformations are managed through [Aspect](https://github.com/scbirlab/aspect). Preprocessing is fitted alongside the estimator and retained in its checkpoint.
|
|
403
|
+
|
|
404
|
+
A `Box` specifies the input features, prediction targets, model and optional transformation pipeline.
|
|
405
|
+
|
|
406
|
+
For example, a pipeline can construct a log-transformed feature:
|
|
407
|
+
|
|
408
|
+
```json
|
|
409
|
+
{
|
|
410
|
+
"column_transforms": {
|
|
411
|
+
"log_x": ["x", "log"]
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
The resulting feature can then be selected for model training.
|
|
417
|
+
|
|
418
|
+
Arvore also supports batched predictions, making it suitable for evaluating large candidate datasets without materialising every prediction batch simultaneously.
|
|
419
|
+
|
|
420
|
+
## Evaluation and reproducibility
|
|
421
|
+
|
|
422
|
+
Evaluate models against held-out data using standard regression metrics:
|
|
423
|
+
|
|
424
|
+
```python
|
|
425
|
+
predictions, metrics = box.evaluate(
|
|
426
|
+
"validation.csv",
|
|
427
|
+
metrics=[
|
|
428
|
+
"rmse",
|
|
429
|
+
"mae",
|
|
430
|
+
"pearson",
|
|
431
|
+
"spearman"
|
|
432
|
+
]
|
|
433
|
+
)
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Portable checkpoints
|
|
437
|
+
|
|
438
|
+
A saved `Box` retains the information needed to recover a fitted experiment:
|
|
439
|
+
|
|
440
|
+
- Model configuration and fitted estimator
|
|
441
|
+
- Feature definitions and fitted preprocessing
|
|
442
|
+
- Training-data provenance and retained training references
|
|
443
|
+
- Prepared uncertainty and novelty resources, when requested
|
|
444
|
+
|
|
445
|
+
Training data may be embedded or retained by reference, depending on its source and the checkpoint settings.
|
|
446
|
+
|
|
447
|
+
Model persistence uses backend-native formats where supported and skops for scikit-learn models. Some scikit-learn checkpoints require explicitly trusting internal estimator types during loading. An unsafe joblib fallback is available for otherwise unsupported estimators.
|
|
448
|
+
|
|
449
|
+
Only load checkpoints from trusted sources.
|
|
450
|
+
|
|
451
|
+
### Reproducible command-line experiments
|
|
452
|
+
|
|
453
|
+
Configurations can be overridden without editing the original experiment definition:
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
arvore train train.csv \
|
|
457
|
+
--config experiment.json \
|
|
458
|
+
--checkpoint experiment.ao \
|
|
459
|
+
--set box.model.init_args.n_estimators=500
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
This makes the same experiment definition reusable across model hyperparameters, datasets and automated workflows.
|
|
463
|
+
|
|
464
|
+
## Extending Arvore
|
|
465
|
+
|
|
466
|
+
Arvore is designed to accommodate external estimators and prediction diagnostics with minimal integration code.
|
|
467
|
+
|
|
468
|
+
### Box
|
|
469
|
+
|
|
470
|
+
`Box` is the central interface for a fitted experiment.
|
|
471
|
+
|
|
472
|
+
It brings together:
|
|
473
|
+
|
|
474
|
+
| Component | Responsibility |
|
|
475
|
+
| --- | --- |
|
|
476
|
+
| Model | A fitted estimator or ensemble |
|
|
477
|
+
| Features and targets | Definitions of model inputs and outputs |
|
|
478
|
+
| Pipeline | Feature transformations and preprocessing |
|
|
479
|
+
| Data provenance | Resolution and retention of training data |
|
|
480
|
+
| Scorers | Optional uncertainty and novelty diagnostics |
|
|
481
|
+
| References | Reusable training-dependent resources |
|
|
482
|
+
| Checkpoint | Persistence of the complete fitted experiment |
|
|
483
|
+
|
|
484
|
+
The main operations are `fit()`, `predict()`, `evaluate()`, `save()` and `load()`.
|
|
485
|
+
|
|
486
|
+
Model-specific operations are delegated to adapters, keeping `Box` independent of a particular estimation library.
|
|
487
|
+
|
|
488
|
+
### Writing a custom Scorer
|
|
489
|
+
|
|
490
|
+
A minimal scorer only needs to be callable:
|
|
491
|
+
|
|
492
|
+
```python
|
|
493
|
+
import numpy as np
|
|
494
|
+
|
|
495
|
+
def feature_norm(context):
|
|
496
|
+
return np.linalg.norm(context.X, axis=1)
|
|
497
|
+
|
|
498
|
+
results = box.predict(
|
|
499
|
+
candidates,
|
|
500
|
+
score={"feature_norm": feature_norm}
|
|
501
|
+
)
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
The `ScoreContext` provides backend-independent access to information such as:
|
|
505
|
+
|
|
506
|
+
- `X`: transformed candidate features
|
|
507
|
+
- `predictions`: model predictions
|
|
508
|
+
- `model`: fitted model or ensemble
|
|
509
|
+
- `batch`: original candidate columns
|
|
510
|
+
- `targets`: prediction target names
|
|
511
|
+
- `member_predictions`: optional ensemble-member predictions
|
|
512
|
+
- `tree_predictions`: optional individual-tree predictions
|
|
513
|
+
- `state`: scorer-specific prepared resources
|
|
514
|
+
- `box`: the fitted `Box`
|
|
515
|
+
|
|
516
|
+
More advanced methods can declare requirements and implement preparation hooks.
|
|
517
|
+
|
|
518
|
+
For example, a scorer wrapping an external uncertainty implementation:
|
|
519
|
+
|
|
520
|
+
```python
|
|
521
|
+
from dataclasses import dataclass
|
|
522
|
+
from typing import ClassVar
|
|
523
|
+
|
|
524
|
+
from arvore.scorers import (
|
|
525
|
+
Requirements,
|
|
526
|
+
ScoreContext,
|
|
527
|
+
register_scorer
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
from external_package import ExternalUncertainty
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
@register_scorer
|
|
534
|
+
@dataclass(frozen=True)
|
|
535
|
+
class ExternalScore:
|
|
536
|
+
name: ClassVar[str] = "external_score"
|
|
537
|
+
|
|
538
|
+
@property
|
|
539
|
+
def requirements(self):
|
|
540
|
+
return Requirements(
|
|
541
|
+
outputs=("prediction",)
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
def prepare(self, box, *, batch_size=1024):
|
|
545
|
+
# Construct or retrieve any resources needed
|
|
546
|
+
# by the external implementation.
|
|
547
|
+
return ExternalUncertainty(box.model)
|
|
548
|
+
|
|
549
|
+
def __call__(self, context: ScoreContext):
|
|
550
|
+
return context.state.score(context.X)
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
The scorer can then be invoked by name:
|
|
554
|
+
|
|
555
|
+
```python
|
|
556
|
+
results = box.predict(
|
|
557
|
+
candidates,
|
|
558
|
+
score="external_score"
|
|
559
|
+
)
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
The external implementation above is illustrative; its constructor and `score()` method should be adapted to the actual library.
|
|
563
|
+
|
|
564
|
+
### Scorer extension points
|
|
565
|
+
|
|
566
|
+
Scorers can implement several optional hooks:
|
|
567
|
+
|
|
568
|
+
| Hook | Purpose |
|
|
569
|
+
| --- | --- |
|
|
570
|
+
| `requirements` | Declare required candidate columns, model capabilities and prediction outputs |
|
|
571
|
+
| `prepare_candidates(data, box=...)` | Generate or resolve auxiliary candidate columns |
|
|
572
|
+
| `validate(box, prepared)` | Check compatibility before scoring |
|
|
573
|
+
| `prepare(box, batch_size=...)` | Initialise training references, indices or calibration resources |
|
|
574
|
+
| `__call__(context)` | Evaluate the scorer for a prediction batch |
|
|
575
|
+
| `finalize(result, name=..., box=...)` | Inspect the completed result or issue diagnostics |
|
|
576
|
+
|
|
577
|
+
Arvore validates declared requirements and supplies common inference resources, including ensemble-member predictions and individual-tree predictions, through model adapters where supported.
|
|
578
|
+
|
|
579
|
+
A scorer can return one value per sample or per target. It may also return a mapping containing a primary score and additional named outputs.
|
|
580
|
+
|
|
581
|
+
### Reusing reference resources
|
|
582
|
+
|
|
583
|
+
Scorers that depend on training data can request reusable resources through `box.references.get_or_build()`.
|
|
584
|
+
|
|
585
|
+
```python
|
|
586
|
+
reference = box.references.get_or_build(
|
|
587
|
+
{
|
|
588
|
+
"type": "external_reference",
|
|
589
|
+
"version": 1,
|
|
590
|
+
"metric": "euclidean"
|
|
591
|
+
},
|
|
592
|
+
builder
|
|
593
|
+
)
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
Here, `builder` is a callable that constructs the resource when it has not already been prepared.
|
|
597
|
+
|
|
598
|
+
Arvore hashes the canonical resource specification to obtain a deterministic cache key. Equivalent requests reuse the same prepared resource, including across scorer instances.
|
|
599
|
+
|
|
600
|
+
Reference types supporting Arvore's checkpoint persistence can be saved and restored alongside the fitted model.
|
|
601
|
+
|
|
602
|
+
This enables integration with external nearest-neighbour libraries, model-specific uncertainty implementations, density estimators or calibration methods without embedding their algorithms in `Box`.
|
|
603
|
+
|
|
604
|
+
### Model adapters
|
|
605
|
+
|
|
606
|
+
Custom estimators can be supported through Arvore's adapter registry.
|
|
607
|
+
|
|
608
|
+
Adapters handle estimator-specific fitting, prediction, model capabilities and persistence. This allows scorers to request capabilities such as individual-tree predictions without depending directly on XGBoost, LightGBM, CatBoost or scikit-learn internals.
|
|
609
|
+
|
|
610
|
+
## Development
|
|
611
|
+
|
|
612
|
+
Clone the repository and install development dependencies:
|
|
613
|
+
|
|
614
|
+
```bash
|
|
615
|
+
git clone https://github.com/scbirlab/treeton.git
|
|
616
|
+
cd treeton
|
|
617
|
+
pip install -e ".[dev]"
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
Run the test suite:
|
|
621
|
+
|
|
622
|
+
```bash
|
|
623
|
+
pytest -q
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
Run module doctests:
|
|
627
|
+
|
|
628
|
+
```bash
|
|
629
|
+
pytest --doctest-modules -q arvore
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
The project is developed using Python 3.11 and later.
|
|
633
|
+
|
|
634
|
+
### Related projects
|
|
635
|
+
|
|
636
|
+
Arvore integrates with other packages in the [scbirlab](https://github.com/scbirlab) ecosystem:
|
|
637
|
+
|
|
638
|
+
- [Providence](https://github.com/scbirlab/providence) — Data resolution, provenance and checkpointing.
|
|
639
|
+
- [Aspect](https://github.com/scbirlab/aspect) — Feature transformation and processing.
|
|
640
|
+
- [Eluent](https://github.com/scbirlab/eluent) — Dataset grouping and splitting.
|
|
641
|
+
- [Schemist](https://github.com/scbirlab/schemist) — Molecular featurisation.
|
|
642
|
+
- [Vectome](https://github.com/scbirlab/vectome) — Biological feature representations.
|
|
643
|
+
|
|
644
|
+
### Issues, problems, suggestions
|
|
645
|
+
|
|
646
|
+
Please report bugs, feature requests and suggestions through the [GitHub issue tracker](https://github.com/scbirlab/arvore/issues).
|
|
647
|
+
|
|
648
|
+
### License
|
|
649
|
+
|
|
650
|
+
MIT. See [LICENSE](https://github.com/scbirlab/arvore/blob/main/LICENSE).
|