Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Deep learning for drug discovery. 60+ models (GCN, GAT, AttentiveFP, MPNN, ChemBERTa, GROVER), 50+ featurizers, MoleculeNet benchmarks, HPO, transfer learning. Unified load-featurize-split-train-evaluate API. For fingerprints use rdkit-cheminformatics; for featurization-only use molfeat.
.claude/skills/jaechang-hits-deepchem/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-06 | ✗→✓ | ▲ Improved | 379% | 0% |
| case-17 | ✗→✓ | ▲ Improved | 386% | 0% |
| case-21 | ✗→✓ | ▲ Improved | 413% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 268% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 345% | 0% |
DeepChem is an open-source Python framework providing a unified API for molecular machine learning across drug discovery, materials science, and quantum chemistry. It wraps 60+ model architectures (graph neural networks, transformers, classical ML) with 50+ molecular featurizers and standardized datasets (MoleculeNet), enabling end-to-end workflows from SMILES strings to trained predictive models.
rdkit-cheminformatics insteadmolfeat-molecular-featurization insteaddeepchem (core), torch or tensorflow (backend-dependent models)bash# Core installation (includes RDKit, scikit-learn, XGBoost) pip install deepchem # With PyTorch backend (GNN models) pip install deepchem[torch] # With TensorFlow backend (legacy models) pip install deepchem[tensorflow] # Full installation (all backends + extras) pip install deepchem[all]
pythonimport deepchem as dc # Load MoleculeNet dataset with featurization + scaffold split tasks, datasets, transformers = dc.molnet.load_delaney(featurizer="ECFP") train, valid, test = datasets # Train and evaluate a multitask regressor model = dc.models.MultitaskRegressor(n_tasks=1, n_features=1024, dropouts=0.2) model.fit(train, nb_epoch=50) metric = dc.metrics.Metric(dc.metrics.pearson_r2_score) print(f"Test R2: {model.evaluate(test, [metric])}") # {'pearson_r2_score': ~0.7}
Load molecular data from CSV files or MoleculeNet benchmark datasets.
pythonimport deepchem as dc # Load from CSV (SMILES + property columns) loader = dc.data.CSVLoader( tasks=["measured_log_solubility"], feature_field="smiles", featurizer=dc.feat.CircularFingerprint(size=2048, radius=3) ) dataset = loader.create_dataset("solubility_data.csv") print(f"Samples: {dataset.X.shape[0]}, Features: {dataset.X.shape[1]}") # Samples: 1128, Features: 2048 # Load from SDF (3D structures) sdf_loader = dc.data.SDFLoader( tasks=["activity"], featurizer=dc.feat.CoulombMatrix(max_atoms=50) ) dataset_3d = sdf_loader.create_dataset("molecules.sdf")
python# Load MoleculeNet benchmark datasets (auto-download + featurize + split) # Available: load_delaney, load_bbbp, load_tox21, load_hiv, load_qm7, load_qm9, etc. tasks, datasets, transformers = dc.molnet.load_tox21(featurizer="ECFP", splitter="scaffold") train, valid, test = datasets print(f"Tasks: {len(tasks)}, Train: {len(train)}, Test: {len(test)}") # Tasks: 12, Train: ~6264, Test: ~631 # Inverse-transform predictions back to original scale y_pred = model.predict(test) y_original = transformers[0].untransform(y_pred)
Convert molecules to numerical representations for ML. DeepChem provides 50+ featurizers spanning fingerprints, descriptors, graph features, and Coulomb matrices.
pythonimport deepchem as dc smiles = ["CCO", "CC(=O)O", "c1ccccc1", "CC(C)O"] # Fingerprints (most common for classical ML) ecfp = dc.feat.CircularFingerprint(size=2048, radius=3) fp_features = ecfp.featurize(smiles) print(f"ECFP shape: {fp_features.shape}") # (4, 2048) # RDKit descriptors (interpretable physicochemical properties) rdkit_desc = dc.feat.RDKitDescriptors() desc_features = rdkit_desc.featurize(smiles) print(f"Descriptor shape: {desc_features.shape}") # (4, 208) # Graph features (for GNN models — returns ConvMol objects) graph_feat = dc.feat.ConvMolFeaturizer() graphs = graph_feat.featurize(smiles) print(f"Atoms in first mol: {graphs[0].get_num_atoms()}") # 3 # Mol2Vec embeddings (pretrained word2vec on molecular substructures) mol2vec = dc.feat.Mol2VecFingerprint() embeddings = mol2vec.featurize(smiles) print(f"Mol2Vec shape: {embeddings.shape}") # (4, 300)
DeepChem provides MultitaskRegressor and MultitaskClassifier as general-purpose models, plus specialized architectures for graph and sequence data.
pythonimport deepchem as dc # Load dataset tasks, datasets, transformers = dc.molnet.load_delaney(featurizer="ECFP") train, valid, test = datasets # Regression model (fingerprint input) model = dc.models.MultitaskRegressor( n_tasks=1, n_features=1024, layer_sizes=[1000, 500], dropouts=0.25, learning_rate=0.001, batch_size=64, ) model.fit(train, nb_epoch=100) # Evaluate with multiple metrics metrics = [ dc.metrics.Metric(dc.metrics.pearson_r2_score), dc.metrics.Metric(dc.metrics.mean_absolute_error), dc.metrics.Metric(dc.metrics.rms_score), ] results = model.evaluate(test, metrics) print(f"R2: {results['pearson_r2_score']:.3f}, MAE: {results['mean_absolute_error']:.3f}")
python# Classification model (e.g., Tox21 toxicity prediction) tasks, datasets, transformers = dc.molnet.load_tox21(featurizer="ECFP") train, valid, test = datasets clf = dc.models.MultitaskClassifier( n_tasks=len(tasks), n_features=1024, layer_sizes=[1000, 500], dropouts=0.5, learning_rate=0.001, ) clf.fit(train, nb_epoch=50) roc_metric = dc.metrics.Metric(dc.metrics.roc_auc_score, np.mean) print(f"Mean ROC-AUC: {clf.evaluate(test, [roc_metric])}")
GNNs operate directly on molecular graphs (atoms as nodes, bonds as edges), avoiding information loss from fixed fingerprints.
pythonimport deepchem as dc # Load with graph featurizer tasks, datasets, transformers = dc.molnet.load_delaney(featurizer="GraphConv") train, valid, test = datasets # Graph Convolutional Network (Duvenaud et al.) gcn_model = dc.models.GraphConvModel( n_tasks=1, mode="regression", graph_conv_layers=[64, 64], dense_layer_size=256, dropout=0.2, learning_rate=0.001, batch_size=64, ) gcn_model.fit(train, nb_epoch=100) metric = dc.metrics.Metric(dc.metrics.pearson_r2_score) print(f"GCN R2: {gcn_model.evaluate(test, [metric])}")
python# AttentiveFP (Xiong et al.) — attention-based GNN, strong on molecular properties tasks, datasets, transformers = dc.molnet.load_delaney( featurizer=dc.feat.MolGraphConvFeaturizer(use_edges=True) ) train, valid, test = datasets attfp_model = dc.models.AttentiveFPModel( n_tasks=1, mode="regression", num_layers=2, graph_feat_size=200, num_timesteps=2, dropout=0.2, learning_rate=0.001, batch_size=64, ) attfp_model.fit(train, nb_epoch=100) print(f"AttentiveFP R2: {attfp_model.evaluate(test, [metric])}")
Fine-tune pretrained chemical language models for downstream tasks with limited data.
pythonimport deepchem as dc from deepchem.models.torch_models import ChemBERTaModel # ChemBERTa — SMILES-based transformer (pretrained on 77M molecules) tasks, datasets, transformers = dc.molnet.load_bbbp(featurizer=dc.feat.SmilesTokenizer()) train, valid, test = datasets chemberta = ChemBERTaModel( task="classification", n_tasks=1, model_dir="chemberta_finetuned/", ) # Fine-tune on downstream task (BBB permeability) chemberta.fit(train, nb_epoch=10) metric = dc.metrics.Metric(dc.metrics.roc_auc_score) print(f"ChemBERTa ROC-AUC: {chemberta.evaluate(test, [metric])}")
Run inference on new molecules with a trained model.
pythonimport deepchem as dc import numpy as np # Assume trained model from Module 3 # Featurize new molecules using same featurizer featurizer = dc.feat.CircularFingerprint(size=1024, radius=2) new_smiles = ["c1cc(O)ccc1", "CC(=O)Nc1ccc(O)cc1", "OC(=O)c1ccccc1"] new_features = featurizer.featurize(new_smiles) new_dataset = dc.data.NumpyDataset(X=new_features) predictions = model.predict(new_dataset) for smi, pred in zip(new_smiles, predictions): print(f"{smi}: {pred[0]:.2f}") # Ensemble predictions from multiple models for robustness models = [model1, model2, model3] # trained models all_preds = np.array([m.predict(new_dataset) for m in models]) ensemble_mean = all_preds.mean(axis=0) ensemble_std = all_preds.std(axis=0) print(f"Ensemble prediction: {ensemble_mean[0][0]:.2f} +/- {ensemble_std[0][0]:.2f}")
All DeepChem workflows follow a consistent 5-step pattern:
Load Data → Featurize → Split → Train → EvaluateCSVLoader, SDFLoader, or dc.molnet.load_*() (auto-loads MoleculeNet datasets)featurizer.featurize(smiles) directlyScaffoldSplitter (recommended for drug discovery), RandomSplitter, ButinaSplittermodel.fit(train_dataset, nb_epoch=N)model.evaluate(test_dataset, metrics_list)| Data Type | Model | Key Feature | Use When | |-----------|-------|-------------|----------| | SMILES + fingerprints | MultitaskRegressor | Fast, baseline | First attempt, small datasets | | SMILES + fingerprints | MultitaskClassifier | Multi-label | Multi-task classification (Tox21) | | Molecular graphs | GraphConvModel | Learned fingerprints | Medium datasets, general properties | | Molecular graphs | GATModel | Attention mechanism | When atom importance matters | | Molecular graphs | AttentiveFPModel | Graph + timestep attention | State-of-art molecular properties | | Molecular graphs | MPNNModel | Message passing | Complex molecular interactions | | Molecular graphs | DMPNNModel | Directed MPNN | Bond-level predictions | | SMILES strings | ChemBERTaModel | Pretrained transformer | Low-data regime, transfer learning | | SMILES strings | GROVERModel | Graph + transformer | Rich molecular representations | | Crystal structures | CGCNNModel | Crystal graph CNN | Materials property prediction | | Crystal structures | MEGNetModel | Graph networks | Materials and molecules | | Protein sequences | ProteinLigandComplexModel | Complex modeling | Binding affinity prediction | | Tabular features | XGBoostModel, RandomForestModel | Classical ML | Interpretability, baselines |
| Featurizer | Class | Output | Best For | |------------|-------|--------|----------| | ECFP/Morgan | CircularFingerprint | Binary vector (1024-2048) | General QSAR, fast baselines | | MACCS Keys | MACCSKeysFingerprint | 167-bit vector | Substructure filtering | | RDKit 2D | RDKitDescriptors | 200+ descriptors | Interpretable models | | Mol2Vec | Mol2VecFingerprint | 300-dim embedding | Similarity, clustering | | ConvMol | ConvMolFeaturizer | Graph features | GraphConvModel input | | MolGraph | MolGraphConvFeaturizer | Node + edge features | AttentiveFPModel, MPNNModel | | Weave | WeaveFeaturizer | Pair features | WeaveModel input | | Coulomb Matrix | CoulombMatrix | Atom-pair distances | QM property prediction | | SMILES tokens | SmilesTokenizer | Token IDs | ChemBERTa, transformer models |
| Splitter | Use Case | Why | |----------|----------|-----| | ScaffoldSplitter | Drug discovery (default) | Tests generalization to new chemotypes | | RandomSplitter | Quick experiments | Baseline, but overestimates performance | | ButinaSplitter | Diversity-based | Clusters by Tanimoto similarity | | FingerprintSplitter | Chemical similarity | Groups structurally similar molecules | | MaxMinSplitter | Maximum diversity test | Extreme generalization test |
Goal: Build a property prediction model from a CSV file with SMILES and activity columns.
pythonimport deepchem as dc import pandas as pd # Step 1: Load and featurize CSV data loader = dc.data.CSVLoader( tasks=["pIC50"], feature_field="smiles", featurizer=dc.feat.CircularFingerprint(size=2048, radius=3), ) dataset = loader.create_dataset("bioactivity_data.csv") # Step 2: Normalize targets transformer = dc.trans.NormalizationTransformer( transform_y=True, dataset=dataset ) dataset = transformer.transform(dataset) # Step 3: Scaffold split (realistic for drug discovery) splitter = dc.splits.ScaffoldSplitter() train, valid, test = splitter.train_valid_test_split(dataset) print(f"Train: {len(train)}, Valid: {len(valid)}, Test: {len(test)}") # Step 4: Train model model = dc.models.MultitaskRegressor( n_tasks=1, n_features=2048, layer_sizes=[1000, 500], dropouts=0.25, learning_rate=0.001, batch_size=64, ) model.fit(train, nb_epoch=100) # Step 5: Evaluate metrics = [ dc.metrics.Metric(dc.metrics.pearson_r2_score), dc.metrics.Metric(dc.metrics.mean_absolute_error), ] results = model.evaluate(test, metrics) print(f"R2: {results['pearson_r2_score']:.3f}, MAE: {results['mean_absolute_error']:.3f}")
Goal: Compare multiple models on a MoleculeNet benchmark dataset.
pythonimport deepchem as dc # Load dataset with graph featurizer (supports both fingerprint and GNN models) tasks, datasets, transformers = dc.molnet.load_bbbp( featurizer="GraphConv", splitter="scaffold" ) train, valid, test = datasets metric = dc.metrics.Metric(dc.metrics.roc_auc_score) # Model 1: Graph Convolutional Network gcn = dc.models.GraphConvModel(n_tasks=1, mode="classification", dropout=0.2) gcn.fit(train, nb_epoch=50) gcn_score = gcn.evaluate(test, [metric]) # Model 2: Random Forest baseline (needs fingerprints) tasks_fp, datasets_fp, _ = dc.molnet.load_bbbp(featurizer="ECFP", splitter="scaffold") train_fp, _, test_fp = datasets_fp rf = dc.models.SklearnModel( model=dc.models.sklearn_models.RandomForestClassifier(n_estimators=500), model_dir="rf_model/" ) rf.fit(train_fp) rf_score = rf.evaluate(test_fp, [metric]) print(f"GCN ROC-AUC: {gcn_score['roc_auc_score']:.3f}") print(f"RF ROC-AUC: {rf_score['roc_auc_score']:.3f}")
Goal: Fine-tune a pretrained model on a small dataset.
SmilesTokenizer featurizer1e-5 to 5e-5) for 5-15 epochsmodel.save_checkpoint()references/workflows_model_catalog.md Workflow 1 for complete hyperparameter optimization code| Parameter | Module | Default | Range / Options | Effect | |-----------|--------|---------|-----------------|--------| | n_features | MultitaskRegressor/Classifier | Required | Matches featurizer output | Input feature dimension | | layer_sizes | MultitaskRegressor/Classifier | [1000] | [256] to [1000, 500, 250] | Hidden layer dimensions | | dropouts | All neural models | 0.0 | 0.0-0.5 | Regularization strength | | learning_rate | All neural models | 0.001 | 1e-5-0.01 | Training step size | | batch_size | All neural models | 100 | 16-256 | Samples per gradient update | | nb_epoch | model.fit() | 10 | 10-300 | Training iterations | | size | CircularFingerprint | 2048 | 512-4096 | Fingerprint bit length | | radius | CircularFingerprint | 2 | 2-4 | Substructure neighborhood radius | | graph_conv_layers | GraphConvModel | [64, 64] | [32] to [128, 128, 64] | Graph convolution widths | | num_layers | AttentiveFPModel | 2 | 1-5 | GNN message passing depth | | graph_feat_size | AttentiveFPModel | 200 | 64-512 | Graph feature dimension | | splitter | dc.molnet.load_*() | "scaffold" | "scaffold", "random", "butina" | Data splitting strategy |
NormalizationTransformer(transform_y=True) before training. Remember to untransform() predictions for interpretable values.MultitaskRegressor + ECFP first. Only move to GNNs if fingerprint baseline is insufficient — GNNs need more data and compute.python # Baseline first baseline = dc.models.MultitaskRegressor(n_tasks=1, n_features=2048)
ConvMolFeaturizer, MolGraphConvFeaturizer). Fingerprint models need CircularFingerprint. Mixing causes silent errors.RandomSplitter are not publishable for molecular property prediction. Reviewers expect scaffold or temporal splits.np.isnan(dataset.y).sum().When to use: Optimize model performance before final evaluation.
pythonimport deepchem as dc tasks, datasets, transformers = dc.molnet.load_delaney(featurizer="ECFP") train, valid, test = datasets # Define parameter grid params = { "n_features": [1024], "layer_sizes": [[500], [1000, 500], [1000, 500, 250]], "dropouts": [0.1, 0.25, 0.5], "learning_rate": [0.001, 0.0005], } optimizer = dc.hyper.GridHyperparamOpt(lambda **p: dc.models.MultitaskRegressor(**p)) metric = dc.metrics.Metric(dc.metrics.pearson_r2_score) best_model, best_params, all_results = optimizer.hyperparam_search( params, train, valid, metric, logdir="hyperparam_logs/" ) print(f"Best params: {best_params}") print(f"Best R2: {best_model.evaluate(test, [metric])}")
When to use: Deploy trained models or resume training.
python# Save model checkpoint model.save_checkpoint(model_dir="saved_model/") # Reload model loaded_model = dc.models.MultitaskRegressor(n_tasks=1, n_features=2048) loaded_model.restore(model_dir="saved_model/") predictions = loaded_model.predict(test)
When to use: Evaluate models with domain-specific metrics.
pythonimport deepchem as dc import numpy as np def enrichment_factor(y_true, y_pred, top_fraction=0.01): """Enrichment factor at top X% of ranked predictions.""" n = len(y_true) n_top = max(int(n * top_fraction), 1) top_indices = np.argsort(y_pred.flatten())[-n_top:] hits_in_top = y_true.flatten()[top_indices].sum() expected = y_true.sum() * top_fraction return hits_in_top / expected if expected > 0 else 0.0 ef_metric = dc.metrics.Metric(enrichment_factor, mode="regression") print(f"EF@1%: {model.evaluate(test, [ef_metric])}")
| Problem | Cause | Solution | |---------|-------|----------| | ModuleNotFoundError: torch | PyTorch not installed | pip install deepchem[torch] for GNN models | | ValueError: n_features mismatch | Featurizer output size does not match model n_features | Check dataset.X.shape[1] and set n_features accordingly | | NaN loss during training | Learning rate too high or unnormalized targets | Apply NormalizationTransformer, reduce learning rate to 1e-4 | | Low scaffold-split performance | Model memorizes scaffolds, not properties | Use more data, try GNN models, or add regularization (dropout 0.3-0.5) | | RuntimeError: CUDA out of memory | Batch size too large for GPU | Reduce batch_size (32 or 16), or use CPU for small datasets | | FeaturizationError on some SMILES | Invalid or complex SMILES strings | Pre-filter with RDKit: Chem.MolFromSmiles(smi) is not None | | Model predicts constant values | Targets not normalized or too few epochs | Apply NormalizationTransformer, increase nb_epoch | | Slow featurization | Large dataset with expensive featurizer | Use CircularFingerprint (fast) or parallelize with n_jobs parameter |
SklearnModel| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 10,164 | 7,005 | -31% | 1 | 1 | 0% | 2,063 | 7,602 | +268% | 0 | 0 | — |
case-02 | pass→pass | 10,062 | 5,751 | -43% | 1 | 1 | 0% | 1,778 | 7,917 | +345% | 0 | 0 | — |
case-03 | pass→pass | 16,946 | 6,630 | -61% | 1 | 1 | 0% | 2,850 | 7,969 | +180% | 0 | 0 | — |
case-04 | pass→pass | 11,683 | 7,233 | -38% | 1 | 1 | 0% | 1,864 | 8,136 | +336% | 0 | 0 | — |
case-05 | pass→pass | 6,430 | 3,939 | -39% | 1 | 1 | 0% | 1,219 | 7,591 | +523% | 0 | 0 | — |
case-06 | fail→pass | 9,037 | 5,067 | -44% | 1 | 1 | 0% | 1,638 | 7,842 | +379% | 0 | 0 | — |
case-07 | pass→pass | 12,102 | 6,514 | -46% | 1 | 1 | 0% | 2,060 | 8,033 | +290% | 0 | 0 | — |
case-08 | pass→pass | 11,416 | 5,255 | -54% | 1 | 1 | 0% | 2,053 | 7,819 | +281% | 0 | 0 | — |
case-09 | pass→pass | 6,926 | 3,103 | -55% | 1 | 1 | 0% | 1,261 | 7,439 | +490% | 0 | 0 | — |
case-10 | pass→pass | 8,762 | 4,171 | -52% | 1 | 1 | 0% | 1,715 | 7,724 | +350% | 0 | 0 | — |
case-11 | pass→pass | 6,738 | 4,207 | -38% | 1 | 1 | 0% | 1,232 | 7,643 | +520% | 0 | 0 | — |
case-12 | pass→pass | 10,030 | 6,969 | -31% | 1 | 1 | 0% | 1,989 | 8,166 | +311% | 0 | 0 | — |
case-13 | pass→pass | 3,147 | 3,187 | +1% | 1 | 1 | 0% | 566 | 7,492 | +1224% | 0 | 0 | — |
case-14 | pass→pass | 29,176 | 2,200 | -92% | 1 | 1 | 0% | 1,007 | 7,240 | +619% | 0 | 0 | — |
case-15 | pass→pass | 3,303 | 2,630 | -20% | 1 | 1 | 0% | 673 | 7,322 | +988% | 0 | 0 | — |
case-16 | pass→pass | 5,598 | 3,089 | -45% | 1 | 1 | 0% | 1,109 | 7,416 | +569% | 0 | 0 | — |
case-17 | fail→pass | 10,587 | 4,111 | -61% | 1 | 1 | 0% | 1,557 | 7,572 | +386% | 0 | 0 | — |
case-18 | pass→pass | 10,695 | 5,467 | -49% | 1 | 1 | 0% | 1,879 | 7,866 | +319% | 0 | 0 | — |
case-19 | pass→pass | 6,296 | 5,093 | -19% | 1 | 1 | 0% | 1,118 | 7,777 | +596% | 0 | 0 | — |
case-20 | pass→pass | 3,905 | 3,630 | -7% | 1 | 1 | 0% | 736 | 7,472 | +915% | 0 | 0 | — |
case-21 | fail→pass | 7,247 | 2,980 | -59% | 1 | 1 | 0% | 1,449 | 7,435 | +413% | 0 | 0 | — |
case-22 | pass→pass | 10,020 | 4,395 | -56% | 1 | 1 | 0% | 1,926 | 7,710 | +300% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +14 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.