Skip to main content

A library to quickly build QSAR models

Project description

Ersilia's LazyQSAR

A Python library for building supervised QSAR models quickly, with minimal configuration. LazyQSAR automates chemical descriptor computation, and model selection to produce robust models for property and activity prediction.

Two entry points:

  • LazyClassifierQSAR: pass SMILES strings directly; built-in descriptors are computed automatically
  • LazyClassifier: bring your own pre-computed descriptor arrays

Table of Contents

Installation

We recommend installation from source:

git clone https://github.com/ersilia-os/lazy-qsar.git
cd lazy-qsar
pip install -e .

The base install includes only lightweight runtime dependencies (numpy, onnxruntime, etc.), sufficient for loading and running pre-trained ONNX models without any ML and chemistry-related packages (RDKit). Therefore, the base install assumes descriptors are provided by the user.

You can install optional extras depending on your use case:

Extra Command Adds
fit pip install -e .[fit] Required to train models (scikit-learn, XGBoost, scipy, skl2onnx)
descriptors pip install -e .[descriptors] Required for built-in molecular descriptors (e.g. RDKit, FPSim2)
all pip install -e .[all] Everything above

The first time you use deep-learning descriptors (Chemeleon, CLAMP, CDDD), their checkpoints are downloaded automatically. To do this in advance:

lazyqsar setup --descriptors

Python API

LazyClassifierQSAR (SMILES)

Pass SMILES strings directly. Choose a descriptor mode:

Mode Descriptors Notes
fast Morgan fingerprints No deep-learning models, fastest
slow Chemeleon, CLAMP, Morgan, RDKit (physchem), CDDD Most thorough
from lazyqsar.qsar import LazyClassifierQSAR

model = LazyClassifierQSAR(mode="slow") # default is "slow"
model.fit(smiles_list=smiles_train, y=y_train)

Available prediction methods:

Method Returns Description
predict(smiles_list) (N,) Binary labels at an optimized threshold
predict_proba(smiles_list) (N, 2) Calibrated class probabilities
predict_logit(smiles_list) (N, 2) Log-odds scores
predict_rank(smiles_list) (N, 2) Rank quantiles (0–1)
predict_score(smiles_list) (N, 2) Raw model scores
predict_lift(smiles_list) (N, 2) Probability / population prior

LazyClassifier (custom descriptors)

Pass your own descriptor arrays or HDF5 files. We recommend the Ersilia Model Hub for descriptor computation — its .h5 output format is supported natively.

from lazyqsar.agnostic import LazyClassifier

# From a NumPy array
model = LazyClassifier()
model.fit(X=X_train, y=y_train)
y_hat = model.predict_proba(X=X_test)[:, 1]

# From an Ersilia .h5 file
model.fit(h5_file="descriptors.h5", y=y_train)
y_hat = model.predict_proba(h5_file="descriptors.h5")[:, 1]

The same prediction methods listed above are available, using X= instead of smiles_list=.

Saving and loading

Models are saved as ONNX files, so inference only requires numpy and onnxruntime, i.e. no scikit-learn or XGBoost at prediction time. Metadata is stored in JSON format.

To save models:

model.save(model_dir)          # directory
model.save("my_model.zip")     # or zip archive

And to load them:

model = LazyClassifierQSAR.load(model_dir)
y_hat = model.predict_proba(smiles_list=smiles_test)[:, 1]

model = LazyClassifier.load(model_dir)
y_hat = model.predict_proba(X=X_test)[:, 1]

For multi-endpoint prediction across multiple model directories, see Ersilia Model Hub integration.

CLI

All commands are available through the lazyqsar entry point.

Fit:

The --input directory must contain one CSV per task, with SMILES in the first column and binary labels (0/1) in the second column, with a header row.

lazyqsar fit --task classification --input $DATA_DIR --output $MODEL_DIR --mode slow

Pass --models_txt to train a subset of tasks (one CSV stem per line); without it, all CSVs in the directory are used.

Predict:

lazyqsar predict --input $INPUT_CSV --model $MODEL_DIR --output $OUTPUT_CSV [--models_txt FILE] [--predict_type TYPE]

The output CSV contains one column per task, ordered alphabetically by task name, or filtered and ordered by --models_txt at predict time. --predict_type controls the output format: proba (default), rank, logit, lift, score, or binary.

How it works

LazyQSAR builds an ensemble for each descriptor set through four steps:

  1. Portfolio selection: the dataset is profiled (sample count, dimensionality, sparsity, class imbalance) and a rule-based selector decides which heads to train. The default portfolio is XGBoost + Random Forest; Linear Models and Support Vector Machines are added automatically for small, high-dimensional, or low-prevalence datasets.

  2. Preprocessing: a scaler (StandardScaler, RobustScaler, MaxAbsScaler, or PowerTransformer) and an optional correlation-based feature reducer are selected automatically from dataset statistics.

  3. Heads: each selected head is fitted on preprocessed features. For severely imbalanced datasets, balanced sub-batches are used and the batch predictions are averaged.

  4. Pooling: head predictions are combined via a learned gating network (InnerClassifierPooler). When using LazyClassifierQSAR, a separate ensemble is trained per descriptor type and their predictions are combined via an AUC-weighted ensemble that accounts for per-sample prediction confidence.

  5. Export: the full pipeline is exported to ONNX for dependency-free inference.

