MaldiDeepKit 0.2.0__tar.gz → 0.3.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.
- {maldideepkit-0.2.0 → maldideepkit-0.3.0/MaldiDeepKit.egg-info}/PKG-INFO +27 -7
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/MaldiDeepKit.egg-info/SOURCES.txt +11 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/MaldiDeepKit.egg-info/requires.txt +8 -1
- {maldideepkit-0.2.0/MaldiDeepKit.egg-info → maldideepkit-0.3.0}/PKG-INFO +27 -7
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/README.md +20 -5
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/__init__.py +17 -3
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/attention/mlp.py +9 -3
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/augment/mixing.py +63 -11
- maldideepkit-0.3.0/maldideepkit/base/__init__.py +23 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/base/classifier.py +255 -50
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/base/data.py +135 -18
- maldideepkit-0.3.0/maldideepkit/base/dual.py +266 -0
- maldideepkit-0.3.0/maldideepkit/dual_branch/__init__.py +22 -0
- maldideepkit-0.3.0/maldideepkit/dual_branch/_smiles.py +87 -0
- maldideepkit-0.3.0/maldideepkit/dual_branch/classifier.py +347 -0
- maldideepkit-0.3.0/maldideepkit/semisupervised/__init__.py +15 -0
- maldideepkit-0.3.0/maldideepkit/semisupervised/self_training.py +289 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/uncertainty/_base.py +7 -27
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/uncertainty/mc_dropout.py +1 -1
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/utils/calibration.py +34 -4
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/utils/loss.py +80 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/utils/lr_finder.py +2 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/utils/reproducibility.py +2 -2
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/utils/training.py +86 -15
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/pyproject.toml +2 -0
- maldideepkit-0.3.0/requirements-all.txt +2 -0
- maldideepkit-0.3.0/requirements-rdkit.txt +1 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/requirements.txt +1 -1
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_base.py +5 -5
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_bin_scaling.py +2 -2
- maldideepkit-0.3.0/tests/test_dual_branch.py +534 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_maldiset_integration.py +1 -1
- maldideepkit-0.3.0/tests/test_sample_weight.py +277 -0
- maldideepkit-0.3.0/tests/test_self_training.py +281 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_sklearn_compat.py +1 -1
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_transformer.py +1 -1
- maldideepkit-0.2.0/maldideepkit/base/__init__.py +0 -16
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/LICENSE +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/MaldiDeepKit.egg-info/dependency_links.txt +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/MaldiDeepKit.egg-info/top_level.txt +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/_bin_scaling.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/_blocks.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/attention/__init__.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/augment/__init__.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/augment/spectra.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/blocks.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/cnn/__init__.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/cnn/cnn.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/py.typed +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/resnet/__init__.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/resnet/resnet.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/transformer/__init__.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/transformer/transformer.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/uncertainty/__init__.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/uncertainty/_result.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/uncertainty/conformal.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/uncertainty/laplace.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/utils/__init__.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/utils/ensemble.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/maldideepkit/utils/sam.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/requirements-dev.txt +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/requirements-docs.txt +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/requirements-uncertainty.txt +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/setup.cfg +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_augment.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_blocks.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_calibration.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_cnn.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_ensemble.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_loss.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_lr_finder.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_mlp.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_resnet.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_sam.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_uncertainty.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_warm_start.py +0 -0
- {maldideepkit-0.2.0 → maldideepkit-0.3.0}/tests/test_warping.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MaldiDeepKit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A catalog of sklearn-compatible deep learning classifiers for MALDI-TOF binned spectra
|
|
5
5
|
Author-email: Ettore Rocchi <ettore.rocchi3@unibo.it>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -30,7 +30,7 @@ Requires-Dist: scikit-learn>=1.3.0
|
|
|
30
30
|
Requires-Dist: matplotlib>=3.4.0
|
|
31
31
|
Requires-Dist: torch>=2.0.0
|
|
32
32
|
Requires-Dist: einops>=0.7.0
|
|
33
|
-
Requires-Dist: maldiamrkit>=0.
|
|
33
|
+
Requires-Dist: maldiamrkit>=0.19.0
|
|
34
34
|
Provides-Extra: dev
|
|
35
35
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
36
36
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -47,6 +47,11 @@ Requires-Dist: ipykernel>=6.0.0; extra == "docs"
|
|
|
47
47
|
Requires-Dist: ipywidgets>=8.0.0; extra == "docs"
|
|
48
48
|
Provides-Extra: uncertainty
|
|
49
49
|
Requires-Dist: laplace-torch<1.0,>=0.2; extra == "uncertainty"
|
|
50
|
+
Provides-Extra: rdkit
|
|
51
|
+
Requires-Dist: rdkit>=2026.3.1; extra == "rdkit"
|
|
52
|
+
Provides-Extra: all
|
|
53
|
+
Requires-Dist: rdkit>=2026.3.1; extra == "all"
|
|
54
|
+
Requires-Dist: laplace-torch<1.0,>=0.2; extra == "all"
|
|
50
55
|
Dynamic: license-file
|
|
51
56
|
|
|
52
57
|
# MaldiDeepKit
|
|
@@ -79,7 +84,7 @@ Dynamic: license-file
|
|
|
79
84
|
<a href="#license">License</a>
|
|
80
85
|
</p>
|
|
81
86
|
|
|
82
|
-
MaldiDeepKit is part of the **MaldiSuite** ecosystem and complements [MaldiAMRKit](https://github.com/EttoreRocchi/MaldiAMRKit) and [MaldiBatchKit](https://github.com/EttoreRocchi/MaldiBatchKit): where MaldiAMRKit handles preprocessing, alignment and AMR-aware evaluation, and MaldiBatchKit harmonises multi-centre spectra, MaldiDeepKit focuses on the *classification* step, providing four PyTorch architectures wrapped in a unified scikit-learn estimator API with defaults calibrated for 6000-bin MALDI-TOF input.
|
|
87
|
+
MaldiDeepKit is part of the **MaldiSuite** ecosystem and complements [MaldiAMRKit](https://github.com/EttoreRocchi/MaldiAMRKit) and [MaldiBatchKit](https://github.com/EttoreRocchi/MaldiBatchKit): where MaldiAMRKit handles preprocessing, alignment and AMR-aware evaluation, and MaldiBatchKit harmonises multi-centre spectra, MaldiDeepKit focuses on the *classification* step, providing four PyTorch backbone architectures (MLP, 1-D CNN, 1-D ResNet, and 1-D Vision Transformer) plus a dual-branch classifier for spectrum + side-feature inputs and a self-training meta-classifier for semi-supervised data, all wrapped in a unified scikit-learn estimator API with defaults calibrated for 6000-bin MALDI-TOF input.
|
|
83
88
|
|
|
84
89
|
## Installation
|
|
85
90
|
|
|
@@ -87,7 +92,7 @@ MaldiDeepKit is part of the **MaldiSuite** ecosystem and complements [MaldiAMRKi
|
|
|
87
92
|
pip install maldideepkit
|
|
88
93
|
```
|
|
89
94
|
|
|
90
|
-
`maldiamrkit` is a core dependency and is installed automatically
|
|
95
|
+
`maldiamrkit` is a core dependency and is installed automatically (MaldiDeepKit duck-types on the `MaldiSet` data model and reuses `maldiamrkit.alignment.Warping` for leak-safe spectral warping).
|
|
91
96
|
|
|
92
97
|
To enable the Laplace-approximation estimator in `maldideepkit.uncertainty`, install the optional `uncertainty` extra (pulls in [`laplace-torch`](https://github.com/aleximmer/Laplace)):
|
|
93
98
|
|
|
@@ -97,6 +102,12 @@ pip install "maldideepkit[uncertainty]"
|
|
|
97
102
|
|
|
98
103
|
Monte Carlo Dropout and split conformal prediction work without any extra.
|
|
99
104
|
|
|
105
|
+
The `smiles_to_fingerprint` helper used in `MaldiDualBranchClassifier` workflows requires RDKit, available via the `rdkit` extra:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
pip install "maldideepkit[rdkit]"
|
|
109
|
+
```
|
|
110
|
+
|
|
100
111
|
### Install the full MaldiSuite
|
|
101
112
|
|
|
102
113
|
To install MaldiDeepKit together with [MaldiAMRKit](https://github.com/EttoreRocchi/MaldiAMRKit) and [MaldiBatchKit](https://github.com/EttoreRocchi/MaldiBatchKit) at compatible versions, install the [`maldisuite`](https://pypi.org/project/maldisuite/) meta-package:
|
|
@@ -128,7 +139,7 @@ See [`CONTRIBUTING.md`](CONTRIBUTING.md) for coding conventions, testing, and PR
|
|
|
128
139
|
- `MaldiTransformerClassifier` - 1-D Vision Transformer with global self-attention, pre-norm, LayerScale, and stochastic depth.
|
|
129
140
|
- **MALDI-TOF defaults**: kernel sizes, depths, patch widths, and warmup / cosine-annealing schedules are tuned for 6000-bin spectra in the 2000-20000 Da range.
|
|
130
141
|
- **Auto-scaling for non-default layouts**: every classifier ships a `from_spectrum(bin_width, input_dim, **overrides)` factory that rescales conv kernels and patches when the user trims the m/z range or picks a different bin width. See the [Spectrum scaling guide](https://maldideepkit.readthedocs.io/en/latest/spectrum_scaling.html).
|
|
131
|
-
- **Training recipes**: AdamW-on-`weight_decay` dispatch, gradient clipping, linear warmup + cosine annealing, focal loss, label smoothing, mixed precision (AMP), Stochastic Weight Averaging, Sharpness-Aware Minimization, post-hoc threshold tuning, and temperature scaling
|
|
142
|
+
- **Training recipes**: AdamW-on-`weight_decay` dispatch, gradient clipping, linear warmup + cosine annealing, focal loss, label smoothing, mixed precision (AMP), Stochastic Weight Averaging, Sharpness-Aware Minimization, post-hoc threshold tuning, and temperature scaling (all exposed as classifier kwargs).
|
|
132
143
|
- **Leak-safe spectral warping**: pass any sklearn-style transformer ([`maldiamrkit.alignment.Warping`](https://github.com/EttoreRocchi/MaldiAMRKit)) via `warping=`; it is fitted on the training fold only and applied to both splits during training and to new spectra at `predict` time, *before* per-feature standardization.
|
|
133
144
|
- **MaldiSet integration**: pass a `maldiamrkit.MaldiSet` directly to `fit` / `predict`; MaldiDeepKit duck-types on the DataFrame-like `.X` attribute, so MaldiSuite's data model flows end-to-end.
|
|
134
145
|
- **Persistence**: `save()` writes a state-dict `.pt` plus a hyperparameter `.json` (and a sibling `.warper.pkl` if a warper was fitted); `load()` fails fast on class or `input_dim` mismatches.
|
|
@@ -236,8 +247,15 @@ For more examples covering training recipes, calibration, attention inspection,
|
|
|
236
247
|
| `MaldiCNNClassifier` | 1-D Conv1D + BatchNorm + ReLU + MaxPool blocks | Local pattern learning from binned spectra |
|
|
237
248
|
| `MaldiResNetClassifier` | 1-D ResNet-18-style residual blocks | Deeper convolutional backbone |
|
|
238
249
|
| `MaldiTransformerClassifier` | 1-D Vision Transformer (LayerScale, stochastic depth) | Long-range peak combinations via global self-attention |
|
|
250
|
+
| `MaldiDualBranchClassifier` | Spectrum branch + per-row side-feature branch + fused head | Multi-modal: condition on antibiotic fingerprint, instrument ID, patient feature, ... |
|
|
251
|
+
|
|
252
|
+
All five inherit from `BaseSpectralClassifier` (or its dual-input subclass `BaseDualSpectralClassifier`) and share the same hyperparameter surface for optimisation, device placement, early stopping, calibration, and persistence.
|
|
253
|
+
|
|
254
|
+
### Semi-supervised wrapper
|
|
239
255
|
|
|
240
|
-
|
|
256
|
+
| Class | Purpose |
|
|
257
|
+
|---|---|
|
|
258
|
+
| `MaldiSelfTrainingClassifier` | Iterative pseudo-labeling on a labeled seed plus an unlabeled pool (rows marked `-1` by default). Wraps any classifier (defaults to `MaldiMLPClassifier`); follows the `sklearn.semi_supervised.SelfTrainingClassifier` API. |
|
|
241
259
|
|
|
242
260
|
### Shared Training Knobs
|
|
243
261
|
|
|
@@ -247,7 +265,7 @@ All four inherit from `BaseSpectralClassifier` and share the same hyperparameter
|
|
|
247
265
|
| Gradient clipping | `grad_clip_norm` | `clip_grad_norm_` before every step. Default on (`1.0`) for the deep models. |
|
|
248
266
|
| Warmup + cosine annealing | `warmup_epochs` | Replaces plateau scheduler. Default `5` (deep models), `0` (MLP/CNN). |
|
|
249
267
|
| Stochastic depth (Transformer) | `drop_path_rate` | Linearly ramped across blocks. Default `0.1`. |
|
|
250
|
-
| LayerScale (Transformer) | `layerscale_init` | Per-channel residual scaling initialised near zero
|
|
268
|
+
| LayerScale (Transformer) | `layerscale_init` | Per-channel residual scaling initialised near zero (crucial on small cohorts). |
|
|
251
269
|
| Focal loss | `loss="focal"` + `focal_gamma` | For imbalanced binary problems. |
|
|
252
270
|
| Label smoothing | `label_smoothing` | Passed to both cross-entropy and focal paths. |
|
|
253
271
|
| Stochastic Weight Averaging | `swa_start_epoch` | `AveragedModel` replaces best-val at end of fit. |
|
|
@@ -255,6 +273,8 @@ All four inherit from `BaseSpectralClassifier` and share the same hyperparameter
|
|
|
255
273
|
| Temperature scaling | `calibrate_temperature` | One-parameter LBFGS calibration on val logits. |
|
|
256
274
|
| Sharpness-Aware Minimization | `use_sam` + `sam_rho` | Two-pass training, ~2× compute. |
|
|
257
275
|
| Spectral warping | `warping` | Any `Warping`-like sklearn transformer; fitted on train only, applied before standardization. |
|
|
276
|
+
| Per-sample weighting | `sample_weight` (`fit`) | sklearn-style weighted-mean loss; composes with `class_weight` and flows into early stopping, threshold tuning, and temperature scaling. |
|
|
277
|
+
| Warm-start / resume | `warm_start` (`fit`) | Reuse the existing fitted module as the training start point (continual / federated / fine-tuning). |
|
|
258
278
|
|
|
259
279
|
### Utilities
|
|
260
280
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
LICENSE
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
|
+
requirements-all.txt
|
|
4
5
|
requirements-dev.txt
|
|
5
6
|
requirements-docs.txt
|
|
7
|
+
requirements-rdkit.txt
|
|
6
8
|
requirements-uncertainty.txt
|
|
7
9
|
requirements.txt
|
|
8
10
|
MaldiDeepKit.egg-info/PKG-INFO
|
|
@@ -23,10 +25,16 @@ maldideepkit/augment/spectra.py
|
|
|
23
25
|
maldideepkit/base/__init__.py
|
|
24
26
|
maldideepkit/base/classifier.py
|
|
25
27
|
maldideepkit/base/data.py
|
|
28
|
+
maldideepkit/base/dual.py
|
|
26
29
|
maldideepkit/cnn/__init__.py
|
|
27
30
|
maldideepkit/cnn/cnn.py
|
|
31
|
+
maldideepkit/dual_branch/__init__.py
|
|
32
|
+
maldideepkit/dual_branch/_smiles.py
|
|
33
|
+
maldideepkit/dual_branch/classifier.py
|
|
28
34
|
maldideepkit/resnet/__init__.py
|
|
29
35
|
maldideepkit/resnet/resnet.py
|
|
36
|
+
maldideepkit/semisupervised/__init__.py
|
|
37
|
+
maldideepkit/semisupervised/self_training.py
|
|
30
38
|
maldideepkit/transformer/__init__.py
|
|
31
39
|
maldideepkit/transformer/transformer.py
|
|
32
40
|
maldideepkit/uncertainty/__init__.py
|
|
@@ -49,6 +57,7 @@ tests/test_bin_scaling.py
|
|
|
49
57
|
tests/test_blocks.py
|
|
50
58
|
tests/test_calibration.py
|
|
51
59
|
tests/test_cnn.py
|
|
60
|
+
tests/test_dual_branch.py
|
|
52
61
|
tests/test_ensemble.py
|
|
53
62
|
tests/test_loss.py
|
|
54
63
|
tests/test_lr_finder.py
|
|
@@ -56,6 +65,8 @@ tests/test_maldiset_integration.py
|
|
|
56
65
|
tests/test_mlp.py
|
|
57
66
|
tests/test_resnet.py
|
|
58
67
|
tests/test_sam.py
|
|
68
|
+
tests/test_sample_weight.py
|
|
69
|
+
tests/test_self_training.py
|
|
59
70
|
tests/test_sklearn_compat.py
|
|
60
71
|
tests/test_transformer.py
|
|
61
72
|
tests/test_uncertainty.py
|
|
@@ -5,7 +5,11 @@ scikit-learn>=1.3.0
|
|
|
5
5
|
matplotlib>=3.4.0
|
|
6
6
|
torch>=2.0.0
|
|
7
7
|
einops>=0.7.0
|
|
8
|
-
maldiamrkit>=0.
|
|
8
|
+
maldiamrkit>=0.19.0
|
|
9
|
+
|
|
10
|
+
[all]
|
|
11
|
+
rdkit>=2026.3.1
|
|
12
|
+
laplace-torch<1.0,>=0.2
|
|
9
13
|
|
|
10
14
|
[dev]
|
|
11
15
|
pytest>=7.0.0
|
|
@@ -23,5 +27,8 @@ nbsphinx>=0.9.0
|
|
|
23
27
|
ipykernel>=6.0.0
|
|
24
28
|
ipywidgets>=8.0.0
|
|
25
29
|
|
|
30
|
+
[rdkit]
|
|
31
|
+
rdkit>=2026.3.1
|
|
32
|
+
|
|
26
33
|
[uncertainty]
|
|
27
34
|
laplace-torch<1.0,>=0.2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MaldiDeepKit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A catalog of sklearn-compatible deep learning classifiers for MALDI-TOF binned spectra
|
|
5
5
|
Author-email: Ettore Rocchi <ettore.rocchi3@unibo.it>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -30,7 +30,7 @@ Requires-Dist: scikit-learn>=1.3.0
|
|
|
30
30
|
Requires-Dist: matplotlib>=3.4.0
|
|
31
31
|
Requires-Dist: torch>=2.0.0
|
|
32
32
|
Requires-Dist: einops>=0.7.0
|
|
33
|
-
Requires-Dist: maldiamrkit>=0.
|
|
33
|
+
Requires-Dist: maldiamrkit>=0.19.0
|
|
34
34
|
Provides-Extra: dev
|
|
35
35
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
36
36
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -47,6 +47,11 @@ Requires-Dist: ipykernel>=6.0.0; extra == "docs"
|
|
|
47
47
|
Requires-Dist: ipywidgets>=8.0.0; extra == "docs"
|
|
48
48
|
Provides-Extra: uncertainty
|
|
49
49
|
Requires-Dist: laplace-torch<1.0,>=0.2; extra == "uncertainty"
|
|
50
|
+
Provides-Extra: rdkit
|
|
51
|
+
Requires-Dist: rdkit>=2026.3.1; extra == "rdkit"
|
|
52
|
+
Provides-Extra: all
|
|
53
|
+
Requires-Dist: rdkit>=2026.3.1; extra == "all"
|
|
54
|
+
Requires-Dist: laplace-torch<1.0,>=0.2; extra == "all"
|
|
50
55
|
Dynamic: license-file
|
|
51
56
|
|
|
52
57
|
# MaldiDeepKit
|
|
@@ -79,7 +84,7 @@ Dynamic: license-file
|
|
|
79
84
|
<a href="#license">License</a>
|
|
80
85
|
</p>
|
|
81
86
|
|
|
82
|
-
MaldiDeepKit is part of the **MaldiSuite** ecosystem and complements [MaldiAMRKit](https://github.com/EttoreRocchi/MaldiAMRKit) and [MaldiBatchKit](https://github.com/EttoreRocchi/MaldiBatchKit): where MaldiAMRKit handles preprocessing, alignment and AMR-aware evaluation, and MaldiBatchKit harmonises multi-centre spectra, MaldiDeepKit focuses on the *classification* step, providing four PyTorch architectures wrapped in a unified scikit-learn estimator API with defaults calibrated for 6000-bin MALDI-TOF input.
|
|
87
|
+
MaldiDeepKit is part of the **MaldiSuite** ecosystem and complements [MaldiAMRKit](https://github.com/EttoreRocchi/MaldiAMRKit) and [MaldiBatchKit](https://github.com/EttoreRocchi/MaldiBatchKit): where MaldiAMRKit handles preprocessing, alignment and AMR-aware evaluation, and MaldiBatchKit harmonises multi-centre spectra, MaldiDeepKit focuses on the *classification* step, providing four PyTorch backbone architectures (MLP, 1-D CNN, 1-D ResNet, and 1-D Vision Transformer) plus a dual-branch classifier for spectrum + side-feature inputs and a self-training meta-classifier for semi-supervised data, all wrapped in a unified scikit-learn estimator API with defaults calibrated for 6000-bin MALDI-TOF input.
|
|
83
88
|
|
|
84
89
|
## Installation
|
|
85
90
|
|
|
@@ -87,7 +92,7 @@ MaldiDeepKit is part of the **MaldiSuite** ecosystem and complements [MaldiAMRKi
|
|
|
87
92
|
pip install maldideepkit
|
|
88
93
|
```
|
|
89
94
|
|
|
90
|
-
`maldiamrkit` is a core dependency and is installed automatically
|
|
95
|
+
`maldiamrkit` is a core dependency and is installed automatically (MaldiDeepKit duck-types on the `MaldiSet` data model and reuses `maldiamrkit.alignment.Warping` for leak-safe spectral warping).
|
|
91
96
|
|
|
92
97
|
To enable the Laplace-approximation estimator in `maldideepkit.uncertainty`, install the optional `uncertainty` extra (pulls in [`laplace-torch`](https://github.com/aleximmer/Laplace)):
|
|
93
98
|
|
|
@@ -97,6 +102,12 @@ pip install "maldideepkit[uncertainty]"
|
|
|
97
102
|
|
|
98
103
|
Monte Carlo Dropout and split conformal prediction work without any extra.
|
|
99
104
|
|
|
105
|
+
The `smiles_to_fingerprint` helper used in `MaldiDualBranchClassifier` workflows requires RDKit, available via the `rdkit` extra:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
pip install "maldideepkit[rdkit]"
|
|
109
|
+
```
|
|
110
|
+
|
|
100
111
|
### Install the full MaldiSuite
|
|
101
112
|
|
|
102
113
|
To install MaldiDeepKit together with [MaldiAMRKit](https://github.com/EttoreRocchi/MaldiAMRKit) and [MaldiBatchKit](https://github.com/EttoreRocchi/MaldiBatchKit) at compatible versions, install the [`maldisuite`](https://pypi.org/project/maldisuite/) meta-package:
|
|
@@ -128,7 +139,7 @@ See [`CONTRIBUTING.md`](CONTRIBUTING.md) for coding conventions, testing, and PR
|
|
|
128
139
|
- `MaldiTransformerClassifier` - 1-D Vision Transformer with global self-attention, pre-norm, LayerScale, and stochastic depth.
|
|
129
140
|
- **MALDI-TOF defaults**: kernel sizes, depths, patch widths, and warmup / cosine-annealing schedules are tuned for 6000-bin spectra in the 2000-20000 Da range.
|
|
130
141
|
- **Auto-scaling for non-default layouts**: every classifier ships a `from_spectrum(bin_width, input_dim, **overrides)` factory that rescales conv kernels and patches when the user trims the m/z range or picks a different bin width. See the [Spectrum scaling guide](https://maldideepkit.readthedocs.io/en/latest/spectrum_scaling.html).
|
|
131
|
-
- **Training recipes**: AdamW-on-`weight_decay` dispatch, gradient clipping, linear warmup + cosine annealing, focal loss, label smoothing, mixed precision (AMP), Stochastic Weight Averaging, Sharpness-Aware Minimization, post-hoc threshold tuning, and temperature scaling
|
|
142
|
+
- **Training recipes**: AdamW-on-`weight_decay` dispatch, gradient clipping, linear warmup + cosine annealing, focal loss, label smoothing, mixed precision (AMP), Stochastic Weight Averaging, Sharpness-Aware Minimization, post-hoc threshold tuning, and temperature scaling (all exposed as classifier kwargs).
|
|
132
143
|
- **Leak-safe spectral warping**: pass any sklearn-style transformer ([`maldiamrkit.alignment.Warping`](https://github.com/EttoreRocchi/MaldiAMRKit)) via `warping=`; it is fitted on the training fold only and applied to both splits during training and to new spectra at `predict` time, *before* per-feature standardization.
|
|
133
144
|
- **MaldiSet integration**: pass a `maldiamrkit.MaldiSet` directly to `fit` / `predict`; MaldiDeepKit duck-types on the DataFrame-like `.X` attribute, so MaldiSuite's data model flows end-to-end.
|
|
134
145
|
- **Persistence**: `save()` writes a state-dict `.pt` plus a hyperparameter `.json` (and a sibling `.warper.pkl` if a warper was fitted); `load()` fails fast on class or `input_dim` mismatches.
|
|
@@ -236,8 +247,15 @@ For more examples covering training recipes, calibration, attention inspection,
|
|
|
236
247
|
| `MaldiCNNClassifier` | 1-D Conv1D + BatchNorm + ReLU + MaxPool blocks | Local pattern learning from binned spectra |
|
|
237
248
|
| `MaldiResNetClassifier` | 1-D ResNet-18-style residual blocks | Deeper convolutional backbone |
|
|
238
249
|
| `MaldiTransformerClassifier` | 1-D Vision Transformer (LayerScale, stochastic depth) | Long-range peak combinations via global self-attention |
|
|
250
|
+
| `MaldiDualBranchClassifier` | Spectrum branch + per-row side-feature branch + fused head | Multi-modal: condition on antibiotic fingerprint, instrument ID, patient feature, ... |
|
|
251
|
+
|
|
252
|
+
All five inherit from `BaseSpectralClassifier` (or its dual-input subclass `BaseDualSpectralClassifier`) and share the same hyperparameter surface for optimisation, device placement, early stopping, calibration, and persistence.
|
|
253
|
+
|
|
254
|
+
### Semi-supervised wrapper
|
|
239
255
|
|
|
240
|
-
|
|
256
|
+
| Class | Purpose |
|
|
257
|
+
|---|---|
|
|
258
|
+
| `MaldiSelfTrainingClassifier` | Iterative pseudo-labeling on a labeled seed plus an unlabeled pool (rows marked `-1` by default). Wraps any classifier (defaults to `MaldiMLPClassifier`); follows the `sklearn.semi_supervised.SelfTrainingClassifier` API. |
|
|
241
259
|
|
|
242
260
|
### Shared Training Knobs
|
|
243
261
|
|
|
@@ -247,7 +265,7 @@ All four inherit from `BaseSpectralClassifier` and share the same hyperparameter
|
|
|
247
265
|
| Gradient clipping | `grad_clip_norm` | `clip_grad_norm_` before every step. Default on (`1.0`) for the deep models. |
|
|
248
266
|
| Warmup + cosine annealing | `warmup_epochs` | Replaces plateau scheduler. Default `5` (deep models), `0` (MLP/CNN). |
|
|
249
267
|
| Stochastic depth (Transformer) | `drop_path_rate` | Linearly ramped across blocks. Default `0.1`. |
|
|
250
|
-
| LayerScale (Transformer) | `layerscale_init` | Per-channel residual scaling initialised near zero
|
|
268
|
+
| LayerScale (Transformer) | `layerscale_init` | Per-channel residual scaling initialised near zero (crucial on small cohorts). |
|
|
251
269
|
| Focal loss | `loss="focal"` + `focal_gamma` | For imbalanced binary problems. |
|
|
252
270
|
| Label smoothing | `label_smoothing` | Passed to both cross-entropy and focal paths. |
|
|
253
271
|
| Stochastic Weight Averaging | `swa_start_epoch` | `AveragedModel` replaces best-val at end of fit. |
|
|
@@ -255,6 +273,8 @@ All four inherit from `BaseSpectralClassifier` and share the same hyperparameter
|
|
|
255
273
|
| Temperature scaling | `calibrate_temperature` | One-parameter LBFGS calibration on val logits. |
|
|
256
274
|
| Sharpness-Aware Minimization | `use_sam` + `sam_rho` | Two-pass training, ~2× compute. |
|
|
257
275
|
| Spectral warping | `warping` | Any `Warping`-like sklearn transformer; fitted on train only, applied before standardization. |
|
|
276
|
+
| Per-sample weighting | `sample_weight` (`fit`) | sklearn-style weighted-mean loss; composes with `class_weight` and flows into early stopping, threshold tuning, and temperature scaling. |
|
|
277
|
+
| Warm-start / resume | `warm_start` (`fit`) | Reuse the existing fitted module as the training start point (continual / federated / fine-tuning). |
|
|
258
278
|
|
|
259
279
|
### Utilities
|
|
260
280
|
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<a href="#license">License</a>
|
|
29
29
|
</p>
|
|
30
30
|
|
|
31
|
-
MaldiDeepKit is part of the **MaldiSuite** ecosystem and complements [MaldiAMRKit](https://github.com/EttoreRocchi/MaldiAMRKit) and [MaldiBatchKit](https://github.com/EttoreRocchi/MaldiBatchKit): where MaldiAMRKit handles preprocessing, alignment and AMR-aware evaluation, and MaldiBatchKit harmonises multi-centre spectra, MaldiDeepKit focuses on the *classification* step, providing four PyTorch architectures wrapped in a unified scikit-learn estimator API with defaults calibrated for 6000-bin MALDI-TOF input.
|
|
31
|
+
MaldiDeepKit is part of the **MaldiSuite** ecosystem and complements [MaldiAMRKit](https://github.com/EttoreRocchi/MaldiAMRKit) and [MaldiBatchKit](https://github.com/EttoreRocchi/MaldiBatchKit): where MaldiAMRKit handles preprocessing, alignment and AMR-aware evaluation, and MaldiBatchKit harmonises multi-centre spectra, MaldiDeepKit focuses on the *classification* step, providing four PyTorch backbone architectures (MLP, 1-D CNN, 1-D ResNet, and 1-D Vision Transformer) plus a dual-branch classifier for spectrum + side-feature inputs and a self-training meta-classifier for semi-supervised data, all wrapped in a unified scikit-learn estimator API with defaults calibrated for 6000-bin MALDI-TOF input.
|
|
32
32
|
|
|
33
33
|
## Installation
|
|
34
34
|
|
|
@@ -36,7 +36,7 @@ MaldiDeepKit is part of the **MaldiSuite** ecosystem and complements [MaldiAMRKi
|
|
|
36
36
|
pip install maldideepkit
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
`maldiamrkit` is a core dependency and is installed automatically
|
|
39
|
+
`maldiamrkit` is a core dependency and is installed automatically (MaldiDeepKit duck-types on the `MaldiSet` data model and reuses `maldiamrkit.alignment.Warping` for leak-safe spectral warping).
|
|
40
40
|
|
|
41
41
|
To enable the Laplace-approximation estimator in `maldideepkit.uncertainty`, install the optional `uncertainty` extra (pulls in [`laplace-torch`](https://github.com/aleximmer/Laplace)):
|
|
42
42
|
|
|
@@ -46,6 +46,12 @@ pip install "maldideepkit[uncertainty]"
|
|
|
46
46
|
|
|
47
47
|
Monte Carlo Dropout and split conformal prediction work without any extra.
|
|
48
48
|
|
|
49
|
+
The `smiles_to_fingerprint` helper used in `MaldiDualBranchClassifier` workflows requires RDKit, available via the `rdkit` extra:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install "maldideepkit[rdkit]"
|
|
53
|
+
```
|
|
54
|
+
|
|
49
55
|
### Install the full MaldiSuite
|
|
50
56
|
|
|
51
57
|
To install MaldiDeepKit together with [MaldiAMRKit](https://github.com/EttoreRocchi/MaldiAMRKit) and [MaldiBatchKit](https://github.com/EttoreRocchi/MaldiBatchKit) at compatible versions, install the [`maldisuite`](https://pypi.org/project/maldisuite/) meta-package:
|
|
@@ -77,7 +83,7 @@ See [`CONTRIBUTING.md`](CONTRIBUTING.md) for coding conventions, testing, and PR
|
|
|
77
83
|
- `MaldiTransformerClassifier` - 1-D Vision Transformer with global self-attention, pre-norm, LayerScale, and stochastic depth.
|
|
78
84
|
- **MALDI-TOF defaults**: kernel sizes, depths, patch widths, and warmup / cosine-annealing schedules are tuned for 6000-bin spectra in the 2000-20000 Da range.
|
|
79
85
|
- **Auto-scaling for non-default layouts**: every classifier ships a `from_spectrum(bin_width, input_dim, **overrides)` factory that rescales conv kernels and patches when the user trims the m/z range or picks a different bin width. See the [Spectrum scaling guide](https://maldideepkit.readthedocs.io/en/latest/spectrum_scaling.html).
|
|
80
|
-
- **Training recipes**: AdamW-on-`weight_decay` dispatch, gradient clipping, linear warmup + cosine annealing, focal loss, label smoothing, mixed precision (AMP), Stochastic Weight Averaging, Sharpness-Aware Minimization, post-hoc threshold tuning, and temperature scaling
|
|
86
|
+
- **Training recipes**: AdamW-on-`weight_decay` dispatch, gradient clipping, linear warmup + cosine annealing, focal loss, label smoothing, mixed precision (AMP), Stochastic Weight Averaging, Sharpness-Aware Minimization, post-hoc threshold tuning, and temperature scaling (all exposed as classifier kwargs).
|
|
81
87
|
- **Leak-safe spectral warping**: pass any sklearn-style transformer ([`maldiamrkit.alignment.Warping`](https://github.com/EttoreRocchi/MaldiAMRKit)) via `warping=`; it is fitted on the training fold only and applied to both splits during training and to new spectra at `predict` time, *before* per-feature standardization.
|
|
82
88
|
- **MaldiSet integration**: pass a `maldiamrkit.MaldiSet` directly to `fit` / `predict`; MaldiDeepKit duck-types on the DataFrame-like `.X` attribute, so MaldiSuite's data model flows end-to-end.
|
|
83
89
|
- **Persistence**: `save()` writes a state-dict `.pt` plus a hyperparameter `.json` (and a sibling `.warper.pkl` if a warper was fitted); `load()` fails fast on class or `input_dim` mismatches.
|
|
@@ -185,8 +191,15 @@ For more examples covering training recipes, calibration, attention inspection,
|
|
|
185
191
|
| `MaldiCNNClassifier` | 1-D Conv1D + BatchNorm + ReLU + MaxPool blocks | Local pattern learning from binned spectra |
|
|
186
192
|
| `MaldiResNetClassifier` | 1-D ResNet-18-style residual blocks | Deeper convolutional backbone |
|
|
187
193
|
| `MaldiTransformerClassifier` | 1-D Vision Transformer (LayerScale, stochastic depth) | Long-range peak combinations via global self-attention |
|
|
194
|
+
| `MaldiDualBranchClassifier` | Spectrum branch + per-row side-feature branch + fused head | Multi-modal: condition on antibiotic fingerprint, instrument ID, patient feature, ... |
|
|
195
|
+
|
|
196
|
+
All five inherit from `BaseSpectralClassifier` (or its dual-input subclass `BaseDualSpectralClassifier`) and share the same hyperparameter surface for optimisation, device placement, early stopping, calibration, and persistence.
|
|
197
|
+
|
|
198
|
+
### Semi-supervised wrapper
|
|
188
199
|
|
|
189
|
-
|
|
200
|
+
| Class | Purpose |
|
|
201
|
+
|---|---|
|
|
202
|
+
| `MaldiSelfTrainingClassifier` | Iterative pseudo-labeling on a labeled seed plus an unlabeled pool (rows marked `-1` by default). Wraps any classifier (defaults to `MaldiMLPClassifier`); follows the `sklearn.semi_supervised.SelfTrainingClassifier` API. |
|
|
190
203
|
|
|
191
204
|
### Shared Training Knobs
|
|
192
205
|
|
|
@@ -196,7 +209,7 @@ All four inherit from `BaseSpectralClassifier` and share the same hyperparameter
|
|
|
196
209
|
| Gradient clipping | `grad_clip_norm` | `clip_grad_norm_` before every step. Default on (`1.0`) for the deep models. |
|
|
197
210
|
| Warmup + cosine annealing | `warmup_epochs` | Replaces plateau scheduler. Default `5` (deep models), `0` (MLP/CNN). |
|
|
198
211
|
| Stochastic depth (Transformer) | `drop_path_rate` | Linearly ramped across blocks. Default `0.1`. |
|
|
199
|
-
| LayerScale (Transformer) | `layerscale_init` | Per-channel residual scaling initialised near zero
|
|
212
|
+
| LayerScale (Transformer) | `layerscale_init` | Per-channel residual scaling initialised near zero (crucial on small cohorts). |
|
|
200
213
|
| Focal loss | `loss="focal"` + `focal_gamma` | For imbalanced binary problems. |
|
|
201
214
|
| Label smoothing | `label_smoothing` | Passed to both cross-entropy and focal paths. |
|
|
202
215
|
| Stochastic Weight Averaging | `swa_start_epoch` | `AveragedModel` replaces best-val at end of fit. |
|
|
@@ -204,6 +217,8 @@ All four inherit from `BaseSpectralClassifier` and share the same hyperparameter
|
|
|
204
217
|
| Temperature scaling | `calibrate_temperature` | One-parameter LBFGS calibration on val logits. |
|
|
205
218
|
| Sharpness-Aware Minimization | `use_sam` + `sam_rho` | Two-pass training, ~2× compute. |
|
|
206
219
|
| Spectral warping | `warping` | Any `Warping`-like sklearn transformer; fitted on train only, applied before standardization. |
|
|
220
|
+
| Per-sample weighting | `sample_weight` (`fit`) | sklearn-style weighted-mean loss; composes with `class_weight` and flows into early stopping, threshold tuning, and temperature scaling. |
|
|
221
|
+
| Warm-start / resume | `warm_start` (`fit`) | Reuse the existing fitted module as the training start point (continual / federated / fine-tuning). |
|
|
207
222
|
|
|
208
223
|
### Utilities
|
|
209
224
|
|
|
@@ -6,16 +6,23 @@ a scikit-learn compatible estimator with sensible defaults.
|
|
|
6
6
|
|
|
7
7
|
Subpackages
|
|
8
8
|
-----------
|
|
9
|
-
- ``maldideepkit.base`` - ``BaseSpectralClassifier``,
|
|
10
|
-
``make_loaders``.
|
|
9
|
+
- ``maldideepkit.base`` - ``BaseSpectralClassifier``,
|
|
10
|
+
``BaseDualSpectralClassifier``, ``SpectralDataset``, ``make_loaders``.
|
|
11
11
|
- ``maldideepkit.attention`` - ``MaldiMLPClassifier`` (MLP with optional
|
|
12
12
|
sigmoid-gated attention).
|
|
13
13
|
- ``maldideepkit.cnn`` - ``MaldiCNNClassifier`` (Conv1D blocks).
|
|
14
14
|
- ``maldideepkit.resnet`` - ``MaldiResNetClassifier`` (1-D ResNet-18).
|
|
15
15
|
- ``maldideepkit.transformer`` - ``MaldiTransformerClassifier`` (1-D ViT).
|
|
16
|
+
- ``maldideepkit.dual_branch`` - ``MaldiDualBranchClassifier``
|
|
17
|
+
(spectrum + per-row side feature) and ``smiles_to_fingerprint``
|
|
18
|
+
helper (requires the ``[rdkit]`` extra).
|
|
19
|
+
- ``maldideepkit.semisupervised`` - ``MaldiSelfTrainingClassifier``
|
|
20
|
+
(iterative pseudo-labeling meta-classifier).
|
|
16
21
|
- ``maldideepkit.blocks`` - re-exports of every backbone and
|
|
17
22
|
composable primitive for users embedding components into their own
|
|
18
23
|
networks.
|
|
24
|
+
- ``maldideepkit.augment`` - per-batch training-time augmentations
|
|
25
|
+
(``SpectrumAugment``, MixUp / CutMix helpers).
|
|
19
26
|
- ``maldideepkit.utils`` - reproducibility helpers and shared
|
|
20
27
|
training primitives.
|
|
21
28
|
- ``maldideepkit.uncertainty`` - uncertainty-quantification
|
|
@@ -38,22 +45,29 @@ from . import uncertainty
|
|
|
38
45
|
from .attention.mlp import MaldiMLPClassifier
|
|
39
46
|
from .base.classifier import BaseSpectralClassifier
|
|
40
47
|
from .base.data import SpectralDataset, make_loaders
|
|
48
|
+
from .base.dual import BaseDualSpectralClassifier
|
|
41
49
|
from .cnn.cnn import MaldiCNNClassifier
|
|
50
|
+
from .dual_branch import MaldiDualBranchClassifier, smiles_to_fingerprint
|
|
42
51
|
from .resnet.resnet import MaldiResNetClassifier
|
|
52
|
+
from .semisupervised import MaldiSelfTrainingClassifier
|
|
43
53
|
from .transformer.transformer import MaldiTransformerClassifier
|
|
44
54
|
|
|
45
|
-
__version__ = "0.
|
|
55
|
+
__version__ = "0.3.0"
|
|
46
56
|
__author__ = "Ettore Rocchi"
|
|
47
57
|
|
|
48
58
|
__all__ = [
|
|
59
|
+
"BaseDualSpectralClassifier",
|
|
49
60
|
"BaseSpectralClassifier",
|
|
50
61
|
"MaldiCNNClassifier",
|
|
62
|
+
"MaldiDualBranchClassifier",
|
|
51
63
|
"MaldiMLPClassifier",
|
|
52
64
|
"MaldiResNetClassifier",
|
|
65
|
+
"MaldiSelfTrainingClassifier",
|
|
53
66
|
"MaldiTransformerClassifier",
|
|
54
67
|
"SpectralDataset",
|
|
55
68
|
"__author__",
|
|
56
69
|
"__version__",
|
|
57
70
|
"make_loaders",
|
|
71
|
+
"smiles_to_fingerprint",
|
|
58
72
|
"uncertainty",
|
|
59
73
|
]
|
|
@@ -261,13 +261,19 @@ class MaldiMLPClassifier(BaseSpectralClassifier):
|
|
|
261
261
|
return logits
|
|
262
262
|
|
|
263
263
|
def fit( # type: ignore[override]
|
|
264
|
-
self,
|
|
264
|
+
self,
|
|
265
|
+
X: Any,
|
|
266
|
+
y: Any,
|
|
267
|
+
*,
|
|
268
|
+
sample_weight: Any | None = None,
|
|
269
|
+
warm_start: bool = False,
|
|
265
270
|
) -> MaldiMLPClassifier:
|
|
266
271
|
"""Fit the model and cache attention weights from the final batch.
|
|
267
272
|
|
|
268
|
-
See :meth:`BaseSpectralClassifier.fit` for shared parameters,
|
|
273
|
+
See :meth:`BaseSpectralClassifier.fit` for shared parameters,
|
|
274
|
+
including ``sample_weight`` and ``warm_start``.
|
|
269
275
|
"""
|
|
270
|
-
super().fit(X, y, warm_start=warm_start)
|
|
276
|
+
super().fit(X, y, sample_weight=sample_weight, warm_start=warm_start)
|
|
271
277
|
if self.use_attention:
|
|
272
278
|
X_np = _to_numpy(X)
|
|
273
279
|
tail = X_np[: min(len(X_np), 64)]
|
|
@@ -38,7 +38,11 @@ def apply_mixup(
|
|
|
38
38
|
y_oh: torch.Tensor,
|
|
39
39
|
alpha: float,
|
|
40
40
|
generator: torch.Generator | None = None,
|
|
41
|
-
|
|
41
|
+
*,
|
|
42
|
+
sample_weight: torch.Tensor | None = None,
|
|
43
|
+
) -> (
|
|
44
|
+
tuple[torch.Tensor, torch.Tensor] | tuple[torch.Tensor, torch.Tensor, torch.Tensor]
|
|
45
|
+
):
|
|
42
46
|
"""Mixup: convex-combine two random permutations of the batch.
|
|
43
47
|
|
|
44
48
|
Parameters
|
|
@@ -52,11 +56,19 @@ def apply_mixup(
|
|
|
52
56
|
values 0.1-0.4 for tabular-ish inputs. Must be ``> 0``.
|
|
53
57
|
generator : torch.Generator or None, default=None
|
|
54
58
|
Seeded RNG for reproducibility.
|
|
59
|
+
sample_weight : torch.Tensor or None, keyword-only, default=None
|
|
60
|
+
Optional per-sample weight tensor of shape ``(batch,)``. When
|
|
61
|
+
given, the function returns a 3-tuple whose third element is
|
|
62
|
+
``lam * sample_weight + (1 - lam) * sample_weight[perm]`` (the
|
|
63
|
+
same convex combination applied to ``y_oh``). When ``None``
|
|
64
|
+
the function returns a 2-tuple for backward compatibility.
|
|
55
65
|
|
|
56
66
|
Returns
|
|
57
67
|
-------
|
|
58
68
|
tuple of torch.Tensor
|
|
59
|
-
``(x_mixed, y_mixed)``
|
|
69
|
+
``(x_mixed, y_mixed)`` or ``(x_mixed, y_mixed, sw_mixed)``
|
|
70
|
+
when ``sample_weight`` is provided. ``x_mixed`` and ``y_mixed``
|
|
71
|
+
have the same shape as the inputs.
|
|
60
72
|
"""
|
|
61
73
|
if alpha <= 0:
|
|
62
74
|
raise ValueError(f"mixup alpha must be > 0; got {alpha!r}.")
|
|
@@ -64,7 +76,11 @@ def apply_mixup(
|
|
|
64
76
|
perm = torch.randperm(x.shape[0], generator=generator).to(x.device)
|
|
65
77
|
x_mixed = lam * x + (1.0 - lam) * x[perm]
|
|
66
78
|
y_mixed = lam * y_oh + (1.0 - lam) * y_oh[perm]
|
|
67
|
-
|
|
79
|
+
if sample_weight is None:
|
|
80
|
+
return x_mixed, y_mixed
|
|
81
|
+
sw = sample_weight.to(device=x.device)
|
|
82
|
+
sw_mixed = lam * sw + (1.0 - lam) * sw[perm]
|
|
83
|
+
return x_mixed, y_mixed, sw_mixed
|
|
68
84
|
|
|
69
85
|
|
|
70
86
|
def apply_cutmix(
|
|
@@ -72,7 +88,12 @@ def apply_cutmix(
|
|
|
72
88
|
y_oh: torch.Tensor,
|
|
73
89
|
alpha: float,
|
|
74
90
|
generator: torch.Generator | None = None,
|
|
75
|
-
|
|
91
|
+
*,
|
|
92
|
+
sample_weight: torch.Tensor | None = None,
|
|
93
|
+
n_spec_cols: int | None = None,
|
|
94
|
+
) -> (
|
|
95
|
+
tuple[torch.Tensor, torch.Tensor] | tuple[torch.Tensor, torch.Tensor, torch.Tensor]
|
|
96
|
+
):
|
|
76
97
|
"""CutMix on 1-D spectra: splice a contiguous m/z window.
|
|
77
98
|
|
|
78
99
|
A window of length ``w = round(n_bins * (1 - lam))`` is drawn
|
|
@@ -90,24 +111,55 @@ def apply_cutmix(
|
|
|
90
111
|
value 1.0 (uniform over window fractions). Must be ``> 0``.
|
|
91
112
|
generator : torch.Generator or None, default=None
|
|
92
113
|
Seeded RNG for reproducibility.
|
|
114
|
+
n_spec_cols : int or None, keyword-only, default=None
|
|
115
|
+
Number of leading spectrum columns. When given (dual-input
|
|
116
|
+
models, where ``x`` is ``[ X_spec | X_side ]``), the spliced
|
|
117
|
+
window is drawn **inside the spectrum block only** and the
|
|
118
|
+
window fraction is taken relative to ``n_spec_cols`` rather
|
|
119
|
+
than the full width. The trailing side columns are instead
|
|
120
|
+
convex-combined with the same ``effective_lam`` and the same
|
|
121
|
+
permutation, so a contiguous m/z window never straddles the
|
|
122
|
+
spectrum / side boundary and ``(x, y)`` stay consistent.
|
|
123
|
+
``None`` treats every column as spectrum.
|
|
124
|
+
sample_weight : torch.Tensor or None, keyword-only, default=None
|
|
125
|
+
Optional per-sample weight tensor of shape ``(batch,)``. When
|
|
126
|
+
given, the function returns a 3-tuple whose third element is
|
|
127
|
+
``effective_lam * sample_weight + (1 - effective_lam) *
|
|
128
|
+
sample_weight[perm]`` (matching how labels are mixed). When
|
|
129
|
+
``None`` the function returns a 2-tuple for backward
|
|
130
|
+
compatibility.
|
|
93
131
|
|
|
94
132
|
Returns
|
|
95
133
|
-------
|
|
96
134
|
tuple of torch.Tensor
|
|
97
|
-
``(x_mixed, y_mixed)``
|
|
135
|
+
``(x_mixed, y_mixed)`` or ``(x_mixed, y_mixed, sw_mixed)``
|
|
136
|
+
when ``sample_weight`` is provided.
|
|
98
137
|
"""
|
|
99
138
|
if alpha <= 0:
|
|
100
139
|
raise ValueError(f"cutmix alpha must be > 0; got {alpha!r}.")
|
|
101
140
|
batch, n_bins = x.shape
|
|
141
|
+
n_cut = n_bins if n_spec_cols is None else min(int(n_spec_cols), n_bins)
|
|
142
|
+
if n_cut <= 0:
|
|
143
|
+
raise ValueError(f"n_spec_cols must be > 0; got {n_spec_cols!r}.")
|
|
102
144
|
lam = _sample_beta(alpha, generator)
|
|
103
|
-
window = int(round(
|
|
104
|
-
window = max(0, min(window,
|
|
145
|
+
window = int(round(n_cut * (1.0 - lam)))
|
|
146
|
+
window = max(0, min(window, n_cut))
|
|
105
147
|
if window == 0:
|
|
106
|
-
|
|
107
|
-
|
|
148
|
+
if sample_weight is None:
|
|
149
|
+
return x.clone(), y_oh.clone()
|
|
150
|
+
return x.clone(), y_oh.clone(), sample_weight.to(device=x.device).clone()
|
|
151
|
+
start = int(torch.randint(0, n_cut - window + 1, (1,), generator=generator).item())
|
|
108
152
|
perm = torch.randperm(batch, generator=generator).to(x.device)
|
|
109
153
|
x_mixed = x.clone()
|
|
110
154
|
x_mixed[:, start : start + window] = x[perm][:, start : start + window]
|
|
111
|
-
effective_lam = 1.0 - window /
|
|
155
|
+
effective_lam = 1.0 - window / n_cut
|
|
156
|
+
if n_cut < n_bins:
|
|
157
|
+
x_mixed[:, n_cut:] = (
|
|
158
|
+
effective_lam * x[:, n_cut:] + (1.0 - effective_lam) * x[perm][:, n_cut:]
|
|
159
|
+
)
|
|
112
160
|
y_mixed = effective_lam * y_oh + (1.0 - effective_lam) * y_oh[perm]
|
|
113
|
-
|
|
161
|
+
if sample_weight is None:
|
|
162
|
+
return x_mixed, y_mixed
|
|
163
|
+
sw = sample_weight.to(device=x.device)
|
|
164
|
+
sw_mixed = effective_lam * sw + (1.0 - effective_lam) * sw[perm]
|
|
165
|
+
return x_mixed, y_mixed, sw_mixed
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Shared primitives for MaldiDeepKit classifiers.
|
|
2
|
+
|
|
3
|
+
Exposes:
|
|
4
|
+
|
|
5
|
+
- :class:`BaseSpectralClassifier` - abstract base for the four
|
|
6
|
+
single-input classifier families (MLP, CNN, ResNet, Transformer).
|
|
7
|
+
- :class:`BaseDualSpectralClassifier` - abstract base for dual-input
|
|
8
|
+
classifiers (e.g. spectrum + antibiotic fingerprint); the side
|
|
9
|
+
input is packed into ``X`` by concatenation to stay
|
|
10
|
+
sklearn-pipeline-friendly.
|
|
11
|
+
- :class:`SpectralDataset` / :func:`make_loaders` - data utilities.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .classifier import BaseSpectralClassifier
|
|
15
|
+
from .data import SpectralDataset, make_loaders
|
|
16
|
+
from .dual import BaseDualSpectralClassifier
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"BaseDualSpectralClassifier",
|
|
20
|
+
"BaseSpectralClassifier",
|
|
21
|
+
"SpectralDataset",
|
|
22
|
+
"make_loaders",
|
|
23
|
+
]
|