Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ce757d5
separate ensemble from base learner predictions, generalise both ense…
sfluegel05 Jul 28, 2026
4a167f9
remove chebi_graph builder (now done via chebi_utils library)
sfluegel05 Jul 29, 2026
b26ba7c
update CLI and integrate MV ensemble into new workflow
sfluegel05 Jul 29, 2026
8b48598
bug fixes and optimized performance for aggregation
sfluegel05 Jul 30, 2026
deb681a
integrate wmv-f1 ensemble into new workflow
sfluegel05 Jul 30, 2026
fbafc8e
optimize prediction storage
sfluegel05 Jul 30, 2026
ea8177b
add hyperparameter optimization for WMV-F1
sfluegel05 Jul 30, 2026
844768a
apply optimized hyperparameters if available
sfluegel05 Jul 30, 2026
4ea20f6
fix handling of missing predictions
sfluegel05 Aug 3, 2026
32e14a1
use chebi_utils SMILES / InChI parsing
sfluegel05 Aug 3, 2026
4334525
add DES and LTR ensembles, major fixes to voting ensemble (rescaled c…
sfluegel05 Aug 6, 2026
ea3afb1
add HEX and ILR inconsistency resolution methods, evaluate multiple e…
sfluegel05 Aug 7, 2026
8ec5a1c
more options for LTR / DES, normalize aggregation outputs
sfluegel05 Aug 11, 2026
8911830
ensemble output is now set to [0,1] range, same for inconsistency res…
sfluegel05 Aug 11, 2026
c43cb83
update symbolic classifiers
sfluegel05 Aug 11, 2026
17c72d1
add bounded HEX algorithm and add collect-classes step for ensemble c…
sfluegel05 Aug 12, 2026
a371097
various bug fixes and optimizations
sfluegel05 Aug 13, 2026
c70d92f
inconsistency resolution fixes and remove legacy methods
sfluegel05 Aug 16, 2026
a2c21f4
add attribution for wmv-f1 + score-based
sfluegel05 Aug 18, 2026
6e0b03f
move ChEBI lookup to inchikeys, fix C3P for inchi inputs
sfluegel05 Aug 31, 2026
620444b
add extra weights for WMV-F1
sfluegel05 Aug 31, 2026
9c1a1f8
use Huggingface to download models / configs automatically, update RE…
sfluegel05 Aug 31, 2026
b7360ea
update pyproject.toml
sfluegel05 Aug 31, 2026
e4a3f72
Merge branch 'dev' into feature/ensemble-08-26
sfluegel05 Aug 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 232 additions & 39 deletions README.md

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions chebifier/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
# even if multiple subpackages are imported later.

from ._custom_cache import PerSmilesPerModelLRUCache, modelwise_smiles_lru_cache
from .ensemble.base_ensemble import BaseEnsemble
from .ensemble.voting_ensemble import (
MajorityVotingEnsemble,
VotingEnsemble,
WMVwithConfidenceEnsemble,
)

__all__ = [
"BaseEnsemble",
"VotingEnsemble",
"MajorityVotingEnsemble",
"WMVwithConfidenceEnsemble",
"PerSmilesPerModelLRUCache",
"modelwise_smiles_lru_cache",
]
85 changes: 85 additions & 0 deletions chebifier/build_ensemble.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import os

import torch

from chebifier.predict import (
base_learner_cache_path,
collect_base_learner_predictions,
load_dense_predictions,
save_dense_predictions,
)


class EnsembleBuilder:
"""
A class to build an ensemble model from base learners and validation data.

Attributes:
base_learners (dict[str, BasePredictor]): A dictionary of base learner models.
ensemble_model (BaseEnsemble): An instance of a BaseEnsemble model.
validation_data (list[Chem.Mol]): Validation data for calibration.
validation_labels (pd.DataFrame): Validation labels for calibration, one column per class.
The column names define the label set the base learner predictions are mapped onto.
prediction_cache_dir (str): Directory to cache predictions.
"""

def __init__(
self,
base_learners,
ensemble_model,
validation_data,
validation_labels,
prediction_cache_dir,
):
self.base_learners = base_learners
self.ensemble_model = ensemble_model
self.validation_data = validation_data
self.validation_labels = validation_labels
self.prediction_cache_dir = prediction_cache_dir
os.makedirs(self.prediction_cache_dir, exist_ok=True)

def build_ensemble(self):
"""
Build an ensemble model from base learners and validation data.

Base learner predictions are cached to avoid recomputation.
"""

# Step 1: Get predictions from base learners on validation data
validation_predictions = {}
classes = {}
# get cached predictions if available, otherwise compute and cache them
for model_name, model in self.base_learners.items():
cache_path = base_learner_cache_path(
self.prediction_cache_dir, model_name, "validation"
)
if os.path.exists(cache_path):
print(f"{model_name} validation predictions found in cache, loading...")
validation_predictions[model_name] = load_dense_predictions(cache_path)
else:
print(f"Computing {model_name} validation predictions...")
validation_predictions[model_name] = model.predict_dense(
self.validation_data
)
save_dense_predictions(cache_path, *validation_predictions[model_name])

# Base learners may be trained on different label sets (e.g. ChEBI25 vs. ChEBI25_3_STAR),
# so their union does not match the labels we calibrate against. Map every base learner
# onto the label set of the validation data instead.
label_classes = [str(cls) for cls in self.validation_labels.columns]
validation_predictions, classes = collect_base_learner_predictions(
validation_predictions, classes=label_classes
)
validation_labels = torch.from_numpy(
self.validation_labels.to_numpy(dtype=bool)
)

print(
f"Collected validation predictions from {len(validation_predictions)} base learners with {len(classes)} unique classes. Calibrating ensemble model..."
)
# Step 2: Calibrate the ensemble model using validation predictions
self.ensemble_model.calibrate(
validation_predictions, self.validation_data, validation_labels
)

return self.ensemble_model
Loading
Loading