# Predicting Drug Response from Gene Expression in Python

By the end of this guide you will be able to build a working Python model that predicts how sensitive a cell line or tumor sample is to a drug, using that sample's [gene expression](/blog/guides/gene-expression) profile as input. You will download public expression and drug screening data, normalize it, select features, train a baseline regressor, evaluate it with cross-validation that does not leak, and predict response for a new sample. You will also know which published methods go beyond the baseline and which mistakes quietly inflate accuracy in most first attempts.

You need Python 3.9 or newer, about 4 GB of free disk space for the datasets used here, and the packages installed in Step 1. No prior machine learning experience is assumed, but basic familiarity with pandas DataFrames helps.

## What Predicting Drug Response from Gene Expression Means

Drug response prediction is the task of estimating, from molecular measurements, how strongly a biological sample reacts to a drug. The molecular measurement in this article is gene expression, usually a normalized read count or intensity value per gene. The response is a number such as an IC50 (the drug concentration that halves cell viability) or an area under the dose-response curve (AUC), or a class such as responder versus non-responder.

The idea has a long history. A 2004 review framed expression-based prediction of chemotherapy response as a central goal of pharmacogenomics [1], and the field has grown along two tracks. One track uses cancer cell lines, where both expression and drug sensitivity are measured at large scale. The other uses patient tumors, where expression comes from biopsies and response comes from clinical outcomes. Machine learning has been applied to both, and a 2020 TCGA study showed that primary tumor expression can predict patient response to 5-fluorouracil and gemcitabine with up to 86 percent accuracy [2].

Python is the practical language for this work because the whole pipeline, from reading matrices to fitting models to plotting dose-response curves, lives in one ecosystem. That is a large part of why Python for bioinformatics has become the default skill set in computational pharmacogenomics.

## Where the Data Comes From

You cannot train anything without paired data, meaning expression profiles and measured drug responses for the same samples. Four public resources cover most needs.

**Cancer Cell Line Encyclopedia (CCLE) and DepMap.** Uniformly processed expression data for over a thousand cancer cell lines, paired with drug screening data from projects such as the Cancer Therapeutics Response Portal (CTRP) and the Genomics of Drug Sensitivity in Cancer (GDSC). The kESVR study trained on 610 cancer cell lines drawn from CCLE and CTRP data [3]. Cell line datasets are the standard training ground because sample sizes are large and responses are quantitative.

**GDSC (Genomics of Drug Sensitivity in Cancer).** A large public screening resource with IC50 values for hundreds of drugs across cell lines. If your question is "which cell lines respond to drug X," GDSC response tables plus a matched expression matrix is the simplest starting point.

**TCGA.** Patient tumor expression with clinical treatment and outcome annotations. The Clayton study used TCGA expression plus clinical trial response data for 5-fluorouracil and gemcitabine, chosen because they had the largest numbers of patients with usable response records [2].

**CTR-DB.** A curated database of patient-derived transcriptomic datasets with drug response information, covering 83 pre-treatment datasets, 28 cancer types, 123 drugs, and 5,139 patient samples, all reprocessed uniformly so you can combine or compare them [4]. This is the fastest route to patient-level training data if cell lines feel too far from the clinic.

A fifth option is drug-induced expression signatures, meaning expression profiles measured after exposing cells to a drug. One ensemble-learning study combined standard screening data with two novel signatures built from drug-induced expression profiles and validated predictions with in vitro experiments [5]. Signatures add a second view of the drug, which helps when the baseline expression of a cell line alone is not informative enough.

## Step-by-Step: Build Your First Drug Response Model in Python

This walkthrough trains a ridge regression model on CCLE expression to predict IC50 values for a single drug from GDSC. The same skeleton works for any expression-response pair.

### Step 1. Set Up the Environment

Create a clean environment and install the core stack.

```bash
python -m venv drugresp
source drugresp/bin/activate
pip install pandas numpy scikit-learn scipy matplotlib seaborn jupyter
```

To confirm versions:

```python
import pandas as pd
import numpy as np
import sklearn
import scipy
print(pd.__version__, np.__version__, sklearn.__version__, scipy.__version__)
```

Expected output looks like this (exact numbers depend on your install date):

