high
A 3-sample noise estimate errs in both directions, so magnitude verdicts are provisional but not systematically inflated
CYP1A2's three-seed SD came in at half the truth; CYP2D6's came in 13% above it. Unreliable, not biased -- which is a much narrower problem than it first looked.
Deep dive
Every honest-gate run printed an effect-versus-seed-noise ratio whose denominator was the standard deviation of the SAME THREE SEEDS that measured the effect. Measuring both bottleneck isoforms' deployed base arms across 12 seeds gives CYP1A2 a true SD of 0.0072 against a 3-seed estimate of 0.0037 (51%, understated) and CYP2D6 a true SD of 0.0052 against a 3-seed estimate of 0.0059 (113%, OVERstated). The first result alone suggested past verdicts were systematically flattering; the second shows they are not. The correct and narrower statement is that a 3-sample SD is unreliable in both directions -- statistical bias accounts for only about 11% at n=3, so the rest is sampling luck -- and every magnitude verdict is therefore provisional until that isoform's SD is measured properly, with no systematic correction to apply. Re-reading both isoforms against measured nulls: CYP1A2's bandl2 at -0.0206 is 2.86 SD and comfortable, its external+3D joint at -0.0104 is 1.45 SD and marginal; CYP2D6's mechanistic block at -0.0077 is 1.48 SD and marginal, which matches the 'weak' label it carried when it deployed. Both isoforms' marginal deploys land within 0.03 SD of each other, at 1.45 and 1.48. The practical outputs are a per-isoform bar for future work -- roughly 0.0072 on CYP1A2 and 0.0052 on CYP2D6 -- and a procedural note that the ratio the gates print should be read as a rough flag rather than a measurement.
honest-gateseed-variancecalibrationself-correctioneffect-sizeswarm · 2026-08-25
high
A 3-seed gate is a weak instrument in both directions - it vetoed one real effect and nearly under-sold another
The same three-seed rule that blocked three CYP3A4-TDI experiments by chance also under-measured a real CYP1A2 effect by a third. More seeds fixes both; adjusting the threshold fixes neither.
Deep dive
Two results now bracket the same weakness. On CYP3A4-TDI a single seed vetoed three consecutive experiments while the other two favoured all three, and auditing 20 seeds showed that seed was the MOST balanced split of the twenty -- the veto was chance. On CYP1A2 the external+3D block measured -0.0104 across three seeds, which the properly calibrated null of 0.0072 put at 1.44 SD, marginal enough that I explicitly weakened my earlier claim about it. Re-running at 12 seeds gives -0.0154, negative on 12 of 12, and 2.14 SD -- established rather than marginal, and the point estimate got LARGER with more data. That direction matters: an effect originally selected for looking impressive should regress toward the mean when re-measured, so growth suggests the original three seeds were unlucky rather than lucky. The general rule is that an all-must-agree rule over three draws has poor power against effects near one SD and errs in BOTH directions, rejecting real effects and certifying small ones, and the remedy in either case is more seeds rather than a looser criterion -- loosening would trade one error for the other. The practical protocol adopted: any effect landing between roughly 1 and 2 SD of its isoform's measured null should be re-run at 12 seeds before being trusted or discarded, with the outcome pre-committed both ways. A secondary observation from the same run: the super-additivity of the two blocks survived quadrupling the seeds, with neither block reaching seed-stability alone even at 12 seeds (9/12 and 8/12) while the pair is perfect at 12/12 and beats its additive prediction of -0.0126.
honest-gatepowerseed-variancereplicationpre-registrationswarm · 2026-08-24
high
A band-aware loss DEGENERATES on imputed donor rows -- and donors are 62-71% of training rows on three of four isoforms
Donor rows are appended with lo = hi = the imputed value. A zero-width band turns bandl2 into plain squared error, so the metric-matched dead zone applies only to real rows. The more donors, the less of the training set is actually fitted under the metric.
Deep dive
Re-deriving the loss gate under the LCO-resolvability rule flipped exactly one arm: CYP3A4 bandl2, -0.0050 at 3/3 seeds and 1.36x its measured seed SD, originally vetoed by an LCO delta of +0.0009 against a 0.0067 threshold. Re-measured inside the deployed stack the sign REVERSES to +0.0034 at 0/3 (control passes: l2 0.4504 vs deployed 0.4492). Removing bagging leaves +0.0025, so the interacting layer is the TDI-donor layer, not bagging. The outcome tracks donor share: 1A2 at 0.0% donors WON -0.0206 (3/3, 2.86 SD) and is the only isoform shipping bandl2; CYP3A4 at 52.4% won -0.0050; the same isoform at 62.1% lost +0.0025; 2D6 at 65.9% and 2C9 at 70.6% both lost. The within-isoform pair is the cleanest evidence -- everything else held fixed, 1,249 extra donor rows flipped the sign. Forward rule: any future band-aware loss must either give donors a real width or be tested at the donor share it will actually meet.
st-raeloss-functionbandl2donorsimputationsixth-criterionrejectedscripts/train/rederive_objective.py, objective_in_deployed.py; data/processed/objective_in_deployed_cyp3a4.json; ledger #97 · 2026-08-27
high
A block can be strongly HARMFUL because a later layer already supplies its information another way
The aux block feeds single-concentration predictions in as columns. The imputation layer feeds the same screen in as rows. Same data twice, and the column version is a noisy estimate of what the rows give directly.
Deep dive
CYP3A4's aux block gated at -0.0129 with all seeds improving, and in the deployed pipeline it measures +0.0495 at 0 of 3 seeds and 13.38 SD -- a swing of +0.062 with a sign flip, the most extreme configuration-dependence recorded in this campaign. The mechanism is redundancy by another route: the imputation layer supplies 2,571 single-concentration donor ROWS on that isoform, and the aux block supplies model predictions of the same screen as COLUMNS. Two blocks were silently dropped from shipped models by the imputation gate running its arms on 'base' alone, and both were aux-type blocks -- so the layer that dropped them was precisely the layer that made them redundant. The accidents were not random and that is why all four came out fortunate. Practical consequence: when auditing whether a passing block belongs in a stack, check whether a later layer already carries its information, because such a block does not merely fail to help, it actively hurts. The corollary for gate design is that a block gated before a data layer exists cannot be assumed to survive that layer's arrival.
redundancyimputationaux-blocksixth-criterioncyp3a4configurationscripts/train/mech_readd.py; data/processed/aux_readd.json; ledger #119 · 2026-08-28
high
A block carrying the WRONG kind of information is worse than a block carrying none
384 random columns cost CYP2D6 nothing; the same 384 columns filled with ChemBERTa cost it 0.0178.
Deep dive
Frozen ChemBERTa-77M-MLM embeddings were gated on CYP2D6's deployed pipeline (control reproduces at 0.8930). The real block is +0.0178 WORSE, 0 of 3 seeds, 3.01 SD. Because 384 columns on a 2,265-column base is a 17% widening, a permutation null was run: the block row-shuffled at two seeds, keeping width, column marginals and collinearity while destroying the molecule-to-feature link. Nulls: -0.0028 and +0.0030, mean +0.0001. A signal-free block of identical shape is FREE. So the failure is not dimensionality dilution -- it is what the embedding encodes. Working hypothesis: ChemBERTa's MLM objective rewards reconstructing masked SMILES tokens, so it encodes syntactic and scaffold similarity, while CYP2D6's signal is orthogonal to gross structural similarity (uncorrelated with all three other isoforms, driven by a protonatable-amine pharmacophore). Confident scaffold-similarity features give a tree something to split on that does not survive a scaffold split; random features give it nothing to overfit. Practical consequence: when a wide block is rejected, run the permutation null before blaming width -- and if the null is free, the fix is to change WHAT is encoded, not to reduce dimensionality.
chembertarepresentationcyp2d6permutation-nulldimensionalitydata/processed/reverify_emb_cyp2d6.json · 2026-08-25
high
A candidate measured on a co-measured subset is measuring the subset
Compounds run on several isoforms were chosen by the organisers. Any effect estimated on them inherits that choice, and a stripped baseline inflates it further.
Deep dive
Cross-task stacking looked like a real lever on the co-measured subsets: CYP2C9 <- predicted CYP3A4 gave -0.0522 ST-RAE (n=473) and CYP2D6 <- predicted CYP3A4 gave -0.0476 (n=250), both comparable to the largest levers ever deployed in this campaign. On the full training sets with the DEPLOYED recipes, both reversed sign and were rejected: CYP2C9 +0.0125 with LCO 0.6164 -> 0.6330, CYP2D6 +0.0037 with LCO 0.9215 -> 0.9247, neither seed-stable, and both base arms reproducing their deployed score exactly (0.6033 and 0.8930), so the harness was sound. Two distinct inflations were at work. First, SELECTION: compounds measured on several isoforms are not a random draw, so an effect fitted on them need not generalise to the 73% measured on one. Second, a STRIPPED BASELINE: the subset arm used a plain base with no imputation, while the deployed recipes feed ALL FOUR isoforms' single-concentration log2fc into the imputation calibration -- so the cross-isoform signal was already in the incumbent and the subset experiment merely rediscovered it. This is the absorbed-by-base pattern operating at the scale of a whole modelling family rather than one feature block. Rule: measure against the deployed pipeline on the full training set, or you will rediscover what you already have and call it an improvement.
selection-biassubsetabsorbed-by-basemultitaskstackingswarm · 2026-08-24
high
A cheap pilot with a pre-registered contrast killed a 3,000-cofold plan for about five dollars
Before scaling an expensive mechanism, buy the smallest experiment that could falsify it.
Deep dive
The cofold heme-Fe lever was the top-ranked remaining idea for CYP2D6 and was scoped as ~3,000 cofolds on Explorer. Instead: 24 compounds, deliberately stratified across the full pIC50 range so a real effect would be visible at tiny n, with the decision rule fixed BEFORE looking (Cohen's d > 0.5 on the potent-vs-inactive contrast supports scaling). Cost .80 and about 20 minutes. Result d=0.34 - below threshold - so the array is not funded. Extrapolating the full run at the same /usr/bin/bash.20/ligand and 5 samples, this saved roughly 00 of shared Boltz credit plus days of Explorer queue, and more importantly avoided building an entire feature pipeline on a mechanism that does not hold. The general lesson for the campaign: stratify the pilot across the response range rather than sampling randomly (random 24 would mostly have been inactives and shown nothing either way), and write the decision rule down first.
pilotcost-controlexperiment-designfalsificationcofold-pilot · 2026-08-23
high
A cheap screen's rule held over its measured range and broke on the first point outside it
The disagreement-direction rule fit five points perfectly across a span from -0.175 to +0.027. The first candidate scoring +0.118 was predicted to help most and made things worse -- the rule interpolates, it does not extrapolate.
Deep dive
Screening four candidate second families on CYP2D6 for one seed each returned morgan_only (LightGBM on the 2048 Morgan bits, no physchem) at a disagreement of +0.118, over 4x the incumbent ExtraTrees' +0.027 and the first candidate ever in the strongly positive regime. Its gate: +0.0092, 0/3 seed-stable, 1.78 SD worse, control reproducing -- rejected. Adding the point drops the rule's fit from spearman -1.00 / pearson -0.963 to -0.83 / -0.588. Mechanism, foreseeable in hindsight: morgan_only is a strict feature SUBSET of the deployed model, so it is a degraded copy rather than an independent view, and such a candidate can show disagreement aligned with the base's error just by being noisier in a correlated way. The screen cannot separate correcting the base from over-correcting along the base's own error axis. Restriction to a subset of the incumbent's inputs is therefore not a second family. The complementary lesson came from ridge, which scored positive (+0.068) with a solo MAE of 1.3190 against the deployed model's ~0.58: direction without competence is worthless, and the rule had been reduced to direction alone. The screen still paid for itself -- four candidates for about 25 minutes versus hours to gate them all -- because its verdicts buy a gate and never a deploy.
ensemblingscreeningextrapolationscoperefutedcyp2d6scripts/train/candidate_screen.py, candidate_gate.py; data/processed/candidate_screen_cyp2d6.json, candidate_gate_cyp2d6_morgan_only.json; ledger #114 · 2026-08-28
high
A control is only as good as the thing it controls against
The fifth gate criterion asks whether the baseline reproduces the deployed score. It silently answered yes against a model we had already replaced.
Deep dive
Two ticks ago the campaign adopted a fifth gate criterion after a -0.0402 artifact: any harness re-implementing a deployed pipeline must reproduce that pipeline's deployed score before its deltas are transferable. It was implemented as deployed_score(), which reads the FEATURE/IMPUTATION gate artifact. One tick later the objective gate (#44) added a layer ON TOP -- CYP1A2 now ships bandl2 at 0.8139 while final_cyp1a2.json still records 0.8345 for its superseded l2 pipeline. The external-feature gate then ran, its base arm scored 0.8345, the control printed REPRODUCES INCUMBENT, and it certified a -0.0118 'improvement' to 0.8214 -- which is WORSE than the 0.8139 already deployed. The control passed while comparing against a model that no longer exists. Fixed by making deployed_score() consult the objective artifact first and fall back to the recipe artifact, and by fitting BOTH arms of the gate under the objective the isoform actually ships. The general failure is that a layered pipeline has a layered incumbent, and a control anchored at one layer goes stale the moment another layer is added -- so the anchor must be derived from the full deployment path, not from whichever artifact was current when the control was written. Worth noting the rule violated here is one this campaign wrote down the previous tick: measure against the DEPLOYED pipeline. Writing a rule down does not implement it.
honest-gatecontrolincumbentlayered-pipelineself-correctionswarm · 2026-08-24
high
A dead-zone loss must apply to MEASURED rows only -- on imputed rows it discards the only signal there is
A credible band on a real row encodes measurement precision, so ignoring error inside it is free. An imputed row has no measurement; its label is the model's only handle on that chemistry, and a dead zone around it throws the gradient away.
Deep dive
#97 attributed bandl2's failure on donor-heavy isoforms to a degeneracy -- donors enter with lo = hi, collapsing bandl2 to plain squared error. Testing the fix that mechanism implies REFUTED it: widening donor bands to imputed +/- k*calibration-residual SD on the deployed CYP3A4 stack gives +0.0034 (k=0) -> +0.0040 (k=1) -> +0.0141 (k=2), monotonically worse, 0/3 seed-stable throughout, control passing. Revised account fitting both results: bandl2's benefit is the dead zone on REAL rows only, and the donor share in #97's table tracks DILUTION of those rows -- CYP3A4 fell from 47.6% real to 37.9% real when 1,249 TDI donors were added, and the sign flipped. CYP1A2, the only isoform with zero donors, is the only one shipping bandl2. The zero-width degeneracy turns out to be the least-bad treatment of donor rows, not the defect. Loss-function family closed for the three donor-bearing isoforms.
st-raeloss-functionbandl2imputationdonorsrefutedself-correctionscripts/train/donor_band_gate.py; data/processed/donor_band_cyp3a4.json; ledger #98 · 2026-08-27
high
A difference of two precise numbers can be imprecise, and no model recovers that
Both pIC50 levels are well measured and well predicted. Their difference is mostly measurement error, because subtraction cancels the shared signal and adds both noises.
Deep dive
The TDI shift is pIC50-under-preincubation minus pIC50-direct, and the binary TDI label is that shift thresholded at log10(2). Measured on identical rows and folds, the two LEVELS are healthy and the DIFFERENCE is not. CYP3A4: TDI-condition pIC50 has SD 1.132 against a mean credible-band width of 0.715 (ratio 1.58) and predicts at scaffold-CV spearman 0.717; direct pIC50 1.093 / 0.878 / 1.25 and rho 0.740; the SHIFT has SD 0.364 against a band width of 1.157 -- ratio 0.31, its measurement width more than 3x its entire population spread -- and predicts at rho 0.278. CYP2D6 is the same shape: levels at ratio 2.17 and 1.86 with rho 0.308 and 0.352, shift at ratio 0.64 with rho 0.076. Predictability collapses in lockstep with the ratio. This explains, retroactively, why five separate TDI attempts (baseline, class weighting, label-confidence weighting, structural alerts, and now shift regression) all failed on CYP2D6: the underlying continuous quantity is essentially unpredictable from structure, so the MCC 0.9011 oracle from thresholding the TRUE shift is unreachable in principle rather than merely in practice. Two rules follow. Before modelling a DERIVED quantity, check its spread against its own measurement width -- subtraction destroys information that no model can recover, and regressing two levels separately then subtracting is worst of all because it compounds two models' errors (two_reg was the weakest arm on both isoforms). And where a derived target is noise-dominated, the THRESHOLDED label is the better target, because thresholding acts as variance reduction -- the opposite of the usual intuition that binarising discards information.
tdinoise-floorderived-targetssubtractionmeasurement-errorswarm · 2026-08-24
high
A donor set can be worse alone and still worth adding
Gating a new source against the incumbent source asks the wrong question. The question is whether the union beats either, and coverage can win where quality loses.
Deep dive
CYP3A4's imputation gate compared four arms on identical rows: no imputation 0.5307, the deployed single-concentration donors 0.4773, the new TDI-condition donors alone 0.5159, and both together 0.4643. The new donors are clearly WORSE than the incumbent donors on their own -- by +0.0386, a margin the honest gate calls meaningful -- and yet adding them to the incumbent is worth -0.0130 ST-RAE, seed-stable on 3/3 with LCO improving 0.5120 to 0.5020. Had the experiment been framed as 'are TDI-condition donors better than single-conc donors', the answer would have been a confident no and the win would have been discarded. What makes them pay is COVERAGE rather than quality: 1,238 of the 1,249 TDI-condition donors are absent from the single-concentration screen entirely, so they extend the chemistry rather than re-describe it, and their individually noisier labels are outweighed by reaching compounds the incumbent never sees. This is a concrete instance of the campaign's standing rule that combinations must be measured per isoform every time -- interference, super-additivity and substitution have each held exactly once here and generalised to nothing. It also sharpens ledger #46's null: improving calibration QUALITY bought nothing on the shift-corrected isoforms, while adding ROWS on the un-shifted isoform pays. Those are different levers, and the earlier negative did not transfer across them.
imputationdonorscoveragecombination-effectscyp3a4swarm · 2026-08-24
high
A layer can DROP a block silently, because the configuration is inferred from an artifact filename
Nobody decided to remove CYP2C9's aux block. A later gate ran its arms without it, and the recipe reader then inferred it was never there.
Deep dive
recipe() reconstructs each isoform's configuration by matching artifact filenames (impute_bias_mech_emax_<iso>.json -> 'base+mech', impute_bias_emax_<iso>.json -> 'base'). CYP2C9's aux block won final_cyp2c9.json at 0.6894; the imputation gate that superseded it ran none/r2/shift on 'base' alone, so the filename carries no aux and the shipped model has cfg='base'. The drop was invisible because every individual step was correct. Re-tested properly, adding the block back on top of imputation costs +0.0539 ST-RAE, 0 of 3 seeds helped, LCO agreeing -- so the accident was fortunate, but it was still an accident. The general risk: any layer that re-gates a subset of the configuration can silently discard the rest of it, and inferring configuration from filenames makes the loss unobservable. A deployed recipe should be an explicit record, not a string parsed out of a path.
layeringrecipecyp2c9harnessauxdata/processed/reverify_aux_cyp2c9.json · 2026-08-25
high
A leave-cluster-out gain does not forecast a scaffold-CV gain - they came apart completely
I predicted CYP3A4 would benefit because its external block improved LCO. The LCO improvement happened exactly as predicted, and scaffold-CV got meaningfully worse at the same time.
Deep dive
Priors were recorded in advance for the joint external+3D gate. CYP3A4 was called the best chance of the three untested isoforms, on the grounds that its external block had improved leave-cluster-out by -0.0075 even while failing seed-stability. The prediction was refuted, and informatively: CYP3A4 is the WORST of the three rejections at +0.0156, its external block costing +0.0125 on scaffold CV, while its LCO improved exactly as forecast (0.5020 -> 0.4976 for +ext, 0.4973 for +both). The two splits did not merely disagree in magnitude, they moved in opposite directions on the same arm. So LCO and scaffold CV are measuring different things, and an LCO gain cannot be treated as a faint or noisy version of a scaffold-CV gain that better seeds would reveal. That has a direct consequence for the campaign's outstanding flag. CYP1A2 had twice shown resolvable LCO gains alongside scaffold-CV instability, and a pre-registered condition was logged for revisiting those blocks if a leaderboard signal ever suggested scaffold CV was optimistic. That condition should now be read narrowly: it applies to CYP1A2, where the two splits AGREED once the blocks were combined (-0.0104 with LCO 0.8420 -> 0.8267), and not to CYP3A4, where they actively contradict each other. The general form: when two validation schemes disagree, that is information about the schemes, and resolving it requires a third source of truth rather than a preference for whichever one currently favours deployment.
validationleave-cluster-outscaffold-cvrefuted-priorforecastingswarm · 2026-08-24
high
A lever is worth its ceiling times the fraction that survives estimation
Both TDI isoforms have a real, sizeable threshold ceiling. Neither can be captured - and on the weaker one, trying makes things worse than doing nothing.
Deep dive
Measuring the MCC-optimal decision threshold on both scored TDI isoforms gave genuine headroom in each case: CYP3A4 oracle 0.4075 against prevalence 0.3571 (+0.0504, 14% relative) and CYP2D6 oracle 0.1439 against 0.1059 (+0.0380, 36% relative -- proportionally the larger of the two). Neither survived. An inner-cross-validation estimator, choosing the cut on training folds only, captured 36.5% of the ceiling on CYP3A4 while failing seed-stability, and on CYP2D6 realised -101.8% of it: it moved the opposite direction by slightly more than the ceiling's own magnitude, making a tuned threshold WORSE than the untuned default. The thresholds explain it. On CYP3A4 the estimator picked 0.009 / 0.002 / 0.004 against oracle values of 0.011 / 0.006 / 0.017 -- the right neighbourhood, unstably. On CYP2D6 it picked 0.254 / 0.214 / 0.036 against oracle 0.043 / 0.228 / 0.053, which does not track at all. So estimation quality scales with the same properties that make the underlying model good, sample size and signal, and the isoform that most needs help is the one least able to estimate its way there. Two consequences. The fix for a variance-limited lever is never a finer search, since more grid points and tighter optimisation both increase estimation noise. And the prevalence default survives on both isoforms for a reason worth stating: it is far from optimal but it is a FIXED rule with zero estimation variance, which on weak-signal targets is worth more than headroom a tuned rule cannot reliably reach. The general form: judge a lever by its ceiling MULTIPLIED BY the fraction that survives estimation, never by the ceiling alone.
decision-rulesestimation-varianceceilingtdithresholdswarm · 2026-08-24
high
A magnitude metric normalised by range punishes you for collecting more data
The expected range of n draws grows with n. Divide an effect by the range and the same effect scores worse the more seeds you run - exactly backwards.
Deep dive
The campaign's effect_vs_seed_noise aid computed ratio = |mean(delta)| / (max(base) - min(base)) across seeds. Range is not a fixed population quantity: for normal draws its expectation is 1.70 SD at n=3, 2.32 at n=5, 3.26 at n=12 and 3.73 at n=20, so an identical effect scores roughly 1.93 times worse simply for being measured with twelve seeds instead of three. This surfaced when CYP1A2's external+3D block was re-run at 12 seeds: the effect GREW from -0.0104 to -0.0154 and its verdict FELL from 'meaningful' (ratio 1.46) to 'weak' (0.67). A metric that degrades as evidence accumulates is worse than none, because it penalises precisely the behaviour that makes results trustworthy. Fixed by dividing by the standard deviation, which estimates a fixed population quantity and is therefore comparable across experiments with different seed counts, with the verdict thresholds rescaled from (1.0, 0.3) to (2.0, 1.0) because the originals were implicitly tuned against a range denominator at n=3, itself about 1.7 SD. Both runs now read 'meaningful' at 2.83 and 2.14, and the 12-seed figure is the trustworthy one since the 3-seed denominator was that isoform's SD underestimated by half. A caveat travels with the fix: the denominator is still estimated from the supplied seeds, and ledger #61 measured 3-seed SD errors of 51 to 191 percent across the four isoforms, so with few seeds this remains a rough flag rather than a measurement and an isoform's separately measured SD should be preferred where one exists.
metricsseed-varianceeffect-sizeharness-defectself-correctionswarm · 2026-08-24
high
A metric helper that derives its own baseline from its inputs is unsafe on a subset
Every activity tranche on every isoform scored above 1.0 while the full-set scores were 0.61-0.88. A subgroup cannot all be worse than the whole unless the baseline moved -- and it had.
Deep dive
cyp.eval's weighted_st_rae computes the baseline mean mu from whatever rows it is passed. Called on a subgroup it therefore scores that subgroup against the SUBGROUP's own mean -- a baseline that already knows which tranche a compound falls in, and a far stronger one than the global mean the metric actually uses. The result is subgroup scores that are not comparable to the headline number or to 1.0. This surfaced only because the arithmetic was inconsistent on its face: tranche scores of 1.21-2.68 alongside a full-set 0.7764 on CYP1A2. Without that cross-check the write-up would have claimed the deployed models fail on every activity tranche, which is not what the numbers show. Fix: pass the baseline in explicitly (st_rae_fixed_mu carries the global mu), and keep the own-mean figure alongside for contrast rather than deleting it. The general rule generalises beyond ST-RAE to any normalised metric -- RAE, relative error, skill scores -- whose denominator is estimated from the evaluation sample. Also motivated persisting OOF predictions to data/processed/oof_<iso>.npz so subgroup analyses no longer require an hour of refitting.
methodsst-raeevaluationself-correctionbugscripts/train/mean_predictor_check.py · 2026-08-29
high
A real, headroom-ordered, four-for-four improvement can still deploy on nothing
Calibration quality is not a dial that pays continuously. Once a mean-shift correction removes the bias, a better calibration has nothing left to remove.
Deep dive
log2fc_std_error lifted out-of-fold calibration R^2 on ALL FOUR isoforms with no inversions, and the gain was perfectly inversely ordered against baseline R^2 (2D6 +0.0342, 2C9 +0.0106, 1A2 +0.0066, 3A4 +0.0043) -- the textbook signature of signal added rather than variance fitted. It deployed on zero isoforms. CYP2D6 shift 0.8930 -> 0.8923 with paired seed deltas +0.0001/-0.0030/+0.0006 and LCO regressing 0.9215 -> 0.9244; CYP2C9 shift 0.6033 -> 0.6038, deltas -0.0021/+0.0065/-0.0029, LCO 0.6164 -> 0.6279. The 'none' arm was byte-identical on both isoforms, so folds were shared and the comparison was properly paired. This REFINES ledger #41, which held that calibration quality is the lever deciding whether row imputation helps or hurts: the Emax lift was ~+0.15 and converted, a +0.03 lift converts to nothing, so there are strong diminishing returns or a threshold. The likely mechanism -- that the mean-SHIFT correction and calibration quality are SUBSTITUTES, both removing bias from imputed labels, so shifting by brute force makes extra precision redundant -- stays SPECULATIVE: its prediction that precision should help the un-shifted r2 arm replicated on 2D6 (-0.0075/-0.0067/-0.0058, sign-stable) and REVERSED on 2C9 (+0.0192/+0.0004/+0.0335). General lesson: an intermediate metric improving is not evidence the deliverable will, and 'improves the quantity a prior finding named as causal' is still a hypothesis, not a result.
calibrationimputationnegative-resultintermediate-metricssingle-concswarm · 2026-08-24
high
A row with no fitted curve is a measurement, not a missing value
The assay declined to fit a curve because nothing happened. That IS the answer -- and it is the half of the data the model most needs.
Deep dive
The PubChem CYP panel carries 46,724 rows labelled Inactive, and 38,877 of them have no pIC50. A routine dropna on the target silently discarded all of them, training any external model on ACTIVES ONLY -- blind to the active/inactive boundary, which is most of what the official assay measures. Adding them back at a censored floor 0.1 below the lowest observed potency improved BOTH self-learnability and cross-assay transfer on all four isoforms with no inversions. Transfer-rho onto official training labels: 3A4 +0.356 -> +0.592, 1A2 +0.344 -> +0.414, 2C9 +0.174 -> +0.411, 2D6 +0.230 -> +0.274. Independent corroboration that this is bias removal and not just more rows: the mean shift between external and official predictions shrinks on every isoform (3A4 +0.93 -> +0.63, 2C9 +0.49 -> +0.17, 1A2 +0.28 -> +0.13), exactly what you expect when an actives-only model stops being biased potent. This partly rehabilitates the public panel, which ledger #7 killed as a lookup for having 0/748 test InChIKey overlap: the lookup is still dead, but the learned transfer was being judged on half its data. General rule: before concluding a data source does not transfer, check what the loader dropped.
external-datacensoringtransferpubchempreflightswarm · 2026-08-24
high
A second model family ships: ExtraTrees members confirm 12/12 on both representation-bound isoforms
Bagging saturated because its members were the same model on different subsamples. Averaging in a genuinely different family breaks that correlation -- but only where the second family is good enough on its own to be worth averaging.
Deep dive
12 seeds per arm inside the deployed stack, deployed arm as the control. CYP2D6: 0.8848 -> 0.8738, delta -0.0110, 12/12 seed-stable, 2.12 SD. CYP1A2: 0.7811 -> 0.7722, delta -0.0089, 12/12, 1.24 SD. Both controls reproduce. Both effects GREW with power rather than shrinking, and CYP1A2 -- the marginal 1.05 SD case at 3 seeds -- held at 12/12. CYP3A4 and CYP2C9 stay rejected, so the competence rule holds: the second family helps only where it is competent solo (solo gaps 2D6 +0.0090 and 1A2 +0.0307 versus 2C9 +0.1179 and 3A4 +0.1396). Deployed per isoform: 3A4 0.4492, 2C9 0.5882, 2D6 0.8738, 1A2 0.7722 -- macro 0.6753 -> 0.6708. This is the first deploy since bagging and the first non-LightGBM model the campaign ships, and it lands on exactly the two isoforms that had rejected nearly every feature block.
ensemblingextratreesmodel-familycyp2d6cyp1a2deployed12-seeddata/processed/family_et_cyp2d6_12seed.json, family_et_cyp1a2_12seed.json; ledger #102 · 2026-08-27
high
A sub-threshold LCO delta is not agreement -- a signal-free block reproduces it at r=0.992
Row-shuffle a feature block so it cannot carry information, and it still 'improves' leave-cluster-out by as much as the real one.
Deep dive
Every gate in this campaign prints an 'LCO agrees' line and it has been quoted as supporting evidence. Tested against a permutation null -- the mechanistic block row-shuffled, preserving column marginals and collinearity while destroying the molecule-to-feature link -- across 4 clusterings per isoform inside the deployed pipeline. CYP2C9: the signal-free null tracks the real block at r = 0.992, the real mean -0.0194 sits at the 25th percentile of the null, and the deployed arm's own LCO ranges 0.6079-0.7479 (sd 0.0665) across four equally-valid splits, dwarfing every block effect measured on that isoform. CYP3A4: null unbiased (mean +0.0010, t=0.57), real +0.0020 at the 50th percentile. The LCO delta is largely a property of WHICH CLUSTERING was drawn. Checked against per-isoform resolvability thresholds (3A4 0.0067, 1A2 0.0081, 2D6 0.0210, and CYP2C9's first-ever measurement at 0.0570), all three recent 'LCO agrees' claims are sub-threshold and CYP2D6's -0.0393 is the only one above. LCO is NOT retired -- it discriminates when the effect is large, which is the 2D6 case -- but sub-threshold deltas must be reported as 'not resolvable'. Wired into cyp.eval.lco_resolvable() and the gate report.
lcogatingpermutation-nullharnessself-correctiondata/processed/lco_null_cyp2c9.json · 2026-08-25
high
A thresholded metric can hide a model improvement that is perfectly stable underneath it
Bagging improves CYP3A4-TDI ranking on 12 of 12 seeds; MCC registers it on 10 and calls it noise.
Deep dive
Bagged averaging was rejected on the TDI track because MCC helped on only 10 of 12 seeds at 0.78 SD. Adding threshold-free scores to the same runs -- same folds, same probabilities -- shows the model was not the problem. CYP3A4: AUROC 0.8051 to 0.8109 (+0.0058) on 12 of 12 seeds and AUPRC 0.5006 to 0.5123 (+0.0117) on 12 of 12, both perfectly seed-stable. The ranking improves every single time; the thresholded metric sees it two times out of twelve less often, because MCC is read through a cut re-estimated per fold from the predicted distribution, and shrinking that distribution moves the cut along with it. CYP2D6 is the contrast that makes the point sharper: its AUROC moves +0.0007 on 7 of 12, not seed-stable, so its ranking is not improvable either and its problem sits upstream of the decision rule. Two practical consequences. First, when a lever fails on a thresholded metric, measure the threshold-free score before concluding the model did not improve -- it costs nothing if the probabilities are already in hand. Second, a confirmed mechanism is not a deploy: bag5 remains REJECTED on MCC, which is what the challenge scores.
tdimccaurocthresholdingmetric-designmechanismdata/processed/tdi_bagged_cyp3a4.json · 2026-08-26
high
A variance-reduction lever pays off in proportion to how quiet the metric already is
Bagging deployed on all four inhibition isoforms and failed on both TDI isoforms, and the relative estimator noise differs by about four-fold.
Deep dive
Seed-bagged averaging was gated identically on both tracks. Inhibition: deployed 4 of 4 (3A4 -0.0151, 2C9 -0.0138, 2D6 -0.0140, 1A2 -0.0188). TDI: rejected 2 of 2 (3A4 +0.0098 but only 10 of 12 seeds and 0.78 SD; 2D6 -0.0020, helping on 4 of 12). The difference is measurable: CYP3A4 inhibition has a seed SD of 0.0037 on a 0.46 ST-RAE, which is 0.8% relative, while CYP3A4-TDI has 0.0125 on a 0.36 MCC, or 3.5%. An effect of comparable practical size lands comfortably outside the noise on one track and inside it on the other. A metric-specific mechanism compounds it: MCC is read through a threshold re-estimated per fold from the predicted distribution, so shrinking the probability spread partly moves the cut along with it, whereas ST-RAE scores against fixed per-compound credible bands that do not move when predictions tighten. The forward-looking rule: before spending compute on variance reduction, check the metric's relative estimator noise and whether the metric reads predictions through a re-fitted decision rule. Where it does, expect much of the gain to be absorbed.
baggingtdimccvariance-reductionmetric-designdata/processed/tdi_bagged_cyp2d6.json · 2026-08-26
high
A verdict from one task does not transfer to another, and this pair has already proved it twice
The same two blocks reversed the sign of their interaction between two isoforms of one task. Carrying either verdict to a different task would assume exactly what that disproved.
Deep dive
The external public-panel block and the 3D conformer/shape block have now been gated across all four isoforms on the inhibition track, with results that refuse to generalise: DEPLOYED on CYP1A2 at -0.0104 and super-additive, REJECTED on CYP2D6 at +0.0055 where the combination is worse than either part, and REJECTED on CYP2C9 at +0.0061. Same blocks, same harness, same seeds, opposite sign of interaction between isoforms of a single task. That record is the argument for testing them on TDI rather than reasoning about it. TDI is not a harder version of inhibition, it is a different physical event: mechanism-based inactivation requires the enzyme to convert the compound into a reactive species which then traps it, whereas pIC50 measures reversible affinity. A block can be absorbed by the base model for affinity and still carry information about whether metabolism occurs at a position that generates a reactive intermediate -- shape and planarity govern how a molecule sits over the heme, which is exactly that question. Equally, the external panel measures inhibition potency in other assays, which is only loosely coupled to inactivation propensity, so it could easily be useless here despite deploying on CYP1A2's affinity task. One implementation note worth recording because it inverts every verdict if missed: MCC is higher-is-better while ST-RAE is lower-is-better, so the seed-stability test, the interaction classifier and the deploy condition all flip sign between the two harnesses.
tditransfercombinationstask-specificityhonest-gateswarm · 2026-08-24
high
An all-seeds-must-agree gate is underpowered below one seed-SD, and the fix is more seeds in advance
Three consecutive experiments were vetoed by the same seed. That seed turned out to be the most balanced split of twenty - so the veto was chance, and the gate simply cannot see effects this small.
Deep dive
The honest gate requires an improvement on every seed. On CYP3A4-TDI that let one seed block three consecutive experiments -- the threshold estimator, the external+3D feature blocks, and predicted inhibition potency -- while the other two seeds favoured all three. Auditing the base arm across 20 seeds settled which explanation held. Seed 42 is NOT an adverse split: its base MCC of 0.3606 sits at the 45th percentile, and it has the LOWEST per-fold positive-rate spread of all twenty seeds (SD 0.0071, 0th percentile; range 0.0195, 5th percentile), with fold sizes identical across seeds. So the veto was chance, not a fold artefact. The base arm's seed-to-seed SD is 0.0125, and all three rejected effects had means of +0.0067, +0.0056 and +0.0184 -- at or below roughly one seed-SD. An all-must-agree rule over three draws has poor power in that regime: a genuine small effect will show negative on at least one seed often enough that it can be vetoed indefinitely no matter how many times it is retried. Two disciplined consequences. This does NOT reopen the three rejections, because their deltas were mostly below the noise and 'underpowered' is not evidence of a hidden positive -- retroactively passing failed results on a power argument is the same error as moving a threshold after seeing it. And the forward fix is to pre-register MORE SEEDS for future work on this isoform, at least ten, with the smallest effect worth chasing set at about 0.0125 MCC. The general rule: when a gate's veto rate looks suspicious, measure the null distribution of the quantity it gates on before either trusting or loosening it.
honest-gatepowerseed-variancetdipre-registrationswarm · 2026-08-25
high
An effect size is a property of a PIPELINE, not of a block -- normalise both on the same one
Measuring an effect in one configuration and its noise in another gives a ratio that means nothing, and it will usually flatter the noise.
Deep dive
Ledger #61 flagged three deployed effects as marginal by dividing each recorded delta by its isoform's 12-seed seed-SD. Two of the three deltas were measured on a different pipeline from the one the SD came from: CYP2D6's mechanistic block and CYP2C9's aux block both came from gate scripts scoring PLAIN RAE, UNWEIGHTED, with no imputation, while the SD was measured on the band-weighted, imputed, deployed pipeline. Re-measured where it actually ships, the 2D6 block is -0.0440 at 8.48 SD, not -0.0077 at 1.48 SD -- five times larger, and the largest per-block inhibition effect in the campaign. The block is genuinely small in the configuration it was first gated in; band weighting and imputation multiply it. scripts/train/reverify_block.py now toggles a block inside the deployed recipe and measures effect and noise together, and inhibition_seed_audit.py records the pipeline behind every historical delta and prints a warning when it is not the deployed one.
gatingeffect-sizeseed-noisecyp2d6harnessdata/processed/reverify_mech_cyp2d6.json · 2026-08-25
high
An oracle is not always an upper bound
Handing the model the true partner label can be WORSE than handing it a prediction, because the truth carries the partner assay's noise and the prediction has already averaged it away.
Deep dive
Standard practice treats an oracle -- give the model the true value of something it cannot have at inference -- as an upper bound on any realistic version. On CYP2D6 that is false in both directions. TRUE CYP3A4 label as a feature: +0.0208 ST-RAE (HURTS). PREDICTED CYP3A4 label: -0.0476 (HELPS). Same inversion with CYP1A2 (+0.0202 true vs -0.0208 predicted). The reason is that CYP2D6 is orthogonal to the other three isoforms (label correlations +0.039, -0.100, +0.077), so the partner's true value contributes only that assay's independent measurement noise -- pure harm -- while the partner's PREDICTION is a smooth, denoised structural summary that works as a derived feature. The mirror-image lesson holds where the isoforms DO correlate: there the oracle massively OVERSELLS, because out-of-fold residuals are near-orthogonal to out-of-fold predictions by construction, so a prediction cannot carry the residual where the oracle's advantage lives. CYP3A4<-CYP2C9 oracle -0.1495 realises +0.0013; CYP2C9<-CYP1A2 -0.0892 realises -0.0042 (4.7%); CYP1A2<-CYP2C9 -0.0677 realises -0.0053 (7.8%). So an oracle bounds the realistic version from ABOVE when the partner is informative and correlated, and from BELOW when it is uninformative and noisy -- run both arms, never quote the oracle alone.
oracleupper-boundmultitaskstackingmeasurement-noiseswarm · 2026-08-24
high
Auxiliary-task payoff is MONOTONIC in how learnable the aux target is - all 4 isoforms order perfectly, giving a pre-flight test
Before spending compute on an auxiliary, measure how well you can predict the AUX target from your features. Below about rho 0.6 it will hurt you under series shift.
Deep dive
Completing the single-conc sweep across all four isoforms produced a perfectly monotonic ordering between how well the aux model predicts its OWN log2fc target (Spearman, structure -> log2fc) and the leave-cluster-out delta on pIC50: 3A4 rho -0.761 -> LCO -0.0365 (DEPLOY); 2C9 -0.645 -> -0.0277 (DEPLOY); 1A2 -0.505 -> +0.0091 (REJECT); 2D6 -0.376 -> +0.0193 (REJECT). No inversions. The deploy/reject boundary sits between rho 0.645 and 0.505, i.e. around 0.55-0.60. This gives a cheap PRE-FLIGHT test for any future auxiliary: fit aux-target ~ features, check the correlation, and only proceed if it clears ~0.6 - otherwise the aux model's predictions are mostly noise and injecting them degrades exactly where the base is already weakest (out-of-series). Second lesson: CYP1A2 had the HIGHEST correlation with base error of any isoform (+0.260) and still failed 3 of 4 gates - correlating with the residual is NECESSARY but not SUFFICIENT, so gate 2 must never be used alone.
auxiliarypre-flight-testhonest-gatemonotonicsingle-concentrationsingleconc-aux · 2026-08-23
high
Averaging is the lever; subsampling is only the price paid to make the members differ
Bagging changes two things at once, and on CYP2C9 the regularisation half actively hurts while averaging more than pays for it.
Deep dive
Seed-bagged ensembles were gated with a three-arm decomposition -- deployed (single deterministic fit), sub1 (one subsampled model, regularisation only), bag5 (five averaged) -- inside each isoform's deployed pipeline with controls reproducing. Regularisation alone: 3A4 -0.0032 (stable), 2D6 -0.0056 (UNSTABLE), 2C9 +0.0081 (HARMFUL), 1A2 -0.0098. Averaging adds: -0.0119, -0.0084, -0.0152, -0.0090. Subsampling does something different on every isoform; averaging carries the effect on all four. The mechanism is metric-specific: ST-RAE charges nothing inside the credible band, band-hit rates are 19-40%, and reducing prediction variance moves borderline predictions into the dead zone -- the same route by which bandl2 won on CYP1A2 by compressing predicted SD. Deployed on 3A4 (-0.0151), 1A2 (-0.0188) and 2D6 (-0.0140); REJECTED on 2C9 at 0.33 of its seed SD. Macro 0.6910 to 0.6790 with no isoform regressing. Practical rule: when a change bundles a regularisation shift with an ensembling step, gate the two separately or the win gets attributed to whichever half is easier to believe.
baggingensemblingvariance-reductionst-raedeployeddata/processed/bagged_cyp2c9.json · 2026-08-25
high
Band weighting and features are SUPER-additive on CYP2D6 (-0.0701 vs -0.0469 predicted) but merely additive on CYP1A2
Weighting does not add information - it makes existing information usable by clearing the inactive tail out of the loss.
Deep dive
Measuring the full cross {base, +mech, +aux, +mech+aux} x {none, band weighting} under ST-RAE shows the two levers INTERACT, and the sign of the interaction differs by isoform. CYP2D6: mechanistic block alone -0.0090, band weighting alone -0.0379, additive prediction -0.0469, ACTUAL combined -0.0701 - super-additive by 0.0232, i.e. the pair delivers ~50% more than the sum of its parts. Magnitude ratio 3.05 (meaningful) and leave-cluster-out agrees (1.0299 -> 0.9649). CYP2D6 lands at 0.9304 from a 1.0005 base, the largest movement of the campaign. CYP1A2 by contrast is merely additive and slightly under: mech -0.0030 + weight -0.0350 = -0.0380 predicted vs -0.0367 actual, and the winner is the SIMPLER base|inv_width (0.8345) since base+mech|inv_width (0.8328) is inside the seed spread. MECHANISM (a hypothesis that fits, not a proven one): band weighting stops the loss being dominated by the loosely-measured inactive tail, which is exactly what was drowning out the mechanistic features. On 2D6 the basic-amine/Asp301 salt-bridge signal is real but only distinguishes POTENT binders - the compounds whose bands are tight and which the real metric actually scores. So weighting does not add information, it makes existing information usable. That predicts complementarity wherever a feature block encodes something specific to actives, and mere additivity where the block encodes a global property like lipophilicity. CONSEQUENCE FOR THE GATE: 'does this feature help?' has no isoform-independent answer, and worse, no weighting-independent answer either - a block can be worthless unweighted and valuable weighted. Every feature previously rejected under an unweighted loss deserves one re-test with weighting on before being called dead.
interactionsuper-additivecyp2d6band-weightingst-raegatingfinal-gate · 2026-08-23
high
Band weighting finally moves CYP2D6 below the mean predictor - and falsifies my own dose-response prediction
The isoform that resisted four levers responds to a change in the LOSS, not the features. And the smallest-spread isoforms gained the most, which is the opposite of what I predicted.
Deep dive
Band weighting deploys on THREE of four isoforms under ST-RAE with the full honest gate: CYP2D6 1.0005 -> 0.9626 (-0.0379, inv_width_cap); CYP1A2 0.8695 -> 0.8345 (-0.0350, inv_width); CYP3A4 0.5541 -> 0.5307 (-0.0234, inv_width_cap); CYP2C9 REJECTS (best -0.0105, fails the gate). Macro ST-RAE 0.7879 -> 0.7638. TWO THINGS MATTER HERE. (1) CYP2D6 finally MOVES. It has resisted four independent levers - richer 2D descriptors, 3x more auxiliary labels, a different task (TDI, AUROC 0.574), and cofold geometry - and sat at the mean predictor throughout. Band weighting takes it BELOW 1.0 for the first time in the campaign, and by the largest margin of any isoform. It is still far from the ~0.17 noise floor, so this is movement, not a solution, but it is the first evidence that 2D6 is not simply irreducible. CYP1A2 also accepts its first-ever deployed change, having rejected every feature block. (2) MY PREDICTION WAS WRONG. I hypothesised the payoff would scale with how much band widths VARY (3A4 p10->p90 spread 19.2x vs 2C9 5.5x) and predicted weak or no effect on 1A2 (8.0x) and 2D6 (5.6x). The opposite happened: the two SMALLEST-spread isoforms took the two LARGEST gains, and spearman(width spread, gain) = -0.2, i.e. no relationship. A better-fitting story is 'the worse the unweighted model, the bigger the gain' (2D6 1.0005/-0.0379, 1A2 0.8695/-0.0350, 3A4 0.5541/-0.0234) - but CYP2C9 breaks even that, and with n=4 isoforms this is curve-fitting a narrative to four points. Recording it as an open question rather than swapping in a second post-hoc mechanism.
band-weightingcyp2d6st-raefalsified-predictionbreakthroughband-weighted · 2026-08-23
high
Band weighting makes feature blocks ~3x more valuable on CYP2D6 - but uniformly, so no rejection reverses
Weighting amplifies every block by about the same factor. Rescaling without reordering cannot rescue anything that was already below the noise floor.
Deep dive
Ledger #32 asked whether blocks rejected under an UNWEIGHTED loss become deployable once band weighting is on. Tested by forcing the single-concentration auxiliary back into the CYP2D6 gate despite its standalone rejection (--force-aux, written to a separate artifact so the original gate is preserved). THE MECHANISM IS CONFIRMED: both feature blocks contribute roughly 3x more under weighting. Aux marginal effect goes from -0.0057 unweighted (base 1.0005 -> 0.9948, essentially nothing, which is why it was rejected) to -0.0166 weighted (0.9626 -> 0.9460) = 2.9x. Mech goes from -0.0090 to -0.0322 = 3.6x. So weighting really does make previously-invisible feature signal usable, exactly as the super-additivity result suggested. BUT NO DEPLOYMENT DECISION CHANGES, and the reason is the interesting part: the amplification is roughly UNIFORM across blocks (2.9x vs 3.6x), so it rescales every contribution without REORDERING them. Mech still beats aux under weighting just as it did without, and the best combined config (base+mech+aux|weighted, 0.9240) beats the winner (base+mech|weighted, 0.9304) by only 0.0064 against a base seed spread of 0.0230 - not resolvable, so the tie-break correctly keeps the simpler model. PRACTICAL CONSEQUENCE: a block that sat 3x below the noise floor unweighted is still below it weighted. Uniform amplification cannot rescue a rejection; only a block whose signal is DIFFERENTIALLY concentrated in tightly-measured actives could reorder, and neither of ours is. This substantially narrows #32 - blanket re-testing of rejected blocks is not worth the compute, and the expectation of reversals was wrong.
band-weightingcyp2d6amplificationledger-32negative-resultforce-aux · 2026-08-23
high
BASE on official data: macro scaffold-CV RAE 0.837 - but CYP2D6 sits at 1.001, no better than the mean predictor
Three isoforms are learnable from 2D structure; 2D6 is not. All the headroom is in one isoform.
Deep dive
scripts/train/multitask_baseline.py --source official, combined Morgan+RDKit features, scaffold 5-fold CV, per-isoform LGBM. RAE: 3A4 0.621 (n=2335), 2C9 0.824 (n=1285), 1A2 0.901 (n=1412), 2D6 1.001 (n=1493). Macro 0.837. RAE>=1.0 means the model is worthless vs predicting the training mean, so 2D6 currently contributes nothing. Against the assay noise floor (2D6 ~0.17) the 2D6 gap is the single largest block of recoverable signal in the challenge. This is consistent with 2D6 being uncorrelated/anti-correlated with the other isoforms: whatever drives 2D6 binding (basic-amine/Asp301 salt bridge, distinct pocket) is not captured by generic 2D descriptors. Priority: 2D6-specific mechanistic features (protonation state at pH 7.4, basic-nitrogen pharmacophore, heme-Fe geometry) rather than more global model capacity.
baselinecyp2d6raeheadroomeda-official · 2026-08-22
high
Better calibration does NOT always mean better imputation - Emax helps 2D6/2C9 and hurts CYP3A4
Extra calibration inputs add variance without information where the original signal was already strong. The isoform that needed help least was hurt most.
Deep dive
After Emax-calibrated imputation gained -0.0374 on CYP2D6 and -0.1242 on CYP2C9, I expected CYP3A4 to improve too since its calibration also rose (0.837 -> 0.865). It does the opposite. Against the no-imputation baseline of 0.5307: uncorrected Emax-calibrated 0.5888 (+0.0581), shift-corrected 0.5729 (+0.0422), neither seed-stable, LCO worse in both. Against the ACTUAL deployed config - log2fc-only uncorrected imputation at 0.4773 - it is 0.0956 worse. TWO REASONS FIT. First, CYP3A4's calibration gain was the smallest of the four (+0.028 vs CYP2D6's +0.151) because log2fc alone was already excellent there, so the extra columns add variance without information on the one isoform that did not need them. Second, bias correction is wrong for 3A4 on independent grounds: its donors are MORE active than its measured compounds (-0.378 log2fc, the only isoform with that sign), so forcing the imputed mean upward moves it away from truth. NET: Emax calibration deploys on 2D6 and 2C9, is rejected on 3A4 and 1A2, and 3A4 keeps its original log2fc-only imputation. That is four isoforms with four different imputation recipes, and the fourth time in this campaign a mechanism has held on some isoforms and not others.
emaxcalibrationcyp3a4per-isoformself-correctionemax-imputation · 2026-08-23
high
Bias-correcting imputed labels rescues CYP2D6 from +0.110 to -0.021 - my 'real population shift so do not correct' call was too strong
Correcting a genuine population shift still helps where the calibration is poor. But it still does not beat the deployed config, so it is promising rather than a win.
Deep dive
Ledger #36 tested whether the imputation harm is correctable. I predicted NO, because donors differ from measured compounds on the independent single-conc screen (2D6 +2.105 log2fc, 1A2 +1.004) - a real population difference, not a calibration artifact. Half right. CYP1A2: mean-shift correction gives 0.8814 vs a 0.8345 baseline, still +0.047 worse and not seed-stable - prediction held. CYP2D6: 0.9415 vs 0.9626 = -0.0211, seed-stable, leave-cluster-out 0.9863 -> 0.9758, magnitude meaningful, DEPLOY - prediction failed. Correction removes most of the damage on both (1A2 +0.5316 -> +0.0469; 2D6 +0.1102 -> -0.0211) but only 2D6 becomes useful. The two factors do not decompose cleanly: 2D6 has the WORST calibration (R^2 0.496) and the LARGEST population shift and benefits most, while 1A2 has good calibration (0.786) and a smaller shift and does not - so no rule is proposed from n=2. CRUCIAL CAVEAT AGAINST OVER-CLAIMING: this is NOT a deployment change. Shift-imputation reaches 0.9415 on base+weighting, but the deployed 2D6 config is base+mech+weighting at 0.9304, still 0.0111 better. A gain measured against its own baseline is not a gain against the incumbent, and the combined mech+shift-imputation test is what would decide it.
imputationbias-correctioncyp2d6self-correctionnot-yet-a-winimpute-bias · 2026-08-24
high
Check whether a shared hyperparameter actually binds before tuning it -- here it bound on one isoform of four
num_leaves=64 saturates every CYP3A4 tree and is never reached by the other three, so three of the four isoforms had nothing to tune.
Deep dive
The campaign used one LightGBM configuration across isoforms whose training sets differ 4.4-fold, which looks like an obvious tuning opportunity. Dumping the trees actually built settles it cheaply: CYP3A4 hits the 64-leaf cap on 100% of trees, while CYP2C9 (40.5 mean leaves), CYP2D6 (46.8) and CYP1A2 (44.1) never reach it because min_child_samples and the data bind first. A parameter that is not binding cannot be tuned in either direction, so three isoforms were excluded by measurement rather than by a null result -- and the sweep collapsed to a single pre-registered test on the one isoform where it mattered. That test then failed decisively: doubling to 128 leaves gives +0.0160 on scaffold-CV and +0.0128 on LCO, positive on 3 of 3 clusterings and above CYP3A4's 0.0067 split-noise threshold, making it resolvable contrary evidence. The likely reading is that the cap is functioning as regularisation against a hard scaffold shift, which is why LCO caught it and scaffold-CV alone would have called it merely unstable. General rule: before tuning a shared hyperparameter, dump the fitted models and check where it actually binds; the measurement is minutes and it usually shrinks the experiment.
hyperparameterscapacitylightgbmlcocyp3a4data/processed/capacity_cyp3a4.json · 2026-08-26
high
Class weighting does NOT transfer to the TDI track - weighting pays only when it corrects a loss/metric mismatch
Band weighting was not a generic trick. It worked because ST-RAE forgives error inside the band; MCC has no such quirk to exploit.
Deep dive
The inhibition track's biggest win was a LOSS change: band weighting cleared the loosely-measured inactive tail out of the objective and let active-specific features surface, super-additively on CYP2D6. Ledger #33 asked whether the same idea transfers to TDI, which is 21% positive and so plausibly dominated by negatives the way inhibition was dominated by inactives. It does NOT. CYP3A4 TDI, scored on MCC (the leaderboard's primary classification metric) at the training-positive-rate threshold, 3 seeds, scaffold CV: base 0.3571; base + scale_pos_weight(3.69) 0.3521 (-0.0050); base+alerts 0.3555 (-0.0016); base+alerts+weighting 0.3505 (-0.0066). NOTHING is seed-stable and every variant is at or below base. The structural-alert block therefore stays withdrawn even under the conditions that rescued a rejected block on the inhibition side. WHY THE ASYMMETRY, and this is the transferable part: band weighting worked because it corrected a specific MISMATCH between loss and metric - ST-RAE forgives error inside the credible band, so the unweighted loss was spending capacity on compounds the metric barely scores. MCC has no analogous forgiveness structure; it treats compounds symmetrically once a threshold is fixed, and prevalence is already handled by thresholding at the training positive rate. scale_pos_weight only shifts the probability scale, which that threshold then undoes. So weighting is not a general-purpose trick - it pays off precisely when it aligns the loss with a quirk of the scoring function, and is inert when no such quirk exists.
tdiclass-weightingmccnegative-resultloss-designtdi-weighted · 2026-08-23
high
Correlated targets, uncorrelated errors: cross-isoform influence correlation is only +0.079
CYP3A4 and CYP1A2 labels correlate at 0.42, but their per-compound contributions to ST-RAE correlate at 0.026. The model captures the shared signal, so what is left in the residual is isoform-specific.
Deep dive
ST-RAE is a ratio of sums, so a compound's effect on it is its delta-method influence (soft - theta*base)/sum(base). Measuring the correlation of those influences on co-measured compounds gives: CYP3A4-CYP2C9 +0.396 (target r 0.71, 56% retained), CYP2D6-CYP1A2 +0.066 (0.08), CYP2C9-CYP1A2 +0.059 (0.45, only 13% retained), CYP3A4-CYP1A2 +0.026 (0.42, 6% retained), CYP2C9-CYP2D6 -0.015 (-0.10), CYP3A4-CYP2D6 -0.060 (0.04). Mean pairwise influence correlation is +0.079. Two consequences. First, averaging four endpoints genuinely buys variance reduction close to the independent ideal, so the macro is a well-behaved summary rather than four copies of the same noise. Second, this explains an earlier result from a second direction: #138 found exactly one isoform pair with a significantly shared error tail, CYP3A4-CYP2C9, and that is the only pair here retaining substantial residual correlation at +0.396. The two analyses agree without having been designed to. Measured on training co-measured compounds (230-473 per pair; only 41 compounds carry all four endpoints), using a first-order approximation to a heavy-tailed statistic.
st-raemacrocross-isoformleaderboardmethodsscripts/train/macro_correlation.py · 2026-08-29
high
Coverage is not what made the CYP3A4 donors work -- label-distribution match is, and 62 percent was a prior correction
With a fixed donor budget, correlation between RAE and measured chemotype coverage is about zero, while correlation with label-distribution mismatch is +0.76. The highest-coverage arm had the worst error.
Deep dive
The campaign's account of its most distinctive CYP3A4 result was that TDI-condition donors helped through coverage rather than quality, since they were worse alone but better together with the single-concentration donors. A controlled surrogate experiment on public CYP3A4 data refutes that reading. Holding the core fixed and the donor budget fixed at 1000 rows so that only donor identity varied, and measuring chemotype coverage rather than asserting it, the correlation between RAE and coverage was approximately zero to slightly negative at 0.00 to -0.07, while the correlation between RAE and label-distribution mismatch was strongly positive at +0.76 falling to +0.38 as the core grew. The arm with the highest measured coverage had the worst RAE. With a representative core, randomly drawn donors won at every core size and every skewed stratum hurt, including the highest-quality stratum. A factorial decomposition separated the pure quality effect, which cost +0.030 shrinking to +0.012 with more data as expected, from the pure identity or coverage effect, which came out at +0.078 shrinking to +0.033 and therefore carried the wrong sign: at matched noise, different compounds were worth less rather than more. The large apparent coverage win does reappear when the core is restricted to actives, which is the campaign-like configuration, but an oracle constant-shift analysis shows roughly 62 percent of that gain is a pure prior correction obtainable with no additional data at all. The actionable rule is to compare a donor set's label distribution against the target's before adding it, and to check whether a simple calibration offset already captures most of the benefit.
methodsdonorscoveragecyp3a4imputationrefutationdata/processed/surrogate_cyp3a4_public.json · 2026-08-30
high
CYP2D6 is orthogonal to the other three isoforms - do NOT train it in one joint multitask head
Multitask only helps where targets actually correlate. 2D6 has a different pharmacophore (basic amine/aspartate) and the data says so.
Deep dive
Pearson on co-measured compounds: 3A4-2C9 = 0.71 (strong), 2C9-1A2 = 0.45, 3A4-1A2 = 0.42, but 3A4-2D6 = 0.04, 2D6-1A2 = 0.08, 2C9-2D6 = -0.10 (NEGATIVE). So the 3A4/2C9/1A2 block genuinely shares signal and should share a trunk; 2D6 should be its own model or a head with no shared gradient pressure. This refines CLAUDE.md learning #5 ('CYP is multi-task by construction, correlated targets') - true for 3 of 4, false for 2D6. Co-measured n is small (230-473) so treat magnitudes as indicative, but the 3A4-2C9 vs 2C9-2D6 gap is far too large to be noise.
multitaskcyp2d6correlationeda-official · 2026-08-22
high
CYP2D6's best model is near-degenerate - predicted SD 0.290 against a 0.272 band width, only ~9% better than the mean
ST-RAE rewards hedging toward the band centre. The gain is real and gated, but the model is close to predicting a constant.
Deep dive
CYP2D6's deployed model reached ST-RAE 0.9072, its best of the campaign, and it passed the full honest gate including leave-cluster-out. But the submitted predictions are close to degenerate and that should be visible next to the headline. Predicted SD collapses from a training SD of 0.916 to 0.434 (v03) to 0.290 (v04) - a 3.2x compression - and the predicted range is 4.02-6.15 against a training range of 1.95-7.53. The predicted spread (0.290) is now barely above CYP2D6's own median credible band width (0.272), which means the model is doing little more than placing almost every compound near the centre and relying on ST-RAE forgiving anything inside the band. Correlation between v03 and v04 2D6 predictions is only 0.669, so this is a large change in behaviour, not a refinement. PUT PLAINLY: ST-RAE 0.9072 is only about 9% better than the mean predictor, which scores 1.0 by construction. The improvement from 1.0005 is real and gated, but CYP2D6 is not solved - the model has learned that the cheapest way to score under this metric is to hedge toward the centre of a tightly-measured distribution. THE RISK: this is only correct if the test set's activity spread and band widths resemble the training set's. We never see test bands. If the blinded 750 are activity-enriched (and CYP3A4's predictions already sit +0.55 above its training mean, which hints they might be), a near-constant 2D6 prediction would be penalised exactly where a wider one would not. Logged as a caveat rather than a reason to revert: the configuration won its gate fairly, and hedging toward the band centre is a rational response to a metric that forgives band-interior error. But a headline of '2D6 improved' without this alongside would misrepresent what the model actually does.
cyp2d6calibrationdegeneratest-raecaveatsubmissionswarm · 2026-08-24
high
CYP2D6's compressed predictions are correct, not degenerate - restoring the training spread costs 48% relative ST-RAE
Scaling up a low-information prediction adds error, not information. The hedging expresses real uncertainty rather than hiding a defect.
Deep dive
Last tick I flagged CYP2D6's deployed model as near-degenerate (predicted SD 0.356 vs training SD 0.916 and a 0.272 median band width) and queued variance matching as likely-cheap insurance against an activity-enriched test set. Measured instead of argued: rescaling out-of-fold predictions around their mean by k gives ST-RAE 0.9072 at k=1.00, 0.9362 at k=1.25, 0.9845 at k=1.50 (already worse than the mean predictor), and 1.3465 at the k=2.57 that restores the training SD exactly - a +0.4392 penalty, +48.4% relative. Critically the band-hit rate FALLS as spread grows (18.5% -> 14.2%), so expansion pushes predictions outside the credible bands without improving their ordering. INTERPRETATION: the compression is not a modelling pathology, it is the correct expression of genuine epistemic uncertainty under a metric that forgives band-interior error. For an isoform the model barely understands, calibrated hedging toward the band centre is the right answer, and a wider prediction would be false confidence. Ledger #40 resolves to ACCEPT rather than variance-match. The residual risk that the blinded test is activity-enriched is real but uniform expansion is not a remedy - it fails locally and there is no mechanism by which it would succeed on a shifted distribution.
cyp2d6calibrationvariancest-raeuncertaintyself-correctionvariance-match · 2026-08-24
high
CYP2D6's deployed model beats a constant by 0.07 log units; CYP3A4's by 0.43
Macro ST-RAE 0.6708 reads like three-quarters of the way to a perfect model. Converted into accuracy, CYP2D6 is a hair's breadth from predicting a constant.
Deep dive
ST-RAE is a ratio against the mean predictor, so a score does not say how much accuracy a model actually buys. Corrupting the true labels with gaussian noise of known sd and scoring the result maps accuracy in log units onto the metric, using only labels and shipped bands -- no model fitting, no test set, no importance weighting. The sd reproducing each deployed score, versus the sd at which a predictor merely ties the mean, gives the margin: 3A4 0.58 vs 1.03 (+0.45), 2C9 0.50 vs 0.70 (+0.20), 2D6 0.66 vs 0.74 (+0.08), 1A2 0.72 vs 0.88 (+0.16). CYP2D6 buys roughly a sixth of what CYP3A4 buys. This is the mechanical reason #94's test-like reweighting pushed 2D6 past 1.0 -- there is almost nothing there to erode -- and it is a far more robust route to that conclusion than the reweighting itself, whose effective sample size on 2D6 is only 505 of 1493 rows. The unbiasedness assumption was tested rather than assumed: repeating with pred = mu + k(y-mu) + noise at k=1.0/0.8/0.6 moves every margin by at most 0.03 and changes no ordering, and the result reproduces under two RNG seeds. This does NOT license shrinking 2D6 toward the mean, which would be tuning on the deployment distribution and was closed on magnitude by #79. It licenses reporting per-isoform margin over a constant alongside macro ST-RAE.
cyp2d6st-raemetricmethodsdistribution-shiftscripts/train/margin_over_constant.py · 2026-08-29
high
CYP2D6's mechanistic block survives its first signal-free control -- but a quarter of the published effect was never mechanism
Against a row-permuted copy of itself the block wins by -0.0419 at 22.8 times the noise, on 6 of 6 seeds. Against absence it wins by -0.0559, and the -0.0140 difference is delivered by 23 columns of pure noise.
Deep dive
The campaign's largest claimed feature effect was re-measured inside the deployed CYP2D6 configuration with three arms: the real block, a row-permuted copy preserving column count and marginals while destroying compound correspondence, and the block removed entirely. Six seeds, paired within seed, fifth gate reproducing at 0.8706 against a shipped 0.8738 with a deployed-arm seed standard deviation of 0.0026. Results: absent to deployed is -0.0559 at 40.3 effect-over-noise, permuted to deployed is -0.0419 at 22.8, and absent to permuted is -0.0140 at 5.6, every contrast improving on all six seeds. Three conclusions follow. First, the block is genuinely real: it is the first block in this campaign to clear a permutation null on the primary metric, and it does so decisively rather than marginally, which matters because the same control run on CYP2C19 found a signal four times smaller and below single-size resolution. Second, roughly twenty-five percent of the historically quoted effect was never mechanism, since a block of pure noise at the same width delivers -0.0140 of the -0.0559 total, so the correct figure to quote for the block's information content is -0.0419 rather than the bundled total. Third, the width term's sign is target-dependent: it is negative here, meaning noise columns actively help, while it is approximately +0.005 on CYP3A4 and +0.0003 on CYP2C19, so it cannot be treated as a constant property of block width. Separately, the total came out at -0.0559 rather than the published -0.0440 because that figure was measured when the deployed score was 0.893, before seed-bagging and ExtraTrees were added; the effect grew twenty-seven percent as later layers arrived, which is a direct confirmation of the campaign's own rule that an effect size is a property of a configuration.
cyp2d6mechanismpermutation-nulldeployedsixth-gatedecompositiondata/processed/mech_perm_cyp2d6_deployed.json · 2026-08-30
high
CYP2D6-TDI MCC has a 40% seed-to-seed range, so three seeds resolve nothing below ~0.03
The base arm alone swings from 0.0852 to 0.1196 depending only on the fold seed. Any single-seed reading of a TDI experiment on this isoform is noise.
Deep dive
Gating the external and 3D blocks on CYP2D6-TDI produced base MCC values of 0.1196, 0.0852 and 0.1128 across three scaffold-CV seeds -- a 40% relative range on the incumbent arm, with nothing changed but the fold assignment. Against that backdrop the +3d arm gave 0.1511 on seed 42, a +0.0315 apparent gain that matched the mechanistic prediction, and then regressed on both remaining seeds to a mean delta of exactly +0.0000. The external block was worse, at -0.0145. This sets a practical floor for the TDI track on this isoform: with n=1497 and a 21.6% positive rate, three seeds cannot honestly resolve an MCC difference below roughly 0.03, which is larger than any effect the five previous TDI attempts produced. Two consequences. Future CYP2D6-TDI experiments should either pre-commit to more seeds or accept that only large effects are detectable, and any TDI result quoted from a single seed should be treated as uninformative regardless of how well it fits the story being told. The methodological failure worth recording alongside the number is that the seed-42 value was called encouraging mid-run, before the other seeds existed -- the gate's all-seeds-negative requirement exists exactly to prevent that reading, so the error was impatience with a known rule rather than ignorance of it.
tdicyp2d6seed-variancemccresolutiondisciplineswarm · 2026-08-24
high
CYP2D6-TDI's apparent headroom has no route: the shift itself is unpredictable from structure
23.5% of ceiling looks like the campaign's biggest unclaimed gap. But the ceiling assumes you can observe the shift, and regressing it from a molecular graph reaches rho 0.076.
Deep dive
The replicate-assay ceiling assumes a predictor that OBSERVES the continuous shift. #49 measured how well that shift can be regressed from structure under scaffold CV: rho 0.278 on CYP3A4 and 0.076 on CYP2D6. Simulating a predictor with exactly that correlation and cutting at the training prevalence yields MCC 0.099 and 0.029 -- so the deployed classifiers, at 0.3559 and 0.1540, beat the shift route by 3.6x and 5.3x. That independently reproduces and explains #49's verdict of winner=clf: the shift is a difference of two correlated noisy pIC50s, so subtraction cancels signal while noise adds (SNR 0.31 and 0.64 against 1.25-2.17 for the components), and the binary label retains structure the difference throws away. Consequence for planning: CYP2D6-TDI's gap to its ceiling is not a labelling-noise problem to engineer around and is not reachable via the shift; the binding constraint is that the underlying continuous quantity is nearly unpredictable from a molecular graph. A number being far from its ceiling does not by itself mean there is anything to go and get.
tdicyp2d6mccshift-regressionnegativemethodsscripts/train/tdi_noise_floor.py · 2026-08-29
high
Distance from the noise floor tells you which lever can work
The floor bounds what is achievable. How far you sit above it tells you whether your error is measurement scatter or missing chemistry - and those need opposite interventions.
Deep dive
CYP1A2 and CYP2C9 both carry a genuine replicate of the scored pIC50 in the TDI file, with 100% coverage, and inverse-variance averaging cuts the training label's measurement SD by about 30% (CYP1A2 0.153 -> 0.107, CYP2C9 0.184 -> 0.125), close to the 1/sqrt(2) an ideal replicate pair would give. On CYP1A2 that produced nothing: mean +0.0039, ivw +0.0023, both seed-unstable and noise-order against a control reproducing the incumbent exactly. The reason is arithmetic rather than experimental. CYP1A2 scores 0.8139 against a shipped noise floor of 0.163 -- five times above it -- so measurement scatter is a small share of its error budget and shrinking that share by 30% cannot move the total. The useful reframing: the inherited lesson that the noise floor is the ceiling says what is ACHIEVABLE, but the RATIO of current performance to the floor says which kind of intervention is even capable of helping. Near the floor, label quality, calibration and loss shape are the live levers -- which is consistent with band weighting and bandl2 being the only things CYP1A2 has ever accepted, since both act on how error is counted rather than on how much information the model has. Far above the floor, only representation can move it: better chemistry, better features, better structure. Current ratios are CYP2C9 2.4x, CYP3A4 2.2x, CYP1A2 5.0x, CYP2D6 5.3x -- so CYP2D6 and CYP1A2, the two bottlenecks, are precisely the two where label-side work is least likely to pay and representation work is the only remaining route.
noise-floorlabel-noisereplicatesstrategyerror-budgetswarm · 2026-08-24
high
Diversity and competence trade off directly: regularising the partner model into usefulness destroys its independence
Ridge looks diverse when it is fitting noise, and looks redundant the moment it is regularised enough to be worth blending.
Deep dive
A cross-class blend needs two conditions: the partner must be individually competent, and its errors must be weakly correlated with the incumbent's. Measured on CYP3A4 in the deployed pipeline across seven decades of ridge alpha, those conditions move in opposite directions. Competence (ST-RAE within 1.5x of the GBM's 0.4642) arrives only at alpha >= 1e3, where ridge reaches 0.5537 at 1.19x. Error correlation is 0.715 at alpha=1, 0.836 at alpha=1e3 and 0.877 at 1e4 -- so at every point where ridge is good enough to blend, it is also predicting nearly the same thing. No alpha in the grid satisfies both. The interpretation is that a weakly-regularised linear model on p greater than n is diverse because it is fitting noise, and noise-driven diversity is worthless in a blend: averaging with it adds variance without adding signal. Once regularisation forces it onto the dominant signal, it converges toward whatever the incumbent already found. The practical rule is to measure BOTH preconditions on the same grid before designing a blend, because a partner tuned to satisfy one will usually violate the other, and a single-point check can make either condition look satisfiable in isolation.
ensemblingmodel-classridgebias-diversityclosed-familydata/processed/blend_precondition_cyp3a4.json · 2026-08-26
high
Donor layers are the campaign's most valuable components: they add rows AND regularise
Removing CYP2D6's 2,883 imputed rows costs +0.0328, more than twice what deploying bagging on all four isoforms bought.
Deep dive
Three leave-one-out ablations across two isoforms now show every deployed layer earning its place, and the donor layers dominating. CYP2D6's imputation costs +0.0328 on scaffold-CV and +0.0302 on LCO to remove, positive on 3 of 3 clusterings and above that isoform's 0.0210 threshold -- the first ablation where LCO is resolvable rather than below noise, so both estimators agree independently. CYP3A4's TDI-condition donors cost +0.0261, twice the -0.0130 they were gated at. CYP3A4's band weighting costs +0.0243, unchanged from its -0.0234. For scale, the entire bagging deploy that moved macro from 0.6910 to 0.6753 was worth -0.0151 on CYP3A4. The reason donors dominate is that they do two jobs at once: they add rows on an endpoint where data is the binding constraint, and #83 showed they simultaneously regularise, since they enter as calibrated predictions at r-squared-scaled weights and pull the fit toward a smooth consensus -- which is why CYP2D6 stopped looking over-trained the moment they were restored. The corollary is the campaign's clearest structural explanation for CYP1A2: it is the only isoform where imputation was tested and decisively rejected (r-squared arm 1.3661 against none at 0.8345, because its single-concentration signal is the weakest at rho 0.376), and it remains the isoform with the least room to improve by any means found.
ablationimputationdonorscyp2d6stackdata/processed/ablate_impute_cyp2d6.json · 2026-08-27
high
Double dissociation: removing ExtraTrees costs the width term half its value and the information term almost nothing
The same manipulation that halves the benefit of noise columns leaves the mechanistic block's genuine signal 95 percent intact. The two effects come apart cleanly.
Deep dive
Disabling ExtraTrees as the only change inside the deployed CYP2D6 configuration, across three matched seeds, separates two components of the block's measured benefit that had previously been quoted as one number. The width term, defined as the improvement a row-permuted block of identical shape delivers over having no block at all, falls from -0.0133 to -0.0066, retaining half its value. The information term, defined as the real block's improvement over its own permuted copy, falls only from -0.0430 to -0.0409, retaining ninety-five percent. This is a double dissociation and it was not designed for; it emerged from a test aimed at a different question. Its importance is that it independently corroborates the permutation result through a completely different manipulation. The permutation control establishes that the block outperforms a signal-free copy of itself, which rules out the possibility that its benefit comes merely from adding columns of the right shape. The dissociation adds that the block's advantage does not depend on the ensemble's randomisation machinery either, since stripping that machinery leaves the advantage essentially untouched while visibly degrading the part that does depend on it. Two independent lines therefore agree that the roughly -0.042 information term is genuine mechanistic signal rather than an artifact of either feature width or ensembling, which is a stronger conclusion than the permutation test alone supports. A practical corollary follows for any future change of model family on this isoform: the mechanistic signal is portable across estimators and would largely survive, whereas the width bonus is substantially an ExtraTrees phenomenon and would not.
methodscyp2d6double-dissociationextratreespermutation-nullmechanismdata/processed/mech_perm_cyp2d6_deployed.json · 2026-08-30
high
Estimating a decision threshold better does not make the score better
The seed whose threshold estimate was closest to optimal lost the most MCC. How much a miss costs is fold-dependent, and that swamps how big the miss is.
Deep dive
Chasing a +0.0504 MCC ceiling on CYP3A4-TDI, three variance-reduced threshold estimators were tried after a pooled argmax failed seed-stability: a median across inner folds, and log-space shrinkage toward the fixed prevalence threshold at two pre-registered levels. The variance reduction worked exactly as intended -- median_inner recovered 44.4% of the ceiling against the pooled argmax's 36.5%, and over-shrinking at L=0.75 fell back to 23.0%, tracing a clean bias-variance curve. Every arm still failed, all on the same seed. The diagnostic explains why, and it retires the whole approach. Comparing each seed's estimated threshold to its oracle: seed 42 estimated at 0.83x the oracle -- the closest of the three -- and lost 0.0414 MCC; seed 7 at 0.41x lost 0.0198; seed 2024 at 0.22x, four and a half times off, lost only 0.0348. Threshold accuracy and MCC cost are inversely related across these folds, which means the MCC-versus-threshold curve is knife-edged on some folds and flat on others. The consequence is general: when the payoff surface for a tuned parameter varies between folds, improving the estimate cannot reliably improve the score, because the estimated quantity is not what determines the outcome. That retires the obvious next moves -- more inner folds, finer grids, better shrinkage -- since all of them improve threshold accuracy, which has just been shown not to predict the result. It also gives the untuned prevalence default a second justification beyond having zero estimation variance: it is not aiming at a target whose payoff shifts underneath it.
thresholdmccestimationfold-dependencetdiretired-approachswarm · 2026-08-24
high
Every magnitude verdict was scored against a 3-sample noise estimate, and it ran half the truth
The gate measured an effect on three seeds and measured the noise on the same three seeds. On CYP1A2 that estimate came out at 0.0037 when twelve seeds say 0.0072.
Deep dive
Every honest-gate run in this campaign printed an effect-versus-seed-noise verdict, and the noise in that ratio was the standard deviation of the SAME THREE SEEDS used to measure the effect. Measuring CYP1A2's deployed base arm across twelve seeds gives a true SD of 0.0072 against the three-seed estimate of 0.0037 -- 51% of the truth. The statistical bias of a 3-sample SD is only about 11% low (E[s] = 0.886 sigma for n=3), so most of that gap is sampling luck, which is the sharper problem: a 3-sample SD is not merely biased low, it is unreliable enough that any single instance can land anywhere. Re-reading CYP1A2's history against the measured null: bandl2 at -0.0206 is 2.86 SD and comfortable; the external+3D joint block at -0.0104 is 1.45 SD and MARGINAL, not the solid win it was first reported as; the 3D block alone at -0.0059 (0.82 SD) and the external block alone at -0.0027 (0.38 SD) both sit inside one SD and were correctly rejected. Nothing is withdrawn -- those verdicts came from a pre-registered gate whose seed-stability and leave-cluster-out criteria are separate evidence from the mean delta -- but the CONFIDENCE attached to them was calibrated against a floor half the real height, and the correction runs in the flattering direction. Two rules follow. Treat any 'meaningful' magnitude verdict as provisional until that isoform's SD has been measured properly. And set the smallest-effect-worth-chasing from a many-seed estimate: on CYP1A2 that is about 0.0072, roughly double what the old number implied.
honest-gateseed-variancecalibrationself-correctioneffect-sizeswarm · 2026-08-25
high
Every model is attenuated toward the mean, and correcting it is worth nothing under ST-RAE
Potent compounds are under-predicted on all four isoforms, monotonically. Fixing that earns credit at the extremes and pays numerator across the dead middle, and the two cancel exactly.
Deep dive
Out-of-fold bias by activity quartile shows textbook regression-to-the-mean attenuation everywhere: mean(pred-y) runs from -0.302 to +0.596 on CYP3A4, -0.358 to +0.531 on CYP2C9, -0.556 to +0.587 on CYP2D6, -0.346 to +1.139 on CYP1A2. CYP2D6 under-predicts potent compounds hardest, and on its most-active quartile the soft error is almost entirely below-band (195.4 against 12.7 above) -- the model lands under the narrow credible bands that potent compounds carry, exactly the failure a calibration exists to fix. A nested screen (calibration fitted on 4/5 of the cached OOF, applied to the held-out 1/5) gives: linear alpha 0.4438/0.5828/0.8706/0.7608 against identity 0.4451/0.5857/0.8706/0.7603, every delta inside the isoform's measured 12-seed SD (0.0037/0.0113/0.0052/0.0072); isotonic regression is WORSE on all four by 0.037-0.043. The mechanism is ST-RAE's U-shaped denominator: rows whose band contains the global mean score zero in the denominator, so undoing attenuation adds numerator across the middle with no credit available there. Scope: a screen, not a gate -- folds are random because the OOF cache carries no scaffolds; a positive result would have needed a scaffold-CV gate, a null this far inside seed noise does not.
calibrationst-raeattenuationall-isoformsnegativemethodsscripts/train/attenuation_screen.py · 2026-08-29
high
ExtraTrees amplifies the benefit of extra feature columns rather than substituting for it
A pre-registered prediction said removing ExtraTrees should make noise columns more valuable. Removing it halves their benefit instead, on every seed.
Deep dive
A hypothesis was proposed that the benefit of adding uninformative feature columns and the benefit of ExtraTrees are the same decorrelation phenomenon, which would imply the two are substitutes and that removing ExtraTrees should make noise columns more valuable because the ensemble would then be short of randomisation. The prediction was falsifiable and the decision rule was written into code before any number was produced: the hypothesis counts as supported if the noise-column benefit grows by more than 0.002 when ExtraTrees is disabled, refuted if it shrinks by more than 0.002, and unresolved in between. Measured on CYP2D6 across three matched seeds with ExtraTrees as the only change inside the deployed configuration, the noise benefit was -0.0176, -0.0105 and -0.0119 with ExtraTrees active and -0.0114, -0.0016 and -0.0069 with it disabled, means of -0.0133 and -0.0066 respectively. The benefit halves rather than growing, a change of +0.0067 that is well outside the pre-registered band, and the direction is consistent on every seed. The hypothesis is refuted and the opposite relationship holds: ExtraTrees amplifies the effect of extra columns rather than replacing it. The mechanism is straightforward once stated. ExtraTrees samples roughly 48 of 2,288 available columns at each split, so adding 23 columns materially changes its candidate pool, whereas LightGBM at a feature fraction of one already considers every column and additional ones change comparatively little. The two effects are linked through feature sampling but multiplicatively rather than as substitutes, and this also accounts for the observed cross-target pattern in which noise columns help on the isoforms where ExtraTrees helps and cost where it does not.
methodsextratreesrandomizationrefutationpre-registrationfeature-samplingdata/processed/mech_perm_cyp2d6_deployed.json · 2026-08-30
high
Feature blocks are NOT additive - on CYP3A4 the two-block model is worse than the better block alone, exactly as the PXR ensemble lesson warned
Two features that each help are not a feature that helps twice. Measure the combination; never add the deltas.
Deep dive
Joint gate on CYP3A4 (scripts/train/combined_gate.py), identical folds, 3 seeds. Scaffold-CV RAE: base 0.6215, base+mech 0.6186 (-0.0029 alone), base+aux 0.6086 (-0.0129 alone), base+mech+aux 0.6092. If the deltas were additive the two-block model would score 0.6057; it actually scores 0.6092 - WORSE than the aux block alone at 0.6086. So the mechanistic block, which genuinely helps by itself, costs a little when stacked on top of the auxiliary: they explain overlapping variance and the extra 23 columns are net dilution. This is the inherited PXR finding reproduced on CYP with a controlled comparison - 'the ultimate ensemble regressed while a robust base plus one disciplined calibration won'. Practical rule for the rest of the campaign: report per-block deltas as INDEPENDENT measurements only, and never quote a combined macro that was assembled by summing them. The campaign macro was deliberately frozen at the last verified 0.831 for several ticks for exactly this reason, and that caution is now vindicated.
additivityensemblingcyp3a4honest-gatepxr-lessoncombined-gate · 2026-08-23
high
Feature-block signal is small and target-dependent, not a constant swamped by width
A tempting synthesis said blocks carry a constant ~0.005-0.007 of signal that the width penalty either covers or eats. Both constants failed on measurement.
Deep dive
Midway through the surrogate program a unifying model was proposed: that mechanistic feature blocks carry a roughly constant quantity of real signal, and that whether a block appears to work is decided by whether the dataset's width penalty exceeds it. The attraction was that it would have reframed the campaign's long record of absorbed physics blocks from physics does not help to physics is real but arrives too wide, which implies a concrete and hopeful direction, namely narrower encodings of the same mechanism. Direct measurement refutes both of its constants. First, the width penalty is not a fixed property of block width: on CYP2C19 it is approximately zero overall at +0.0003 RAE, and at n=1500 it is -0.0018 plus or minus 0.0019, which excludes a +0.005 penalty at 3.5 standard errors. The collection where the mechanistic block did least therefore had the lowest width penalty in the whole program, so nothing was being swamped there. Second, the signal is not constant across targets: expressed in absolute pIC50 units the information gap is about -0.0010 on CYP2C19 against about -0.0044 on CYP2D6, a four-fold difference. What survives is a weaker and more honest statement. Blocks carry small, genuinely real, target-dependent information; the width penalty is a separate size-dependent cost that vanishes with enough training data; and the two must be measured separately because testing against absence confounds them. On CYP2D6 the information is real and reproducible at roughly -0.004 pIC50 across mixed, homogeneous and size-matched collections alike, while on CYP2C19 it is real but four times smaller and below the resolution of any single training size, showing as a consistent sign across five sizes at p=0.031 rather than as a significant individual result.
methodsphysicsfeature-blockssurrogaterefutationsynthesissurrogate program #145 · 2026-08-30
high
First verified macro: 0.8354 -> 0.8248 scaffold-CV, and 0.8595 -> 0.8404 under series shift
The deployed blocks help MORE out-of-series than in-scaffold - the right direction for a blinded test that is itself a series shift.
Deep dive
First joint-gated result across all four isoforms (scripts/train/combined_gate.py, identical scaffold folds, 3 seeds, base vs +mech vs +aux vs +both). Winners and per-isoform scaffold-CV RAE: CYP3A4 base+aux 0.6215->0.6086; CYP2C9 base+aux 0.8255->0.8036; CYP2D6 base+mech 0.9954->0.9878 (magnitude weak); CYP1A2 base 0.8993 (nothing qualified). MACRO 0.8354 -> 0.8248, delta -0.0106. Under leave-cluster-out the macro goes 0.8595 -> 0.8404, delta -0.0191 - nearly DOUBLE the scaffold-CV gain, which is the encouraging direction: the deployed blocks help MORE under series shift than under scaffold CV, and the blinded test is a series shift (11.5% scaffold overlap, 0% compound overlap). Two corrections to the record: the previously-quoted macro of 0.831 was never verified and was assembled by assuming additivity - the real base is 0.8354 and the real best is 0.8248. And the single-concentration auxiliary, not the mechanistic block, is doing almost all the work: it wins outright on both isoforms where it qualified, and CYP2D6's mechanistic-only gain remains noise-order. Artifact: data/processed/combined_summary.json.
macrojoint-gateverifiedleave-cluster-outcombined-gate · 2026-08-23
high
Five ensemble members is already saturation: 5 to 15 buys 0.43 SD, exactly what 1/n predicts
Tripling the ensemble removes only 13% of the member variance, and that is below every isoform's noise floor.
Deep dive
After seed-bagged averaging deployed at n=5, n=15 was tested on CYP3A4 (best-resolved) and CYP2C9 (the rejected isoform, and the best rescue candidate since its averaging component was the largest at -0.0152 while subsampling cost it +0.0081). The direction confirmed: 2C9's averaging grew to -0.0186 and its total from -0.0071 to -0.0105, 3A4's total from -0.0151 to -0.0167. But the bag15-minus-bag5 difference is -0.0016 on 3A4 (0.43 SD) and -0.0034 on 2C9 (0.30 SD), neither resolvable against the measured seed nulls. That is precisely the 1/n prediction: going from 5 to 15 members removes (1/5 - 1/15) = 13% of member variance, and 13% of an effect that was itself around 0.015 is around 0.002. bag5 is retained everywhere; the extra 3x compute buys nothing that can be distinguished from noise. CYP2C9 stays rejected at 0.93 SD -- close enough that a 12-seed re-run is the honest next step rather than a discard.
baggingensemblingsaturationcyp2c9data/processed/bagged_cyp2c9.json · 2026-08-25
high
Four criteria all computed from the same metric cannot catch a mis-transferred decision rule
A +0.0361 MCC gain passed 12/12 seeds, a 2.89 SD bar and 3/3 LCO clusterings -- and came from a threshold estimator that is 4.2x too low.
Deep dive
Bagged probabilities plus an inner-fold argmax threshold beat the shipped CYP3A4-TDI model by +0.0361 MCC on every one of 12 seeds, at 2.89 SD against the measured 0.0125 null, with LCO agreeing 3 of 3. Both halves alone had been correctly rejected (bagging +0.0098 at 10/12; the inner cut alone +0.0184 in #58), so it presented as a genuine combination effect of the kind that has worked here before. A pre-registered diagnostic then measured what none of the four criteria could see: the inner-estimated cut is 0.0068 against the outer fold's own optimum of 0.0283, so the estimator is 4.2x too low, because inner folds train on fewer rows and produce systematically lower probabilities (median 0.0013 vs 0.0017). The gain is a by-product of that mis-calibration rather than of finding the right cut, and the size of the bias depends on the inner-to-outer fold-size ratio -- which differs between CV evaluation and the final fit-on-all-data-then-predict-test setup, so it would not transfer. The structural lesson: all four honest-gate criteria are computed FROM the scored metric, so they pass identically whether a win comes from a better model or from a decision rule that is broken in a locally helpful direction. When a lever changes how predictions are converted into a score rather than the predictions themselves, at least one check must sit outside that metric.
tdithresholdinggatingestimator-biasmccdata/processed/tdi_threshold_diagnostic_cyp3a4.json · 2026-08-26
high
Four isoforms, four different winning configurations - no single architecture is right for CYP
Every isoform wants a different combination of features and loss weighting. Optimising one global model would be wrong three times out of four.
Deep dive
The full cross {base, +mech, +aux, +mech+aux} x {none, band weighting} gated under ST-RAE gives FOUR DIFFERENT winning configurations, one per isoform, every one clearing the magnitude check: CYP3A4 base+mech+aux + weighting 0.5541->0.5265 (-0.0276); CYP2C9 base+aux with NO weighting 0.7275->0.6894 (-0.0381); CYP2D6 base+mech + weighting 1.0005->0.9304 (-0.0701); CYP1A2 plain base + weighting 0.8695->0.8345 (-0.0350). MACRO 0.7879 -> 0.7452 (-0.0427), and under leave-cluster-out 0.8196 -> 0.7641 (-0.0555) - again the gain is LARGER under series shift than in-scaffold, which is the reassuring direction given the blinded test is a series shift. Three structural observations. (1) No configuration wins twice. A single global architecture would have to be wrong on at least three isoforms, which retroactively justifies gating per-isoform and refusing to optimise a macro directly. (2) Band weighting deploys on 3 of 4 but NOT on CYP2C9, where the single-concentration auxiliary alone wins - and 2C9 is the isoform whose band widths vary least among the deployers. (3) The two levers INTERACT with isoform-dependent sign: super-additive on 2D6 (-0.0701 actual vs -0.0469 additive), merely additive on 1A2, and on 3A4 every weighted config beats every unweighted config with a seed spread of only 0.0018, so weighting dominates feature choice entirely there. Worth recording that a single-seed read of 3A4 suggested features INTERFERE on top of weighting; across three seeds the full config won. Single-seed reads have now misled this campaign twice, which is the argument for keeping seed-stability as a hard gate criterion rather than a formality.
final-gateper-isoformst-raeband-weightingarchitecturefinal-gate · 2026-08-23
high
Gate a layer by removal from the final stack, not only by addition to an old one
CYP3A4's TDI donors were gated at -0.0130 and now cost +0.0261 to remove: the layer doubled in value while nobody was looking.
Deep dive
Every layer in this campaign was gated when added, against the incumbent that existed at that moment, and none had been re-tested by removal from the stack as it now stands. Layers here demonstrably interact: band weighting and imputation multiply a feature block's effect fivefold (#63), donor imputation absorbs the loss-shaping levers (#66), and donors absorb a capacity lever (#83). A greedy assembly path can therefore end on a configuration containing a layer that is redundant or harmful. Leave-one-out ablation on CYP3A4, control reproducing 0.4492 exactly: removing the TDI-condition donors costs +0.0261, twice the -0.0130 they were gated at, so that layer has grown more valuable; removing band weighting costs +0.0243 on every seed against the -0.0234 it was gated at, so that one is unchanged. Both stay. The band result also refutes a specific prior: I expected donors to have absorbed band weighting because #66 showed them absorbing precision-weighting levers, but #66 tested SWITCHING schemes and objectives, whereas removing the weighting entirely is a different operation and still matters. Donors absorb variations among precision-weighting schemes without substituting for having one. The practical rule is that a stack assembled greedily should be ablated once it stops changing, because the value of an early layer is measured against a model that no longer exists.
ablationlayeringstackcyp3a4interactionsdata/processed/ablate_tdi_donors_cyp3a4.json · 2026-08-27
high
Imputation and the single-conc auxiliary SUBSTITUTE, not stack - same data, two encodings, and the simplest config wins
Both derive from the same screen. Once one encoding is in, the other adds nothing - and stacking both costs 0.013 ST-RAE in complexity.
Deep dive
CYP3A4, full cross {base, +aux, +mech+aux} x {no-imp, imp} under ST-RAE with the winning band scheme. WINNER IS THE SIMPLEST CONFIG: base|imp at 0.4773 (base|noimp 0.5307, -0.0534), LCO 0.6110 -> 0.5120. Adding features ON TOP of imputation makes it WORSE, not better: base+aux|imp 0.4904, base+mech+aux|imp 0.4863. The imputation delta collapses as soon as the auxiliary is present: base -0.0534, base+aux -0.0001, base+mech+aux -0.0039. THE EXPLANATION IS STRUCTURAL, not statistical. Both levers draw on the SAME source - the single-concentration screen. The auxiliary encodes it as predicted log2fc FEATURES; imputation encodes it as log2fc-derived LABELS on extra rows. They are two encodings of one information source, so they SUBSTITUTE rather than stack, and the better encoding simply wins. Imputation is the better encoding here (-0.0534 vs -0.0402 for aux alone), plausibly because extra labelled rows teach the model where the response surface actually sits, whereas a predicted feature can only re-describe inputs the model already has. PRACTICAL RULE: before combining two derived signals, ask whether they trace back to the same measurement. If they do, expect substitution and pick the stronger encoding instead of stacking both - stacking cost 0.013 ST-RAE here (0.4904 vs 0.4773) for extra complexity. This is the third distinct interaction pattern observed in this campaign: features interfered with each other on 3A4, features and weighting were super-additive on 2D6, and now features and imputation substitute. There is no default assumption that survives - combinations must be measured every time.
cyp3a4imputationsubstitutioninteractionst-raesimplicityfinal3 · 2026-08-23
high
Imputation donors are silently regularising: they turn a -0.0655 over-training gap into +0.0027
CYP2D6 looks badly over-trained at 500 trees on raw data, and perfectly tuned once its 2,883 donor rows are restored.
Deep dive
A convergence diagnostic on base features showed every isoform peaking well before 500 trees and then degrading -- CYP2D6 best at 25 iterations with a -0.0655 ST-RAE gap to 500, the largest apparent unexploited effect in the campaign. Gated properly in the deployed pipeline with a pre-registered n_estimators=200, it becomes +0.0027, better on 1 of 3 seeds, with LCO -0.0002 at sign stability 0.33: the effect vanishes. The reason is that CYP2D6's deployed pipeline trains on 4,376 rows rather than 1,194, because 2,883 imputation donors are added, and those donors regularise by construction -- they are calibrated predictions entering at r-squared-scaled weights, so they pull the fit toward a smooth consensus and prevent exactly the over-fitting that 500 trees produce on raw data. The tree budget only looked wrong because the diagnostic had removed the thing making it right. This is the third independent arrival at the same rule: #63 found band weighting and imputation MULTIPLY a feature block's effect, #66 found donor imputation ABSORBS loss-shaping levers, and here donors absorb a capacity lever. A hyperparameter's correct value is a property of the configuration it sits in, so a diagnostic run on a stripped pipeline is measuring a different model.
hyperparametersimputationregularisationcyp2d6configurationdata/processed/estimators_cyp2d6.json · 2026-08-26
high
Imputation harm scales with injected variance - 15x between k=1.0 and k=0.2
The imputed labels carry no information where donors live, so what they do to a model depends on their spread, not their accuracy.
Deep dive
Scaling CYP1A2's imputed labels around their own mean (y' = mean + k*(y - mean)) sweeps the harm almost perfectly with k: k=1.0 costs +0.1427 ST-RAE, k=0.7 +0.0599, k=0.4 +0.0144, k=0.2 +0.0093 -- a 15-fold reduction, monotone across that range, with LCO tracking it from 1.0296 down to 0.8651. That is what you expect if the labels convey nothing and act only through their distribution, which the donor-region calibration result independently requires (negative R^2 on every isoform). But two boundaries matter. First, no value of k rescues CYP1A2: the best arm still loses to no imputation by +0.0093, so its 2,964-donor row supply is unusable at any variance level and that question is closed rather than open. Second, k=0.0 -- a pure constant label -- is WORSE than k=0.2 (0.8626 vs 0.8232), so the curve is U-shaped and the benefit is not pure shrinkage; a little label variation beats none. A single unified mechanism across isoforms is NOT established and should not be asserted: CYP3A4 has the strongest signal of the four, benefits most from imputation, and has the best donor-region behaviour (random-split R^2 0.8554, donors 98.1% in-range and MORE inhibitory than measured compounds), which fits genuine information transfer rather than shrinkage. The defensible reading is mixed -- information on CYP3A4, shrinkage on CYP2D6 -- with CYP1A2 getting neither because its own signal is comparatively strong and its inv_width loss already shrinks, so extra rows only dilute.
imputationvarianceshrinkagecyp1a2mechanismswarm · 2026-08-24
high
Imputing missing labels from the dense single-conc matrix makes CYP2D6 much WORSE - imputed labels are 4.8x noisier than the assay
More rows is not more information when each new label carries several band-widths of error. Scarcity beats noise at volume.
Deep dive
Ledger item 4 (sparse-matrix framing) tested in the form with real leverage: the single-concentration screen is 100% DENSE and covers 89% of train, so a compound measured only on 3A4 still has a MEASURED log2fc for 2D6. Calibrating log2fc -> pIC50 per fold and adding the imputed compounds as extra training ROWS would give 3A4 2.10x, 2C9 3.40x, 2D6 2.93x, 1A2 3.10x more data. Note this is NOT the auxiliary route that failed earlier: that predicted log2fc FROM STRUCTURE and fed it back as a feature, so it could only re-express the model's own inputs. Here the log2fc is measured, and it manufactures new LABELS. Not circular either - the labels come from an independent assay, never from our own pIC50 predictions. RESULT ON CYP2D6: badly negative. ST-RAE 0.9626 -> 1.0728 (R^2-weighted) and -> 1.0764 (flat 0.5 weight); leave-cluster-out 0.9863 -> 1.2055/1.2164. Adding 2.93x more rows pushes the isoform from below the mean predictor to well ABOVE it. WHY, quantified: imputed labels are far noisier than real ones. Residual SD of the log2fc->pIC50 calibration vs the assay's own SD is 2.1x (3A4), 2.4x (2C9), 3.1x (1A2) and 4.8x (2D6). 2D6 is worst on BOTH sides - the poorest calibration (R^2 0.496 vs 0.78 for 3A4/1A2) and the tightest real measurements (assay SD 0.134) - so imputation is least accurate exactly where extra data is most wanted. Worse for this metric specifically: a 0.650 SD imputed label is roughly 2.4x CYP2D6's entire median credible band (0.272), so imputed rows actively teach the model to land OUTSIDE the bands that ST-RAE scores. GENERAL LESSON: label noise at volume beats label scarcity only when the noise is small relative to the metric's tolerance. 1,493 clean labels beat 4,376 labels carrying several band-widths of error, and down-weighting does not rescue it because the noisy rows are 66% of the training set.
imputationsparse-matrixcyp2d6label-noisenegative-resultst-raeimpute-rows · 2026-08-23
high
Independent corroboration: the isoform that gained most WIDENED its predictions, the one that gained least compressed further
Not a test I designed - it fell out of comparing two submissions. The shrinkage-tracks-ignorance relationship holds within a single update.
Deep dive
Comparing submissions v04 and v05, which differ only in the Emax-calibrated imputation deployed on CYP2C9 and CYP2D6. CYP2C9 took the campaign's largest single-isoform gain (-0.1242, 0.7275 -> 0.6033) and its predicted SD ROSE from 0.799 to 0.911, now slightly above its training SD of 0.782. CYP2D6 gained far less (-0.0142, 0.9072 -> 0.8930) and its predicted SD FELL further, 0.290 -> 0.257, against a training SD of 0.916. CYP3A4 and CYP1A2 are byte-identical between versions (corr 1.0000) since their recipes did not change, which also confirms the per-isoform builder is not perturbing isoforms it should not touch. WHY THIS MATTERS: the earlier variance-matching work established that prediction shrinkage tracks model ignorance - CYP3A4 needed k=1.32 to restore its training spread and paid +13.3%, CYP2D6 needed k=2.57 and paid +48.4%. That was measured deliberately across two isoforms. This is the same relationship appearing unbidden in a comparison run for a different purpose: a model that learns more about an isoform stops hedging, and one that learns little hedges harder. Corroboration from an experiment not designed to test it is worth more than another deliberate replication, because there was no opportunity to fit the analysis to the expectation.
shrinkagecalibrationcorroborationcyp2c9cyp2d6submission-audit · 2026-08-23
high
Loss reweighting fixes metric misalignment, never information scarcity - three experiments now agree
Band weighting worked because ST-RAE forgives band-interior error. Where there is no misalignment to correct, or the limit is information, reweighting does nothing.
Deep dive
Three weighting experiments across both tracks now form a consistent rule. (1) BAND WEIGHTING on inhibition: large win, deployed on 3 of 4 isoforms, because ST-RAE forgives error inside the credible band so an unweighted loss spent capacity on compounds the metric barely scores - a genuine LOSS/METRIC MISALIGNMENT. (2) CLASS WEIGHTING on TDI: clean null on both scored isoforms, because MCC has no forgiveness structure and prevalence is already handled by thresholding at the training positive rate. (3) LABEL-CONFIDENCE WEIGHTING on TDI, tested this tick: also null, and for a third reason. The TDI label is close to a z-test outcome - |pic50_shift| / band_width correlates +0.695 (3A4) and +0.639 (2D6) with it - so boundary compounds have coin-flip labels and down-weighting them looked principled. It changes nothing: 3A4 best scheme +0.0045, CYP2D6 best +0.0013, neither seed-stable. The reason is that this addresses label NOISE while CYP2D6's TDI problem is an INFORMATION limit - MCC 0.106 means structure barely predicts the label at all, and no reweighting manufactures information that is absent. RULE: loss reweighting fixes misalignment, never scarcity. Diagnose which one you have before reweighting - and if the metric has no forgiveness structure and the model is near chance, do not bother.
tdiweightingmccnegative-resultunifying-ruletdi-labelconf · 2026-08-24
high
Make the harness reproduce a known value before reading any contrast
A defect renders as a confident null. If the control cannot recover a number you already know, the effect you are measuring is the harness.
Deep dive
Three defects in one tick, each one commit from being recorded as science, all caught by the same move. (1) A custom LightGBM objective starts from raw score 0, not the label mean, so it scored 10x baseline and read as 'training on the metric is catastrophic'; init_score fixed it (9.4591 -> 0.8304). (2) With that fixed, softband still lost -- but collapsing its band to a point makes it mathematically IDENTICAL to builtin l1, and it scored MAE 0.7877 against l1's 0.5919. LightGBM renews leaf values to the median for builtin l1/huber/quantile and NOT for custom objectives, so sign gradients with a constant Hessian pin every leaf near +-1 and the fit goes high-variance (pred SD 0.68 vs 0.26). The entire softband-vs-l2 contrast was leaf-value handling. (3) The objective harness re-runs each isoform's DEPLOYED recipe, so its l2 arm must recover the deployed score. It did exactly for CYP3A4 (0.4773) and CYP1A2 (0.8345) but not for the two isoforms using Emax imputation (CYP2C9 0.6924 vs deployed 0.6033) -- donor NaNs were filled from full-table medians instead of donor-subset medians. The apparent CYP2C9 l1 win of -0.0402 was measured against the wrong incumbent. Two standing controls adopted: a custom objective must reproduce its builtin twin, and any harness re-running a deployed recipe must reproduce its deployed score within 0.01 before its deltas are transferable to a submission.
harnessvalidationlightgbmobjectivemetaswarm · 2026-08-24
high
MCC on a 21% positive rate wants a far more permissive cut than prevalence matching
The MCC-optimal probability threshold sits around 0.002-0.017. Prevalence matching sits at 0.058-0.082, and the naive 0.5 is a disaster. Nobody had looked.
Deep dive
All six TDI experiments in this campaign thresholded at the training positive rate, a default that makes predicted prevalence match observed prevalence and was never questioned. Measuring it on CYP3A4-TDI: an oracle threshold chosen on the evaluation fold reaches MCC 0.4075 against the incumbent's 0.3571, so threshold choice alone is worth +0.0504, or 14% relative -- larger than any feature effect the TDI track has produced. The direction is the substantive part. MCC-optimal cuts land at 0.002 to 0.017 in probability, roughly an order of magnitude BELOW prevalence matching, because at a 21% positive rate MCC rewards recovering positives more than it penalises the false positives that come with them. That is a property of the scoring function rather than of any model, and it stayed invisible while every experiment shared one default. The incumbent is nonetheless only half-wrong: cutting at 0.5 costs -0.0616, so prevalence matching was far from arbitrary, it simply stops short. A realistic estimator -- choosing the cut by MCC on an inner cross-validation of the training fold, never touching the evaluation fold -- recovers 36.5% of the ceiling (+0.0184) and improves leave-cluster-out by +0.0382, but fails seed-stability, and the reason is visible: the inner-CV optima themselves scatter across 0.002, 0.004 and 0.009 between seeds. So the difficulty is ESTIMATING the cut, not the existence of a better one, which points specifically at a smoothed or shrunk estimator rather than at abandoning the idea.
tdimccthresholdclass-imbalancedecision-ruleswarm · 2026-08-24
high
Measure the ceiling, then measure what survives estimation - a large ceiling with poor survival is closed, not an invitation
Both TDI isoforms have threshold headroom bigger than any feature effect the track has produced. Neither can reach it, and the estimator improving as theory predicts did not change that.
Deep dive
Threshold choice on the TDI task offers +0.0504 MCC on CYP3A4 and +0.0380 on CYP2D6 at the oracle, both larger than any feature effect six TDI experiments produced. Two rounds of estimator work followed. Pooled argmax on an inner cross-validation captured 36.5% on CYP3A4 while failing seed-stability and -101.8% on CYP2D6, actively worse than the untuned default. Variance reduction then did exactly what bias-variance theory prescribes: on CYP3A4 the median across inner folds lifted capture to 44.4% and log-space shrinkage traced a clean optimum (37.3% at L=0.5, over-shrinking to 23.0% at L=0.75), while on CYP2D6 increasing shrinkage monotonically halved the damage at every step -- -101.8%, -51.1%, -27.1%, -11.8% -- converging on the incumbent as L approaches 1. That monotone ordering matters independently of the verdict, because it shows the mechanism was implemented correctly and the null is real rather than a bug. Neither isoform crossed into a deployable gain. The CYP3A4 diagnostic explains why no further estimator work would help: the seed whose threshold estimate was CLOSEST to its oracle (0.83x) lost the MOST MCC (0.0414), while a seed 4.5x off lost less, so threshold accuracy and MCC cost are inversely related across folds and the payoff surface for the estimated quantity shifts underneath it. The transferable procedure: for any tuned decision rule, measure the oracle ceiling first, then measure what fraction survives honest estimation, and treat a large ceiling with poor survival as a CLOSED question rather than a reason to estimate harder.
decision-rulesceilingestimationbias-variancetdiclosed-questionswarm · 2026-08-24
high
Model capacity is at a local optimum: more hurts where the cap binds, less does nothing where it does not
num_leaves=64 was never tuned, and testing both directions shows there is nothing to gain either way.
Deep dive
The campaign shipped one LightGBM capacity across four isoforms without examination. Dumping the fitted trees showed the 64-leaf cap binds on CYP3A4 alone (100% of trees) and never on CYP2C9, CYP2D6 or CYP1A2 (40.5, 46.8, 44.1 mean leaves, bounded by min_child_samples and the data). Both directions were then tested with LightGBM's own default of 31 as the reduced value, chosen over a search so it cannot be accused of being picked because it worked. Results: CYP3A4 at 128 leaves is +0.0160 on scaffold-CV with LCO +0.0128 positive on 3 of 3 clusterings and above its 0.0067 threshold, which is resolvable contrary evidence; CYP2D6 at 31 leaves is +0.0026 at 0.5 SD; CYP1A2 at 31 leaves is -0.0001 at 0.02 SD. The effect magnitudes track where the cap binds -- CYP3A4's is six times CYP2D6's -- which is the internal consistency check that the diagnostic was measuring something real. The practical reading is that the cap is doing useful work as regularisation against a hard scaffold shift on the one isoform with enough data to overfit, and is simply inactive elsewhere. Capacity is closed as a lever in both directions.
hyperparameterscapacitylightgbmclosed-familydata/processed/capacity_cyp2d6.json · 2026-08-26
high
Near-constant imputed labels are a regulariser, not a bug
CYP2D6's calibration collapses to a fifth of the real label spread, and imputation still deploys there. Under a band-forgiving metric, pulling predictions toward the centre is rational.
Deep dive
Measuring the imputed-label distributions across all four isoforms overturned an assumption worth stating. CYP2D6's donors sit 99.6% OUTSIDE the measured single-conc log2fc range, so its calibration extrapolates and produces labels with a standard deviation only 0.202 of the real labels' -- nearly a constant, spanning 17% of the real range. That looks like a broken calibration, and imputation is nonetheless DEPLOYED on CYP2D6, where it is worth 0.9304 -> 0.8930. The reason is the metric: ST-RAE charges nothing inside each compound's credible band, so a large block of rows carrying an approximately constant label acts as a shrinkage prior toward the band centre, which is exactly the rational prediction where the model has no discriminating signal. By contrast CYP1A2, where imputation is catastrophic (1.37, far worse than the mean predictor), has donors 98.7% INSIDE the measured range with an imputed spread of 1.068x the real one -- interpolating, realistically varied, directionally correct in its bias, and still destructive. So the usual diagnostic instinct is inverted here: the isoform whose imputed labels look worst by every distributional check is the one where they help, and the isoform whose labels look healthiest is the one where they wreck the model. Judge imputed labels by what they do under the scoring metric, not by how much they resemble real ones. CYP1A2's failure remains unexplained after donor mass, effective sample size, and extrapolation were each ruled out.
imputationregularisationst-raecyp1a2cyp2d6diagnosticsswarm · 2026-08-24
high
No label-based precondition can be evaluated on the population a donor layer is applied to
A calibrator can only be scored on compounds that have the label. Donor rows are, by definition, the compounds that do not. So a precondition measured on the labelled set says nothing reliable about the unlabelled one it will be used on.
Deep dive
Cross-isoform completion for CYP1A2 gave a decisive precondition -- adding other-isoform pIC50 labels lifted scaffold R2 for predicting held-out CYP1A2 from 0.1042 to 0.1985, better on 3 of 3 seeds -- and the gate then rejected it: 0.7688 deployed against 0.7794 with donors, +0.0106 worse on every seed at 1.47 SD, control reproducing. The precondition was measured on the 469 compounds that have a CYP1A2 label while donors are by construction those that do not, and an earlier tick had already shown calibration runs negative-R2 in the donor region on all four isoforms. The consequence generalises to every donor or imputation layer: such preconditions are structurally incapable of predicting donor-layer success, so the gate is not an expensive confirmation but the only available test. It also explains without further appeal why CYP1A2's imputation failed four separate ways while the identical machinery is worth +0.1045 on CYP2C9 -- donor-layer value is not a function of calibration quality. Sparse-matrix completion, the last untried item on the priority list, is closed on this measurement.
imputationdonorspreconditionsmatrix-completioncyp1a2rejectedscripts/train/crossiso_gate.py; data/processed/crossiso_gate_cyp1a2.json; ledger #123, #124 · 2026-08-29
high
On a noisy endpoint the SEED BLOCK is part of the configuration, not just its size
Three estimates of the same deployed CYP2D6 TDI model span 1.17 SD depending only on which twelve seeds were drawn. Matching the number of seeds is not the same as matching the seeds.
Deep dive
The same shipped model scores MCC 0.0791 on seeds 42-53, 0.0970 across a 20-seed audit, and 0.1058 on the incumbent's own twelve seeds. CYP2D6 TDI has a measured MCC seed SD of 0.0229, so the choice of seed block moves the absolute score by more than most effects this campaign measures. A gate that uses a different block from the incumbent fails the fifth criterion even when its own arms are internally consistent: here the control missed by 0.0179 against a 0.0132 tolerance, so a +0.0715 improvement at 3.12 SD is formally not transferable and does not deploy. The paired delta itself is sound -- both arms share every seed and fold, so a low block cannot manufacture the difference -- but 'the delta is fine' is precisely the argument shown insufficient when a clean delta over a wrong baseline fooled this campaign before. Practical rule: gates must reuse the incumbent's seed list, not merely the same number of seeds.
seed-noisefifth-criteriontdicyp2d6controlsharnessdata/processed/tdi_family_cyp2d6.json, tdi_seed_audit_cyp2d6.json; ledger #107 · 2026-08-28
high
On CYP3A4 the binding constraint on physics is block WIDTH, not block quality
Adding 20 to 23 arbitrary columns costs about +0.005 RAE. The real mechanistic blocks beat their permuted twins by only 0.0025 to 0.0088. The signal is real and the column budget eats it.
Deep dive
Running each feature block against its own row-permutation null on public CYP3A4 data separates two effects that are normally confounded. A permuted block preserves column count, column marginals and within-block collinearity while destroying the compound correspondence, so the difference between an absent block and a permuted block measures the pure cost of widening the feature matrix, and the difference between a permuted block and the real block measures genuine signal. On CYP3A4 the width cost of adding 20 to 23 arbitrary columns is approximately +0.005 RAE, while the real mechanistic and heme-ligation blocks beat their permuted twins by 0.0025 to 0.0088. Both blocks therefore carry real signal of roughly the same magnitude as the penalty they incur simply by being that wide, which is why they never separate from absence and appear to be worthless. The constraint is not the quality of the physics but the width in which it arrives, and the implication is that a narrow block encoding the same mechanism could win where a wide one cannot. This also explains why real-versus-absent is the wrong comparison and real-versus-permuted is the right one: the former conflates signal with width penalty. Supporting diagnosis from the same run: the strongest single mechanistic term correlates with the target at +0.218 but with the base model's error at only +0.039, which is the campaign's long-standing observation that alignment with truth is not the same as adding signal, now measured at 3010-compound resolution.
methodspermutation-nullwidth-penaltycyp3a4physicsfeature-blocksdata/processed/surrogate_cyp3a4_public.json · 2026-08-30
high
One cheap solo run predicts whether a second model family will help -- break-even is a solo gap of +0.03 to +0.05
Averaging a second family in helps only if that family is nearly as good alone. Measure it alone first: that single arm tells you the sign before you pay for the full gate.
Deep dive
Sweeping ExtraTrees' max_features on CYP3A4 cut its solo gap 63% (sqrt/~48 features +0.1395, 0.1/227 +0.0724, 0.3/680 +0.0514) -- so the MAGNITUDE of its incompetence was largely an untuned hyperparameter of mine, not a property of the family. The full gate at mf=0.3 still rejected (+0.0097, 0/3, 2.63 SD, control reproducing), exactly as the rule predicted, and the HARM fell by the same 63% as the gap -- a within-isoform pair with everything else fixed, far stronger evidence than the original cross-isoform monotonicity. Across five measured configurations: gap +0.0090 -> -0.0110 (2D6), +0.0307 -> -0.0089 (1A2), +0.0514 -> +0.0097 (3A4 mf=0.3), +0.1179 -> +0.0095 (2C9), +0.1395 -> +0.0261 (3A4 sqrt). Break-even is therefore bracketed between +0.031 and +0.051. The mechanism behind the ceiling: competence and decorrelation move against each other (max_features -> 1.0 turns ExtraTrees into a plain randomized-threshold forest), so improving the second model improves it as an ensemble member proportionally but does not convert it into one. Cost matters too -- mf=0.3 is roughly 10x the fit time for a result that is still a rejection.
ensemblingextratreesscreeningcompetencecyp3a4rejectedhyperparametersscripts/train/et_competence_sweep.py; data/processed/et_competence_cyp3a4.json, family_et_cyp3a4_mf03.json; ledger #103 · 2026-08-27
high
Optimal calibration slope flips sign with model quality: good models want expansion, weak ones want shrinkage
CYP3A4 and CYP2C9 want their predictions stretched; CYP2D6 and CYP1A2 want theirs pulled toward the mean.
Deep dive
An explicit shrinkage pred' = mean + alpha*(pred - mean) was swept from 0.70 to 1.10 on all four isoforms' deployed out-of-fold predictions. The per-isoform optima disagree in SIGN: CYP3A4 1.06 and CYP2C9 1.08 want expansion, CYP2D6 0.86 and CYP1A2 0.88 want shrinkage, with corr(best alpha, deployed ST-RAE) = -0.919. The reading is mechanical: a well-predicted model is under-confident and benefits from stretching, while a model close to the mean predictor is mostly noise and benefits from being pulled toward the mean. The practical consequence is that any selection method which pools across isoforms -- leave-one-isoform-out here -- averages opposing signals toward alpha near 1.0 and lands each isoform on the wrong side of its own optimum, which is exactly what happened (2D6's optimum 0.86, LOIO handed it 1.04, delta +0.0024). The family closes anyway on magnitude: even the in-sample optimum, fitted on the same predictions it scores and therefore an upper bound, is worth at most -0.0050 on CYP1A2 against that isoform's 0.0072 seed null. A gain smaller than the noise cannot be captured honestly by any estimator.
calibrationshrinkagest-raecross-isoformrejecteddata/processed/shrinkage_gate.json · 2026-08-26
high
Patching a symptom twice is the signal to fix the pattern
The incumbent-reproduction control has now anchored on a superseded model twice, for the same structural reason, because the first fix hardcoded one layer instead of walking them all.
Deep dive
The fifth gate criterion says a harness re-implementing a deployed pipeline must reproduce that pipeline's score. It was implemented as deployed_score(), reading the feature/imputation gate artifact. The objective gate (#44) then stacked a layer on top and the control silently anchored CYP1A2 at a superseded 0.8345 instead of the bandl2 0.8139 it actually ships -- caught, and fixed by special-casing the objective artifact. One tick later the donor gate (#50) stacked ANOTHER layer, and the identical failure recurred: the donor-weight sweep's control reported DOES NOT REPRODUCE because deployed_score() returned CYP3A4's pre-donor 0.4773 while the live model scores 0.4643. The verdict was unaffected -- the alpha=1.00 arm reproduced 0.4643 to four decimals, so the sweep was sound -- but a control that cries wolf is worse than none, because the next real failure gets waved through. The first fix treated the objective layer as a special case; the correct fix treats LAYERING as the invariant. deployed_score() now walks an ordered list of deployment layers, newest first, returning the score of the last one that actually deployed, with a comment instructing future layers to be added there rather than patched at the call site. General rule: when the same defect recurs in a new guise, the earlier fix addressed an instance rather than the mechanism, and the second occurrence is the cue to generalise rather than patch again.
controlhonest-gatelayered-pipelineself-correctiontechnical-debtswarm · 2026-08-24
high
Permutation-null bias is a property of the block's column statistics, not of the comparator
The same control reads -0.008 to -0.015 on a dense descriptor block and indistinguishable from zero on a sparse count block. Permuting a mostly-zero column just yields another mostly-zero column.
Deep dive
A zero-information control block, built by copying columns verbatim out of the base feature matrix, was used to calibrate how much a block gains simply from its permuted twin being a damaged comparator. On non-CYP surrogates that control showed a large bias of -0.008 to -0.015 RAE under LightGBM, which appeared to threaten every permutation-null verdict in the program. Repeating it inside the deployed CYP2D6 configuration gives a bias floor of -0.0023 plus or minus 0.0011 on 4 of 6 seeds at p=0.34, which is not distinguishable from zero, so the mechanistic block's raw information term of -0.0419 corrects only to -0.0396, retaining 94.5 percent. The reason for the six-fold discrepancy is the decisive part and it generalises. Column statistics differ sharply between the two blocks: the mechanistic block has a median column cardinality of 4, with 52 percent of columns taking five or fewer distinct values and a mean zero-fraction of 0.50, whereas the duplicated descriptor block has median cardinality 971, no low-cardinality columns and a mean zero-fraction of 0.04. Permuting a sparse low-cardinality column produces another sparse low-cardinality column, which can barely win a greedy split search and therefore does little damage to the null arm. Permuting a dense continuous column produces strong competing noise that does damage it, inflating the apparent advantage of whatever is being tested against it. The operational rule is that the bias floor must be measured per block rather than applied as a constant: dense continuous blocks such as learned embeddings, 3D shape descriptors and quantum-chemical features require the correction, while sparse count-based blocks such as SMARTS alerts and the mechanistic block barely do. Note also that a correction measured on a dense block and subtracted from a sparse block's comparison is conservative, so such a corrected figure is a lower bound.
methodspermutation-nullbiascontrolscolumn-statisticscyp2d6data/processed/dupe_null_cyp2d6.json · 2026-08-30
high
Prediction shrinkage tracks model ignorance on BOTH isoforms tested - compression is calibration, not a defect
The better the model, the less it hedges and the cheaper hedging is to undo. Shrinkage is the model reporting what it does not know.
Deep dive
Replication of the CYP2D6 variance-matching result on CYP3A4, deliberately run because a mechanism proposed from one isoform has failed five times in this campaign. CYP3A4 (ST-RAE 0.5313, well modelled): predicted SD 0.827 vs training 1.093, so k=1.32 restores the spread and full matching costs +0.0705 = +13.3% relative. CYP2D6 (ST-RAE 0.9072, barely modelled): predicted SD 0.356 vs 0.916, k=2.57, cost +0.4392 = +48.4%. Both the amount of compression and the cost of undoing it scale with how well the isoform is modelled. Band-hit rate falls with expansion in both cases (3A4 36.2% -> 34.7%, 2D6 18.5% -> 14.2%), so widening pushes predictions out of the credible bands without improving ordering regardless of model quality. CONCLUSION: under ST-RAE, prediction shrinkage is a calibrated response to epistemic uncertainty rather than a pathology, and the penalty for forcing a realistic-looking spread scales with ignorance. Never variance-match on this challenge; read a compressed prediction as the model reporting uncertainty. Worth flagging that CYP3A4 is where expansion looked most affordable at 13.3% - and it still buys nothing.
calibrationshrinkagest-raereplicationcyp3a4cyp2d6variance-match · 2026-08-23
high
Re-measuring at higher power is two-sided: CYP2C9's effect grew across the bar, CYP1A2's shrank away from it
If extra seeds only ever promoted effects, the re-run protocol would just be a slow way of tuning on the evaluation.
Deep dive
Ledger #62 pre-registered that effects near the deploy bar get re-run at higher power before being trusted or discarded, with the outcome committed both ways. Two cases now bracket what that buys. CYP2C9's bagged averaging read -0.0105 at 3 seeds and 0.93 SD, then -0.0138 at 12 seeds and 1.22 SD, crossing the bar and deploying. CYP1A2's reduced tree budget read -0.0032 at 3 seeds and 0.43 SD, then -0.0024 at 12 seeds and 0.33 SD, moving further below it. In both cases the effect itself never changed; only the instrument did, and it moved in opposite directions. That is the property that makes the protocol honest rather than a ratchet: a procedure that only ever revised effects upward would eventually promote anything measured often enough, which is tuning on the evaluation by a slower route. It also cautions against reading a 3-seed estimate as a lower bound. A related distinction worth holding separately: CYP1A2 improved on 12 of 12 seeds, p about 0.0002 on a sign test, so its DIRECTION is essentially certain while its MAGNITUDE is a third of the isoform's seed noise. Direction and magnitude are different claims and the deploy bar governs the second.
powerseed-noisepre-registrationgatingepistemicsdata/processed/estimators_cyp1a2.json · 2026-08-26
high
REFUTED: the screen is not redundant on CYP2D6 because of donors -- the same block is 4x worse on the isoform with none
I claimed the single-conc screen fails on CYP2D6 because imputation donors already import it. CYP1A2 has no donors, so that predicts a better result there. It is four times worse.
Deep dive
This corrects a high-confidence finding published one tick earlier. The claim was that a learned representation of the single-concentration screen hurt CYP2D6 (+0.0281) because that isoform deploys with imp=True and therefore already receives the screen through imputation donors. CYP1A2 is the only isoform with imp=False, making it the discriminating test. Gated inside apply_deployed(cyp1a2) with the control reproducing at 0.7688 against a recorded 0.7722: deployed 0.7688, plus-embedding 0.8830, delta +0.1141, better on 0 of 3 seeds. That is 4.1 times worse than on CYP2D6, the opposite of what the donor explanation predicts. The replacement account fits both isoforms and the external literature: CYP inhibition is a lipophilicity-dominated endpoint, with logP or logD the sole descriptor in roughly 80 percent of published CYP QSARs at R above 0.9, and the one controlled study testing a QM descriptor block against a lipophilicity endpoint found it degraded the model. Appending 64 learned columns to a tree that already carries 2,265 features on 1,412 compounds is dilution rather than information, and CYP1A2 suffers most because it already carries the joint block's extra columns. The generalisable methodological point is that the original explanation was consistent with every observation available when it was written and still wrong, because the isoform that discriminates it had not been run: a causal claim published from a single isoform is a hypothesis, not a finding.
cyp1a2cyp2d6single-concself-correctionrefutationmethodsscripts/train/gate_embed_block.py · 2026-08-29
high
Rescue a rejected block by testing its combination, not by relaxing the gate
When two blocks each miss on the same criterion, the tempting move is to decide that criterion mattered less. The honest move is to ask whether they pass together under the rules as written.
Deep dive
CYP1A2 produced the same signature twice from unrelated feature families: the external public-panel block improved leave-cluster-out by -0.0127 and the 3D conformer/shape block by -0.0116, both exceeding CYP1A2's measured resolvable LCO threshold of 0.0081, while both failed scaffold-CV seed-stability and were rejected. That is exactly the situation where a campaign talks itself into moving the goalposts -- arguing after the fact that LCO deserves more weight than seed-stability because the blinded test is a scaffold shift, which happens to be true and is therefore especially seductive. The discipline that keeps this honest is to separate two different questions. Whether the GATE is right is a question to settle in advance, on general grounds, never while staring at a result you would like to deploy. Whether a COMBINATION passes the existing gate is a fresh empirical question that costs nothing in integrity, because the criteria are unchanged and the answer can still be no. The campaign's own record supports asking it: interference, super-additivity and substitution have each held exactly once here and generalised to nothing, so combination behaviour is genuinely unpredictable per isoform and must be measured rather than inferred from single-block deltas. If the joint arm fails too, the blocks stay rejected and the LCO pattern remains a flagged near-miss with a pre-registered condition for revisiting -- which is a perfectly good outcome, and better than a deployment obtained by rewriting the rules.
honest-gatecombinationsdisciplinecyp1a2goalpost-movingswarm · 2026-08-24
high
Row imputation FLIPS SIGN by isoform: -0.053 on CYP3A4 (biggest gain of the campaign) vs +0.110 on CYP2D6
Imputation pays exactly when the imputed label's error is small relative to the credible band the metric forgives.
Deep dive
Row imputation from the dense single-concentration matrix does NOT have a single sign - it flips by isoform, and the flip tracks imputed-label noise almost exactly. CYP3A4 (calibration R^2 0.777, imputed residual SD 0.524 vs assay SD 0.253 = 2.1x noise ratio, 2.10x more rows): ST-RAE 0.5307 -> 0.4773 (-0.0534, DEPLOY, magnitude meaningful) and leave-cluster-out 0.6110 -> 0.5120 (-0.099). That is the LARGEST single gain of the entire campaign, and the series-shift gain is nearly double the in-scaffold one. CYP2D6 (R^2 0.496, residual SD 0.650 vs assay SD 0.134 = 4.8x noise ratio, 2.93x more rows): ST-RAE 0.9626 -> 1.0728 (+0.110) and LCO 0.9863 -> 1.2055. Same procedure, opposite sign, and a swing of 0.16 ST-RAE between the two isoforms. THE MECHANISM SURVIVES AND IS NOW BIDIRECTIONAL EVIDENCE: what matters is how noisy the imputed label is RELATIVE to the metric's tolerance. On 3A4 an imputed label carries 0.524 SD against a median credible band of 0.379 - same order, so imputed rows still point the model at roughly the right place while tripling the data. On 2D6 it carries 0.650 SD against a 0.272 band - about 2.4 band-widths of error, so imputed rows teach the model to land outside the region ST-RAE actually scores. PREDICTION for the two untested isoforms, from their noise ratios: CYP2C9 (2.4x, band 0.526) should GAIN, and CYP1A2 (3.1x, band 0.328) is the genuinely uncertain case sitting between the two regimes. Both are now running as a real test rather than a confirmation.
imputationcyp3a4cyp2d6sign-flipst-raeself-correctionimpute-rows · 2026-08-23
high
Seed noise is monotone in training-set size, so the effect-size bar differs 3x between isoforms
CYP2C9 needs an effect three times larger than CYP3A4 to clear the same bar. Nobody knew that, and it means CYP2C9 experiments have been the least powered all along.
Deep dive
Measuring each isoform's deployed base arm across 12 scaffold-CV seeds gives seed-SDs that are perfectly monotone in training-set size: CYP2C9 with 1,285 rows at 0.0113, CYP1A2 with 1,412 at 0.0072, CYP2D6 with 1,493 at 0.0052, and CYP3A4 with 2,335 at 0.0037. That is a threefold spread in the noise floor across isoforms of the same campaign, which means the smallest effect worth chasing is isoform-specific and had been treated as if it were not. The three-seed estimates every gate printed were 0.0216, 0.0037, 0.0059 and 0.0020 -- errors of 191%, 51%, 113% and 54%, two overstating and two understating, so the unreliability is symmetric and there is no systematic correction to apply. Re-reading the whole deployed model against measured nulls: CYP3A4 band weighting 6.32 SD, CYP3A4 TDI-condition donors 3.51 SD, CYP1A2 bandl2 2.86 SD, CYP2C9 single-conc aux 1.95 SD, CYP2D6 mechanistic block 1.48 SD, CYP1A2 external+3D 1.44 SD -- three comfortable, three marginal, none withdrawn. The gate has been sorting correctly regardless: every deployed effect exceeds every rejected one in SD terms bar a single 1.34-SD near-miss. One caution learned in passing: the monotone SD-versus-n ordering does NOT support a scaling law. Fitting a power law to three of the points gave a slope of -5.13 against the -0.5 that sampling noise predicts, and extrapolating it would have missed CYP3A4's true SD by a factor of seven. Three points over a 16% range in n can order isoforms without being able to scale them.
seed-varianceeffect-sizeper-isoformcalibrationhonest-gateswarm · 2026-08-24
high
ST-RAE is almost entirely a test of the potency extremes; the middle of the range is pure downside
A row whose credible band contains the global mean has a denominator of exactly zero. It can only add numerator, never denominator. Between 15% and 37% of rows are like that.
Deep dive
ST-RAE's denominator is the mean predictor's soft error, and it is strongly U-shaped in potency. Bottom and top deciles carry 45-58% of ALL denominator mass (3A4 45.3, 2C9 58.3, 2D6 56.4, 1A2 54.8) while middle deciles carry essentially zero (3A4 deciles 4-6: 0.3 / 0.0 / 3.6). Rows whose band contains the global mean have a denominator of exactly 0 -- 357/2335 on 3A4 (15.3%), 470/1285 on 2C9 (36.6%), 279/1493 on 2D6 (18.7%), 321/1412 on 1A2 (22.7%). Those rows cannot help the score and can only hurt it. Two consequences. First, the same RMSE converts into very different ST-RAE on different isoforms, because the fraction of dead rows varies 2.4x -- so cross-isoform score comparisons are not accuracy comparisons. Second, the metric rewards getting the actives and the inactives right and is indifferent to the middle, which is where the band-weighting and bandl2 levers already deployed get their leverage. Computed from labels and shipped credible bands alone, no model fitting.
st-raemetricmethodsall-isoformsscripts/train/margin_over_constant.py · 2026-08-29
high
ST-RAE's dead zone is not being exploited: the deployed levers win outside the bands, not inside them
bandl2 shrinks predictions 16% yet lands inside the credible bands no more often than plain l2 does.
Deep dive
ST-RAE charges nothing for a prediction inside a compound's credible band, so a lever could improve it by shrinking toward band centres rather than predicting better. Both deployed inhibition levers shrink spread, making the campaign's 0.6910 to 0.6753 move a fair target for this suspicion. Audited with band-blind metrics plus the in-band rate of predictions. Bagging: real on both isoforms tested, with MAE, RMSE and Spearman all improving and shrinkage of only 1-4% (3A4 SD ratio 0.988, 2D6 0.960). bandl2 on CYP1A2: ST-RAE -0.0206 and MAE -0.0061 improve, Spearman flat at -0.0045, RMSE worsens +0.0111, predicted SD shrinks to 0.843 -- and the in-band rate is UNCHANGED at 22.1% versus 21.7%. Since the in-band count does not move, the ST-RAE gain comes from shorter out-of-band distances: being less wrong when wrong, which is what the metric is defined to reward. The MAE/RMSE divergence names the cost precisely -- shrinkage helps the many mid-range compounds and hurts the extremes. Practical rule: to test whether a metric's forgiveness region is being gamed, measure how often predictions land in that region, not whether proxy metrics happen to agree.
st-raedead-zonebandl2baggingmetric-gamingauditdata/processed/deadzone_objective_cyp1a2.json · 2026-08-26
high
State a precondition, then MEASURE it before running -- ridge alone was worse than the mean predictor
The blend's failure was determined before any gate ran, by a thirty-second check I wrote down and skipped.
Deep dive
A 50/50 GBM-plus-ridge blend was pre-registered on CYP3A4 to buy bias diversity, which bagging cannot supply because its members share a tree's inductive bias. The pre-registration explicitly named the condition -- where two models are individually COMPARABLE and their errors are weakly correlated, the average beats both -- and then tested the blend without measuring either half. The gate returned the largest negative in the campaign: +0.0458 scaffold-CV and +0.0699 LCO, resolvable at ten times threshold. The decomposition shows exactly one of the two conditions failed: error correlation was 0.274, genuinely low, so diversity WAS available; but ridge alone scored 2.1142 against the GBM's 0.5548, worse than predicting the mean, because alpha=1.0 on 2265 standardised features with 1868 rows is p greater than n and barely regularised at all -- its predicted SD was 2.013 against a label SD of 1.093. Blending a good model with one that bad at equal weight can only destroy. The transferable habit is narrow and cheap: when a pre-registration names a precondition, measure it as its own step before the experiment. Fitting the second model alone costs seconds and either validates the design or makes the run unnecessary.
ensemblingmodel-classpre-registrationridgeself-correctiondata/processed/blend_cyp3a4.json · 2026-08-26
high
Stratifying residuals on the true label measures shrinkage, not opportunity -- it refuted a load-bearing claim
The campaign believed base under-predicts cationic CYP2D6 ligands by +0.211 log at 4.8 sigma. Measured properly it is +0.0141 at p=0.567, and within potency deciles it reverses sign.
Deep dive
Two Queens independently hit the same statistical trap and it invalidates a claim the campaign had been building on. Any regression model shrinks predictions toward the mean, so residual correlates with the true label by construction: Queen C measured residual-versus-truth at r = +0.915 with slope +0.822 on held-out CYP2D6 data. Consequently any subgroup that is more potent than average will appear to be systematically under-predicted, and that appearance is a property of shrinkage rather than a missing feature. The campaign's claim that the base model under-predicts cationic CYP2D6 ligands by +0.211 log units at 4.8 sigma was exactly this artifact. Re-measured on 8,961 public CYP2D6 compounds the cationic-versus-neutral residual difference is +0.0141 with t = 0.57 and p = 0.567, and stratifying within potency deciles reverses the sign to -0.2355. Cationic ligands are simply more potent, by +0.28 log units in that key. The decisive practical test is that applying an in-fold cationic offset correction buys exactly -0.0000 RAE. Queen A reached the same conclusion independently on CYP2C19, where potency-decile eta squared of 0.63 collapsed to 0.0016 on ionisation and 0.0104 on chemotype once strata were chosen independently of the label. The rule adopted is to stratify residual analyses only on label-independent variables such as chemotype, molecular weight, source and ionisation class, and to report potency-decile structure explicitly as shrinkage rather than as an opportunity. A related casualty: on CYP2D6 logD7.4 turns out to be an ionisation proxy rather than a lipophilicity signal, since protonation controlling for clogP gives +0.267 while logD controlling for protonation gives +0.034 at p=0.186.
methodsstatisticsshrinkagecyp2d6refutationfailure-analysisdata/processed/surrogate_cyp2d6_public.json · 2026-08-30
high
TDI baseline established: CYP3A4 AUROC 0.804 but CYP2D6 only 0.574 - 2D6 is structure-opaque on BOTH tracks, not just regression
The 2D6 problem is not a regression problem. The same isoform is near-chance on a completely different task with different labels and different chemistry driving it.
Deep dive
First TDI models (scripts/train/tdi_baseline.py, LGBM classifier on Morgan+RDKit, scaffold 5-fold CV, 3 seeds). CYP3A4: n=3583, 21.3% positive, AUROC 0.804 / AUPRC 0.503 / MCC 0.30, holding at AUROC 0.775 under leave-cluster-out - a genuinely useful model. CYP2D6: n=1497, 21.6% positive, AUROC 0.574 / AUPRC 0.284 / MCC 0.08, LCO 0.578. AUPRC 0.284 against a 0.216 base rate is close to no lift. This matters strategically: TDI is mechanism-based (reactive metabolite covalently kills the enzyme) and is driven by metabolic liability, NOT binding affinity - a completely different problem with different labels. 2D6 being near-chance on BOTH tracks means the issue is not the pIC50 objective or the RAE metric; whatever determines 2D6 chemistry is not encoded in 2D structure at all. Strengthens the case that 2D6 needs 3D/mechanistic representation rather than any further 2D modelling.
tdicyp2d6cyp3a4baselinestructure-opaquetdi-baseline · 2026-08-23
high
TDI class weighting is a clean null on BOTH scored isoforms - the alert block stays dead
The conditions that rescued a rejected block on the inhibition track do nothing here, because MCC has no forgiveness structure to exploit.
Deep dive
TDI, scored on MCC (the leaderboard's primary classification metric) at the training-positive-rate threshold, 3 seeds, scaffold CV, testing {base, base+alerts} x {none, scale_pos_weight}. CYP3A4 base 0.3571: balanced 0.3521 (-0.0050), +alerts 0.3555 (-0.0016), +alerts+balanced 0.3505 (-0.0066). CYP2D6 base 0.1059: balanced 0.1059 (+0.0000), +alerts 0.1006 (-0.0053), +alerts+balanced 0.1046 (-0.0013). NOTHING is seed-stable on either isoform and nothing clears the magnitude check; every variant is at or below base. The structural-alert block stays withdrawn even under the exact conditions that were expected to rescue it. Also worth stating plainly: CYP2D6's TDI model is at MCC 0.106, which is close to useless, and no weighting or alert variant changes that - consistent with 2D6 being structure-opaque on the TDI track as well as the inhibition track. WHY THE INHIBITION INSIGHT DID NOT TRANSFER: band weighting worked because it corrected a MISMATCH between loss and metric - ST-RAE forgives error inside the credible band, so an unweighted loss spent capacity on compounds the metric barely scores. MCC has no such forgiveness structure; it treats compounds symmetrically once a threshold is fixed, and prevalence is already handled by thresholding at the training positive rate, so scale_pos_weight merely shifts a probability scale that the threshold then undoes. The rule to carry forward is that loss weighting pays off when it aligns the loss with a quirk of the scoring function, and is inert otherwise - not that weighting is generally worth trying.
tdimccclass-weightingnegative-resultcyp2d6tdi-weighted · 2026-08-23
high
TDI is scored on MCC, not AUROC - and tuning the threshold for MCC makes it WORSE once validated nested
Threshold selection is a fitting step. An optimum found on the data you score it on is not a gain, it is a leak.
Deep dive
Two discoveries about the TDI track. FIRST, the leaderboard's classification metrics are MCC, Accuracy, Precision, Recall, F1 - and the config comment states the primary/sort metric is listed first, i.e. MCC. AUROC is NOT scored at all, yet the campaign selected and reported the TDI model on AUROC. MCC is threshold-dependent, so the decision threshold matters as much as the ranking: on CYP3A4, MCC moves from ~0.30 at a naive 0.5 cut to 0.3545 at the training-positive-rate cut - a ~18% relative swing from thresholding alone. SECOND, and this is the part that saved a mistake: tuning the threshold to maximise MCC on out-of-fold predictions LOOKED like a further free +0.0323 on 3A4. Validated properly - threshold chosen only on each fold's TRAIN part, then applied to the held-out fold - the gain INVERTS: 3A4 0.3606 -> 0.3000 (-0.0607) and 2D6 0.1196 -> 0.0127 (-0.1069). The chosen thresholds do not transfer at all (sd 0.138 on 3A4, and 2D6's mean optimal threshold lands at 0.935), because a model is overconfident on its own training rows so the probability scale shifts between fit and inference. DECISION: keep the training-positive-rate threshold. It is distribution-matched by construction and depends only on prevalence, which is a stable quantity, instead of trying to locate an optimum on a shifted probability scale. GENERAL LESSON, and this is the third time it has bitten this campaign: threshold selection is a FITTING step. It needs nested validation exactly like feature selection and model selection do. An 'optimal' threshold measured on the data it was chosen from is not evidence.
tdimccthresholdnested-validationnegative-resultleakagetdi-threshold · 2026-08-23
high
TDI's first deploy came from changing the MODEL, after a dozen experiments changed only inputs and losses
Every previous TDI attempt fed a LightGBM classifier different features, weights, thresholds or targets. Swapping the classifier for ExtraTrees raised CYP2D6's MCC by 46%.
Deep dive
On the incumbent's own seed block, with the control reproducing exactly (deployed 0.1058 vs the recorded 0.1058), a plain ExtraTrees classifier scores MCC 0.1540 against 0.1058 (+0.0482, 11 of 12 seeds, sign-test p=0.0032, 2.10x the measured 0.0229 seed SD) with AUROC 0.6253 vs 0.5719 improving on 12/12. It beats the averaged ensemble arm (0.1487), so the simpler single-model arm ships -- model selection, not ensembling. The effect SHRANK when measured on the correct seed block (+0.0672 -> +0.0482), which is exactly what the reproduce-the-incumbent control exists to catch, and it still cleared every bar with none waived. Shipped as 12_tdi_et2d6.csv, validated PASS, with a per-isoform reader so CYP3A4 keeps LightGBM (ExtraTrees is less competent there). Scope stated plainly: AUROC 0.6253 is modest and MCC 0.154 is a low number that is merely much better than 0.106. The transferable diagnosis: when a dozen input-side levers all fail on one endpoint, the estimator is the untested variable.
tdicyp2d6extratreesmodel-selectiondeployedfirst-deploydata/processed/tdi_family_cyp2d6.json; submissions/12_tdi_et2d6.csv; ledger #108 · 2026-08-28
high
The blinded test is a hard scaffold shift - only 11.5% of test scaffolds exist in train, 0% compound overlap
Validate on scaffold-held-out folds or your local number is fiction. This is the PXR series-shift trap again.
Deep dive
750 test compounds span 546 Bemis-Murcko scaffolds; only 11.5% of those appear among the 4,526 train scaffolds, and InChIKey overlap with train is exactly 0. So the test is a genuine out-of-scaffold draw, not a random split - random CV will be badly optimistic (in PXR it was ~0.1 RAE optimistic). Mandates cyp.eval.scaffold_kfold_indices / leave_cluster_out_indices for every gate, plus a never-touched holdout. Also means the inactive-dominated training distribution (79% of 3A4 below pIC50 5, median 4.27) may not match the test's activity mix.
scaffold-shiftvalidationgeneralisationeda-official · 2026-08-22
high
The cost of adding useless feature columns falls to zero as training data grows -- it is a size effect, not a dataset property
A signal-free block of the same width costs +0.0034 RAE at n=100 and about zero by n=3000 on a fixed collection. Two Queens reached this from different directions after one of them proposed the wrong explanation and withdrew it.
Deep dive
Adding k uninformative columns to a feature matrix carries a measurable cost, and quantifying it separates two things that the campaign's usual comparison confounds. Testing a block against its absence measures signal plus width penalty together; testing it against a row-permuted copy of itself, which preserves column count, marginals and within-block collinearity while destroying the compound correspondence, isolates signal alone. Measured on a fixed CYP2C19 collection while varying only training size, the width penalty runs +0.0034 at n=100, about -0.0005 at 300, +0.0008 at 1000, -0.0018 at 1500 and -0.0003 at 3000, so it decays to nothing as the model acquires enough data to reject noise splits. On CYP2D6 an apparent five-fold difference in width penalty between a mixed collection and a single-assay homogeneous subset was initially attributed to assay composition, but the two subsets differed in size as well, and a matched-size control settled it: subsampling the mixed collection to exactly the homogeneous subset's size gave +0.0047 plus or minus 0.0033, statistically indistinguishable from the homogeneous +0.0065 and clearly above the full-size mixed +0.0013. Size is the driver and the composition interpretation was withdrawn. The deeper methodological lesson is the more valuable one: the original composition claim rested on two single collection draws with no error bar on the collection itself, and the spread across three equivalent draws ran 0.0022 to 0.0084, a four-fold range that spans the entire gap being interpreted. A point estimate carries no evidence about a sampling unit whose noise has not been measured. Note also that collection size at fixed training size and training size at fixed collection are related but not identical axes, and should not be merged without saying so.
methodspermutation-nullwidth-penaltystatisticsself-correctionsurrogatedata/processed/reconcile_width_penalty_cyp2c19.json + surrogate_cyp2d6_public.json · 2026-08-30
high
The CYP2D6 mechanistic block passes the honest gate on 3 of 4 isoforms - and is correctly REJECTED on CYP1A2
Gate per isoform, not globally. A block that helps three targets can still be noise on the fourth.
Deep dive
Same 23-feature block, identical gate (marginal-over-base, corr-with-error, seed-stability over seeds 42/7/2024, leave-cluster-out). Mean scaffold-CV RAE delta: 3A4 -0.0029, 2C9 -0.0109, 2D6 -0.0077, 1A2 -0.0021. 1A2 FAILS seed-stability - seed 7 regressed +0.0075 - so it does not deploy there despite a negative mean. Revealing control: block-ALONE RAE is 0.784 on 3A4 and 0.911 on 2C9 (real standalone signal, driven by logP r=+0.60 with target - the known promiscuity axis) but 1.156 on 2D6 and 1.081 on 1A2 (no standalone signal). Yet 2D6 gets the second-LARGEST marginal gain despite the block being useless alone there - evidence the salt-bridge geometry contributes something the base genuinely lacks for 2D6 specifically. Deployed on 3A4/2C9/2D6; new macro approx 0.831 (from 0.837).
honest-gateper-isoformcyp1a2deploycyp2d6-mechanistic · 2026-08-23
high
The deployed models LOSE to the mean predictor mid-range on all four isoforms -- and no rule can reach it
ST-RAE is a ratio of sums, so it splits exactly over potency terciles. The split says the model beats a constant on actives and inactives and loses to it in the middle. But the model cannot tell which of its own predictions are mid-range any better than chance, so the free score is visible and untouchable.
Deep dive
Decomposing the deployed OOF (share sums to the isoform's score; local = that tercile's break-even against the mean predictor, >1.0 = worse than a constant): actives 0.37/0.54/0.73/0.60, inactives 0.32/0.52/0.86/0.82, MIDDLE 1.40 (3A4) / 7.84 (2C9) / 4.89 (2D6) / 2.56 (1A2) -- 8-28% of each isoform's entire score. The cause is structural: ST-RAE's denominator IS the mean predictor's soft error, and the label mean sits inside mid-potency bands almost by definition, so the metric allots the middle tercile only 1-9% of its budget while the model still errs there. The deployable lever -- emit the training mean where the model's own prediction lands mid-tercile -- was REJECTED 4/4 (3A4 +0.0086, 2C9 +0.0060, 1A2 +0.0040, all 0/3 seed-stable; 2D6 -0.0018 at 0.34 SD). Why: predicted-middle captures true-middle at only 0.563/0.425/0.413/0.356 against a 0.333 chance floor, and 44% (3A4) to 64% (2D6) of that bin is truly ACTIVE or inactive -- the narrow-band compounds #95 proved are unforgiving. The isoform with the worst score has the LEAST identifiable middle (2D6, 0.356 = chance), so the mid-range deficit is not a separate defect to patch: it IS the accuracy deficit seen through the metric, and only a better model closes it.
st-raeerror-decompositioncyp2d6abstentionrejectedoracle-conditionedscripts/train/error_locus.py, mid_band_abstain.py, tercile_purity.py; data/processed/error_locus.json; ledger #96 · 2026-08-27
high
The external 14k public panel shares ZERO chemistry with the challenge test set - read-across is dead as a lever
We assumed abundant public CYP data meant coverage was solved. It is not: there are no neighbours to read across from.
Deep dive
Official test = 750 OCNT-* compounds. Overlap with data/external/cyp_external_wide.parquet (14,055 InChIKeys, PubChem NCGC + ChEMBL): 0/748 on FULL InChIKey AND 0/748 on the skeleton (first block); formats verified identical (27-char). Train overlap only 2.9%. Contradicts CLAUDE.md premise #4 ('coverage is NOT the wall for CYP - external data is a real lever'). External data may still help as PRETRAINING/representation learning, but nearest-neighbour read-across has no support. Ledger item #7 must be re-scoped.
externalcoverageread-acrossnegative-resulteda-official · 2026-08-22
high
The ExtraTrees layer reverses sign on a test-like distribution -- and the control shows it is the layer, not the measure
A layer that wins on the training distribution can lose on a shifted one. The way to tell that apart from a measure that dislikes everything is to run the same check on a different layer -- and bagging goes the opposite way.
Deep dive
Re-scoring deployed and layer-ablated out-of-fold predictions under an activity-matched reweighting, 3 seeds: the ExtraTrees layer reverses on both isoforms where it ships -- CYP1A2 from -0.0075 to +0.0443, CYP2D6 from -0.0098 to +0.0365, four to six times the size of the gain it replaces and in the opposite direction. The essential control rules out the alternative reading: on identical weights, seeds and machinery, ablating BAGGING instead shows its benefit GROWING under the same shift, CYP1A2 -0.0214 to -0.0554 and CYP2D6 -0.0100 to -0.0469. So the shifted measure is not penalising averaging in general; it is penalising this specific layer. This is the first ranking flip in the campaign -- a configuration that wins on the training distribution and loses on a test-like one -- and it sits in the shipped model. It is NOT being acted on yet: the honest gate is defined on scaffold-CV where ET passed 12/12 at 1.24-2.12 SD with an exact control, so removing it means changing the deploy criterion, which requires pre-registration plus retroactive application to every deployed layer. Caveats bound the level but not the ranking: weights clipped at 5x, activity-model error unmeasured, ESS 843 and 505.
covariate-shiftst-raeextratreesranking-flipdeployed-stackcontrolsscripts/train/shift_check_et.py; data/processed/shift_check_et.json, shift_check_bagging.json; ledger #116 · 2026-08-28
high
The fix for a sub-threshold LCO reading is more clusterings, not a weaker criterion
CYP1A2's objective layer looked unsupported on one clustering and is supported 9-for-9 on nine.
Deep dive
An audit of all ten deployed layers against the #64 split-noise thresholds flagged exactly one: CYP1A2's bandl2 objective, LCO -0.0053 against a 0.0081 threshold (0.65x). Re-measured over 9 clusterings, the paired delta is -0.0163, sd 0.0113, negative on 9 of 9, sign stability 1.00 -- 2.01x the threshold. The gate's own clustering reproduces exactly (-0.0053) and was simply the low end of the spread. The economics matter: that layer sits below CYP1A2's external+3D joint layer and has no imputation, so nine clusterings cost roughly one joint-gate seed. Running LCO once was never justified by cost. Standing practice: when an LCO delta falls below its isoform's threshold, re-measure the paired contrast over many clusterings before recording anything about it -- and include the gate's own (k, seed) pair explicitly, since resampling k and seed together does not generally reproduce it. After this, every deployed layer has resolvable LCO support; the #64 finding changed how the criterion is checked without costing the campaign a single deploy.
lcogatingauditcyp1a2harnessdata/processed/lco_remeasure_objective_cyp1a2.json · 2026-08-25
high
The honest gate cannot see a defect shared by both of its arms
A gate compares two arms of the same harness, so anything wrong with the harness cancels out of the comparison while quietly corrupting the baseline.
Deep dive
CYP2C9 l1 scored -0.0402 against l2, seed-stable on 3/3, surviving leave-cluster-out (0.7001 -> 0.6732), magnitude 'meaningful'. It passed all four honest-gate criteria and was entirely an artifact: the harness filled donor NaNs from full-table medians where the deployed pipeline uses donor-subset medians, which diverge most on the sparse Emax columns. Both arms inherited the defect, so the DELTA looked clean while the BASELINE was wrong -- the l2 arm scored 0.6924 against a deployed 0.6033. Correcting one expression made the l2 arm reproduce 0.6033 exactly, and l1 flipped to +0.0154 WORSE. Seed-stability, LCO and effect-vs-noise are all internal to the harness and structurally cannot catch this; only reproducing a known external value can. FIFTH GATE CRITERION for any script that re-implements a deployed pipeline: its baseline arm must reproduce the deployed score within 0.01 before any delta is transferable. Enforced in code -- objective_match.py prints a [control] line and writes reproduces_incumbent into the artifact, and make_submission.py refuses to read a winner past a False. Verified: CYP2C9 and CYP2D6 now both drift +0.0000.
honest-gatevalidationharnessfalse-positivemetaswarm · 2026-08-24
high
The imputation bias is a REAL population difference, not a calibration artifact - donors differ on the independent screen too
The organisers chose which compounds got full curves, so 'measured' is a selected subpopulation. Imputation imports that selection, and correcting the mean would assert something the raw data contradicts.
Deep dive
Row imputation helped CYP3A4 (-0.0534, the campaign's largest single gain) and hurt CYP2D6 (+0.110) and CYP1A2 (+0.5316). I attributed that to systematic BIAS in the imputed labels (imputed minus real mean: 3A4 +0.41, 2C9 -0.30, 2D6 -0.74, 1A2 -1.56) but could not tell whether the bias was a CALIBRATION artifact - fixable by shifting - or a REAL population difference, in which case shifting would inject error rather than remove it. The discriminating evidence is INDEPENDENT of our models: compare donors and measured compounds on the single-concentration screen itself, a direct measurement neither the calibration nor the pIC50 model touches. Mean log2fc, measured vs donor: CYP3A4 -1.688 vs -2.066 (shift -0.378, donors MORE inhibitory); CYP2C9 -0.791 vs -0.647 (+0.144); CYP1A2 -1.323 vs -0.319 (+1.004); CYP2D6 -1.797 vs +0.307 (+2.105, donors barely inhibit at all). So donors ARE genuinely different compounds - the shift is real, not a calibration failure. And the sign lines up exactly with the outcome: CYP3A4 is the ONLY isoform where donors are MORE active than the measured set, and the only one where imputation helps. WHY THIS HAPPENS: the organisers chose which compounds got full dose-response curves, plausibly using the single-conc screen itself, so 'measured' is a selected subpopulation and 'donor' is what was left over. Imputation therefore imports a population shift, not just measurement noise. CONSEQUENCE for ledger #36: mean-shift correction should NOT rescue the failing isoforms, because forcing donor labels onto the measured-compound mean asserts something the independent screen contradicts. Running that correction on 1A2 and 2D6 as a falsification test rather than assuming - this campaign has had five predictions overturned already.
imputationselection-biaspopulation-shiftcyp3a4cyp2d6diagnosticimpute-bias · 2026-08-24
high
The magnitude bar is calibrated on the wrong distribution for shift-amplified blocks
A block whose value is five times larger on a test-like distribution is judged by dividing its training-distribution delta by its training-distribution seed noise. Both halves of that ratio come from the distribution the model will not be scored on.
Deep dive
An enriched CYP2D6 pharmacophore encoding improves the deployed model on 12 of 12 seeds (sign test p = 0.0002) by a mean of -0.0040, which is 0.76 times the isoform's measured seed SD and therefore under the magnitude bar, so it was rejected. Its shift-corrected gain is -0.0209, 5.3 times the unweighted one and consistent with the 4.9x amplification independently measured for the mechanistic block it extends. The bar divides the unweighted delta by the unweighted seed SD, so for exactly the features that matter most on an active-enriched test set it systematically under-reads. The shifted delta cannot simply be substituted, because the seed SD under the shifted weighting has never been measured and a shifted magnitude ratio is therefore not computable. That measurement is a twelve-seed job and is the prerequisite for even asking whether such blocks clear the bar on the distribution that matters; until it exists no criterion should change, since pre-registration and a retroactive sweep both require the denominator. Two blocks now sit certain-in-direction and sub-bar on the two isoforms furthest from their noise floors.
honest-gatemagnitudecovariate-shiftcyp2d6pharmacophorecriteriascripts/train/pharm_gate.py; data/processed/pharm_gate_cyp2d6.json; ledger #126 · 2026-08-29
high
The MCC resolution floor is a property of the isoform, not of the metric or the task
Same metric, same harness, same three seeds: one isoform's base arm varies by 4% and the other by 40%. Quoting a shared TDI sensitivity would misstate both.
Deep dive
Running identical feature-block gates on both scored TDI isoforms produced base-arm MCC across three scaffold-CV seeds of 0.3485-0.3623 on CYP3A4 (about 4% relative) and 0.0852-0.1196 on CYP2D6 (about 40%). Nothing differed but the isoform: same script, same seeds, same fold construction, same metric. So the roughly 0.03 MCC resolution floor recorded for CYP2D6 last tick is NOT a property of MCC, and not a property of the TDI task -- it follows from that isoform's sample size (1,497 versus 3,583) together with whether the model has real signal at all (CYP2D6-TDI sits near chance at 0.106, CYP3A4-TDI is genuinely predictive at 0.357). It would have been easy and wrong to file the earlier number as a TDI-track constant. Practical consequence: CYP3A4-TDI experiments can honestly resolve effects around 0.01, CYP2D6-TDI cannot resolve below roughly 0.03, and any future TDI claim should state which isoform's floor it is being judged against. The general form is that a resolution floor must be measured per target rather than per metric, because it is set by the data available for that target rather than by the scoring function -- the same reason ledger #25 had to measure leave-cluster-out variance separately for each isoform rather than assuming one threshold.
tdimccresolutionseed-varianceper-isoformswarm · 2026-08-24
high
The metric implementation checks out on all eight invariants, and its one silent path is dormant
Every deploy decision in the campaign routes through st_rae, and only one of its properties had ever been tested.
Deep dive
cyp.eval.st_rae computes every number in this campaign and was documented as a verbatim port of the official scorer, with a single property verified when written (mean predictor = 1.0). An audit of the invariants the definition implies now passes all eight: mean predictor exactly 1.000000000000000, perfect prediction 0.0, any prediction inside its band 0.0, a prediction exactly AT the band edge 0.0, monotone in distance outside the band, exactly linear in that distance (2x gives 2.0000x), symmetric above versus below, and above 1.0 for a worse-than-mean prediction. Separately, the one way a port can diverge without any invariant firing is silent row dropping: st_rae drops rows whose bands are non-finite, which would score a subset locally while the leaderboard scores all 750. That behaviour is confirmed, and its exposure is zero -- across all 6,525 training rows there are no non-finite bands and none inverted with lower above upper. The limitation is worth naming: this verifies the implementation against the DEFINITION, not against the backend's source, so a divergence in the definition itself would be invisible to invariants derived from that same definition. What is now established is that no arithmetic or edge-case bug sits between the documented formula and the campaign's numbers.
metricst-raeverificationauditscripts/strae_audit.py · 2026-08-27
high
The model family behaves like the prior, and mechanism does not -- replicated on two independent targets
ExtraTrees' advantage decays monotonically as training data grows, which is what a prior does. The mechanistic block is flat in n, which is what an ordinary weak feature does.
Deep dive
Two Queens ran the same learning-curve experiment on independent targets with frozen scaffold-disjoint answer keys. On CYP2C19 (11,286 compounds, 3,000-compound key, 10 resamples) the ExtraTrees advantage over the deployed LightGBM base ran -0.1296, -0.0663, -0.0458, -0.0403, -0.0266 across n = 100, 300, 1000, 1500, 3000. On CYP2D6-public (8,961 compounds, 3,138-compound key, 12 to 20 resamples) it ran -0.1175, -0.0891, -0.0499, -0.0421, -0.0239, -0.0130 across n = 100, 300, 1000, 1500, 3000, 5000, with every point improving on 12 of 12 or 20 of 20 resamples. Monotonic decay with data is the defining signature of a prior: it substitutes for information the data does not yet contain, so its value must shrink as data accumulates. The mechanistic block shows no such behaviour on either target, oscillating without trend in a narrow band and never growing as data shrinks, which makes it an ordinary weak feature rather than a constraint standing in for data. The practical consequence is large. At the challenge's own training size of about 1500 compounds, the CYP2D6 counterfactual is base 0.9274 improving to 0.8808 with the best arm, a margin of -0.0466 at 20 of 20 resamples and 4.00 SD, and that margin decomposes into -0.0421 from the estimator switch and only -0.0045 from the mechanistic block. Roughly ninety percent of the available improvement is model-family choice. On CYP2C19 the largest feature-block effect was seventeen times smaller than the estimator swap. This does not say mechanism is worthless: on CYP2D6 every mechanistic block beat its own row-permutation null under both model families, so the signal is real where the pharmacophore is real, and on CYP2C19 no block ever separated from its null. It says mechanism is small and flat while family choice is large and data-dependent.
methodsestimatorlearning-curvesurrogateextratreespriordata/processed/surrogate_cyp2c19.json + surrogate_cyp2d6_public.json · 2026-08-30
high
The official label matrix is 73% single-isoform - multitask must use a masked loss, not a dense 4-vector
The data looks like a 4-task matrix but is really four mostly-disjoint datasets stacked.
Deep dive
4,905 train compounds carry only 6,525 compound x isoform measurements: fill rate 33%, mean 1.33 isoforms/compound, 73.3% measured on exactly ONE isoform, only 0.84% on all four. Per-isoform n: 3A4 2335, 2C9 1285, 2D6 1493, 1A2 1412. Consequence: any joint model MUST mask missing targets (scripts/train/chemprop_multitask.py already does); dense-target formulations or naive imputation will fabricate labels for two-thirds of the matrix. It also caps how much multitask can borrow - the co-measured overlap is only 230-473 compounds per pair.
multitasksparsitymasked-losseda-official · 2026-08-22
high
The permutation null is a biased comparator: 21 duplicated columns beat their own null more than any real block
A block built by copying columns verbatim out of the base matrix carries zero new information, yet it wins against its row-permuted twin by -0.008 to -0.015 RAE under LightGBM -- larger than any mechanistic block measured.
Deep dive
The row-permutation null was adopted mid-program as the correct comparator for a feature block, on the reasoning that permuting rows preserves column count, marginals and within-block collinearity while destroying the compound correspondence, so the difference isolates information from width. A deliberate zero-information control shows the comparison is biased. The control block, called dupe, consists of 21 columns copied verbatim out of the base feature matrix; it adds nothing, and its own RAE equals the base model's to four decimal places. Yet dupe beats its own permutation null by -0.0080 on hERG at n=1500, -0.0114 on hERG at n=3000, and -0.0142 to -0.0146 on aromatase, on 9 or 10 of 10 resamples with p at or below 0.011. Those margins exceed every real mechanistic block measured on either target. The mechanism is that the bias lives in the null arm rather than the treatment arm: permuted columns are pure noise that can win greedy split searches and actively degrade the model, whereas duplicated real columns are harmless and simply ignored. Crucially the bias is estimator-dependent. Under LightGBM it is worth -0.008 to -0.015 RAE; under ExtraTrees on hERG the null is nearly unbiased, with et_dupe at exactly +0.0000 on 5 of 10 resamples, and there the real blocks do clear the floor but only by -0.002 to -0.004 and not in mechanism order. The consequence for the program is that no verdict of the form block beats its permutation null should be believed until a matched zero-information block has been run in the same configuration and its margin subtracted. This is a sixth-gate result about a gate: whether the control is valid is itself a property of the configuration it runs in.
methodspermutation-nullcontrolsbiasextratreessurrogatedata/processed/surrogate_herg_kcnh2.json + surrogate_aromatase_cyp19a1.json · 2026-08-30
high
The same effect read 0.49, 0.93 then 1.22 SD as calibration and power improved -- nothing about it changed
Two of those three readings would have discarded CYP2C9's bagging effect, and the effect was identical throughout.
Deep dive
CYP2C9's bagged-averaging effect was measured three times. First at bag5 over 3 seeds, scored against a 3-sample SD of 0.0216: -0.0071, ratio 0.33, dismissed as indistinguishable from noise. Then rescored against the MEASURED 12-seed null of 0.0113: ratio 0.93, just under the bar and inside the re-run band. Then re-measured at 12 seeds: -0.0138, 12 of 12 negative, ratio 1.22, deployed. The effect did not change; the instrument did. Two independent errors compounded in the same direction -- a 3-sample SD that happened to run 1.9x high, and 3-seed power that understated the effect itself. Higher power also shrank the confounder: the subsampling cost fell from +0.0081 to +0.0023, so most of what looked like a real regularisation penalty was also sampling noise. The rule this supports: when an effect lands within a factor of two of a gate's threshold, the threshold is not the thing to argue about -- the measurement is. Re-measure with a calibrated null and adequate seeds before either trusting or discarding, which is exactly what ledger #62 pre-registered and what would have been skipped if the first reading had been taken at face value.
seed-noisepowercalibrationcyp2c9gatingdata/processed/bagged_cyp2c9.json · 2026-08-25
high
The same feature block rejects under LightGBM and passes under ExtraTrees on the same folds
The MBI alert block scored -0.0115 MCC on 2/12 seeds with LightGBM and +0.0072 on 10/12 with ExtraTrees, identical data and splits. The estimator was the entire result.
Deep dive
The mechanism-based-inactivation structural alert block was gated on CYP2D6-TDI twice with everything held constant except the classifier. Under LightGBM: MCC 0.1058 to 0.0943, delta -0.0115, better on 2 of 12 seeds, seed-stability False. Under ExtraTrees, which is the deployed CYP2D6 TDI classifier since #108 replaced LightGBM there: MCC 0.1552 to 0.1624, delta +0.0072, better on 10 of 12 seeds, sign-test p=0.019. Both controls are near-exact, the LightGBM arm reproducing the pre-ExtraTrees 0.1058 and 0.5719 to four decimals and the ExtraTrees arm reproducing the shipped 0.1540. Reporting the first run as the verdict would have rejected a block that works, which is the sixth gate criterion paying for itself: an effect is a property of a configuration, so a block must be measured with the estimator it would actually ship alongside. The practical rule is that when a campaign changes model family on one endpoint, every previously-rejected block for that endpoint becomes untested rather than settled, because the rejection was measured on a configuration that no longer exists. CYP3A4, where LightGBM IS still deployed, gave +0.0018 on 8 of 12 seeds with sign-test p=0.194 and is rejected on stability.
methodstdiestimatorsixth-gatecyp2d6extratreesscripts/train/gate_tdi_alerts_et.py · 2026-08-30
high
The same two blocks are super-additive on one isoform and substitutive on another
Combination behaviour is not a property of the blocks. It is a property of the block-pair-and-isoform together, and it reverses sign between isoforms.
Deep dive
The external public-panel block and the 3D conformer/shape block were run as base / +ext / +3d / +both on two isoforms, each under its own full deployed recipe. On CYP1A2 the pair is SUPER-ADDITIVE: -0.0027 and -0.0059 alone, -0.0104 together, beating the -0.0086 that additivity predicts, and seed-stable on all three seeds when neither part is. On CYP2D6 the same pair is SUBSTITUTIVE: +0.0004 and +0.0027 alone, +0.0055 together -- worse than either block on its own. Same two blocks, same harness, same three seeds, opposite sign of interaction. This turns the campaign's standing rule from a caution into an observation: combination behaviour cannot be transferred across isoforms, and single-block deltas predict neither the magnitude nor the direction of the joint effect. Mechanistically the contrast is coherent rather than mysterious. On CYP1A2 the blocks supply non-overlapping ignorance -- other assays' read on molecules the training set covers thinly, plus planarity and shape for a narrow planar binding slot. On CYP2D6 the 3D block has nothing to contribute: ledger #54 measured its shape descriptors flat against pIC50 at |rho| < 0.01 and showed CYP2D6 cares THAT a basic nitrogen exists rather than WHERE it sits, so combining two weak blocks there only spends model capacity. Practical consequence: a block pair that deploys on one isoform must still be gated separately on every other, and the cheap assumption that a win generalises is exactly the assumption this pair falsifies.
combinationsinterferencesuper-additiveisoform-specifichonest-gateswarm · 2026-08-24
high
The single-conc plate effect is an artefact of pooling enzymes
Plate means look like they span 1.75 log2fc units. But plate encodes enzyme, so that spread is the enzyme difference wearing a batch-effect costume.
Deep dive
The single-concentration file has 36 plate_ids and the pooled per-plate mean log2fc ranges -2.042 to -0.288, a spread of 1.754 against a within-plate sd of 0.911 -- which reads as a serious batch effect in the auxiliary signal feeding the imputation calibration, and would justify plate-correcting log2fc before calibration. It is not real. The 36 plates are 9 per enzyme x 4 enzymes, and WITHIN enzyme the between-plate variance component is CYP1A2 0.6%, CYP2C9 0.9%, CYP3A4 0.9%, CYP2D6 2.2% of total variance. There is no batch effect worth correcting, and plate-correcting pooled log2fc would have removed genuine between-isoform signal while claiming to remove noise. Recorded because the confound was self-inflicted -- the grouping variable silently carried a second factor -- and the same trap exists anywhere an ID column encodes more than it names. Separately, the audit confirmed the single-conc file has ZERO missing values in all 12 columns, so the dropped-inactives bug found in the public PubChem panel has no analogue here.
batch-effectconfoundsingle-concauditmetaswarm · 2026-08-24
high
The single-conc screen carries large transferable signal for CYP2D6 as an auxiliary task
Used as imputation donors it is extra rows of the same task. Used as a shared trunk it reshapes the representation, and that is worth -0.1333 ST-RAE on 3/3 seeds -- on a model too weak to ship.
Deep dive
The screen (4,376 compounds x 4 isoforms = 17,504 measurements, same chemistry as train) has only ever been used as imputation donors. A shared-trunk MLP with a pIC50 head and a 4-isoform single-conc head, ablated by aux_weight alone on identical folds and seeds, gives single-task 1.1057 versus auxiliary 0.9724 on CYP2D6: delta -0.1333, better on 3/3 seeds, which is 25.6x the isoform's seed SD and 5.7x its leaderboard bootstrap SD. LightGBM cannot express a shared trunk, which is why this framing was never tested. CYP2D6 was chosen because it is the representation-bound isoform at 5.25x its noise floor with label, calibration and loss levers all spent. The result does NOT ship, and the reason is the absolute level rather than the delta: the mean predictor scores 1.0, the single-task MLP 1.1057 (worse than a constant), the auxiliary MLP 0.9724 (barely better), and the deployed LightGBM stack 0.8738 -- so the auxiliary task rescues a bad model and still trails what already ships by 0.0986. This is the sixth gate criterion applied reflexively: an effect is a property of a configuration, so a large delta measured on a non-competitive vehicle does not transfer. Leakage control verified non-vacuous, dropping 315-342 of 4,376 auxiliary compounds per fold for sharing a Murcko scaffold with validation. The actionable follow-up is distillation: take the aux-trained trunk embedding as a feature block for the deployed stack and gate it honestly.
cyp2d6auxiliary-taskrepresentationsingle-concneuralmethodsscripts/train/aux_task_mlp.py · 2026-08-29
high
The single-conc screen is already in the CYP2D6 model via donors, so re-adding it as features hurts
An auxiliary-task MLP gained -0.1333 from the screen, but that MLP had no imputation donors. The deployed model already has the screen, and giving it again as 64 learned columns costs +0.0281.
Deep dive
Distilling the aux-trained trunk's 64-dim embedding into a feature block for the deployed LightGBM stack, gated inside apply_deployed(cyp2d6): deployed 0.8704/0.8773/0.8676 mean 0.8718 against +embedding 0.8939/0.9045/0.9011 mean 0.8998. Delta +0.0281, better on 0/3 seeds, stability False, control reproducing the incumbent at tolerance 0.0100. That is worse by more than five times the isoform's seed SD. The explanation is that CYP2D6 deploys with impute=True, so the single-concentration screen already contributes rows through imputation donors; the auxiliary-task MLP of #140 had no donors at all, so its large gain was largely the MLP gaining access to information the deployed stack already holds rather than discovering new signal. Both encodings now agree: the aux block as four prediction COLUMNS was previously rejected on this isoform (delta -0.0037, all_seeds_improve false, LCO +0.0193), and a learned REPRESENTATION is rejected harder. The screen is not an untapped source for CYP2D6. This also confirms a prediction made in advance: #140's write-up stated that an effect measured on a non-competitive MLP does not transfer to the deployed pipeline, and it did not.
cyp2d6single-concrepresentationnegativemethodssixth-gatescripts/train/gate_embed_block.py · 2026-08-30
high
The single-concentration screen covers 89% of train and 0% of test - useful only as a learned auxiliary, never as a feature
Check overlap before designing the feature. This is the second official data source that looks like a lookup table and is not one.
Deep dive
4,376 single-conc compounds cover 4,375 of 4,905 train compounds (89.2%) but 0 of 750 TEST compounds. So the measured log2fc can never be read off at inference time - the same trap that killed external read-across, but disguised, because the train-side coverage looks excellent. The only legitimate use is to train a model on log2fc and apply that MODEL to test compounds (transfer, not lookup - the labels are independent experiment, so this is not circular). Worth noting for architecture: the single-conc matrix is 100% DENSE (4,376 x 4) against 0.333 fill for pIC50, and its cross-enzyme correlations independently REPRODUCE the pIC50 finding on 3x more data - 3A4-2C9 +0.72, but 2D6 lowest against everything (+0.16 / +0.24 / +0.33). That corroborates 2D6 orthogonality, which previously rested on only 230-473 co-measured pairs.
single-concentrationcoverageleakagecyp2d6singleconc-aux · 2026-08-23
high
The single-concentration screen helps exactly where the isoform is already structurally learnable - it amplifies signal, it cannot create it
More labels of a quantity you also cannot predict from structure is not more information. The auxiliary inherits the same wall.
Deep dive
17,504 single-conc measurements (4,376 compounds x 4 enzymes, log2 fold-change at 49.5 uM) used as a LEARNED auxiliary: predict log2fc from structure, feed the 4 predictions as features. Scaffold-disjoint per fold to prevent leakage (89% of pIC50 train compounds also appear in single-conc). Results track structural learnability almost perfectly. DEPLOY: 3A4 mean delta -0.0129, leave-cluster-out -0.0365 (largest gain of the campaign), aux predicts its own log2fc at rho -0.761; 2C9 -0.0220 / LCO -0.0277, rho -0.645. DO NOT DEPLOY: 2D6 - fails seed-stability AND actively HURTS under leave-cluster-out (+0.0193), and the aux predicts 2D6 log2fc at only rho -0.376. So 2.93x more labels for 2D6 (4,376 vs 1,493) bought nothing, because log2fc for 2D6 is as structurally opaque as pIC50 for 2D6. General rule: an auxiliary trained on the SAME features as the base can only redistribute information, never add it - it pays off only when the auxiliary target is itself learnable from those features.
single-concentrationauxiliarycyp2d6honest-gatetransfersingleconc-aux · 2026-08-23
high
The solo-competence screen ranks CONFIGURATIONS of one family, not families against each other
Within ExtraTrees, how good the second model is alone predicted exactly how much averaging it in helped or hurt. DART is better alone than ExtraTrees ever was on CYP3A4 -- and hurts more. The one-number rule does not cross family boundaries.
Deep dive
On CYP3A4, control reproducing: ExtraTrees at max_features=sqrt has a solo gap of +0.1395 and costs +0.0261; at max_features=0.3 a gap of +0.0514 and costs +0.0097; DART at 1000 trees has a SMALLER gap of +0.0440 and costs +0.0147 (0/3 seed-stable, 3.97 SD). DART is off the ExtraTrees curve entirely. The mechanism vindicates the original diversity-versus-competence trade-off: DART is competent precisely because it shares the deployed model's library, features and hyperparameters, and that is exactly what makes it undiverse -- it buys competence with the diversity that made averaging worth doing. The screening instrument survives with its scope corrected: use it to choose a configuration within a family, never to rank candidate families. Stated prediction, untested and queued: DART's predictions should correlate with the deployed model's substantially more than ExtraTrees', whose disagreement correlated with the base model's error at only +0.024.
ensemblingdartextratreescompetencediversityscoperefutedscripts/train/dart_family_gate.py; data/processed/dart_family_cyp3a4_t1000.json; ledger #111 · 2026-08-28
high
The ST-RAE error tail is not a shared blind spot, so there is no cross-isoform lever in it
If the same compounds failed on every isoform, fixing one chemotype would improve four endpoints. They do not: the only significant overlap is the most correlated target pair, and the orthogonal pair overlaps below chance.
Deep dive
Following #137's finding that leaderboard variance dwarfs recent mean gains, the natural target became the heavy tail generating that variance. Concentration first: the worst decile of compounds carries 42.3% (CYP3A4), 47.0% (CYP2C9), 36.4% (CYP2D6) and 36.0% (CYP1A2) of total soft error against the 10% a uniform error would give, and 19.8-42.1% of compounds score exactly zero by landing inside the band. Then overlap, computed only over co-measured compounds and tested by exact hypergeometric against a Bonferroni threshold of 0.0083 for six pairs: CYP3A4-CYP2C9 gives 16 observed against 5.3 expected, ratio 3.04, p<0.0001 -- and it is the only significant pair. It is also the campaign's most correlated target pair at r=+0.71. The orthogonal pair CYP2C9-CYP2D6 (r=-0.10) overlaps BELOW chance at ratio 0.67. Ranking all six by target correlation against overlap ratio gives spearman +0.829 with an exact permutation p of 0.0583 over all 720 orderings -- suggestive, not significant, and reported as such. The reading is that shared tail failure is what correlated labels predict rather than evidence of a shared representational weakness: if two endpoints' true values correlate, a compound hard for one is hard for the other for reasons unrelated to featurisation. No cross-isoform tail lever exists to pursue.
st-raetailcross-isoformnegativemethodsleaderboardscripts/train/tail_structure.py · 2026-08-29
high
The TDI label is a threshold on a number we never modelled
is_TDI is not a category. It is 'did this continuous shift exceed 2x', and the shift ships in the data with its own error bars.
Deep dive
The TDI training file carries CYP<ISO>_pIC50_TDI_condition -- the pIC50 measured under preincubation -- with conf_high, conf_low and std, for all four isoforms, next to the direct-inhibition pIC50. The binary label is simply their difference thresholded at log10(2) = 0.301. Thresholding the TRUE shift reproduces the shipped label at MCC 0.7410 on CYP3A4 and 0.9011 on CYP2D6, against classifiers scoring 0.30 and 0.08. On CYP2D6, where 99.7% of labelled rows carry a finite shift, the shift-to-label map is near-deterministic, so essentially ALL of the model's failure lies in predicting the shift rather than in the thresholding -- which reframes 'CYP2D6 TDI is structure-opaque' as 'we have been asking a classifier to rediscover a magnitude we deliberately discarded'. Five TDI attempts (baseline, class weighting, label-confidence weighting, structural alerts, and the alert-conditioned variant) all classified the binary label. To a classifier a compound with shift 0.30 and one with shift 2.59 are the same row, and one at 0.31 is a coin flip it is asked to learn as certain -- ledger #43 had already measured that the label is close to a z-test outcome (|shift|/band-width predicts it at spearman +0.752 / +0.640) without drawing the modelling conclusion. The asymmetry that makes the regression framing non-free: the shift needs BOTH pIC50s, and on CYP3A4 only 2,334 of 3,583 labelled rows have one, so it is a richer target on ~65% of the rows.
tdiregressionthresholded-labellabel-constructionmccswarm · 2026-08-24
high
The TDI track has a measured ceiling at last: MCC 0.56 on CYP3A4, 0.66 on CYP2D6
is_TDI is a threshold on a continuous quantity the drop ships with its own uncertainty. Ask what a second run of the same assay would score against the shipped labels -- no model can beat a direct re-measurement.
Deep dive
shift = pIC50_TDI_condition - pIC50_direct_inhibition, sd_shift = sqrt(std_TDI^2 + std_direct^2), and the 2x threshold recovers from the data as 0.300 against log10(2)=0.301 (verified, not assumed). Drawing a replicate measurement and thresholding it gives MCC 0.5629 [0.537, 0.586] on CYP3A4 and 0.6559 [0.616, 0.689] on CYP2D6. Against deployed 0.3559 and 0.1540 that is 63.2% and 23.5% of ceiling. 45.7% of CYP3A4 compounds and 27.1% of CYP2D6 compounds sit within one standard deviation of the threshold and are close to coin flips on repeat measurement, which is what caps the metric. The ceiling is optimistic by construction because the observed shift is treated as the latent truth, so the replicate carries one noise draw rather than two -- the honest floor is at or below these numbers, the safe direction for a bound meant to decide whether to keep investing. Practical reading: CYP3A4-TDI has far less headroom than MCC 0.36 sounds like, and the inhibition track's noise-floor discipline now extends to the half of the challenge that lacked it.
tdimccnoise-floorcyp3a4cyp2d6methodsscripts/train/tdi_noise_floor.py · 2026-08-29
high
The width penalty is real but small at the widths that matter: +0.007 at 19-23 columns, +0.042 at 384
Signal-free columns cost CYP3A4 almost nothing at 4, a bit at 19-23, and a lot at 384 -- and every block this campaign rejected sits at the cheap end.
Deep dive
Signal-free blocks (row-shuffled embedding columns) added to CYP3A4's deployed pipeline at increasing width, control reproducing at 0.4643 with seed SD 0.0020: K=4 +0.0017 (0.85 SD), K=19 +0.0067 (3.34 SD), K=23 +0.0069 (3.44 SD), K=64 +0.0192, K=128 +0.0279, K=384 +0.0420 (20.97 SD). Monotone, with LCO rising in step from 0.5020 to 0.5437. The real block widths in this campaign are: external panel 4, 3D conformer 19, mechanistic 23, ChemBERTa 384. So a previously-claimed +0.027 to +0.039 handicap on rejected blocks was measured at a width no rejected block has, and is corrected to about +0.007. That is small but not nothing -- roughly half a typical deployed effect here - so the practical rule is to gate a narrow block against a WIDTH-MATCHED NULL rather than the bare base, which costs one extra arm and removes the ambiguity entirely. Applying the correction retrospectively changes no decision: 3A4's joint block goes +0.0156 to +0.0087 (still rejected), 2C9's +0.0061 to -0.0008 (neutral), and CYP2D6 cannot be corrected this way because its own 384-column null was FREE, so its width curve is likely flat.
dimensionalitypermutation-nullgatingwidth-penaltyself-correctiondata/processed/width_penalty_cyp3a4.json · 2026-08-25
high
Two blocks that each fail seed-stability can be jointly stable, super-additively
If each block covers compounds the other misses, the union has fewer seed-sensitive failure modes than either part - so stability is a property of the combination, not an average of the pieces.
Deep dive
On CYP1A2, the external public-panel block gives -0.0027 and the 3D conformer/shape block -0.0059, and NEITHER is seed-stable, so both were correctly rejected alone. Together they give -0.0104, seed-stable on all three seeds (0.8084 < 0.8109, 0.8038 < 0.8180, 0.7983 < 0.8128), with LCO 0.8420 -> 0.8267 and magnitude 'meaningful'. The joint delta EXCEEDS the -0.0086 that simple additivity predicts, so this is super-additivity rather than averaging: each block is covering compounds the other misses, which reduces the seed-sensitive failure modes of the union below those of either part. The mechanism fits -- the external block supplies other assays' read on molecules the training set covers thinly, while the 3D block supplies planarity and shape for CYP1A2's narrow planar binding slot. Those are different kinds of ignorance and they do not overlap. Two lessons. First, seed-stability is a property of a CONFIGURATION, not an attribute a block carries around, so a block failing it alone says nothing about whether it fails in company -- which is a sharper version of the campaign's standing rule that combinations must be measured per isoform every time. Second, and more uncomfortable: both blocks had a resolvable leave-cluster-out gain and a tempting story about the blinded test being a scaffold shift, so rescuing either by reweighting the criteria was available and would have shipped a WEAKER model while corrupting the gate. The disciplined route was also the better-performing one.
combinationsseed-stabilitysuper-additivecyp1a2honest-gateswarm · 2026-08-24
high
Two hand-rolled layer updates fought and mis-reported the macro while the model was right
The single source of truth for a layered pipeline's live score already existed. Writing a second one next to it guaranteed they would disagree.
Deep dive
Two ticks ago the incumbent-reproduction control fired a false alarm because deployed_score() lagged a deployment layer, and the fix was to make it walk an ORDERED LIST of layers newest-first, with a comment telling future layers to register there. This tick added a new layer -- the joint external+3D block on CYP1A2 -- and instead of registering it, the submission builder got its own bespoke score-overwrite block, sitting immediately before the objective layer's equally bespoke one. They then overwrote each other in sequence: the joint block set CYP1A2's score to 0.8035, the objective block reset it to 0.8139, and the META recorded score_before_objective: 0.8035 as the fingerprint. The reported expected macro came out 0.6936 instead of 0.6910. The MODEL was correct throughout -- joint_ext_3d: True and n_external_models: 4 confirm both blocks were fitted and applied -- so this was a reporting defect, not a scientific one, caught by noticing the macro had not moved despite a deployed win. Two things worth keeping. Reporting defects are easy to wave through precisely because the predictions are fine, and a submission whose META misstates its own expected score is a trap for every later comparison. And the deeper failure is that the generalisation already existed and was not used: writing a second implementation of a rule beside the first guarantees they diverge the moment either changes. make_submission now calls deployed_score() as the single source of truth and the per-layer overwrites are deleted.
reportinglayered-pipelinesingle-source-of-truthself-correctionswarm · 2026-08-24
high
Two layers with the SAME mechanism are not substitutes -- bagging and ExtraTrees both earn their place
Bagging averages subsampled fits of one model; ExtraTrees averages across a second model family. Both reduce variance, so one might have made the other redundant. Removing either hurts, on every seed.
Deep dive
Leave-one-layer-out inside the deployed stack, 3 seeds, both controls reproducing. CYP2D6: -bagging costs +0.0100 (3/3, 1.93 SD) and -et costs +0.0098 (3/3, 1.88 SD). CYP1A2: -bagging costs +0.0214 (3/3, 2.98 SD) and -et costs +0.0075 (3/3, 1.05 SD). So subsampled averaging within one family and averaging across two families reduce different parts of the variance and the stack keeps both. The asymmetry is informative in its own right and confirms the competence rule a third time: the two layers are worth the same on CYP2D6 but bagging is worth nearly 3x ET on CYP1A2, tracking ET's solo competence gap (+0.0090 vs +0.0307) -- the more competent the second family, the more of the stack's variance reduction it carries. That rule was established by adding ET, sharpened within an isoform via its hyperparameter, and now holds on removing it.
ensemblingablationbaggingextratreesredundancystack-hygienescripts/train/layer_ablation_et.py; data/processed/layer_ablation_et_cyp2d6.json, _cyp1a2.json; ledger #109 · 2026-08-28
high
Under ST-RAE, shrink-to-mean is a WIDE-BAND strategy -- and the blinded test is enriched for narrow bands
A prediction inside the credible band scores zero, so pulling toward the mean pays only where the band is wide enough to catch you. On actives the band is ~0.2 wide and the mean is ~0.9 away, so there is nothing to catch you there -- and the test set is enriched for actives.
Deep dive
Sweeping the shrinkage coefficient a in pred'=mu+a*(pred-mu) over the deployed OOF, scored under a test-like activity reweighting, moved the optimum DOWN on 0 of 4 isoforms -- refuting my prediction that models losing to the mean predictor are over-confident. CYP2D6 moved 0.85 -> 1.10 (interior; the grid runs to 1.15) and at a=0.5 degrades 1.0300 -> 1.1012. The mechanism is visible in the labels alone, with no model involved: on the active tercile the credible band is ~0.2 wide while mu sits ~0.9 away, so mu is outside the band for 0.00 of actives on ALL FOUR isoforms, while inactive bands are 0.96-2.05 wide. ST-RAE's dead zone is what makes shrinkage pay, and on the population the shift up-weights that dead zone is unreachable from the mean. So CYP2D6 falling below the mean predictor is an ACCURACY failure on actives, not a calibration failure -- and every future calibration, blending, damping or ensemble-averaging lever inherits the same asymmetry: it buys forgiveness on inactives and pays for it on actives.
st-raecalibrationcovariate-shiftcyp2d6refutedscripts/train/shift_ranking_flip.py; data/processed/shift_ranking_flip.json; ledger #95 · 2026-08-27
high
We have been optimising the WRONG metric - the leaderboard scores ST-RAE, which forgives any prediction inside the credible band
The target is the experimental band, not the point estimate. And CYP2D6 has the tightest bands, so it gets the least forgiveness.
Deep dive
The leaderboard metric is ST-RAE (rae_soft_threshold_absolute_error), not plain RAE. Source: OpenADMET/CYP-Challenge-Tutorial evaluation/config.py + custom_scoring_functions.py, which the tutorial states is ported from the challenge backend. Mechanics: soft_error = max(y_pred - conf_high, 0) + max(conf_low - y_pred, 0), so a prediction landing anywhere INSIDE the per-compound credible band scores exactly zero; the denominator softens the mean predictor the same way, so 1.0 still means 'no better than the mean'. The training data already ships conf_low/conf_high, so this is scoreable locally. Re-scoring our own out-of-fold predictions: MACRO base RAE 0.8349 -> ST-RAE 0.7879, and base+mech 0.8287 -> 0.7780. Every reported number in this campaign has been ~0.05 PESSIMISTIC. Band-hit rates (fraction scoring a free zero): 3A4 36.9%, 2C9 39.5%, 1A2 22.2%, 2D6 19.2%. THREE CONSEQUENCES. (1) CYP2D6 gets the LEAST relief and is actually WORSE under the real metric (0.9912 vs 0.9873 plain) because its assay bands are the tightest (median width 0.27 vs 3A4's 0.38) - there is no measurement slack to hide in, so the 2D6 problem is harder than we have been reporting, not easier. (2) The metric CHANGES RANKINGS: on CYP3A4 the mechanistic block beats base on plain RAE (0.6195 vs 0.6206) but exactly TIES on ST-RAE (0.5548 vs 0.5548) - its entire 3A4 gain was in the region the real metric forgives. Gating on plain RAE can therefore deploy features that do nothing on the leaderboard. (3) The optimisation target is the BAND, not the point estimate - where the assay was uncertain there is free slack, where it was precise precision is mandatory. All future gating must use ST-RAE as the primary metric. Implemented as cyp.eval.st_rae (verified: mean predictor scores exactly 1.0, perfect scores 0.0) plus cyp.eval.band_hit_rate.
st-raemetricscoringleaderboardcyp2d6campaign-widest-rae-discovery · 2026-08-23
high
We weight imputed rows by an R-squared of 0.96 that is actually negative where they live
The calibration is scored on compounds that have a measured label. Donors are, by definition, compounds that do not - and there the same calibration is worse than predicting the mean.
Deep dive
Row imputation weights each donor by its calibration R^2, measured in-domain on compounds that carry both a single-conc log2fc and a measured pIC50 -- 0.9674 on CYP3A4, 0.9826 on CYP2C9. Donors are by construction compounds the organisers declined to run a dose-response on, so they occupy a different region of log2fc space. Reaching that region using measured compounds only (rank by distance from the donor median log2fc, fit the calibration on the far half, evaluate on the near half) gives NEGATIVE R^2 on ALL FOUR isoforms: CYP3A4 -0.2803, CYP2C9 -0.8786, CYP2D6 -0.1817, CYP1A2 -0.1511, against random-split R^2 of 0.8554 / 0.7500 / 0.5934 / 0.8270. The number used to weight donors is therefore not merely optimistic, it has the wrong sign where it is applied. Two consequences. First, imputation cannot be working by supplying accurate labels, because the labels are demonstrably worse than a constant in the donor region -- and it still helps three of four isoforms, so it must be working as a REGULARISER, a block of rows pulling predictions toward the centre, which under ST-RAE is the rational prediction wherever the model has no discriminating signal. Second, the honest way to set donor weights is a held-out estimate in the donor region rather than an in-domain fit; the current scheme happens to work because the weight it produces is roughly the right SIZE for shrinkage, not because it measures label quality. This also refutes concept shift as the explanation for CYP1A2's failure: the mapping breaks down everywhere, and CYP1A2's breakdown is the mildest of the four.
imputationcalibrationregularisationdonor-weightscovariate-shiftswarm · 2026-08-24
high
Weighting training rows by inverse credible-band width beats every feature block so far - and a control proves it is about precision, not potency
The assay measured actives tightly and inactives loosely, so the real metric grades them differently. Put that in the loss, not the features.
Deep dive
Band width is not random: spearman(band_width, pIC50) = -0.93 (3A4), -0.90 (2C9), -0.89 (1A2), -0.56 (2D6). Inactive compounds were measured imprecisely (3A4 p90 width 2.52 log units) and potent ones tightly (p10 0.13). Since ST-RAE only penalises distance OUTSIDE the band, the real metric effectively forgives the inactive tail and demands precision on actives - the opposite of what an unweighted fit optimises, given 79% of 3A4 training rows sit below pIC50 5. Band widths ship with the TRAINING data but are never available for the blinded test, so they belong in the LOSS, not the features: weight each row by how much its error will actually cost. No inference-time dependency and no leakage. CYP3A4 result (ST-RAE, scaffold CV, 3 seeds, full honest gate): unweighted 0.5541; inv_width_cap 0.5307 (-0.0234, DEPLOY); inv_width 0.5329 (-0.0212, DEPLOY); inv_sqrt_width 0.5409 (fails leave-cluster-out). THE CONTROL IS THE POINT: 'active_focus', which upweights potent compounds via a sigmoid on pIC50 WITHOUT using band information at all, gives only -0.0080 - about a third of the band-weighted gain. So the effect is genuinely about measurement precision, not merely about caring more about actives. Note the mechanism is NOT more predictions landing inside bands (band-hit barely moves, 36.9% -> 36.6%); it is smaller distances outside the band where the band is narrow enough to matter. At -0.0234 this is roughly 3x larger than anything the mechanistic block or the single-concentration auxiliary delivered on 3A4 under the real metric.
st-raesample-weightingband-widthcyp3a4loss-designband-weighted · 2026-08-23
high
When a dozen input-side levers all fail on one endpoint, suspect the ESTIMATOR
CYP2D6's TDI model had been fed new features, new losses, new thresholds and new weights a dozen times, always with the same classifier underneath. Swapping the classifier nearly doubled its MCC.
Deep dive
On CYP2D6 TDI at 12 seeds, a plain ExtraTrees classifier on identical features and folds scores MCC 0.1506 against the deployed LightGBM's 0.0791 (+0.0715, 3.12x the measured seed SD of 0.0229, better on 11 of 12 seeds), with AUROC 0.6237 vs 0.5692 improving on 12/12. Notably et_only BEATS the averaged +et5 arm (0.1464), so this is model selection rather than ensembling. It is REJECTED under the honest gate as written, which requires every seed to improve -- both arms fail on the same seed by -0.0039, or 0.17 SD -- and is reported as rejected rather than relaxed. CYP3A4 behaves oppositely and consistently with the competence rule: ET is less competent there (solo gap -0.0255) and averaging it in hurts (-0.0077, 0/3), so the #103 screen transfers across tracks and across metrics from ST-RAE to MCC. The durable lesson is the diagnosis: twelve TDI experiments varied inputs and losses and none varied the model class, on the endpoint where the deployed model sits closest to chance.
tdicyp2d6extratreesmodel-selectionestimatorrejectedscripts/train/tdi_family_gate.py; data/processed/tdi_family_cyp2d6.json; ledger #105 · 2026-08-28
high
Width is not the cost -- splittability is: 1,889 dead columns cost +0.0006, 384 dense ones cost +0.0420
LightGBM already ignores inert features for free, so removing them buys nothing; what hurts is a column good enough to attract a split but carrying no signal.
Deep dive
Between 73% and 83% of the 2265-column base matrix receives zero splits on every isoform (3A4 1665, 2C9 1889, 2D6 1848, 1A2 1876). With bagging now deployed at feature_fraction=0.8, each tree samples ~1812 columns of which three quarters are dead, which looked like a real dilution cost -- especially since #69 had measured signal-free columns degrading ST-RAE by +0.0017 at K=4 rising to +0.0420 at K=384. Pruning to the used columns inside each fold, selected on training rows only, gives +0.0006 on CYP2C9 with 1 of 3 seeds improving and LCO +0.0016 well under its 0.0570 threshold. The reconciliation: #69's penalty came from permuted ChemBERTa columns, which are dense, continuous and high-variance, so they readily win splits while carrying no information. The columns pruned here are dead because the split-gain criterion already declined them -- 66 constant, 552 active in fewer than 5 rows. LightGBM filters inert features at no cost, so there is nothing to recover. The forward-looking rule is unchanged in substance but sharper in scope: sparse or degenerate columns can be left alone, while any DENSE block should still be compressed before gating, because those are the ones that absorb spurious splits.
featuresdimensionalitylightgbmwidth-penaltyrejecteddata/processed/feature_prune_cyp2c9.json · 2026-08-26
medium
A second model family has THREE measurable properties, and the cheapest one was never used
Competence alone failed to predict whether averaging a family in helps. Measuring residual correlation and the direction of disagreement as well explains both the successes and the failures -- and the direction is the cheapest thing to measure.
Deep dive
On CYP3A4, one seed, one member per family: ExtraTrees has residual correlation 0.894 with the deployed model and DART 0.979, so independent-error content (1 - r^2) is 0.201 versus 0.042 -- ExtraTrees carries 4.8x more independent error to average away. DART is simultaneously the more competent model (solo MAE 0.5508 vs 0.6761), confirming by a non-ST-RAE route that it buys competence with diversity. The unplanned result: the correlation between a family's disagreement and the base model's error is -0.175 for ExtraTrees here, while the same diagnostic on CYP2D6 -- where ExtraTrees deploys -- gave +0.024. Near zero means orthogonal disagreement and pure variance reduction; negative means the family pulls in the direction that worsens the base's error. So the same family has opposite-signed disagreement on different isoforms and the sign tracks whether it helps. Three properties, then: competence, independent-error content, and direction of disagreement -- and the third needs one seed and no gate. Medium confidence: one seed, one isoform, one member per family, and the +0.024 figure came from five members on a different isoform, so the comparison is directional. The honest next step is the same diagnostic on CYP2D6 and CYP1A2 where ExtraTrees deploys.
ensemblingdiversitycompetencediagnosticsscreeningcyp3a4scripts/train/family_diversity.py; data/processed/family_diversity_cyp3a4.json; ledger #112 · 2026-08-28
medium
A second model family helps in proportion to its SOLO competence -- and only on the representation-bound isoforms
Averaging two models helps when both are good and they disagree for different reasons. Measure how good the second one is on its own, and you can predict the sign of the ensemble before building it.
Deep dive
ExtraTrees averaged as equal-weight members alongside the deployed LightGBM bag, 3 seeds, all controls passing. The outcome is monotone in how far ExtraTrees lands from the deployed model SOLO: CYP2D6 gap +0.0090 -> ensemble -0.0098 (3/3, 1.88 SD); CYP1A2 gap +0.0307 -> -0.0075 (3/3, 1.05 SD); CYP2C9 gap +0.1179 -> +0.0095 (0/3); CYP3A4 gap +0.1396 -> +0.0261 (0/3, 7.06 SD). The two that gain are exactly the two isoforms previously identified as representation-bound (1A2 at 4.99x its noise floor, 2D6 at 5.25x), which have rejected nearly every feature block -- the second family helps precisely where the primary model extracts least. Mechanism confirmed and it is NOT new signal: corr(ET - LGBM, LGBM residual) = +0.024 on 2D6, so the disagreement is orthogonal to the base's error and this is ensemble decorrelation, exactly the headroom predicted by bagging's measured saturation (1/n explains only 13% of member variance). Medium confidence pending a 12-seed confirmation, since CYP1A2 sits at 1.05 SD. This also refutes the earlier closure of the blend family: competence was correctly named as the binding constraint, but the family was closed after sampling one badly-chosen point (a ridge on 2,265 mostly-binary features).
ensemblingextratreesmodel-familycyp2d6cyp1a2decorrelationdeploy-pendingscripts/train/family_gate.py, family_diagnose.py; data/processed/family_et_*.json; ledger #100 · 2026-08-27
medium
A wide block's width penalty tracks how GOOD the model already is, not how many rows it has
384 random columns cost CYP3A4 0.0394 and CYP2D6 nothing -- and CYP2D6 has more training rows than CYP1A2, which pays 0.0273.
Deep dive
Permutation nulls (a row-shuffled 384-column ChemBERTa block: same width, marginals and collinearity, no molecule-to-feature link) were run on all four isoforms inside their deployed pipelines. Null cost vs deployed ST-RAE: CYP3A4 +0.0394 at 0.4643, CYP2C9 +0.0375 at 0.6033, CYP1A2 +0.0273 at 0.8036, CYP2D6 -0.0028 at 0.8930. Monotone with no inversions; corr(null cost, deployed ST-RAE) = -0.857. The rows-per-feature explanation was pre-registered and is REFUTED by a clean control: CYP2D6 and CYP2C9 have identical 4,376-row training sets (real plus imputed donors) and null costs of -0.0028 versus +0.0375, and corr(null cost, rows) is only +0.167. The mechanism that fits: random columns dilute an INFORMATIVE feature set, and CYP2D6's model sits near the mean predictor so it has almost nothing to dilute. Consequence beyond this block: every wide block ever rejected on 3A4, 2C9 or 1A2 was charged an unmeasured width penalty of +0.027 to +0.039, which is larger than almost every effect this campaign has measured -- those blocks competed against a handicap nobody had quantified. Caveats: n = 4 isoforms, so the monotone ordering is stronger evidence than the correlation coefficient, and CYP2C9's +0.0375 is only 1.74 SD because its own seed noise is large (0.0216). AMENDED 2026-08-25 (#69): the sentence 'every wide block ever rejected on 3A4, 2C9 or 1A2 was charged an unmeasured width penalty of +0.027 to +0.039' was wrong in MAGNITUDE and in scope. That figure was measured at 384 columns, and no block this campaign rejected is remotely that wide -- external panel 4, 3D conformer 19, mechanistic 23. The measured width curve on CYP3A4 is +0.0017 at K=4, +0.0067 at K=19, +0.0069 at K=23, +0.0192 at K=64, +0.0279 at K=128, +0.0420 at K=384. The real handicap on those rejections is about +0.007, not +0.035. It is still nonzero (3.3-3.4 SD) and about half a typical deployed effect, so the practical fix is to gate narrow blocks against a width-matched null; but applying the correction retrospectively overturns no decision.
dimensionalitypermutation-nullgatingwidth-penaltydata/processed/reverify_emb_cyp3a4_perm11.json · 2026-08-25
medium
Adding ExtraTrees made the bandl2 objective stop paying -- a later layer superseding an earlier one
Both layers shrink prediction spread: ExtraTrees by averaging a decorrelated family, bandl2 by a dead zone that charges nothing inside the credible band. Once the first is present, the second has less left to do.
Deep dive
Measured on CYP1A2 with identical seeds and only the baseline stack differing: without ExtraTrees, removing bandl2 costs +0.0085 on 3/3 seeds at 1.18 SD and the layer clearly earns its place; with ExtraTrees present -- the actual deployed configuration -- removing bandl2 IMPROVES the score by 0.0063 on all three seeds at 0.87 SD. A swing of -0.0148 attributable entirely to a layer sitting above it. This is the first measured instance of a later layer superseding an earlier one inside the deployed stack, as distinct from the four blocks that were silently dropped and turned out to be redundant with the imputation layer. It is not being acted on: 0.87 SD is under the magnitude bar, so the direction is consistent across every seed but the size does not clear the criterion, and it is recorded as the stack's first identified redundancy candidate worth 12 seeds if CYP1A2 is revisited. Medium confidence on three seeds. Measured alongside it: CYP2C9's imputation costs +0.1045 at 9.25 SD to remove, the most load-bearing layer in the campaign, more than the entire gap between CYP2C9 and CYP3A4.
ablationredundancybandl2extratreescyp1a2cyp2c9imputationscripts/train/loo_untested.py; data/processed/loo_untested.json; ledger #120 · 2026-08-28
medium
All four isoforms show the same shape: LCO improves while scaffold-CV does not
The split that simulates the blinded test likes these blocks; the split the gate is built on does not.
Deep dive
CYP1A2's external-panel and 3D blocks each improved leave-cluster-out by more than the isoform's resolvable LCO threshold while failing scaffold-CV seed-stability -- and jointly they passed the gate as written, at -0.0154 over 12 seeds. The mechanistic block has now produced the same signature on every other isoform, in each one's deployed pipeline with the control reproducing: CYP3A4 LCO -0.0006 with scaffold-CV +0.0022 (1 of 3 seeds), CYP2C9 LCO -0.0080 with scaffold-CV +0.0017 (2 of 3), CYP1A2 LCO -0.0067 with scaffold-CV -0.0013 (1 of 3, 0.26 SD). That is four isoforms and two unrelated feature families showing LCO and scaffold-CV disagreeing in the same direction, and the sign of the LCO delta is negative in every single case. This is recorded, NOT acted on: all three new cases fail the gate and stay rejected. It matters because the blinded test is a hard scaffold shift (546 test scaffolds, 11.5% seen in training), so LCO is the split that resembles it -- but rescuing a block by promoting LCO over seed-stability after seeing the result is exactly the after-the-fact criterion change the campaign has refused twice. The legitimate move, if one is ever warranted, is a pre-registered joint test like the one that passed on CYP1A2.
lcoscaffold-cvgatinggeneralisationdata/processed/reverify_mech_cyp3a4.json · 2026-08-25
medium
Assembled the missing middle rung: only 2 of 6 methods replicate their sign across independent abundant targets
Five single-target learning curves are five chances to be fooled by one dataset. The shared arm set was mandated so rankings could be compared ACROSS targets -- but the comparison was never made.
Deep dive
Cross-target paired deltas vs base (RAE, negative = better), assembled from the five surrogate artifacts at two rungs. At the challenge's own n=1500: base+et 5/5 targets better (mean -0.0246, sign p=0.031) and mech 5/5 better (mean -0.0028, p=0.031) while its permutation null is 1/3; ET SOLO is only 4/5 (fails on CYP3A4-public, +0.0231) and precision-weighting is 1/4. At the abundant rung mech still replicates 5/5 but base+et drops to 4/5 and ET solo to 3/5 -- the ensemble's advantage shrinks with n, exactly as the small-data-prior story predicts. So the campaign's two deployed levers behave differently under replication: the ET ENSEMBLE generalises across targets, the ET SWAP does not, matching the shipped model (ET on 2D6/1A2, rejected on 3A4/2C9). CAVEATS carried in the artifact: aromatase's pool tops out at n=1500 so its abundant column is degenerate (4 targets clear rung 2, not 5); hERG and aromatase share a Queen and codebase so treat effective units as 4; and precision-weighting is a protocol SLOT filled by three different operations, so its 1/4 is not one technique failing.
surrogatevalidationreplicationextratreesmechanismdata/processed/surrogate_rung2_crosstarget.json · 2026-09-03
medium
CYP1A2 has rejected five independent levers - and none of the usual explanations fit
Not scarcity, not calibration, not unlearnability. 1A2 has more data than 2C9, better calibration than 2C9, and 2C9 just took the biggest gain of the campaign.
Deep dive
CYP1A2 has now rejected every lever this campaign has put to it except band weighting: the mechanistic block (seed 7 regressed, +0.0075), the single-concentration auxiliary (LCO +0.0091), uncorrected row imputation (+0.5316, catastrophic), bias-corrected imputation (+0.0469), and now Emax-calibrated bias-corrected imputation (+0.1087, not seed-stable). Its joint-gate winner is plain base plus weighting, and in the joint gate its ENTIRE within-noise set was all four weighted configs (seed spread 0.0127) - meaning no feature choice was resolvable there at all. This is not a run of bad luck; five independent levers with different mechanisms have failed on the same isoform. WHAT MAKES 1A2 DIFFERENT is not obvious and the usual explanations do not fit. It is not data scarcity - 1A2 has 1,412 compounds, more than CYP2C9's 1,285, and 2C9 just took the campaign's largest single gain (-0.1242). It is not poor calibration - 1A2's log2fc+Emax calibration reaches R^2 0.837, HIGHER than 2C9's 0.763 which flipped from reject to a large win. It is not that the isoform is unlearnable - base ST-RAE 0.8345 is respectable and far from the mean predictor, unlike CYP2D6. The one structural fact that stands out is the population shift: 1A2 donors sit +1.004 log2fc above measured compounds on the independent screen, versus 2C9's +0.144 - so 1A2's donor pool is far less exchangeable with its measured set even though its calibration is better. That is a hypothesis, not a conclusion, and it is recorded as such: it is exactly the kind of single-isoform story that has been overturned five times here. PRACTICAL POSITION: stop spending ticks on CYP1A2 feature and data levers. It is the second-cheapest isoform to leave alone (0.8345 against a 0.163 noise floor) and every attempt has cost compute for nothing.
cyp1a2negative-resultpatternopen-questionemax-imputation · 2026-08-23
medium
CYP1A2's ExtraTrees layer moves half an active band to buy ~1% of score
ST-RAE only charges for predictions outside the credible band, so what matters is how far a layer moves predictions relative to band width. On CYP1A2 that ratio is half a band -- for the smallest gain of any deployed layer.
Deep dive
Comparing the submissions built before and after the ExtraTrees layer: CYP2D6's median prediction moves 0.0347 against a mean active band of 0.223 (0.16x) for a 0.0110 ST-RAE gain, while CYP1A2's moves 0.1075 against a 0.219 band (0.49x) for a smaller 0.0089 gain -- three times the movement for less return, making it the stack's highest movement-per-gain layer. The ablation agrees from the other side: removing ET costs CYP1A2 only +0.0075 against bagging's +0.0214, while on CYP2D6 the two contribute equally. This is exposure, not measured harm. The blinded test set was found to be more active with credible bands roughly half as wide as training's, so the 0.49x ratio there is plausibly a full band, and a large movement for a small measured gain means the gain is an average over the training distribution while the movement is the exposure to a different one. The layer passed 12 of 12 seeds at 1.24 SD and is not being removed on a speculative concern; the correct test is to re-score the ExtraTrees arms under the shift-corrected reweighting, which is queued.
st-raecyp1a2extratreesriskcovariate-shiftdeployed-stackscripts/submission_delta_check.py; submissions/10_bagged_all4.csv, 11_et_family.csv; ledger #115 · 2026-08-28
medium
CYP2D6 is still at the mean predictor after mechanistic features - 1.001 to 0.993 - so 2D6 needs 3D, not more 2D
A gated win that does not move the isoform off RAE 1.0 is a signpost, not a solution.
Deep dive
The 2D6 salt-bridge/basic-amine hypothesis produced a real, seed-stable, leave-cluster-out-surviving gain - but only -0.008 RAE, leaving 2D6 at ~0.993 against a 0.170 noise floor. The block explains a sliver of the residual and nothing more. Reading: the discriminating information for 2D6 is geometric rather than compositional - WHICH atom sits 5-7 A from the heme iron in a bound pose, not whether a basic nitrogen exists somewhere in the molecule. That is exactly what a 2D topological block cannot represent and what cofolding (ligand + HEME + receptor, min ligand-to-Fe distance, pocket engagement) can. Next lever for 2D6 should be structural, not more descriptors. Do NOT keep adding 2D blocks expecting a different answer.
cyp2d6headroomcofoldnext-stepcyp2d6-mechanistic · 2026-08-23
medium
CYP2D6 sits at parity with a constant under distribution shift, not below it
#94 reported 2D6 at 1.0300 on a test-like reweighting. Sweeping the arbitrary knobs shows the cells that cross 1.0 are exactly the cells that throw away two-thirds of the effective sample.
Deep dive
A clip/bins sweep of the shift-corrected evaluation (3 seeds, deployed config) puts CYP3A4 (0.578-0.592), CYP2C9 (0.606-0.616) and CYP1A2 (0.856-0.877) below 1.0 in 0 of 12 cells each. CYP2D6 exceeds 1.0 in 9 of 12 -- but at clip=3, which retains the most effective sample (ESS 815-871 of 1493 rows), it scores 0.9792-0.9839, just BELOW 1.0. The crossing cells are clip=5 (ESS 502-519), clip=10 (ESS 260-355) and unclipped (ESS 146-315). So the claim that the deployed CYP2D6 model loses to a constant on the deployment distribution is an artifact of how much weight concentration one tolerates; the defensible statement is parity, 0.98-1.05. This converges with an independent route that shares no machinery: converting ST-RAE into accuracy puts CYP2D6 only 0.07 log units better than a constant, which is exactly what hovering at parity under a modest shift looks like. Neither result licenses shrinking 2D6 toward the mean -- selecting shrinkage on a test-like score is tuning toward the blinded distribution, and #79 closed that family on magnitude.
cyp2d6distribution-shiftst-raemethodsimportance-weightingscripts/train/mean_predictor_check.py · 2026-08-29
medium
CYP2D6's shipped predictions span 1.56 log units against CYP3A4's 4.16
The attenuation measured in the diagnostics is visible in the file we would actually upload: 2D6's predictions are compressed into a narrow band around the mean.
Deep dive
In submission 11_et_family.csv the predicted ranges are CYP2D6 4.44-6.00 (span 1.56), CYP1A2 3.92-6.21 (2.29), CYP3A4 2.27-6.43 (4.16), CYP2C9 2.70-6.74 (4.04), against training labels spanning roughly 1.9-7.5 on every isoform. This is the same fact three independent measurements have now reported: #133 put CYP2D6 at 0.07 log units of accuracy over a constant against CYP3A4's 0.45, #135 measured its attenuation span at 1.143 with the largest under-prediction of potent compounds (-0.556), and here the shipped file shows the compression directly. A model whose output range is a third of its label range is close to predicting the mean, which is what the margin analysis concluded from a different direction. TDI positive rates in 12_tdi_et2d6.csv match training prevalence closely (0.2173 against 0.2164 for CYP2D6, 0.2133 against 0.2132 for CYP3A4), consistent with the prevalence-matched threshold that #58 kept for its zero estimation variance.
cyp2d6attenuationsubmissionmethodsscripts/official_validator.py · 2026-08-29
medium
Diversity as a DIRECTION predicts ensembling; diversity as a MAGNITUDE predicts backwards
Ask not how much a second model disagrees with the base, but which way. If its disagreement points along the base's error it corrects; if it points against, it amplifies. The size of the disagreement says nothing.
Deep dive
Measuring corr(second-family prediction minus base prediction, base residual) on one seed with one member, then comparing against every ensembling verdict the campaign has reached: 2D6 ExtraTrees +0.027 -> -0.0110 (deploys), 1A2 ET -0.014 -> -0.0089 (deploys), 2C9 ET -0.067 -> +0.0095, 3A4 DART -0.077 -> +0.0147, 3A4 ET -0.175 -> +0.0261. Spearman -1.00 and pearson -0.963, monotone across four isoforms AND two model families, and it places DART correctly where the competence gap had inverted. By contrast residual correlation -- the intuitive diversity magnitude -- ranks backwards across isoforms (spearman -0.40, wrong sign): CYP2D6 has the HIGHEST residual correlation at 0.973 and is where ExtraTrees deploys, while CYP3A4 has the lowest at 0.894 and is where it fails worst. Practically this is the cheapest screen available: one seed, one member, no gate arms, roughly five minutes, versus hours for a full three-arm gate. Medium confidence -- five points, one seed each, ensemble deltas from runs of differing seed counts, and no candidate has yet occupied the strongly-positive regime the rule predicts would help most.
ensemblingdiversityscreeningdiagnosticscheap-screencross-familyscripts/train/family_diversity.py; data/processed/family_diversity_cyp{3a4,2d6,1a2,2c9}.json; ledger #113 · 2026-08-28
medium
Donor imputation absorbs the loss-shaping levers: both band weighting and bandl2 die once donors are added
Imputation already downweights uncertain rows by calibration r-squared, so a second precision-weighting scheme has little left to do.
Deep dive
Two loss-shaping levers were re-tested inside the CURRENT deployed pipelines, both with controls reproducing exactly. CYP2C9 inv_sqrt_width band weighting was -0.0105 and seed-stable 3/3 on the pre-imputation base; with emax-shift imputation it REVERSES to +0.0040, 0 of 3 seeds. CYP3A4 bandl2 was -0.0050 and seed-stable 3/3 before the TDI-condition donor layer; with it, -0.0011 and no longer seed-stable. Both are levers that reweight or reshape the loss according to measurement precision, and both stopped working once a donor layer existed. Proposed mechanism, NOT established: imputed donor rows carry no credible bands (they collapse to points) and enter at weight r2 * mean(w), which is itself a precision-weighting scheme, so changing the band scheme mostly shifts the real-versus-donor weight balance rather than reweighting real rows. This is the mirror image of CYP2D6, where band weighting and imputation MULTIPLIED the mechanistic block's effect five-fold. Both directions say the same thing: a recipe element's value is a property of the configuration it sits in, not of the element, so the order layers are gated in matters and an early rejection is not durable evidence.
imputationband-weightingbandl2layeringcyp2c9cyp3a4data/processed/reverify_recipe_cyp2c9_inv_sqrt_width.json · 2026-08-25
medium
Every deployed model is strong where ST-RAE pays and weak where it does not; CYP2D6 is the exception
Scored by activity quartile against the global mean, the second-most-active tranche exceeds 1.0 on all four isoforms -- and that is exactly the near-zero-denominator region where a row can only add numerator.
Deep dive
Quartiles by predicted activity, least to most active, ST-RAE against the GLOBAL baseline mean (3 seeds, deployed config): CYP3A4 0.330/0.595/1.544/0.202, CYP2C9 0.472/1.028/2.128/0.383, CYP2D6 0.709/1.172/1.209/0.816, CYP1A2 0.560/0.848/2.164/0.737. Tranche 2 exceeds 1.0 everywhere, which is the middle of the potency range where the denominator is near zero; the extremes, carrying 45-58% of all denominator mass, score 0.20-0.47 on the three healthy isoforms. This is the mechanism behind band weighting being the campaign's largest lever -- it directs capacity to where the denominator lives. CYP2D6 is the exception: it is the only isoform failing to excel on the most-active tranche (0.816 against CYP3A4's 0.202) and its profile is nearly flat, which localises the weakness behind its 0.07 log-unit margin over a constant. CAVEAT, and it matters: ranking the four isoforms by most-active-tranche score reproduces their margin ranking exactly, but n=4 gives an exact permutation p of 0.083 two-sided (scipy's reported 0.000 is an asymptotic artifact invalid at this n), and the two quantities are largely mechanically linked since both derive from the same OOF predictions under the same metric. This is a localisation of where CYP2D6 loses, not independent evidence that it loses.
st-raecyp2d6methodsdiagnosticsband-weightingscripts/train/mean_predictor_check.py · 2026-08-29
medium
Only one deployed layer reverses under shift-correction -- the other five get better
If a shifted evaluation made every layer look bad, it would say nothing about any of them. Five of seven layers improve under it, by 1.4x to 4.9x, and the two that reverse are the same layer.
Deep dive
Sampling layer kinds rather than one isoform: CYP2D6 mechanistic block -0.0442 -> -0.2155 (grows 4.9x), CYP1A2 bagging -0.0214 -> -0.0554 (2.6x), CYP2D6 bagging -0.0100 -> -0.0469 (4.7x), CYP3A4 band weighting -0.0108 -> -0.0208 (1.9x), CYP3A4 TDI-condition donors -0.0075 -> -0.0107 (1.4x) -- against ExtraTrees at -0.0098 -> +0.0365 and -0.0075 -> +0.0443. So reversal is rare across a loss change, a data layer, a feature block and an ensemble layer, and ExtraTrees is the sole anomaly on both isoforms where it ships. The single largest number was incidental to the question: CYP2D6's mechanistic block amplifies nearly fivefold under the shift, the biggest layer effect measured in the campaign, which matches the biology since that isoform binds basic amines through an anionic pocket, the block encodes protonation state and the basic-N pharmacophore, and the blinded test set is enriched for actives. A layer gated as a modest win on training CV is the stack's most valuable component on a test-like distribution. Medium confidence: three seeds, weights clipped at 5x, activity-model error unmeasured, ESS 505 to 1907 -- the level of a shifted score is unreliable and only the ranking is being read.
covariate-shiftst-raedeployed-stackmechanistic-blockcyp2d6extratreesscripts/train/shift_sweep.py; data/processed/shift_sweep.json; ledger #117 · 2026-08-28
medium
Optimal shrinkage is not predicted by attenuation magnitude: the most attenuated models want more shrinkage
CYP2D6 and CYP1A2 are the most attenuated and want alpha below 1; CYP3A4 and CYP2C9 are the least attenuated and want alpha above 1. The naive reading of the bias diagnosis points the wrong way.
Deep dive
Selecting the linear coefficient in pred' = mu + alpha*(pred-mu) inside nested folds gives alpha 1.06 (CYP3A4), 1.12 (CYP2C9), 0.94 (CYP2D6), 0.92 (CYP1A2). Ranked by attenuation span the order is CYP1A2 1.486 > CYP2D6 1.143 > CYP3A4 0.898 > CYP2C9 0.889, so the two MOST attenuated isoforms are exactly the two wanting shrinkage rather than expansion. The reason is that alpha trades bias against variance and CYP2D6 and CYP1A2 are the weaker models -- damping prediction variance pays more than correcting the bias does. The practical warning is that a bias diagnosis does not license a bias correction; the sign of the optimal fix depends on how much signal the model has, not on how biased it looks. These values independently reproduce #79's per-isoform optima (1.05 / 1.10 / 0.85 / 0.85) measured on a different harness, which is stronger evidence than either run alone -- and both agree the effect is too small to deploy.
calibrationshrinkagemethodscyp2d6cyp1a2replicationscripts/train/attenuation_screen.py · 2026-08-29
medium
Row imputation deploys ONLY on CYP3A4 - and the harm tracks systematic label BIAS, not noise (my noise rule is refuted)
Donor compounds are not exchangeable with measured ones: the organisers chose what to run full curves on, so imputation transfers a population shift.
Deep dive
All four isoforms, row imputation from the dense single-conc matrix, gated under ST-RAE. Only CYP3A4 deploys: 0.5307 -> 0.4773 (-0.0534, LCO 0.6110 -> 0.5120). CYP2C9 improves scaffold-CV slightly (-0.0119) but REGRESSES under leave-cluster-out (0.7332 -> 0.7401) so it fails the gate. CYP2D6 +0.110. CYP1A2 is catastrophic at +0.5316 (0.8345 -> 1.3661; LCO 0.8473 -> 1.5585). MY NOISE-RATIO RULE IS REFUTED: 1A2 has a BETTER noise ratio than 2D6 (3.1x vs 4.8x) and does far more damage, so the ordering is non-monotonic and the rule cannot predict. WHAT ACTUALLY ORDERS THE HARM is systematic BIAS - the imputed labels are shifted relative to the real ones. Imputed mean minus real mean: 2C9 -0.30 (neutral), 3A4 +0.41 (gains), 2D6 -0.74 (harmful), 1A2 -1.56 (catastrophic). The two smallest shifts are the two non-harmful isoforms and the two largest are the two harmful ones. LIKELY CAUSE, offered as a hypothesis not a conclusion: donor compounds are NOT exchangeable with measured ones. The organisers chose which compounds got full dose-response curves, plausibly using the single-concentration screen itself, so donors are systematically weaker - imputation therefore transfers a POPULATION SHIFT, not merely measurement error. CYP3A4 has by far the highest measured fraction (2,335 of 4,905 = 48% vs 26-30% for the others), i.e. the least selective split and the smallest bias. IMPORTANT CAVEAT: bias ordering four points post-hoc is exactly the kind of story that has failed five times in this campaign. It is logged as an observation, NOT as a deploy rule. The defensible practical conclusion is narrower: imputation must be gated per isoform empirically, and a cheap pre-flight check of imputed-vs-real mean shift is worth computing before spending the compute.
imputationselection-biascyp1a2cyp3a4refuted-ruleper-isoformimpute-rows · 2026-08-23
medium
Scaffold CV and leave-cluster-out disagree, and the blinded test is the second one
A block can fail in-scaffold validation and still improve resolvably under series shift. The test set is a series shift.
Deep dive
The public-panel feature block was rejected on CYP3A4 and CYP1A2 for failing scaffold-CV seed-stability, and that rejection stands. But its leave-cluster-out score improved on BOTH isoforms and under BOTH objectives -- CYP3A4 0.5120 -> 0.5045, CYP1A2 0.8420 -> 0.8293 under l2 and again under bandl2. Ledger #25's multi-clustering tool was run to decide whether those are noise: CYP1A2's absolute LCO is very noisy (mean 0.9229, SD 0.0165, range 0.9051-0.9436) but its PAIRED deltas are 4x tighter at SD 0.0040, giving a smallest resolvable delta of 0.0081. The block's -0.0127 exceeds that; on CYP3A4 the threshold is 0.0067 and the block gave -0.0075, which also exceeds it. So both gains are resolvable. This is the first lever in the campaign where the two validation regimes disagree in a resolvable way, and it matters because the blinded test is a hard scaffold shift -- 546 test scaffolds with only 11.5% seen in training and zero compound overlap -- so LCO is the closer analogue of the actual scoring conditions while scaffold CV is what the gate is built on. The gate is NOT being moved after seeing this. The pre-registered condition for revisiting: if a leaderboard signal ever indicates scaffold CV is optimistic relative to the blind test, this block is the first candidate to reconsider. Caveat: the 0.0081 threshold was measured on the base-vs-mech contrast, so it proxies the external contrast's paired-delta spread rather than measuring it directly.
leave-cluster-outscaffold-cvseries-shiftvalidationexternal-dataswarm · 2026-08-24
medium
The donor weight BINDS where donors carry signal and goes FLAT where they only regularise
A scalar can be optimal because it is the right value, or optimal because nothing depends on it. Measuring the spread across the whole grid against the isoform's own seed noise tells the two apart -- and they call for different next moves.
Deep dive
Sweeping the donor sample weight alpha over a pre-registered {0.5, 1.0, 2.0} inside the deployed stack, both controls passing: CYP3A4 has a real interior optimum at alpha=1.0, losing +0.0030 (1/3) at 0.5 and +0.0037 (0/3) at 2.0. CYP2D6 does not -- alpha=0.5 gives -0.0013 (2/3) and alpha=2.0 gives -0.0024 (3/3) at only 0.47 SD. Spread across the whole 4x range against each isoform's measured seed SD: 3A4 1.00 (binds), 2C9 0.55 (flat), 2D6 0.47 (flat). Proposed mechanism, with the prediction it makes: the weight binds where donors carry SIGNAL and goes flat where they act as REGULARISATION. CYP3A4 is the only isoform with TDI-condition donors, pearson 0.947 with the target; single-conc donors are the ones shown to be negative-R2 in the donor region. Prediction -- any single-conc-only isoform is flat -- and the free check (CYP2C9) confirms it. That is 2 flat vs 1 binding on a post-hoc grouping, hence medium confidence: a hypothesis with one confirmed prediction, not an established fact. Practical consequence: on CYP2D6 this closes a lever rather than tuning one, on the isoform with the largest remaining gap.
donorsimputationsample-weightcyp2d6cyp3a4rejectedknob-sensitivityscripts/train/donor_weight_gate.py; data/processed/donor_weight_deployed_cyp2d6.json, _cyp3a4.json; ledger #99 · 2026-08-27
medium
The pre-flight bar ranked backwards: headroom beat transfer quality
How well an external source predicts the target does not tell you where it will help. Where the model is already strong, there is nothing left to add.
Deep dive
Ledger #45 pre-registered a bar for spending a gate on the public panel -- rho_self >= 0.6 AND rho_transfer >= 0.45 -- extending the #13 rule that an auxiliary pays off only when its own target is learnable. CYP3A4 cleared it comfortably (self +0.703, transfer +0.592); CYP1A2 missed on transfer (+0.705, +0.414) and was run anyway as a declared test OF the bar. The ranking inverted: CYP3A4 gave +0.0042 and was not seed-stable, while CYP1A2 gave the larger and seed-stable effect (-0.0118 against its then-baseline). CYP3A4 is the strongest isoform in the campaign (ST-RAE 0.4773) with the most training data (2,335 rows vs 1,412), so it has the least room for an external opinion to add anything, while CYP1A2 is data-poor. That is the same headroom-ordering seen in ledger #46, where a calibration lift was perfectly inversely ordered against baseline R^2. So transfer quality predicts whether an external model is any good; HEADROOM predicts whether that goodness can pay. The #13 pre-flight rule should be read as a necessary condition, not a ranking. Both isoforms were ultimately REJECTED once the gate was run against the correct incumbent, so this is a lesson about how to choose what to test, not about a deployed win.
pre-flightexternal-dataheadroombarrefutedswarm · 2026-08-24
medium
The PXR physics wins (AIMNet2, DFT-D4, DBSTEP, strain, SOAP) port directly and should rank HIGHER here, because CYP reactivity is atomic.
Reuse the proven physics blocks, but expect Fukui/charge/heme-distance to matter more than they did for PXR's activation task.
Deep dive
In PXR these were honestly-gated residual wins of ~−0.001 to −0.01 RAE each: AIMNet2 (learned-NNP charges/forces), DFT-D4 (dispersion/polarizability), DBSTEP (sterics/3D shape), MMFF strain, SOAP, OrbMol. Semi-empirical xTB alone was absorbed; learned NNPs escaped the sink.
For CYP, atomic reactivity is mechanistic (physics cards), so atomic Fukui indices and partial charges — cheap from AIMNet2/xTB — plus the cofold heme-Fe distance should rank above generic physchem. Hooks are documented in scripts/features/featurize_cyp.py.
Process rule unchanged: deploy a block only if it improves marginal-over-base, correlates with the base model's error, is seed-stable, and survives leave-cluster-out. Alignment-with-truth ≠ adds-signal.
physics-featuresaimnet2gatingseed · 2026-08-12
speculative
A multitask model over the four isoforms (masked loss) is the right BASE, not a marginal add — CYP is jointly-labelled and the isoforms share a promiscuity axis.
Start from one shared-representation model with four heads; single-task per-isoform models throw away the correlation you are handed for free.
Deep dive
Unlike PXR (single target, where multitask was a marginal aux-head win), CYP arrives as a 4-target matrix. The shared lipophilic/heme-ligating cause (chemistry card) means a shared trunk transfers real signal, and masked loss lets partially-labelled compounds train every observed head.
- Baseline built:
scripts/train/multitask_baseline.py (per-isoform LGBM on shared features) — proven end-to-end on external data. - GNN:
scripts/train/chemprop_multitask.py (4-head D-MPNN, masked loss). - The TDI heads (3A4, 2D6) can hang off the same trunk as classification outputs.
Validate per isoform and macro; watch for one isoform's abundant data dominating the shared trunk (weight the loss by inverse label count if so).
multitaskbase-modelmasked-lossseed · 2026-08-12
speculative
Band weighting compresses CYP2D6 predictions (sd 0.54 to 0.43) - correct under ST-RAE, but only if test bands resemble train bands
The compression is the metric working as intended. It becomes a liability only if the test set was measured more precisely than the training set.
Deep dive
Comparing v01 (plain-RAE-gated) with v02 (ST-RAE-gated, band-weighted) per isoform, predicted standard deviation: 2D6 0.539 -> 0.434, 1A2 0.711 -> 0.647, 3A4 0.972 -> 1.009, 2C9 unchanged (its winner is identical in both, pearson 1.0000). Cross-submission correlations: 2C9 1.000, 3A4 0.981, 1A2 0.932, 2D6 0.897 - so band weighting changed CYP2D6's predictions most, which is also where it bought the most (-0.0701). The COMPRESSION is expected and is the metric working as intended: weighting concentrates the loss on tightly-measured potent compounds and effectively stops paying for the sprawling inactive tail, so the model stops predicting extreme low values it was previously being penalised into. Under ST-RAE those inactives have wide bands, so a compressed prediction still lands inside them and scores zero. THE RISK WORTH NAMING: this is only correct if the TEST bands resemble the TRAIN bands. We never see test bands. If the organisers measured the test set more precisely - narrower bands - then v02's compression would be penalised exactly where v01 would not, and v02 could score WORSE despite winning every local gate. Train band widths vary a lot by isoform already (median 0.27 on 2D6 vs 0.38 on 3A4), so this is not an idle worry. Mitigation if a leaderboard signal ever becomes available: submit v01 and v02 in separate windows and compare, since they are the same pipeline differing only in the loss. Both files are validated and retained rather than one overwriting the other, specifically to keep that comparison possible.
calibrationst-raeband-weightingsubmissionriskfinal-gate · 2026-08-23
speculative
External data is a REAL lever here (unlike PXR) — the public CYP space is huge, so read-across / auxiliary-head pretraining should genuinely move the needle.
The wall that stopped PXR (no public data near the test) is down for CYP; pull hard on PubChem + ChEMBL and use them as heads, not just pretraining.
Deep dive
PXR's #1 finding was that coverage, not representation, was the wall — almost no public data sat near its test. CYP flips this: the PubChem NCGC qHTS panel alone gives ~13k compounds across the isozymes; ChEMBL adds thousands more.
- Pre-staged:
data/external/cyp_external_wide.parquet — 14k compounds, all 4 isoforms, 740 fully covered (read-across backbone). - Use it as: (a) auxiliary multitask heads (the RyeCatcher-style mechanism that lifted in PXR), (b) read-across features (nearest-neighbour public pIC50), (c) pretraining for the D-MPNN.
Honest caveat that still applies: gate everything on the never-tuned holdout with corr-with-error; abundant data ≠ automatic gain if it is off-manifold. But the *prior* here is much more favourable than PXR.
external-datacoverageread-acrosspubchemseed · 2026-08-12
speculative
Submitted CYP3A4 predictions sit 0.55 log units above its training mean - the opposite of shrinkage bias
Predictions drifting AWAY from the training mean is unusual. Either the test set is activity-enriched or the model extrapolates - both matter for RAE.
Deep dive
Comparing the submission's predicted distribution against the training distribution per isoform: cyp3a4 train_mean 4.096 pred_mean 4.646 shift +0.549; train_sd 1.093 pred_sd 0.972 | cyp2c9 train_mean 4.581 pred_mean 4.779 shift +0.198; train_sd 0.782 pred_sd 0.793 | cyp2d6 train_mean 4.784 pred_mean 4.605 shift -0.179; train_sd 0.916 pred_sd 0.539 | cyp1a2 train_mean 4.955 pred_mean 4.958 shift +0.002; train_sd 1.030 pred_sd 0.711. Two patterns. (1) CYP3A4 predictions sit +0.55 log units ABOVE its training mean. Shrinkage normally pulls predictions TOWARD the training mean, so a large upward shift is the opposite of the expected bias - it suggests either the 750 test compounds are genuinely enriched for actives relative to the inactive-dominated training set (79% of 3A4 train sits below pIC50 5, median 4.27), or the model extrapolates upward on unseen scaffolds. A challenge organiser would plausibly enrich the test set to make it scoreable rather than mirror an 80%-inactive screen. (2) Predicted standard deviations are much SMALLER than training ones across the board - the classic regression-to-the-mean compression. This matters for RAE specifically, because RAE's denominator is the TEST set's own mean absolute deviation: if the test spread is wider than our predictions, compression costs us directly. CANNOT be verified without labels, so logged as an observation, not a finding - but it argues for checking calibration/variance-matching before the final deadline rather than only chasing point accuracy.
calibrationdistribution-shiftraesubmissioncombined-gate · 2026-08-23