SabaPivot's picture
download
raw
38.9 kB
"""Write every logbook page from the reproduction outputs.
Pages are markdown; each trackio cell is a `---` separator, a
`<!-- trackio-cell {json} -->` header and a body.
"""
from __future__ import annotations
import json
import os
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PAGES = os.path.join(ROOT, ".trackio", "logbook", "pages")
BUCKET = "https://huggingface.co/buckets/SabaPivot/repro-semiknockoffs-artifacts"
def cell(meta: dict, body: str) -> str:
return (
"\n---\n<!-- trackio-cell\n"
+ json.dumps(meta)
+ "\n-->\n"
+ body.strip()
+ "\n"
)
def write(slug: str, heading: str, cells: str) -> None:
path = os.path.join(PAGES, slug, "page.md")
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w") as f:
f.write(f"# {heading}\n\n" + cells)
print("wrote", path)
# --------------------------------------------------------------- exec summary
EXEC = """
**Outcome: all six claims reproduce.** Working only from the arXiv PDF, I
re-implemented Semi-knockoffs (Algorithms 1-4 and the Eq. (1) knockoff
threshold) plus an HRT baseline, and tested each theorem where its own
hypotheses hold. With oracle conditional expectations the Wilcoxon p-values are
uniform (KS p = 0.35, 2,000 null p-values, n = 300) and the realised FDR sits at
or below the nominal q at every q on 500 replicates (q = 0.1 -> 0.075,
0.3 -> 0.287, 0.5 -> 0.486). The train/test split really is dispensable: with
everything estimated on the same n = 300 samples, Semi-knockoffs holds a type-I
error of 0.052 at alpha = 0.05, while the same holdout randomization test run
without a split blows up to 0.953. The two rate theorems fit their predicted
exponents (Thm 4.1: -0.60 measured against -1/2 predicted, R^2 = 0.995;
Thm 4.3: -1.036 measured against the -1.048 predicted from separately measured
a_n and b_n), the power comparison reproduces Figure 4 (SKO 0.990 vs HRT 0.877
power, +0.113 paired, p = 6.3e-11, with half the type-I error), and the
Wisconsin Breast Cancer type-I estimates match Figure 6 to two decimals on all
three model classes (RF 0.08, NN 0.04, GB 0.02).
**One caveat the paper does not state.** The 5-permutation derandomisation of
Section 5 does raise power as claimed (0.22 -> 0.46 at n = 50, p = 1e-5), but it
also inflates the type-I error (0.059 -> 0.094 in the same setting; 0.22 at 20
permutations). A global-null control isolates the cause: with *oracle*
nu = rho the derandomised test stays exact (0.048 at 20 permutations), so the
inflation is an estimation effect - averaging over permutations shrinks the
sampling noise but not the rho-hat-versus-nu-hat bias, and it does not vanish
with n. Theorem 3.3 covers the single-permutation Algorithm 1/2 and is not
contradicted; the Rao-Blackwellised variant has no accompanying theory.
## Scope & cost
| Item | Value |
| --- | --- |
| Scope | 6 / 6 claims reproduced independently: Thm 3.3, Thm 3.4, Thm 4.1, Thm 4.3, Figs 4-5 (Sec 5.1), Fig 6 (Sec 5.2) |
| Hardware | CPU only (shared x86 box, joblib over 100 workers); no GPU, no accelerator, no API key |
| Compute time | ~35 min wall clock for all seven experiment scripts plus figures |
| Cost | $0 |
| Software | Python 3, NumPy 2.2, SciPy 1.15, scikit-learn 1.7, matplotlib. Wisconsin Breast Cancer via `sklearn.datasets.load_breast_cancer` |
| Seeds | master seed 20260725; every replicate uses a derived `numpy.random.default_rng` stream, printed in each script |
| Independence | written from the PDF's Algorithm boxes; the authors' code at <https://github.com/AngelReyero/loss_based_KO> was located but neither read nor executed |
"""
def exec_summary():
with open(os.path.join(ROOT, "poster", "poster_embed.html")) as f:
embed = f.read().strip()
body = "````html\n" + embed + "\n````"
txt = cell({"type": "markdown", "title": "Executive summary", "pinned": True}, EXEC)
txt += cell(
{
"type": "figure",
"title": "Reproduction poster (poster_embed.html)",
"pinned": True,
"poster": True,
},
body,
)
write("executive-summary", "Executive summary", txt)
# ------------------------------------------------------------------- claim 1
C1_CLAIM = (
"Semi-knockoffs avoids the train-test data split required by prior "
"conditional-independence testing methods such as HRT while still yielding "
"valid p-values, via nonparametric paired tests requiring only conditional "
"expectations ν_j and ρ_j rather than exact knockoff construction "
"(Theorem 3.3, Section 3.1)."
)
C1 = f"""
> **Claim (verbatim).** {C1_CLAIM}
## Verdict: **verified**
## What Theorem 3.3 actually asserts
Given the *oracle* conditional expectations ν_j = E[X^j | X^-j] and
ρ_j = E[X^j | X^-j, y], the nonparametric paired test of Algorithm 2 returns a
valid p-value. Under H0 conditional independence forces ρ_j = ν_j, so the two
imputed populations are drawn from one law and the paired loss differences are
symmetric. Nothing in the argument needs a held-out sample, and nothing needs the
joint pairwise exchangeability that a genuine model-X knockoff requires.
## Independent method
Three separate tests, all in `scripts/c1_pvalue_validity.py`.
**A - oracle validity.** Gaussian design X ~ N(0, Σ), Σ_ij = 0.6^|i-j|, p = 50,
y = β'X + ε with support {{0, 1}}. ν_j and ρ_j are computed in **closed form**
from the joint Gaussian law (`gaussian_nu`, `gaussian_rho` in
`scripts/semiknockoffs.py`) - the exact hypothesis of the theorem. 200 replicates
x 10 null coordinates = 2,000 null p-values per configuration, at n = 30, 100,
300, for the Wilcoxon and sign variants. Uniformity is tested with a one-sample
KS test.
**B - the decisive no-split contrast.** Everything estimated (ridge imputers) on
the same n = 300 sample, a gradient-boosting black box, and four procedures:
SKO-Wcx with the model trained on all n and tested on all n; HRT with model and
sampler fit on all n and tested on all n; HRT with a proper 50/50 split and a
df-corrected residual sampler; HRT with a 50/50 split and the exact Gaussian
conditional sampler. 100 replicates x 12 null features = 1,200 null p-values.
**C - "only conditional expectations, not exact knockoffs".** A heavy-tailed
multivariate-t(3) elliptical design, where the conditional *mean* is still the
same linear map but the conditional law is heteroscedastic and non-Gaussian, so a
Gaussian model-X sampler is mis-specified. 200 replicates x 10 null coordinates.
**Boundary probe.** Algorithms 1-4 say "sample π_j,1 and π_j,2 *permutations*",
whereas the proof in Appendix E.2 uses i.i.d. uniform indices U_1..U_n. Under
permutations the n paired differences are not independent, which the Wilcoxon
signed-rank test formally requires. Both schemes were measured.
## Numerical result
Oracle Wilcoxon, null p-values (type-I error at α = 0.05, MC s.e. ~0.005):
| n | permutations | i.i.d. draws | KS p (perm) |
| --- | --- | --- | --- |
| 30 | 0.0400 | 0.0400 | 0.0048 |
| 100 | 0.0530 | 0.0545 | 0.036 |
| 300 | **0.0445** | 0.0525 | **0.348** |
The oracle **sign test** is valid but conservative (0.038 at n = 300, mean
p-value 0.547); its KS rejection is pure discreteness, and it rejects less often
than nominal at every level - consistent with the paper's remark that the
Wilcoxon variant is the more powerful one.
Split versus no split, everything estimated (1,200 null p-values):
| procedure | split | type-I @ 0.05 | type-I @ 0.10 | KS p |
| --- | --- | --- | --- | --- |
| **SKO-Wcx** | **none** | **0.0525** | 0.1058 | **0.362** |
| HRT | none | 0.9525 | 0.9667 | < 1e-300 |
| HRT | 50/50 | 0.0842 | 0.1342 | 3.6e-5 |
| HRT, oracle sampler | 50/50 | 0.0408 | 0.0967 | 0.281 |
Heavy-tailed t(3) elliptical design (2,000 null p-values):
| procedure | type-I @ 0.05 | KS p |
| --- | --- | --- |
| **SKO-Wcx, oracle ν (conditional mean only)** | **0.0405** | **0.501** |
| HRT + split + Gaussian knockoff sampler | 0.1300 | 4.2e-22 |
## Expected value
Valid p-values means P(p ≤ α) ≤ α and, for a continuous statistic, uniformity.
Expected 0.05 at α = 0.05 and a non-significant KS test. Observed 0.0445
(oracle) and 0.0525 (fully estimated, no split).
## Limitation
- Theorem 3.3 is stated for oracle ν_j, ρ_j; test A is the faithful test of it.
Test B additionally shows the estimated Algorithm 1 stays valid in this
signal-bearing regime, which the theorem does not itself guarantee.
- Under an adversarial **global null** (y independent of X, so a flexible model
can only memorise noise) the *estimated* Algorithm 1 becomes anti-conservative:
0.0795 at n = 300, and it does not improve with n (0.0815 at n = 1,000). See
claim 5 - this is the same ρ-hat-versus-ν-hat bias, and it is exactly what
Theorems 4.1 and 4.3 exist to control.
- HRT with a split shows 0.084 rather than 0.05 here because its residual-based
conditional sampler is itself estimated; with the exact Gaussian sampler it
falls to 0.041. That is a sampler-estimation effect, not a defect of HRT, and
it is reported so the power comparison in claim 5 is read fairly.
## Artifacts
- `scripts/semiknockoffs.py` - Algorithms 1-4, Eq. (1) threshold, HRT, oracle
ν/ρ, data generators
- `scripts/c1_pvalue_validity.py` - this experiment
- `outputs/claim1_pvalue_validity.json` - all raw numbers
- `figs/claim1_pvalue_validity.png`
- Bundle: <{BUCKET}>
"""
# ------------------------------------------------------------------- claim 2
C2_CLAIM = (
"Theorem 3.4 establishes that the Semi-knockoffs procedure controls the "
"false discovery rate at level q, i.e. FDR(S_SKO) ≤ q (Theorem 3.4, "
"Section 3.2)."
)
C2 = f"""
> **Claim (verbatim).** {C2_CLAIM}
## Verdict: **verified**
## Independent method
`scripts/c2_fdr.py`. A known ground-truth support, many replicates, and the
realised FDR (mean FDP over replicates) compared with the nominal q on a grid
q ∈ {{0.05, 0.1, 0.2, 0.3, 0.5}}. This is a direct, decisive test: if
Theorem 3.4 is true, FDR ≤ q must hold at finite n, for **every** q, for **any**
model m-hat.
Setting: X ~ N(0, Σ), Σ_ij = 0.6^|i-j|, n = 300, p = 50, support = first 12
coordinates with β_j ~ U[1, 2], ε ~ N(0, 1).
- **Oracle regime** (Algorithm 3, the exact hypothesis "given ν_j and ρ_j"):
ν_j and ρ_j taken in closed form from the joint Gaussian law. 500 replicates
with a gradient-boosting black box, 500 more with a Lasso black box.
- **Estimated regime** (Algorithm 4): ν-hat, ρ-hat are ridge regressions fitted
on the same n samples. 500 replicates.
- **Boundary probes:** a nonlinear design where the linear imputer is
mis-specified (300 reps); "BH on the Wilcoxon p-values" as the alternative
route the paper says should be worse (300 reps); and the global null with no
signal at all (300 reps).
W^j_SKO = (1/n) Σ_i [ l(m-hat(X~1_i), y_i) - l(m-hat(X~2_i), y_i) ], threshold
T_q from Eq. (1) in its knockoff+ form, S = {{j : W^j ≥ T_q}}.
## Numerical result
Realised FDR (mean FDP over 500 replicates), 95% half-width in brackets:
| q | oracle + GB | oracle + Lasso | estimated + GB | mis-specified imputer |
| --- | --- | --- | --- | --- |
| 0.05 | 0.0026 (0.0029) | 0.0008 (0.0016) | 0.0026 (0.0029) | 0.0028 (0.0038) |
| 0.10 | **0.0746** (0.0087) | 0.0686 (0.0077) | 0.0759 (0.0085) | 0.0520 (0.0105) |
| 0.20 | **0.1749** (0.0130) | 0.1597 (0.0114) | 0.1969 (0.0138) | 0.1593 (0.0173) |
| 0.30 | **0.2871** (0.0146) | 0.2266 (0.0108) | 0.3034 (0.0152) | 0.2582 (0.0200) |
| 0.50 | **0.4858** (0.0141) | 0.2797 (0.0083) | 0.4950 (0.0135) | 0.4640 (0.0191) |
Power is 1.000 at every q ≥ 0.1 in the oracle and estimated regimes, 0.836-0.958
under the mis-specified imputer. Under the **global null** (no true signal) the
realised FDR is 0.000 / 0.000 / 0.043 / 0.093 / 0.387 for the five q values -
controlled everywhere, and far below q at small q.
The BH-on-p-values alternative is also controlled but strictly more conservative
(FDR 0.032 / 0.065 / 0.134 / 0.200 / 0.345), matching the paper's Appendix F.5
statement that the knockoff threshold should be preferred.
## Expected value
FDR ≤ q at every q. Observed: satisfied in every oracle configuration with
margin. The single value above its nominal level is the estimated-imputer run at
q = 0.30 (0.3034 vs 0.300), which is 0.44 standard errors above q - inside Monte
Carlo error, and outside the theorem's stated hypotheses anyway (Theorem 3.4 is
conditional on the true ν_j, ρ_j).
## Limitation
- At q = 0.05 with p = 50 the Eq. (1) threshold needs at least 1/q = 20
discoveries before it can fire; the true support has only 12 members, so the
procedure correctly returns the empty set (power 0.006). This is the standard
knockoff detection floor, not a failure of the theorem.
- 500 replicates give a Monte Carlo s.e. of about 0.007 on the FDR at q = 0.2, so
a violation smaller than ~0.015 would not be detectable here.
- The estimated-imputer column is reported for completeness; Theorem 3.4 does not
cover it (Sections 4.2-4.5 argue it holds approximately).
## Artifacts
- `scripts/c2_fdr.py`, `outputs/claim2_fdr.json`, `figs/claim2_fdr.png`
- Bundle: <{BUCKET}>
"""
# ------------------------------------------------------------------- claim 3
C3_CLAIM = (
"Theorem 4.1 shows that for null (non-relevant) features, regularized "
"empirical risk minimizers trained with and without the feature remain "
"close, with a ‖θ̃^j − θ̂‖₂ ≤ O_P(√(log(1/δ)/n)) bound, giving "
"optimization stability guarantees for regularized models (Theorem 4.1, "
"Section 4.2)."
)
C3 = f"""
> **Claim (verbatim).** {C3_CLAIM}
## Verdict: **verified**
## Independent method
`scripts/c3_stability.py`. R_n(θ) = (1/n) Σ_i l(θ'χ_i, z_i) + λ‖θ‖² as in
Eq. (2); θ-hat is the minimiser over R^p, θ-hat^{{-j}} the minimiser over R^{{p-1}},
and θ-tilde^j = (0, θ-hat^{{-j}}) re-embedded. (scikit-learn's Ridge minimises
‖Xw - z‖² + α‖w‖², so α = nλ.)
1. **Figure 1 reproduction.** z = χβ + ε with β 0.25-sparse in blocks of 5,
n = 300, p = 50, χ ~ N(0, Σ) with Σ_ij = 0.6^|i-j|, noise level ‖χβ‖/2.
Ridge and Lasso, 50 replicates.
2. **Rate in n.** Fit log Q_{{1-δ}}(‖θ-tilde^j - θ-hat‖₂) = a log n + c over
n ∈ [50, 3200] for null coordinates only; the theorem predicts a = -1/2.
60 replicates per sample size.
3. **Rate in δ.** At the largest n, regress the (1-δ)-quantile on
√(log(1/δ)) for δ from 0.5 down to 0.005.
4. **Boundary probes.** λ swept over {{1e-1, 1e-2, 1e-3, 1e-6}} (the proof needs
λ > 0 for strong convexity but identifies θ* with the *unregularised*
population minimiser via Assumption E.4, so a bias floor of order λ was a
plausible failure mode); and a t_2 design, which breaks the sub-Gaussian
Assumption E.2.
5. **The quantity the method actually uses.** ν-hat regresses X^j on X^-j and
ρ-hat regresses X^j on (X^-j, y): here the "extra uninformative feature" is y
itself, which is precisely what Section 4.2 invokes. Null versus important j,
and the rate in n.
## Numerical result
Figure 1 reproduced (n = 300, p = 50, λ = 1e-2, 50 replicates):
| learner | mean, unimportant j | mean, important j | separation | AUC |
| --- | --- | --- | --- | --- |
| Ridge | 0.342 | 1.869 | 5.46x | 0.994 |
| Lasso | 0.315 | 1.874 | 5.95x | 0.994 |
Fitted decay exponents at δ = 0.05 (predicted **-0.50**):
| configuration | fitted exponent | exponent over the last 3 sample sizes | R² |
| --- | --- | --- | --- |
| Ridge λ = 1e-3 | **-0.600** | -0.545 | 0.995 |
| Ridge λ = 1e-2 | -0.588 | -0.551 | 0.997 |
| Ridge λ = 1e-1 | **-0.492** | -0.487 | 0.998 |
| Ridge λ = 1e-6 | -0.601 | -0.545 | 0.995 |
| Lasso λ = 1e-2 | -0.640 | -0.609 | 0.998 |
| Ridge, **t_2 design (E.2 broken)** | -0.683 | -0.577 | **0.569** |
δ-dependence at n = 3,200 (Ridge λ = 1e-3): the quantile is linear in
√(log(1/δ)) with **R² = 0.994**; the log-log exponent on log(1/δ) is +0.72
rather than +0.50, which is what a linear fit a + b√x with a negative intercept
produces over a finite δ range - still O(√(log(1/δ))).
The ν-hat / ρ-hat coefficients (test 5), Q_0.95 of ‖θ-tilde - θ-hat‖₂:
| n | 50 | 100 | 200 | 400 | 800 | 1600 | 3200 | fitted exponent |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| null j | 1.010 | 0.510 | 0.342 | 0.255 | 0.182 | 0.120 | 0.085 | **-0.565** |
| important j | 2.001 | 1.696 | 1.550 | 1.553 | 1.534 | 1.470 | 1.477 | **-0.062** |
## Expected value
Exponent -1/2 in n, and a √(log(1/δ)) dependence on the confidence level.
Measured -0.49 to -0.60 with R² ≥ 0.995 across regularisation strengths and both
learners, and the δ-scaling fits √(log(1/δ)) at R² = 0.994.
## Limitation
- The fitted exponents run slightly *steeper* than -1/2 at small λ (-0.60), and
the estimate drifts toward -0.545 over the last three sample sizes, so the
asymptotic slope is consistent with -1/2 but the finite-n fit is not exactly
-0.5. O_P is an upper bound, so a steeper measured decay is not a violation.
- No bias floor was found even at λ = 1e-1 (tail exponent -0.487), so the gap
between the λ-strongly-convex argument and Assumption E.4's unregularised θ*
is not visible at these scales; it may only bite at larger λ.
- Breaking the sub-Gaussian design assumption (t_2) is what degrades the fit -
R² falls from 0.995 to 0.569 at δ = 0.01 - which is the expected behaviour
outside the theorem's hypotheses, but a heavier-tailed sweep would pin the
breakdown more sharply.
- Only the quadratic loss is tested; the paper also verifies the assumptions for
cross-entropy.
## Artifacts
- `scripts/c3_stability.py`, `outputs/claim3_stability.json`,
`figs/claim3_stability.png`
- Bundle: <{BUCKET}>
"""
# ------------------------------------------------------------------- claim 4
C4_CLAIM = (
"Theorem 4.3 provides a double-robustness property: the loss difference "
"between imputed feature distributions decays at a compound rate "
"O_P(a_n b_n) even when both the predictive model and the sampler have "
"estimation error (Theorem 4.3, Section 4.4)."
)
C4 = f"""
> **Claim (verbatim).** {C4_CLAIM}
## Verdict: **verified** (for the differentiable m-hat the theorem assumes)
## Independent method
`scripts/c4_double_robustness.py`. Theorem 4.3 says: for j ∈ H0, with
t ↦ l(t, y) twice differentiable with bounded derivatives, m-hat differentiable
in coordinate j, a_n := ∂_{{x^j}} m-hat and ν-hat - ν = O_P(b_n),
l(m-hat(X~'), y) - l(m-hat(X~), y) = O_P(a_n b_n).
The strategy is to measure a_n and b_n **separately** on the same runs, predict
the compound exponent as their sum, and compare it with the measured decay of the
loss gap. X~ uses the oracle ν and X~' the estimated ν-hat with the *same*
residual index, so the difference isolates the imputer error.
1. **Figure 3 reproduction.** y = 0.8X¹ + 0.6X² + 0.4X³ + 0.2X⁴ + sin(X¹) + ε,
ε ~ N(0, 0.5), n = 2000, X ~ N(0, Σ) with Σ_ij = 0.5^|i-j|, ν-hat linear,
null coordinate j = 0; Random Forest, Neural Network, Gradient Boosting.
Blue = the semi-knockoff statistic l(m(X~'_1),y) - l(m(X~'_2),y); orange =
l(m(X~'_1),y) - l(m(X~_1),y), which is the doubly-robust quantity.
2. **Compound-rate fit.** Sweep n ∈ [100, 6400], measure a_n (secant sensitivity
of m-hat in coordinate j), b_n = ‖ν-hat - ν‖₂/√n, and D_n = the 0.9-quantile
of the per-observation |loss gap| (Theorem 4.3 is a pointwise statement, so a
pointwise scale is used rather than an average over i, which would contribute
its own 1/√n).
3. **Boundary probe / discriminating test.** Repeat for an **important**
coordinate. There a_n is O(1) rather than O_P(n^-1/2), so only b_n survives
and the predicted exponent moves from about -1 to about -1/2. If the measured
exponent tracked b_n alone in both cases, the compound-rate claim would be
falsified.
## Numerical result
Figure 3 reproduced, n = 2000, 8 replicates, null coordinate j = 0:
| m-hat | sd(blue) | sd(orange) | concentration ratio |
| --- | --- | --- | --- |
| Random Forest | 0.0359 | 0.0059 | **6.1x** |
| Neural Network | 0.3843 | 0.0364 | **10.6x** |
| Gradient Boosting | 0.0336 | 0.0127 | **2.6x** |
Compound-rate fits (exponents in n; "predicted" = fitted a_n exponent + fitted
b_n exponent, measured on the same runs):
| m-hat, coordinate | a_n exp | b_n exp | predicted a_n b_n | measured (Q_0.9) | measured (mean\\|d\\|) |
| --- | --- | --- | --- | --- | --- |
| **linear, null j** | -0.545 | -0.503 | **-1.048** | **-1.036** | -1.032 |
| **linear, important j** | -0.001 | -0.482 | **-0.483** | **-0.496** | -0.502 |
| NN, important j | +0.006 | -0.443 | -0.437 | -0.400 | -0.410 |
| NN, null j | +0.169 | -0.496 | -0.327 | -0.219 | -0.212 |
| RF, null j | -0.067 | -0.496 | -0.563 | -0.387 | -0.412 |
| GB, null j | -0.567 | -0.481 | -1.048 | -0.267 | -0.594 |
## Expected value
For a linear m-hat and a null coordinate, Remark 4.4 predicts a_n = β-hat^j =
O_P(n^-1/2) and b_n = O_P(n^-1/2), so the compound rate is O_P(1/n): predicted
exponent -1.048, measured **-1.036** (0.012 apart). For an important coordinate
the single-robust rate -1/2 is expected: predicted -0.483, measured **-0.496**.
Both match, and the two cases differ by a factor of √n exactly as the theorem
requires.
## Limitation
- Theorem 4.3 assumes m-hat is differentiable in coordinate j. Tree ensembles are
piecewise constant, so the derivative is identically zero; a secant sensitivity
at h = 0.25 sd(X^j) is used as a surrogate for a_n on RF and GB. For those
models the predicted and measured exponents differ substantially (GB null:
-1.048 predicted, -0.267 to -0.594 measured), so the quantitative compound rate
is **not** recovered for non-differentiable learners. The paper says as much
("strict differentiability is not necessary in practice ... we still observe
faster convergence") and the qualitative claim does hold: Figure 3 reproduces
with 2.6-10.6x concentration.
- The neural-network null case is the weakest fit (measured -0.22 against a
predicted -0.33): the fitted a_n exponent is *positive* (+0.169) for
scikit-learn's default MLP, i.e. its sensitivity to the null coordinate does
not shrink at these sample sizes, so the compound-rate mechanism has nothing to
compound.
- The surrogate a_n is a scalar summary of a function-valued sensitivity, so the
"predicted" column carries its own estimation error.
## Artifacts
- `scripts/c4_double_robustness.py`, `outputs/claim4_double_robustness.json`,
`figs/claim4_double_robustness.png`
- Bundle: <{BUCKET}>
"""
# ------------------------------------------------------------------- claim 5
C5_CLAIM = (
"On simulated data with adjacent-feature support, Semi-knockoffs maintains "
"type-I error control while achieving higher power than HRT, and "
"derandomization with 5 permutations under masked correlation further "
"increases power (Figure 4, Figure 5, Section 5.1)."
)
C5 = f"""
> **Claim (verbatim).** {C5_CLAIM}
## Verdict: **verified**, with a validity caveat the paper does not report
## Independent method
`scripts/c5_power_hrt.py`, `scripts/c5b_derandomization.py`,
`scripts/c5c_derand_validity.py`. Both of the paper's settings at its own scale:
n = 300, p = 50, 50 replicates, α = 0.05.
- **Figure 4 - adjacent support.** X ~ N(0, Σ), Σ_ij = 0.6^|i-j|,
y = β'X + ε, the first 0.25p coordinates of β drawn in [1, 2] and the rest
zero, ε ~ N(0, 1). Pre-trained black box: gradient boosting.
- **Figure 5 - masked correlation.** One relevant coordinate l,
y = X_l + 0.5ε₁, and a correlated **null** variable X_{{l-1}} = X_l + 0.5ε₂.
Pre-trained black box: neural network (scikit-learn defaults, which reproduce
the paper's reported R²).
- Methods: HRT (50/50 split, K = 200 draws, df-corrected residual sampler),
SKO-Wcx (Algorithm 1, one permutation, no split), SKO-Wcx-p5 (Rao-Blackwellised
over 5 permutations, no split), and a LOCO-Wilcoxon refit baseline.
- **Derandomisation sweep.** Because the masked setting saturates at power 1.000
for every method at n = 300, the permutation count is swept over
{{1, 2, 5, 10, 20}} at n ∈ {{50, 75, 100, 150, 300}}, 100 replicates each, to
measure the gain in the non-saturated regime.
- **Validity control.** A clean global null (y drawn independently of X, so every
coordinate is null), with **oracle** ν = ρ and separately with estimated
ν-hat, ρ-hat, sweeping the permutation count. 200 replicates, 2,000 null
p-values per cell.
## Numerical result
Figure 4, adjacent support, gradient boosting (R² 0.888 no-split / 0.850 split,
against the paper's 0.910 / 0.886):
| method | power | type-I | AUC |
| --- | --- | --- | --- |
| LOCO-Wcx | 0.340 | 0.056 | 0.791 |
| HRT (50/50 split) | 0.877 | 0.071 | 0.964 |
| **SKO-Wcx (no split)** | **0.990** | **0.044** | 0.998 |
| SKO-Wcx-p5 | 1.000 | 0.057 | 1.000 |
Paired over the same 50 replicates: SKO-Wcx - HRT = **+0.1133 power**
(p = 6.3e-11); SKO-Wcx-p5 - SKO-Wcx = +0.0100 (p = 0.013); SKO-Wcx-p5 - HRT =
+0.1233 (p = 2.4e-12).
Figure 5, masked correlation, neural network (R² 0.548 / 0.468, against the
paper's 0.581 / 0.567): power is **1.000 for HRT, SKO-Wcx and SKO-Wcx-p5** -
saturated - with type-I errors 0.089 / 0.049 / 0.069. LOCO-Wcx reaches 0.660.
Derandomisation in the non-saturated regime (masked setting, 100 replicates):
| n | perms=1 | perms=2 | perms=5 | perms=10 | perms=20 |
| --- | --- | --- | --- | --- | --- |
| **power**, n = 50 | 0.220 | 0.340 | **0.460** | 0.560 | 0.600 |
| power, n = 75 | 0.580 | 0.770 | 0.940 | 0.980 | 1.000 |
| power, n = 100 | 0.800 | 0.950 | 0.980 | 1.000 | 1.000 |
| **type-I**, n = 50 | 0.059 | 0.072 | **0.094** | 0.134 | 0.180 |
| type-I, n = 300 | 0.049 | 0.051 | 0.070 | 0.088 | 0.134 |
The n = 50 gain from 5 permutations is +0.240 power, paired p = 9.8e-6.
Global-null control (type-I at α = 0.05, 2,000 null p-values per cell):
| configuration | 1 perm | 2 | 5 | 10 | 20 |
| --- | --- | --- | --- | --- | --- |
| **oracle ν = ρ, n = 100** | 0.048 | 0.044 | 0.037 | 0.044 | 0.040 |
| **oracle ν = ρ, n = 300** | 0.054 | 0.057 | 0.051 | 0.052 | 0.048 |
| estimated, n = 100 | 0.066 | 0.090 | 0.114 | 0.155 | 0.192 |
| estimated, n = 300 | 0.080 | 0.097 | 0.130 | 0.170 | 0.225 |
| estimated, n = 1000 | 0.082 | 0.093 | 0.129 | 0.170 | 0.217 |
## Expected value
Both halves of the claim reproduce: type-I control (0.044 against a nominal
0.05) with higher power than HRT (+0.113, p = 6.3e-11) in the adjacent-support
setting, and a clear power gain from 5-permutation derandomisation under masked
correlation (+0.240 at n = 50).
## Limitation
- **The paper's exact Figure 5 configuration saturates in my reproduction.** At
n = 300 every method reaches power 1.000, so the derandomisation gain is not
measurable there and I had to lower n to expose it. My SKO implementation is
therefore *more* powerful than the paper's in that setting, not less.
- **The derandomised variant is anti-conservative.** The same 5 permutations that
lift power push the type-I error from 0.059 to 0.094 (n = 50) and from 0.049 to
0.070 (n = 300). The global-null control isolates the cause: with **oracle**
ν = ρ the derandomised test stays exact at every permutation count
(0.048 at 20 permutations, n = 100), so the inflation comes from the
*estimated* ν-hat / ρ-hat. ρ-hat carries one extra predictor (y) fitted on the
same sample, so its residuals are systematically slightly smaller than
ν-hat's; averaging over permutations shrinks the sampling noise by 1/√k but
leaves that bias untouched, and it does not vanish with n (0.129 at n = 1,000
with 5 permutations). Theorem 3.3 covers the single-permutation Algorithm 1/2
and is **not** contradicted - the Rao-Blackwellised variant of Section 5 has no
accompanying theory - but the power comparison should be read with this in
mind.
- The global-null design is adversarial: a flexible learner fitted on pure noise
is maximally sensitive to the imputed coordinate. In the signal-bearing
settings the single-permutation test stays valid (0.044-0.052).
- Only the paper's two settings and two model classes were run; VIM comparators
other than LOCO-Wilcoxon (SCPI, SAGE, dCRT) were not reimplemented.
## Artifacts
- `scripts/c5_power_hrt.py`, `scripts/c5b_derandomization.py`,
`scripts/c5c_derand_validity.py`
- `outputs/claim5_power.json`, `outputs/claim5b_derandomization.json`,
`outputs/claim5c_derand_validity.json`
- `figs/claim5_power.png`, `figs/claim5b_derandomization.png`
- Bundle: <{BUCKET}>
"""
# ------------------------------------------------------------------- claim 6
C6_CLAIM = (
"On the Wisconsin Breast Cancer real dataset, Semi-knockoffs is applied "
"across Random Forest, Neural Network, and Gradient Boosting models to "
"demonstrate model-agnostic feature selection (Figure 6, Section 5.2)."
)
C6 = f"""
> **Claim (verbatim).** {C6_CLAIM}
## Verdict: **verified**
## Independent method
`scripts/c6_wdbc.py`. The Wisconsin Diagnostic Breast Cancer set exactly as
described in Appendix F.6: n = 569 patients, p = 30 numeric features, binary
malignant/benign target, loaded from `sklearn.datasets.load_breast_cancer` and
standardised. Because the true support is unknown, an **artificial null feature
correlated at 0.6 with the original inputs** is appended (a normalised random
combination of the standardised columns plus independent noise); its rejection
frequency over seeds estimates the type-I error, which is precisely the
construction the paper uses to annotate Figure 6.
Per model class - Random Forest, Neural Network, Gradient Boosting - and over 50
seeds: SKO-Wcx (Algorithm 1, no split), SKO-Wcx-p5 (5-permutation
derandomisation), and HRT with a 50/50 split as the split-based comparator, all
at α = 0.05 with the log-loss. The FDR-controlling variant (Algorithm 4 plus the
Eq. (1) threshold) is also run at q ∈ {{0.1, 0.2, 0.3, 0.5}}. Discovery-set
stability across seeds is measured by mean pairwise Jaccard similarity.
## Numerical result
Discoveries among the 30 real features, and the artificial-null rejection rate
(50 seeds, α = 0.05):
| m-hat | method | discoveries | type-I (ours) | type-I (paper Fig. 6) |
| --- | --- | --- | --- | --- |
| Random Forest | **SKO-Wcx** | 2.42 ± 1.25 | **0.08** | **0.08** |
| Random Forest | SKO-Wcx-p5 | 3.40 ± 1.31 | 0.06 | 0.04 |
| Random Forest | HRT (split) | 5.38 ± 2.11 | 0.04 | 0.04 |
| Neural Network | **SKO-Wcx** | 4.72 ± 1.98 | **0.04** | **0.04** |
| Neural Network | SKO-Wcx-p5 | 7.06 ± 1.58 | 0.08 | 0.06 |
| Neural Network | HRT (split) | 3.78 ± 2.43 | 0.06 | 0.22 |
| Gradient Boosting | **SKO-Wcx** | 1.90 ± 1.15 | **0.02** | **0.02** |
| Gradient Boosting | SKO-Wcx-p5 | 2.66 ± 1.44 | 0.06 | 0.00 |
| Gradient Boosting | HRT (split) | 2.06 ± 1.70 | 0.06 | 0.08 |
In-sample accuracy 1.000 for all three learners; held-out accuracy on the split
half 0.955 (RF) / 0.972 (NN) / 0.950 (GB).
Knockoff-threshold variant (Algorithm 4), mean features selected and
artificial-null selection rate:
| m-hat | q = 0.1 | q = 0.2 | q = 0.3 | q = 0.5 |
| --- | --- | --- | --- | --- |
| Random Forest | 0.00 (0.00) | 0.36 (0.00) | 1.50 (0.06) | 6.30 (0.20) |
| Neural Network | 0.00 (0.00) | 0.48 (0.02) | 1.00 (0.06) | 5.74 (0.28) |
| Gradient Boosting | 0.00 (0.00) | 0.14 (0.00) | 0.90 (0.04) | 4.76 (0.14) |
## Expected value
The claim is that the procedure applies across all three model classes and makes
discoveries while controlling the error. That reproduces: SKO-Wcx runs unchanged
on RF, NN and GB, makes 1.9-4.7 discoveries per seed, and its
artificial-null rejection rate is **0.08 / 0.04 / 0.02** - identical to the
values printed beside Figure 6 of the paper. The relative ordering of discovery
counts across model classes (NN > RF > GB) also matches the paper's panel scales.
## Limitation
- The artificial null feature is re-drawn per seed and its exact construction is
not fully specified in the paper (only "correlated at 0.6 with the original
inputs"); I use a normalised random linear combination of the standardised
columns plus independent noise scaled to give correlation 0.6.
- With 50 seeds the type-I estimate has resolution 0.02 and a Monte Carlo s.e. of
about 0.03, so the two-decimal agreement with Figure 6 should not be
over-interpreted.
- **Discovery sets are seed-dependent** (mean pairwise Jaccard 0.06-0.42), so the
paper's stronger statement that Semi-knockoffs shows "consistent numbers of
discoveries, unlike other methods whose results vary significantly with the
random seed" is only partly reproduced: SKO-Wcx-p5 is indeed the most stable
arm (Jaccard 0.21 / 0.42 / 0.11 against HRT's 0.20 / 0.11 / 0.06), but no
feature is rejected in ≥ 80% of seeds by all three model classes.
- The knockoff-threshold variant selects nothing at q = 0.1 with p = 31, because
Eq. (1) needs at least 1/q = 10 discoveries before it can fire - the same
detection floor noted on the claim-2 page.
- The other comparators in Figure 6 (SCPI, SAGE, LOCO-W, dCRT) were not
reimplemented.
## Artifacts
- `scripts/c6_wdbc.py`, `outputs/claim6_wdbc.json`, `figs/claim6_wdbc.png`
- Bundle: <{BUCKET}>
"""
# ------------------------------------------------------------------- conclusion
CONCL_ART = "semiknockoffs-repro/repro-bundle:v0"
CONCL_MD = f"""
## Summary
| Claim | Result | Verdict | Key number |
| --- | --- | --- | --- |
| 1 | Thm 3.3 - valid p-values without a split | **verified** | type-I 0.0445 (oracle) / 0.0525 (estimated, no split) vs 0.953 for HRT without a split |
| 2 | Thm 3.4 - FDR(S_SKO) ≤ q | **verified** | realised FDR 0.075 / 0.175 / 0.287 / 0.486 at q = 0.1 / 0.2 / 0.3 / 0.5, 500 replicates |
| 3 | Thm 4.1 - O_P(√(log(1/δ)/n)) stability | **verified** | fitted exponent -0.60 (predicted -0.50), R² = 0.995 |
| 4 | Thm 4.3 - compound rate O_P(a_n b_n) | **verified** | predicted -1.048 from separately measured a_n, b_n; measured -1.036 |
| 5 | Figs 4-5 - power vs HRT, derandomisation | **verified** | +0.113 power over HRT (p = 6.3e-11) at half the type-I error; +0.240 from 5 permutations at n = 50 |
| 6 | Fig 6 - WDBC across RF / NN / GB | **verified** | artificial-null type-I 0.08 / 0.04 / 0.02, matching Figure 6 exactly |
**What the reproduction adds.** Three things the paper does not report.
(i) Running HRT *without* its split drives the type-I error to 0.953, which turns
the paper's motivation from an assertion into a measurement.
(ii) On a heavy-tailed t(3) elliptical design - where a Gaussian model-X sampler
is mis-specified and reaches 0.130 - Semi-knockoffs stays exact at 0.041, because
its exchangeability argument only needs ρ = ν under the null and never the
additive-innovation assumption.
(iii) The 5-permutation derandomisation of Section 5 buys its power gain with
validity: type-I 0.059 -> 0.094 at n = 50, 0.049 -> 0.070 at n = 300, and up to
0.225 at 20 permutations. A global-null control with oracle ν = ρ stays exact,
so the inflation is an estimation effect - averaging shrinks the noise but not
the ρ-hat-vs-ν-hat bias - and it does not vanish with n.
**Where the reproduction is weakest.** Theorem 4.3's compound rate is recovered
exactly for the differentiable models it assumes, but not quantitatively for tree
ensembles, where the derivative a_n does not exist and a secant surrogate has to
stand in. The paper's own masked-correlation configuration saturates at power
1.000 in my hands, so the derandomisation gain had to be measured at smaller n.
## Download the reproduction bundle
Everything is in the HF bucket
**<{BUCKET}>**:
- `scripts/` - `semiknockoffs.py` (Algorithms 1-4, Eq. (1) threshold, HRT,
closed-form oracle ν/ρ, data generators) plus one script per claim
- `outputs/` - the raw JSON for every experiment, and the run logs
- `figs/` - the six claim figures
- `poster/` - `poster.html`, `poster_preview.pdf/png`, `poster_embed.html`,
`GATE_REPORT.json`
## Rerun
```bash
pip install numpy scipy scikit-learn matplotlib joblib
python scripts/c1_pvalue_validity.py # Claim 1 (~1 min)
python scripts/c2_fdr.py # Claim 2 (~4 min)
python scripts/c3_stability.py # Claim 3 (~9 min)
python scripts/c4_double_robustness.py # Claim 4 (~12 min)
python scripts/c5_power_hrt.py # Claim 5 (~5 min)
python scripts/c5b_derandomization.py # Claim 5, derandomisation sweep
python scripts/c5c_derand_validity.py # Claim 5, global-null validity control
python scripts/c6_wdbc.py # Claim 6 (~9 min)
python scripts/make_figs.py # all figures
```
Every script takes its seeds from the module-level `SEED0 = 20260725` and is
deterministic given the same scikit-learn version. CPU only, $0.
Paper: [arXiv 2601.23124](https://arxiv.org/abs/2601.23124) &middot;
[OpenReview Xf9hJMGwDd](https://openreview.net/forum?id=Xf9hJMGwDd).
Official code exists at
<https://github.com/AngelReyero/loss_based_KO>; it was located but deliberately
neither read nor executed, so this reproduction is independent.
"""
def main():
exec_summary()
for slug, heading, body in [
(
"claim-1-valid-p-values-without-train-test-split-thm-3-3",
"Claim 1: Valid p-values without train-test split (Thm 3.3)",
C1,
),
(
"claim-2-fdr-control-at-level-q-thm-3-4",
"Claim 2: FDR control at level q (Thm 3.4)",
C2,
),
(
"claim-3-optimization-stability-for-null-features-thm-4-1",
"Claim 3: Optimization stability for null features (Thm 4.1)",
C3,
),
(
"claim-4-double-robustness-compound-rate-thm-4-3",
"Claim 4: Double robustness compound rate (Thm 4.3)",
C4,
),
(
"claim-5-power-vs-hrt-and-derandomization-sec-5-1",
"Claim 5: Power vs HRT and derandomization (Sec 5.1)",
C5,
),
(
"claim-6-wisconsin-breast-cancer-model-agnostic-application-sec-5-2",
"Claim 6: Wisconsin Breast Cancer model-agnostic application (Sec 5.2)",
C6,
),
]:
write(slug, heading, cell({"type": "markdown", "title": heading}, body))
txt = cell(
{
"type": "artifact",
"title": "Reproduction bundle",
"artifact_type": "dataset",
},
CONCL_ART,
)
txt += cell({"type": "markdown", "title": "Download & rerun"}, CONCL_MD)
write("conclusion", "Conclusion", txt)
if __name__ == "__main__":
main()

Xet Storage Details

Size:
38.9 kB
·
Xet hash:
bab87aa98e010d830fd38666b56a1f89bf16f24dda008c407335843d1d7c2345

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.