```
2.1.4 1.26.4 1.4.2 1.12.0
```

A note on tooling for Python for bioinformatics: Biopython is the standard library for sequence work, file format parsing, and NCBI Entrez queries, and a good biopython tutorial will cover FASTQ handling and BLAST integration. Biopython does not manage expression matrices or drug screens, so for this workflow pandas and scikit-learn carry the load, and you would reach for Biopython when your pipeline also touches raw sequences or needs to fetch reference annotations programmatically.

### Step 2. Download Expression and Response Data

Get two files:

1. A CCLE expression matrix, gene by cell line, from the DepMap Portal (depmap.org). Choose the CCLE expression dataset, typically TPM values on a log2 scale, in CSV format.
2. A GDSC drug response file with IC50 values per cell line and drug, from the GDSC site (cancerrxgene.org). The fitted parameters file contains cell line names, drug names, and IC50 in micromolar.

Place both files in a `data/` directory and load them.

```python
import pandas as pd

expr = pd.read_csv("data/ccle_expression.csv", index_col=0)
resp = pd.read_csv("data/gdsc_fitted_ic50.csv")

print(expr.shape)
print(resp.columns.tolist())
```

Expected output, with real numbers varying by release:

```
(1375, 19184)
['CELL_LINE_NAME', 'DRUG_NAME', 'IC50_uM', 'MAX_CONC', ...]
```

The expression matrix has cell lines as rows and genes as columns. The response table has one row per cell line and drug combination.

### Step 3. Pick One Drug and Merge the Tables

Multi-drug tables complicate a first model because each drug has its own potency scale. Pick one drug, for example a MEK inhibitor such as AZD6244 (selumetinib), which appears in published pharmacogenomic biomarker work [6].

```python
drug = "AZD6244"
sub = resp[resp["DRUG_NAME"] == drug].copy()
sub = sub.dropna(subset=["IC50_uM"])

# Expression row labels usually use cell line IDs, response uses names.
# Build a mapping or standardize keys before merging.
expr.columns = [c.split(" ") for c in expr.columns]  # strip gene extra fields if needed
```

The merge is the step where most people first get stuck. Cell line identifiers differ across resources: DepMap uses names like `ACH-000001` plus display names, GDSC uses names and COSMIC IDs. Join on the most stable key available and verify the overlap size before anything else.

```python
# If both files carry cell line names, inner-join on uppercase names
sub["key"] = sub["CELL_LINE_NAME"].str.upper()
X_full = expr.copy()
X_full.index = X_full.index.str.upper()

common = sub["key"].isin(X_full.index)
print(f"{common.sum()} of {len(sub)} response rows match an expression profile")

merged = sub.merge(
    X_full.T,  # transpose so genes are rows, cell lines columns
    left_on="key",
    right_index=True,
    how="inner"
)
```

Expected output:

```
232 of 247 response rows match an expression profile
```

If the overlap is tiny, the identifiers are formatted differently. Fix the keys rather than forcing a bad merge.

### Step 4. Preprocess and Normalize

Expression from different sources comes on different scales. For a single-dataset model, z-score standardization per gene is a safe default. This matters more than most beginners expect. In a cross-platform study of infliximab response in ulcerative colitis, z-score and log2 transformation preserved predictive signal across microarray and RNA-seq platforms far better than quantile normalization, reaching a mean cross-validation AUC of 0.824 and an external RNA-seq test AUC of 0.821 [7].

```python
import numpy as np

feature_cols = [c for c in merged.columns if c not in
                ["CELL_LINE_NAME", "DRUG_NAME", "IC50_uM", "MAX_CONC", "key"]]

X = merged[feature_cols].to_numpy(float)
y = np.log10(merged["IC50_uM"].to_numpy(float))

# z-score each gene across samples
X = (X - X.mean(axis=0)) / (X.std(axis=0) + 1e-8)
```

Two deliberate choices here:

- **Model log10(IC50), not raw IC50.** IC50 spans orders of magnitude. Working on the log scale makes the target roughly Gaussian and the errors interpretable as fold-changes in concentration. A difference of 1.0 in predicted log10(IC50) means a tenfold difference in potency.
- **Keep the standardization inside cross-validation** if you plan to select features later. Fitting the scaler on all samples before splitting leaks information. The code above is acceptable only because ridge regression with all genes does no per-feature selection. The safer pattern appears in Step 6.

