Skip to content

fix(predict): disable uninformative RBP model behind an honest 1.0 default#101

Merged
jam-sudo merged 2 commits into
mainfrom
fix/rbp-transform-honest-default
Jul 5, 2026
Merged

fix(predict): disable uninformative RBP model behind an honest 1.0 default#101
jam-sudo merged 2 commits into
mainfrom
fix/rbp-transform-honest-default

Conversation

@jam-sudo

@jam-sudo jam-sudo commented Jul 5, 2026

Copy link
Copy Markdown
Owner

What

The RBP prediction path carried a compound bug that this PR replaces with an explicit, honest default.

xgboost_rbp.json's target is a raw blood:plasma ratio (per its meta.json), but _predict_rbp read the model output as log10(RBP) and applied 10** — inflating every prediction (e.g. caffeine 0.72 → 5.3) past the [0.5, 3.0] clip ceiling. An asymmetric reset abs(rbp - 1.0) > 0.5 — whose low branch is unreachable (clip floor 0.5 sits exactly on the threshold) — then snapped the clipped 3.0 down to 1.0.

Net effect: all 107 holdout drugs resolved to exactly 1.0 regardless of structure (verified empirically: KEPT=0/107).

Why this is the right fix

The model is uninformative — scaffold-CV R²=−0.08, i.e. worse than predicting the population mean — and its own meta.json documents the intended behaviour: "Pipeline defaults to RBP=1.0." Activating the model (fixing only the 10**) would inject known-worse-than-mean noise into all 107 drugs and require a benchmark re-pin, against the correctness-first principle. Instead, _predict_rbp() now returns a constant Distribution(1.0, cv=_RBP_CV), making the documented default explicit rather than incidental.

Headline impact: none (bit-identical)

Both the old buggy path and the new constant yield Distribution(mean=1.0, cv=0.3) for every holdout drug — confirmed via the real predict_adme path on a diverse sample (sirolimus, digoxin, morphine, quinine, tamoxifen, abacavir, famotidine). No canonical regen / re-pin required.

Changes

  • _predict_rbp → constant Distribution(1.0, cv=_RBP_CV); removes the 10** mis-transform, the dead-branch reset, and the misleading log_rbp naming. Docstring records the history.
  • Caller updated (rbp = _predict_rbp()).
  • Model file xgboost_rbp.json retained for a future retrain.
  • Tests: _predict_rbp() is a constant 1.0 with _RBP_CV; RBC partitioners (chloroquine, tacrolimus) are not distinguished from aspirin/benzene.

Tests

tests/unit/test_adme_ivive.py 22 passed; broad downstream sweep (predict/engine-flux/pipeline/model-registry) 134 passed.

…fault

The RBP path carried a compound bug. xgboost_rbp.json's target is a raw
blood:plasma ratio (per its meta.json), but _predict_rbp read the output as
log10(RBP) and applied 10**, inflating every prediction (caffeine 0.72 -> 5.3)
past the [0.5, 3.0] clip ceiling. An asymmetric reset (abs(rbp-1.0) > 0.5)
whose low branch was unreachable then snapped the clipped 3.0 down to 1.0. Net
effect: all 107 holdout drugs resolved to exactly 1.0 regardless of structure.

The model is uninformative anyway (scaffold-CV R2=-0.08, worse than the mean),
and its meta.json documents the intended behaviour outright: default to 1.0.
Make that explicit instead of incidental: _predict_rbp() returns a constant
Distribution(1.0, cv=_RBP_CV). Output is bit-identical to the old buggy path on
every holdout drug (verified via the real predict path), so no benchmark
re-pin is required. The model file is retained for a future retrain.

Removes both bugs (the 10** mis-transform and the dead-branch reset) and the
misleading log_rbp naming. Adds guards that _predict_rbp() is a constant 1.0
and that RBC partitioners (chloroquine, tacrolimus) are not distinguished.
@jam-sudo
jam-sudo enabled auto-merge (squash) July 5, 2026 01:57
@jam-sudo
jam-sudo merged commit f8a4663 into main Jul 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant