Status: Phase 1 & 2 Complete β | Phase 3 In Progress π
ChemFLM unifies and extends two previous implementations (chemfpformer and chemfpformer-main) into a comprehensive, production-ready repository for molecular property prediction using transformers.
ChemFLM is a pretrained ModernBERT-based transformer model trained on molecular SMILES and DNA-encoded library (DEL) fingerprints. The model performs hit prediction on DEL fingerprints through fine-tuning, with a strong focus on out-of-distribution (OOD) generalization to molecules significantly different from the training set.
- β Large-scale pretraining across multiple molecular datasets (40M SMILES, CHEMBL, MOSES, DEL libraries)
- β Multiple OOD evaluation strategies to rigorously test generalization
- β Dynamic split generation for flexible cross-validation
- β Advanced evaluation metrics (PR-AUC, ROC-AUC, Precision@k, Enrichment@k)
- β Span masking for learning SMILES-fingerprint relationships
- β Configuration-driven experiments using Hydra
- Repository structure and organization
- HuggingFace-compatible tokenizer
- Base model architecture (ModernBERT)
- Configuration system (Hydra)
- Utility functions (seed, logging)
- Fingerprint Generation (8 types: ECFP4/6, FCFP4/6, MACCS, Avalon, AtomPair, TopTor)
- On-demand Clustering with hierarchy rectification
- Three OOD Split Strategies:
- Hierarchical clustering (3 levels: 0.85/50%, 0.75/25%, 0.65/10%)
- Library-based splits (3 levels: 30%, 20%, 10% exclusion)
- Building block overlap (k=0, 1, 2 test buckets)
- Dynamic split architecture (splits generated on-demand during CV)
- Comprehensive data preparation script with metadata tracking
- Pretraining infrastructure (needs verification)
- Fine-tuning with LoRA and focal loss
- Early stopping and model selection
- Cross-validation output analysis has been refactored into a reusable, config-driven framework under
analysis/src/. - Metrics, curves, ranking metrics, statsig exports, and advanced analyses are generated by thin notebooks in
analysis/notebooks/.
See:
docs/ANALYSIS_FRAMEWORK_USAGE.mdanalysis/notebooks/README.md
See docs/IMPLEMENTATION_STATUS.md for detailed progress tracking.
ChemFLM combines the best features from two previous implementations:
- β Large-scale pretraining (40M SMILES, CHEMBL, MOSES)
- β
Hierarchical clustering for OOD evaluation
- Now implemented with dynamic on-demand generation
- Hierarchy rectification for proper nesting
- β Baseline comparisons (LGBM, Decision Trees)
- β End-to-end workflows from pretraining to fine-tuning
- β Library-based splits for OOD testing
- β Advanced metrics (Prec@k, Enrich@k, PR/ROC curves)
- β Cross-validation framework for statistical significance
- β Comprehensive baselines (LGBM, XGBoost)
- π Dynamic split generation - Splits created on-demand during CV
- π Building block overlap splits - Novel OOD strategy with k=0,1,2 evaluation
- π Unified vocabulary - Single tokenizer for pretrain and finetune
- π Span masking - Learn SMILES-fingerprint relationships (configurable)
- π On-demand clustering - Memory-efficient with caching
- π Enhanced configurations - Complete Hydra-based system
# Clone repository
git clone git@github.com:GenerativeDrugDiscovery/ChemFLM.git
cd ChemFLM
# Activate conda env (recommended)
conda activate chemfp
# Install dependencies
pip install -r requirements.txtIf you need a more robust activation (e.g., non-interactive shells), you can also:
source scripts/activate_chemfp.sh# Prepare data with default configuration (DEL only)
python scripts/prepare_data.py
# Prepare data with SMILES + fingerprints
python scripts/prepare_data.py --config-name data_prep/data_prep_smiles_fp
# Prepare data with large-scale pretraining (40M SMILES)
python scripts/prepare_data.py --config-name data_prep/data_prep_40mfrom src.data.splits import create_hierarchy_split
from datasets import load_from_disk
# Load finetune dataset (saved whole, unsplit)
dataset = load_from_disk("processed_data/default/dataset/ft_DCAF7")
# Generate hierarchical split dynamically
train_idx, val_idx, test_idx = create_hierarchy_split(
dataset,
dataset_path="processed_data/default",
dataset_name="DCAF7",
seed=42,
config={'threshold': 0.85, 'ood_percentage': 0.5, 'val_fraction': 0.1}
)
# Or library split
from src.data.splits import create_library_split
train_idx, val_idx, test_idx = create_library_split(
dataset,
dataset_path="processed_data/default",
dataset_name="DCAF7",
seed=42,
config={'exclusion_percentage': 0.30, 'min_library_size': 1000, 'val_fraction': 0.1}
)
# Or building block split (returns 3 test buckets)
from src.data.splits import create_building_block_split
train_idx, val_idx, test_dict = create_building_block_split(
dataset,
dataset_path="processed_data/default",
dataset_name="DCAF7",
seed=42,
config={'holdout_fraction': 0.40, 'label_aware_sampling': True, 'val_fraction': 0.1}
)
# test_dict contains: 'test_0bb', 'test_1bb', 'test_2bb'ChemFLM/
βββ configs/ # Hydra configurations
β βββ config.yaml # Main config
β βββ data/ # Data prep configs
β β βββ data_prep.yaml
β β βββ data_prep_del_only.yaml
β β βββ data_prep_smiles_fp.yaml
β βββ splits/ # Split strategy configs
β β βββ hierarchy.yaml
β β βββ library.yaml
β β βββ building_block.yaml
β βββ model/ # Model configs
β β βββ modernbert_base.yaml
β β βββ modernbert_small.yaml
β βββ training/ # Training configs
β βββ default.yaml
β
βββ src/ # Source code
β βββ data/ # Data processing
β β βββ fingerprints.py # 8 fingerprint types
β β βββ clustering.py # On-demand clustering
β β βββ splits.py # 3 OOD split strategies
β β βββ tokenizer.py # HuggingFace tokenizer
β β βββ transforms.py # Molecular tokenization
β β βββ dataloader.py # PyTorch data loaders
β βββ model/ # Model components
β β βββ chemfpformer_model.py
β β βββ pretrain_model.py
β β βββ finetune_model.py
β β βββ finetuning_strategies.py # LoRA, etc.
β βββ utils/ # Utilities
β βββ seed.py
β βββ logging_utils.py
β
βββ scripts/ # Execution scripts
β βββ prepare_data.py # Main data prep script
β
βββ docs/ # Documentation
β βββ IMPLEMENTATION_STATUS.md
β βββ IMPLEMENTATION_PLAN_OVERVIEW.md
β βββ PHASE2_IMPLEMENTATION_PLAN_REVISED.md
β βββ IMPLEMENTATION_SUMMARY.md
β βββ ANALYSIS_FRAMEWORK_USAGE.md
β
βββ analysis/ # Analysis framework + thin notebooks
β βββ configs/ # Analysis configs (YAML)
β βββ notebooks/ # Thin Jupyter notebooks (call analysis/src)
β βββ reports/ # Generated outputs (figures/results)
β βββ src/ # Reusable analysis modules
β
βββ data/ # Raw data (not in repo)
βββ SMILES-40M/
βββ CHEMBL/
βββ MOSES/
βββ [DEL libraries]/
The analysis workflow is now config-driven and writes outputs into:
analysis/reports/<analysis.name>/
conda activate chemfp
# or (more robust in scripts/non-interactive shells)
source scripts/activate_chemfp.shStart from the example:
analysis/configs/example_LRRK2_library_initial_baseline.yaml
Open and run (in order as needed):
analysis/notebooks/1_cv_folds_threshold_comparison.ipynb(core tables + metric bar plots)analysis/notebooks/2_curves.ipynb(mean ROC/PR curves)analysis/notebooks/3_ranking_metrics.ipynb(precision@k / recall@k / enrichment@k / ndcg@k)analysis/notebooks/4_summary_export.ipynb(Phase 7-style exports: statsig + recommendations + RESULTS_SUMMARY.md)analysis/notebooks/5_advanced.ipynb(Phase 8 advanced: fold variability, radar, calibration, ensemble)
Example:
analysis/reports/<analysis.name>/
figures/
metrics_comparison/
roc_curves/
pr_curves/
ranking_metrics/
advanced/
results/
metrics_long.csv
metrics_summary.csv
statistical_tests.csv
ranking_metrics_complete_summary.csv
...
RESULTS_SUMMARY.md
Unlike traditional approaches that pre-generate all splits, ChemFLM uses on-demand split generation:
- Data Preparation - Saves finetune datasets whole (unsplit)
- Cross-Validation - Generates splits dynamically for each fold
- Benefits:
- Simpler file structure
- Easy parameter experimentation
- Memory efficient
- Better reproducibility tracking
- Based on molecular similarity (Tanimoto distance)
- Three levels: threshold (0.85/0.75/0.65) Γ OOD% (50%/25%/10%)
- Rectified hierarchy ensures proper nesting
- On-demand cluster generation with caching
- Groups molecules by library prefix
- Three exclusion levels: 30%, 20%, 10%
- Small libraries merged to "OTHER" (always in training)
- No library appears in both train and test
- Based on combinatorial chemistry BBs
- 40% of building blocks held out
- Three test buckets by overlap:
- k=0: All 3 BBs novel (highest OOD)
- k=1: 1 BB shared, 2 novel
- k=2: 2 BBs shared, 1 novel
- Label-aware sampling for enrichment
ChemFLM supports 8 molecular fingerprint types:
- ECFP4, ECFP6 - Extended Connectivity (binary)
- FCFP4, FCFP6 - Functional Connectivity (binary)
- MACCS - 167-bit MACCS keys
- Avalon - Avalon fingerprints
- AtomPair - Atom pair fingerprints
- TopTor - Topological torsion fingerprints
All with robust error handling and batch processing.
docs/IMPLEMENTATION_STATUS.md- Comprehensive progress trackingdocs/IMPLEMENTATION_PLAN_OVERVIEW.md- Project overview and phasesdocs/PHASE2_IMPLEMENTATION_PLAN_REVISED.md- Dynamic splits architecturedocs/IMPLEMENTATION_SUMMARY.md- Finalized design decisionsdocs/IMPLEMENTATION_PLAN_DATA_PIPELINE.md- Data pipeline detailsdocs/ANALYSIS_FRAMEWORK_USAGE.md- How to run the refactored analysis pipeline
The refactor intentionally focused on preserving existing analytics while standardizing the workflow. Remaining TODOs:
-
Multi-run comparisons (pretraining vs no-pretraining)
- Current modules support
run_labelbut the notebooks generally analyzecfg.runs[0]. - TODO: add comparative plots/tables across multiple
analysis.runsin a single report.
- Current modules support
-
Generalized βlevel comparisonβ module
- The legacy
analysis/2. threshold_comparison.ipynblogic is not yet ported intoanalysis/src/plots/. - TODO: implement a
threshold_comparison.py(generalized to hierarchy/library/building_block βlevelsβ).
- The legacy
-
Smarter filesystem discovery
- Discovery currently depends on
analysis.levelsbeing enumerated in config. - TODO: optionally auto-discover existing levels/testsets from output folders/files (useful for incomplete runs).
- Discovery currently depends on
-
Ensemble alignment robustness
- Ensemble currently assumes transformer and LGBM prediction rows align by order.
- TODO: align on a stable sample key if available (e.g., id / smiles / compound_id).
- SMILES parsing success rate
- Fingerprint consistency
- No data leakage between splits
- Label distribution per split
- Cluster hierarchy validation
- Fixed seeds throughout
- Fold assignments saved to YAML
- Metadata tracking for all experiments
- Configuration snapshots
ChemFLM is under active development. Phase 3 (model training) and Phase 4 (cross-validation) are the current focus areas.
[Add license information]
[Add citation information]
- ModernBERT: [Link to paper/repo]
- Original chemfpformer:
/home/bhux/workplace/chemfpformer - Original chemfpformer-main:
/home/bhux/workplace/chemfpformer-main