Negative IC50 values sometimes appear in fitted files when the dose-response curve does not bracket the IC50. Decide on a rule, for example dropping them or clipping at the lowest tested concentration, and apply it consistently. Do not silently log-transform negatives.

### Step 5. Select Features

With roughly 19,000 genes and a few hundred samples, feature reduction helps. Simple approaches that work well:

```python
from sklearn.feature_selection import SelectKBest, f_regression

selector = SelectKBest(f_regression, k=1000)
```

Better approaches use biology. DrugGCN, a graph convolutional network method, builds a gene graph from a protein-protein interaction network and drug-related gene sets, then uses localized filtering to detect gene subnetworks that contribute to response [8]. The DeepDIPK-style framework DIPK similarly integrates gene interaction relationships with expression profiles and molecular structure, and showed gains over methods that ignore gene relationships, including accurate prediction of higher paclitaxel response in the pathological complete response group of a clinical cohort [9]. The practical takeaway even for a linear model: prefer gene panels informed by pathway knowledge or prior drug screens over a purely statistical top-k cut, and validate the panel on data not used to choose it.

A published example of what a validated expression feature looks like: a meta-analytic framework over large screening datasets found that specific transcript isoforms of IGF2BP2, NECTIN4, ITGB6, and KLHDC9 were significantly associated with response to AZD6244, lapatinib, erlotinib, and paclitaxel respectively [6]. Isoform-level features are a strong upgrade when your expression data has transcript resolution.

### Step 6. Train and Evaluate Without Leaking

Cell line panels contain families of related lines, and random splits can put near-duplicate lines in both train and test sets, inflating scores. Use cross-validation and, if you know lineage annotations, consider grouping by tissue type to stress-test generalization.

```python
from sklearn.model_selection import KFold, cross_val_predict
from sklearn.linear_model import Ridge
from sklearn.pipeline import make_pipeline
from sklearn.[preprocessing](/blog/data-analysis/what-is-data-preprocessing) import StandardScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error
from scipy.stats import pearsonr

model = make_pipeline(
    StandardScaler(),
    SelectKBest(f_regression, k=1000),
    Ridge(alpha=10.0)
)

cv = KFold(n_splits=5, shuffle=True, random_state=42)
pred = cross_val_predict(model, X, y, cv=cv)

rmse = np.sqrt(mean_squared_error(y, pred))
mae = mean_absolute_error(y, pred)
r, p = pearsonr(y, pred)
print(f"RMSE={rmse:.3f}  MAE={mae:.3f}  Pearson r={r:.3f}  p={p:.1e}")
```

Expected output for a reasonable single-drug model:

```
RMSE=0.612  MAE=0.447  Pearson r=0.581  p=3.2e-23
```

The pipeline is critical. `StandardScaler` and `SelectKBest` are fit inside each cross-validation fold on the training portion only, so no test-sample statistic leaks into feature selection. If you run `SelectKBest` on the full matrix first and then cross-validate, you will see a suspicious jump in r and you have measured leakage, not skill.

An `alpha` of 10.0 is a starting guess for ridge. Tune it:

```python
from sklearn.model_selection import GridSearchCV

grid = GridSearchCV(
    model,
    param_grid={"ridge__alpha": [0.1, 1.0, 10.0, 100.0]},
    cv=cv,
    scoring="neg_root_mean_squared_error"
)
grid.fit(X, y)
print(grid.best_params_, f"{-grid.best_score_:.3f}")
```

Expected output:

```
{'ridge__alpha': 10.0} 0.605
```

### Step 7. Predict Response for a New Sample

![Worked example converting a predicted log10 IC50 of -0.41 into an IC50 of 0.39 micromolar, showing the tenfold meaning of one log unit.](/article-images/illustrations/predict-drug-response-gene-expression-python-log-ic50-calc.webp)

After fitting on all data, predict a new sample whose [expression vector](/knowledge/molecular-biology/expression-vector) has the same gene order.