Base Models

The components under lazyqsar/base/ can be used independently of the full pipeline:

Module Description
lazyqsar.base.preprocessing Automatic scaler and feature reducer selection
lazyqsar.base.xgboost Automatic XGBoost hyperparameter selection with portfolio comparison
lazyqsar.base.linear Automatic linear model selection (logistic/ridge/SGD)
lazyqsar.base.randomforest Random Forest classifier with zero-shot hyperparameter selection

Ersilia Model Hub integration

LazyQSAR models can be used inside an Ersilia Model Hub template. See eos1lb5 for an example.

Basically, lazyqsar fit can be used to produce a checkpoints folder with one sub-directory per task and per descriptor type:

checkpoints/
└── task1/
    ├── cddd/
    │   ├── featurizer.json
    │   ├── metadata.json
    │   └── batch_0/
    │       ├── preprocessor.onnx
    │       ├── xgboost.onnx
    │       └── pooler.json
    ├── chemeleon/   (same structure)
    ├── clamp/       (same structure)
    ├── morgan/      (same structure)
    └── rdkit/       (same structure)

The code/main.py inference script:

import os, sys
from lazyqsar.api.classifier_predict import predict

root = os.path.dirname(os.path.abspath(__file__))
checkpoints_dir = os.path.abspath(os.path.join(root, "..", "checkpoints"))
predict(model_dir=checkpoints_dir, input_csv=sys.argv[1], output_csv=sys.argv[2], predict_type="rank")

This function computes descriptors once per descriptor type and reuses them across all tasks, making it suitable for scoring large compound libraries. predict_type controls the output format and is available in both the Python API and the CLI (--predict_type).

Multi-model prediction across directories:

model_dir also accepts a dict[str, str] mapping each individual model directory (a leaf directory containing featurizer subdirs) to its exact output column name. This is useful when models for different targets are stored under separate paths:

from lazyqsar.api.classifier_predict import predict

predict(
    model_dir={
        "checkpoints/ecoli/individual_activity_a": "E. coli activity",
        "checkpoints/mtb/individual_activity_a":   "M. tb activity",
    },
    input_csv=sys.argv[1],
    output_csv=sys.argv[2],
    predict_type="rank",
)

The output CSV will contain one column per entry, named exactly as the dict values. Descriptors are still computed once per type and shared across all models.

Roadmap

We are currently working on regression models, mirroring what has been done for classification.

Disclaimer

This library is intended for quick QSAR modeling. For a more complete automated QSAR pipeline, refer to ZairaChem.

ZairaChem's version, with an earlier version of LazyQSAR, was presented in this article:

@article{Turon2023,
  author = {Turon, G. and Hlozek, J. and Woodland, J.G. and et al.},
  title = {First fully-automated AI/ML virtual screening cascade implemented at a drug discovery centre in Africa},
  journal = {Nat Commun},
  volume = {14},
  pages = {5736},
  year = {2023},
  doi = {10.1038/s41467-023-41512-2},
  url = {https://doi.org/10.1038/s41467-023-41512-2}
}

About the Ersilia Open Source Initiative

The Ersilia Open Source Initiative is a tech non-profit organization with the mission to equip laboratories, universities, and clinics in the Global South with AI/ML tools for infectious disease research. We work on the principles of open science, decolonized research, and egalitarian access to knowledge and research outputs. You can support Ersilia by clicking here.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lazyqsar-3.1.4.tar.gz (146.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lazyqsar-3.1.4-py3-none-any.whl (176.1 kB view details)

Uploaded Python 3

File details

Details for the file lazyqsar-3.1.4.tar.gz.

File metadata

  • Download URL: lazyqsar-3.1.4.tar.gz
  • Upload date:
  • Size: 146.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.12.3 Linux/6.17.0-1010-azure

File hashes

Hashes for lazyqsar-3.1.4.tar.gz
Algorithm Hash digest
SHA256 ca703a580bc9c5ec988647db81cb4a139e0313be03f467df14f985565a1666fa
MD5 6d7f1bd3c0e98d81d419decf6d60c2bb
BLAKE2b-256 77fd82d9caaa99704620f0659b08b594bcb5b6f830199b589111fddc6f3947b7

See more details on using hashes here.

File details

Details for the file lazyqsar-3.1.4-py3-none-any.whl.

File metadata

  • Download URL: lazyqsar-3.1.4-py3-none-any.whl
  • Upload date:
  • Size: 176.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.12.3 Linux/6.17.0-1010-azure

File hashes

Hashes for lazyqsar-3.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 1112914b3bca09bf72759893a1821a7a416aebf4747f3c4c2eb10bbd41c04a86
MD5 3b92000c64a9119a70833547e0a42a38
BLAKE2b-256 1d99f407a51287c8a62bfbb4fcce4608a10c062e25b01150154c95e55b367d93

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page