EMR (Extended Mass Range) Binary Classifier (5-model ensemble)
A 1D-CNN ensemble that flags Extended Mass Range (EMR) events in Cassini CDA TOF mass spectra, in the high-mass region, and ranks the full unlabelled pool by EMR-likeness. Because it was trained on only 34 known EMR positives, it is an expert triage / ranking model: sort unknown spectra by the ensemble probability and manually review the top candidates.
Task & data
- Formulation: binary classification β EMR (class 1) vs. unlabelled background (class 0).
- Positives: 34 known EMR spectra. Negative pool: 130,233 spectra, of which 1,000
are subsampled for training (fixed
data_seed=42), giving ~30:1 imbalance. - Input: the spectrum cropped to channels 700-1017 (318 bins), then min-max normalised
to
[0,1]per spectrum. That is the only transform.
Architecture
Shallow 1D CNN (same architecture as the HMOC classifier; kept small to avoid overfitting 34 positives):
Conv1d(1->32, k=7, p=3) + BN + ReLU
Conv1d(32->64, k=5, p=2) + BN + ReLU
Conv1d(64->128, k=3, p=1) + BN + ReLU
AdaptiveAvgPool1d(1)
Linear(128->64) + ReLU + Dropout(0.4)
Linear(64->1) -> sigmoid
Ensemble
Five independent models, one per StratifiedKFold fold, trained with seeds
[42, 100, 2026, 777, 888]. At inference the mean of the 5 sigmoid outputs is the final
EMR probability.
Training
- Loss: Focal Loss (
alpha=0.85,gamma=2.0). - Optimizer: AdamW (
lr=1e-3,weight_decay=1e-4),batch_size=64. - Batches:
WeightedRandomSamplerby inverse class frequency. - Early stopping on validation AUPRC (
patience=15); best-F1 threshold scanned per fold.
Metrics (per seed, validation fold)
| Seed | AUPRC | Precision | Recall | F1 | Best threshold |
|---|---|---|---|---|---|
| 42 | 0.938 | 1.000 | 0.857 | 0.923 | 0.75 |
| 100 | 1.000 | 0.875 | 1.000 | 0.933 | 0.60 |
| 2026 | 0.860 | 0.857 | 0.857 | 0.857 | 0.50 |
| 777 | 0.981 | 1.000 | 0.714 | 0.833 | 0.80 |
| 888 | 0.878 | 0.545 | 1.000 | 0.706 | 0.75 |
Inference over the full 130,233 pool (ensemble mean)
- Probability distribution: mean 0.0457, p50 0.0015, p99 0.6915, max 0.9025.
- Candidates: 4,837 β₯ 0.5 Β· 749 β₯ 0.75 Β· 1 β₯ 0.9 (top: sclk
1561703929, prob 0.9025). - Leakage audit (clean): 0 positive SCLKs appear in the inference pool; 0/100 top candidates were training negatives.
Usage
import numpy as np
from model import predict_ensemble, SEEDS, default_weights_dir
d = default_weights_dir()
paths = [f"{d}/emr_model_seed_{s}.pth" for s in SEEDS]
raw_spectra = [...] # list of FULL raw spectra (1-D arrays); cropped to 700-1017 internally
probs = predict_ensemble(paths, raw_spectra) # -> np.ndarray of EMR probabilities
# or, if you already have the 318-bin cropped region:
# probs = predict_ensemble(paths, cropped_spectra, already_cropped=True)
order = np.argsort(probs)[::-1]
top = [(raw_spectra[i], float(probs[i])) for i in order[:100]] # ranked triage list
Single-model variant:
from model import load_model
net = load_model(f"{d}/emr_model_seed_100.pth")
Files
| Path | Contents |
|---|---|
model.py |
Self-contained architecture, 700β1017 crop, preprocessing and ensemble inference |
config.json |
Architecture, training hyperparameters, per-seed metrics/thresholds |
metrics.json |
Per-fold validation metrics |
emr_model_seed_{42,100,2026,777,888}.pth |
model.state_dict() for each seed |
scripts/train_emr_classifier.py |
5-fold training of the ensemble |
scripts/crop_unknown_data.py |
Crops the unlabelled pool to channels 700β1017 |
scripts/infer_unknown.py |
Scores the 130,233-spectrum pool with the ensemble |
scripts/check_leakage.py |
Leakage audit between training data and the inference pool |
predictions/emr_top100.csv |
Top 100 EMR candidates (original_parquet_index, sclk, emr_probability) |
predictions/emr_candidates_unknown.csv |
EMR probability for every spectrum in the pool |
predictions/leakage_report.json |
Output of the leakage audit |
docs/ML_summary.md |
Write-up of the approach and results |
The scripts keep their original layout: they resolve paths from the workspace root that held EMR Classifier/ and Data Parquet/, so adjust ROOT / the path constants at the top of each script before rerunning. The data itself is not included.
Caveats
Trained on only 34 positives β this is a ranked triage list, not a definitive classifier. Validate top candidates before treating them as confirmed EMR events.
License
No open-source license is provided for these weights; all rights reserved. Do not reuse, redistribute, or build upon this model without the author's permission.
- Downloads last month
- 20