```python
model.fit(X, y)
new_sample = X[0:1]           # in practice, a new expression vector, same gene order
pred_log_ic50 = model.predict(new_sample)
print(f"Predicted log10(IC50) = {pred_log_ic50:.2f} -> IC50 = {10**pred_log_ic50:.2f} uM")
```

Expected output:

```
Predicted log10(IC50) = -0.41 -> IC50 = 0.39 uM
```

Lower IC50 means more sensitivity. A prediction of 0.39 micromolar says the sample is fairly sensitive, but always compare it to the distribution of predictions across your training set rather than judging the raw number.

## Choosing a Model

![Decision path from a ridge baseline to random forest, support vector regression or graph methods, depending on sample size and feature type.](/article-images/illustrations/predict-drug-response-gene-expression-python-model-choice.webp)

Start simple and escalate only when the baseline fails. The table summarizes the main options and when each earns its complexity.

| Model | Target type | When to use | Key caution |
|--|--|--|--|
| Ridge / Lasso regression | continuous (log IC50, AUC) | First baseline, small n, many genes | Requires features on comparable scales |
| [Random forest](/blog/data-analysis/what-is-random-forest) | continuous or class | Nonlinear effects, mixed feature types, strong tabular performer | Weaker extrapolation outside training range |
| Support vector regression | continuous | Small samples, robust to outliers | Kernel and C need tuning |
| Ensemble of cluster-local models | continuous | Heterogeneous samples, unknown subpopulations | More parts to validate |
| Neural network (MLP, CNN, transformer hybrids) | continuous or class | Large data, multimodal inputs | Needs much more data, easy to overfit |
| Graph convolutional network | continuous | When gene-gene network structure should inform the model | Requires a quality PPI graph and careful preprocessing |

Support vector regression combined with PCA and k-means clustering is the core of kESVR, which clusters the samples first and fits local SVR models inside each cluster. That design blends supervised and unsupervised learning and was compared against simple linear regression, plain SVR, quantile regression forests, and a back-propagation neural network on CCLE and CTRP data [3]. If you want to imitate it in scikit-learn, wrap `KMeans` plus `SVR` in a custom pipeline or use `ClusterCentroids`-style logic in a two-stage model.

Random forest is a strong classification choice in patient data. In the TCGA study of 5-fluorouracil and gemcitabine response, Clara clustering paired with random forest classification gave the best performance, and models trained across several cancer types outperformed single-cancer models [10]. That last finding is counterintuitive and worth testing yourself: pooling cancers increases sample size and forces the model to learn general resistance biology rather than tissue-specific noise.

## Beyond Baselines: What the Literature Adds

Once the baseline runs, the published literature tells you where the real headroom is.

**Network-aware deep learning.** DrugGCN overlays expression onto a protein-protein interaction network so the graph convolution reads out local gene subnetworks rather than individual genes, and reported high prediction accuracy against competing methods [8]. In scikit-learn terms there is no direct equivalent, but you can approximate network smoothing by averaging each gene's expression with its interaction partners before fitting a standard model. DIPK takes a related idea further with self-supervised integration of gene interaction relationships, expression, and molecular topology, and extends to single-cell RNA-seq data [9].

**Drug-induced signatures as extra features.** Drug response is a property of a sample and drug pair, yet a sample-only model treats every drug independently. Ensemble methods that add drug-induced expression signatures to screening data improved prediction and were validated experimentally in vitro [5]. With LINCS-style perturbation data you can append a drug's signature vector to each sample's expression vector and let the model learn sample-drug interactions.

**Handling the cell line to patient gap.** Models trained on cell lines often degrade on patient tumors. Velodrome frames this as out-of-distribution generalization, using labelled and unlabelled source data without assuming access to the target domain during training, which matches clinical deployment better than fine-tuning approaches [11]. For your own work, the cheapest safeguard is evaluating on a dataset from a different platform or consortium than your training data, never just held-out folds from the same matrix.

**Normalization as a first-class decision.** The cross-platform ulcerative colitis study makes the point bluntly: the normalization strategy was a decisive factor in whether models transferred from microarray to RNA-seq, with z-score and log2 approaches outperforming quantile normalization [7]. If you ever combine microarray and RNA-seq cohorts, test both standardizations before blaming the model.

**Resistance biology is dynamic.** In glioblastoma, multi-sampling of 128 tissue samples from 44 tumors, including primary, recurrent, and secondary recurrent cases plus stem-cell cultures, showed that intratumoral heterogeneity and longitudinal expression changes drive differential drug sensitivity, which means a single snapshot from one specimen can understate the variability a model must face [12]. Similarly, cell culture format matters. Prostate cancer lines grown in magnetic 3D bioprinted culture showed lower proliferation, more resistance to paclitaxel and docetaxel, and altered gene expression compared with standard 2D culture, making 3D systems more faithful for preclinical drug testing [13]. If your training data comes from 2D monolayers, treat predictions for 3D or in vivo settings as provisional.

**Cross-species transfer.** The COXEN approach filters gene signatures between human and dog datasets based on strong co-expression patterns, and expression-based models predicted doxorubicin treatment outcome correctly in 73 percent of canine osteosarcoma patients [14]. This demonstrates that expression-response signal can transfer across divergent datasets when the feature filter is conservative.

**Deep hybrids for resistance.** HybridDLDR combines CNN, LSTM, and transformer components on gene expression plus molecular descriptors for glioblastoma drug resistance, reporting an MSE of 0.4109, MAE of 0.5040, R2 of 0.9635, and a Pearson correlation of 0.9999 against existing models [15]. Treat such headline correlations with the skepticism described in the mistakes section, since near-perfect in-sample correlations usually signal evaluation problems rather than solved biology.

## Tips That Improve Results

1. **Log-transform the target, not just the features.** Regression on log10(IC50) stabilizes variance and makes residuals interpretable. Compare models on the log scale and report error back-transformed to fold-change.
2. **Standardize per gene with z-scores.** It is the normalization most likely to preserve signal across platforms [7], and it costs one line in a pipeline.
3. **Validate across datasets, not just within one.** Train on CCLE, test on GDSC for the same drug. If performance collapses, you have learned the true generalization ceiling, which cross-validation within one matrix hides.
4. **Use drug-specific feature panels cautiously.** Selecting features per drug inside the cross-validation loop is fine. Selecting them once on the whole dataset and reusing them across drugs is not.
5. **Push toward pathway and network features.** Both DrugGCN [8] and DIPK [9] attribute their gains to gene-gene relationship information. A lightweight network smoothing step is a cheap approximation.
6. **Match your evaluation to the decision.** If the clinical use case is a responder versus non-responder call, evaluate AUC on a binary version of the outcome, as the TCGA models did [2], in addition to RMSE.
7. **Use patient-derived signature databases for clinical grounding.** CTR-DB lets you search and download uniformly processed patient transcriptomes with response labels, which is a far better validation set for a clinical claim than another cell line panel [4].
8. **Version everything.** Record the exact DepMap and GDSC release dates, file checksums, and package versions. Drug screens are reprocessed frequently and results will shift between releases.

## Common Mistakes and Limitations

**Leakage through feature selection.** Running `SelectKBest`, differential expression, or any per-gene filter on the full dataset before splitting is the most common way first models reach inflated accuracy. Keep every data-dependent transform inside the pipeline and the folds.

**Leakage through duplicate cell lines.** Many panels include lines derived from the same patient or from the same tissue with near-identical karyotypes. Random splits place them in both train and test. Group by lineage or patient-of-origin where annotations exist.

**Merging on the wrong identifier.** Cell line names differ in case, hyphenation, and aliases across CCLE, GDSC, and CTRP. A merge that silently matches 40 percent of rows produces a model trained on a biased subset. Always print the overlap fraction and inspect unmatched names.

**Ignoring the platform.** Microarray and RNA-seq expression are not interchangeable without reprocessing, and quantile normalization across platforms can actively destroy signal [7]. When combining cohorts, check per-gene distribution overlap first.

**Reporting R2 or correlation from a biased evaluation.** Very high reported correlations in the literature, including the 0.9999 figure from a deep glioblastoma model [15], should prompt you to check how the evaluation split was built before setting your expectations by them.

**Forgetting that response is sample and drug specific.** A model for one drug says nothing about another drug until you retrain or add drug features such as induced signatures [5] or molecular descriptors [15].

