Skip to content

Repository files navigation

ChemFLM - Unified Chemical Fingerprint Language Model

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.


🎯 Project Overview

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.

Key Features

  • βœ… 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

πŸ“Š Implementation Status

βœ… Phase 1: Core Infrastructure - COMPLETE

  • Repository structure and organization
  • HuggingFace-compatible tokenizer
  • Base model architecture (ModernBERT)
  • Configuration system (Hydra)
  • Utility functions (seed, logging)

βœ… Phase 2: Data Pipeline - COMPLETE

  • 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

πŸ”„ Phase 3: Model Training - IN PROGRESS

  • Pretraining infrastructure (needs verification)
  • Fine-tuning with LoRA and focal loss
  • Early stopping and model selection

βœ… Phase 4-6: Evaluation + Analysis (Refactored)

  • 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.md
  • analysis/notebooks/README.md

See docs/IMPLEMENTATION_STATUS.md for detailed progress tracking.


πŸ—οΈ Architecture Overview

Legacy Implementations (Now Unified)

ChemFLM combines the best features from two previous implementations:

From chemfpformer:

  • βœ… 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

From chemfpformer-main:

  • βœ… 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)

New in ChemFLM:

  • πŸ†• 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

πŸš€ Quick Start

Installation

# 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.txt

If you need a more robust activation (e.g., non-interactive shells), you can also:

source scripts/activate_chemfp.sh

Data Preparation

# 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_40m

Dynamic Split Generation (During CV)

from 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'

πŸ“ Repository Structure

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]/

πŸ“ˆ Analysis (Refactored)

The analysis workflow is now config-driven and writes outputs into:

analysis/reports/<analysis.name>/

1) Activate environment

conda activate chemfp
# or (more robust in scripts/non-interactive shells)
source scripts/activate_chemfp.sh

2) Choose an analysis config

Start from the example:

  • analysis/configs/example_LRRK2_library_initial_baseline.yaml

3) Run thin notebooks

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)

4) Output structure

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

🎨 Key Features Explained

Dynamic Split Architecture

Unlike traditional approaches that pre-generate all splits, ChemFLM uses on-demand split generation:

  1. Data Preparation - Saves finetune datasets whole (unsplit)
  2. Cross-Validation - Generates splits dynamically for each fold
  3. Benefits:
    • Simpler file structure
    • Easy parameter experimentation
    • Memory efficient
    • Better reproducibility tracking

Three OOD Strategies

1. Hierarchical Clustering βœ…

  • 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

2. Library-Based Splits βœ…

  • 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

3. Building Block Overlap βœ…

  • 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

Fingerprint Types Supported

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.


πŸ“– Documentation

  • docs/IMPLEMENTATION_STATUS.md - Comprehensive progress tracking
  • docs/IMPLEMENTATION_PLAN_OVERVIEW.md - Project overview and phases
  • docs/PHASE2_IMPLEMENTATION_PLAN_REVISED.md - Dynamic splits architecture
  • docs/IMPLEMENTATION_SUMMARY.md - Finalized design decisions
  • docs/IMPLEMENTATION_PLAN_DATA_PIPELINE.md - Data pipeline details
  • docs/ANALYSIS_FRAMEWORK_USAGE.md - How to run the refactored analysis pipeline

πŸ”§ Analysis TODOs (Known Gaps)

The refactor intentionally focused on preserving existing analytics while standardizing the workflow. Remaining TODOs:

  1. Multi-run comparisons (pretraining vs no-pretraining)

    • Current modules support run_label but the notebooks generally analyze cfg.runs[0].
    • TODO: add comparative plots/tables across multiple analysis.runs in a single report.
  2. Generalized β€œlevel comparison” module

    • The legacy analysis/2. threshold_comparison.ipynb logic is not yet ported into analysis/src/plots/.
    • TODO: implement a threshold_comparison.py (generalized to hierarchy/library/building_block β€œlevels”).
  3. Smarter filesystem discovery

    • Discovery currently depends on analysis.levels being enumerated in config.
    • TODO: optionally auto-discover existing levels/testsets from output folders/files (useful for incomplete runs).
  4. 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).

πŸ§ͺ Testing & Validation

Data Quality Checks

  • SMILES parsing success rate
  • Fingerprint consistency
  • No data leakage between splits
  • Label distribution per split
  • Cluster hierarchy validation

Reproducibility

  • Fixed seeds throughout
  • Fold assignments saved to YAML
  • Metadata tracking for all experiments
  • Configuration snapshots

🀝 Contributing

ChemFLM is under active development. Phase 3 (model training) and Phase 4 (cross-validation) are the current focus areas.


πŸ“„ License

[Add license information]


πŸ“š Citation

[Add citation information]


πŸ”— References

  • ModernBERT: [Link to paper/repo]
  • Original chemfpformer: /home/bhux/workplace/chemfpformer
  • Original chemfpformer-main: /home/bhux/workplace/chemfpformer-main

About

Drug Discovery Fingerprint Language Model

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages