Ahmed Doghri Logo Image
Ahmed Doghri

cellcontext

The same perturbation lands differently in different cells. cellcontext keeps the cellular context in the model and cuts synthetic response error by 32.8%.

cellcontext reproduced benchmark result

A Cell Is Not An Empty Test Tube

A gene knockout does not have one universal answer. Cell state, lineage, and baseline expression all change the response. A global average can look sensible while missing the cells that matter.

cellcontext generates controlled expression profiles with shared perturbation effects and context-specific interactions. It then holds out context-perturbation pairs, which prevents the benchmark from rewarding memorization.

Keep The Context, Keep The Signal

The baseline learns one average effect per perturbation. The context-aware method retrieves the closest observed cellular state and transfers its residual response instead.

That is deliberately smaller than a single-cell foundation model. The mechanism stays visible, the failure mode stays measurable, and the whole experiment runs with the Python standard library.

Update: "closest observed cellular state" was, on inspection, closest array index. Fixed with a real data-driven similarity measure. Full writeup below.

The Number

Global averaging lands at 0.2699 mean absolute error. Context-aware transfer lands at 0.1813, a 32.8% reduction on held-out context-perturbation pairs.

The benchmark is synthetic and explicitly non-clinical. One deterministic test passes locally and in GitHub Actions on Python 3.9, 3.11, and 3.13.

"Nearest Context" Was Nearest Array Index

The context-aware method's nearest-neighbor step was min(abs(cc - c)) — the context whose integer index was numerically closest to the test context's index. That only counts as "similarity" because the synthetic generator builds the interaction term as a straight line in context index. Real cellular contexts (cell types, donors, tissues) carry no such built-in ordering, so this wasn't demonstrating anything about context transfer in general — it was reading off a property of the data generator.

To check, I built an adversarial variant that shuffles each context's latent identity away from its array index, so index order no longer tracks the true driver of the effect — the situation any real dataset would actually be in. Run through the unmodified index-proximity method, mean error reduction goes solidly negative: -27.7% across 30 tuning seeds and -35.5% on a disjoint 20-seed holdout evaluated once, worse than just averaging.

The fix swaps index distance for a similarity computed straight from training data: two contexts count as "near" if their observed effects agree on the perturbations both have already been measured for. That holds a positive ~30% mean reduction on both the tuning and holdout sweeps, and it still matches — slightly beats, in fact — the original 32.8% number on the unshuffled data (33.9%). The original module is untouched; the published number still reproduces exactly.

Research Basis

Inspired by Nature Methods' 2025 perturbation-response benchmark. The portfolio number above comes from this repository's own controlled benchmark, not from the paper.

Tools Used

Python
Single-Cell Biology
Perturb-seq
Context Transfer
Benchmarking
Data-Driven Similarity
unittest