**Overtrusting cell line predictions for patients.** The data discrepancy between preclinical and clinical datasets is a recognized major challenge, and methods that assume access to the target domain during training fail that assumption in deployment. Position cell line models as hypothesis generators.

**Underweighting tumor heterogeneity and model system.** Single-specimen snapshots miss intratumoral and longitudinal variability documented in glioblastoma [12], and 2D cultures behave differently from 3D systems in both expression and measured drug resistance [13]. These are properties of the biology, not bugs in your code, and they bound what any expression model can promise.

**Interpreting correlated genes as mechanisms.** A high-weight gene is a predictive feature, not necessarily a driver. Even in a focused pharmacogenomic context, tightly related genes can carry opposite relationships with drug-metabolism expression programs, as shown for STAT5A and STAT5B in human liver samples [16]. Validate hits experimentally before building a story.

**Individual clinical decisions.** Models of this kind inform research and stratification, they do not replace clinical judgment, and any real patient case requires the treating oncologist and standard clinical testing.

## Frequently Asked Questions

### Can I really predict drug response from gene expression alone?

Yes, to a useful but limited degree. Published models reach moderate to good accuracy, for example up to 86 percent accuracy predicting patient response to two chemotherapeutics from TCGA tumor expression [2], and expression-only models remain the most common baseline in the field. Accuracy drops when you transfer across platforms or from cell lines to patients.

### What Python libraries do I need for a first model?

pandas, numpy, scikit-learn, scipy, and matplotlib cover loading, preprocessing, modeling, and evaluation. Add seaborn for plots and, when relevant, Biopython for sequence and annotation tasks.

### Where can I get training data?

DepMap (CCLE expression), GDSC and CTRP (cell line drug screens), TCGA (patient tumors with clinical outcomes) [2], and CTR-DB (curated patient transcriptomes with response data) [4] are the standard public starting points.

### Should I model IC50 or AUC?

Model log10(IC50) if you care about potency, or AUC if you care about overall sensitivity across the tested dose range. Log-transforming IC50 makes errors interpretable as fold-changes. Whichever you pick, state it clearly and evaluate on it consistently.

### How many genes should I use as features?

Fewer than you might think. A few hundred to a few thousand genes, chosen inside cross-validation and ideally informed by pathways or prior screens, usually beats using all genes. Network-informed selections tend to generalize better than purely statistical top-k lists [8].

### How do I know if my model is overfitting?

Compare cross-validation performance with performance on a completely separate dataset, ideally from a different consortium or platform. If cross-validated scores are strong and the external score collapses, you have an overfit or non-generalizable model, which is the expected failure mode for cell-line-trained models applied elsewhere.

### Can a model trained on cell lines be applied to patient tumors?

Sometimes, with reduced accuracy. The discrepancy between preclinical and clinical data is a recognized core challenge, and out-of-distribution methods exist specifically to address it. Patient-derived datasets such as those in CTR-DB are the right place to test the transfer before making clinical claims [4].

### Is Biopython useful for drug response prediction?

Indirectly. Biopython handles sequences, file formats, and NCBI queries, which supports annotation and upstream processing, but the expression matrices and drug response tables in this workflow are handled by pandas and scikit-learn. A typical pipeline uses Biopython for reference data and pandas for the modeling inputs.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Can I really predict drug response from gene expression alone?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes, to a useful but limited degree. Published models reach moderate to good accuracy, and expression-only models remain the most common baseline in the field. Accuracy drops when you transfer across platforms or from cell lines to patients."
      }
    },
    {
      "@type": "Question",
      "name": "What Python libraries do I need for a first model?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "pandas, numpy, scikit-learn, scipy, and matplotlib cover loading, preprocessing, modeling, and evaluation. Add seaborn for plots and, when relevant, Biopython for sequence and annotation tasks."
      }
    },
    {
      "@type": "Question",
      "name": "Where can I get training data?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "DepMap (CCLE expression), GDSC and CTRP (cell line drug screens), TCGA (patient tumors with clinical outcomes), and CTR-DB (curated patient transcriptomes with response data) are the standard public starting points."
      }
    },
    {
      "@type": "Question",
      "name": "Should I model IC50 or AUC?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Model log10(IC50) if you care about potency, or AUC if you care about overall sensitivity across the tested dose range. Log-transforming IC50 makes errors interpretable as fold-changes. Whichever you pick, state it clearly and evaluate on it consistently."
      }
    },
    {
      "@type": "Question",
      "name": "How many genes should I use as features?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Fewer than you might think. A few hundred to a few thousand genes, chosen inside cross-validation and ideally informed by pathways or prior screens, usually beats using all genes. Network-informed selections tend to generalize better than purely statistical top-k lists."
      }
    },
    {
      "@type": "Question",
      "name": "How do I know if my model is overfitting?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Compare cross-validation performance with performance on a completely separate dataset, ideally from a different consortium or platform. If cross-validated scores are strong and the external score collapses, you have an overfit or non-generalizable model."
      }
    },
    {
      "@type": "Question",
      "name": "Can a model trained on cell lines be applied to patient tumors?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Sometimes, with reduced accuracy. The discrepancy between preclinical and clinical data is a recognized core challenge, and out-of-distribution methods exist specifically to address it. Patient-derived datasets are the right place to test the transfer before making clinical claims."
      }
    },
    {
      "@type": "Question",
      "name": "Is Biopython useful for drug response prediction?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Indirectly. Biopython handles sequences, file formats, and NCBI queries, which supports annotation and upstream processing, but expression matrices and drug response tables are handled by pandas and scikit-learn."
      }
    }
  ]
}
</script>

## Sources

1. [Predicting drug response based on gene expression.](https://pubmed.ncbi.nlm.nih.gov/15331079/)
2. [Leveraging TCGA gene expression data to build predictive models for cancer drug response](https://pubmed.ncbi.nlm.nih.gov/32998700/)
3. [kESVR: An Ensemble Model for Drug Response Prediction in Precision Medicine Using Cancer Cell Lines Gene Expression](https://pubmed.ncbi.nlm.nih.gov/34070793/)
4. [CTR-DB, an omnibus for patient-derived gene expression signatures correlated with cancer drug response](https://pubmed.ncbi.nlm.nih.gov/34570230/)
5. [Drug response prediction by ensemble learning and drug-induced gene expression signatures](https://pubmed.ncbi.nlm.nih.gov/31533900/)
6. [Gene isoforms as expression-based biomarkers predictive of drug response in vitro](https://pubmed.ncbi.nlm.nih.gov/29066719/)
7. [UCResponNet-X: cross-platform multi-dataset gene expression for predictive modeling of drug response in ulcerative colitis.](https://pubmed.ncbi.nlm.nih.gov/42717746/)
8. [Graph Convolutional Network for Drug Response Prediction Using Gene Expression Data](https://doi.org/10.3390/MATH9070772)
9. [Improving drug response prediction via integrating gene relationships with deep learning](https://pubmed.ncbi.nlm.nih.gov/38600666/)
10. [Abstract 676: Leveraging TCGA gene expression data to build predictive models for cancer drug response](https://doi.org/10.1158/1538-7445.AM2019-676)
11. [Out-of-distribution generalization from labelled and unlabelled gene expression data for drug response prediction](https://doi.org/10.1038/s42256-021-00408-w)
12. [Intratumoral Heterogeneity and Longitudinal Changes in Gene Expression Predict Differential Drug Sensitivity in Newly Diagnosed and Recurrent Glioblastoma](https://pubmed.ncbi.nlm.nih.gov/32102350/)
13. [Comparative Assay of 2D and 3D Cell Culture Models: Proliferation, Gene Expression and Anticancer Drug Response.](https://pubmed.ncbi.nlm.nih.gov/29623827/)
14. [Intra- and interspecies gene expression models for predicting drug response in canine osteosarcoma](https://pubmed.ncbi.nlm.nih.gov/26892349/)
15. [HybridDLDR: A hybrid deep learning-based drug resistance prediction system of Glioblastoma (GBM) using molecular descriptors and gene expression data](https://pubmed.ncbi.nlm.nih.gov/40592112/)
16. [STAT5A and STAT5B have opposite correlations with drug response gene expression](https://pubmed.ncbi.nlm.nih.gov/27264955/)