Spaces:
Sleeping
Sleeping
File size: 2,001 Bytes
0fff343 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | """Permutation null distribution via the fast baseline procedure.
Shuffles the TRAIN labels (via the objective's ``permute``), re-runs the
prefilter on the shuffled labels, fits the baseline (top-K) on
shuffled-label TRAIN, and scores it against the TRUE TEST labels with
the same objective. p = fraction of nulls whose score is at least the
observed value — "could a separation this strong arise by chance?".
The matrix is ranked once and reused for every permutation, so the loop
is fast even at n=200 over ~20k features.
"""
from __future__ import annotations
import numpy as np
import pandas as pd
from engine.baseline import BASELINE_K
from engine.objectives import BinaryAUROCObjective, Objective
from engine.prefilter import precompute_ranks
def permutation_null(
M_train: pd.DataFrame,
y_train: np.ndarray,
M_test: pd.DataFrame,
y_test: np.ndarray,
*,
objective: Objective | None = None,
n_permutations: int = 200,
seed: int = 0,
k: int = BASELINE_K,
) -> list[float]:
obj = objective or BinaryAUROCObjective()
rng = np.random.default_rng(seed)
ranks = precompute_ranks(M_train)
cols = list(M_train.columns)
null_scores: list[float] = []
for _ in range(n_permutations):
y_shuf = obj.permute(y_train, rng)
per_feature = obj.prefilter_score_per_feature(ranks, y_shuf)
scores = pd.Series(per_feature, index=cols)
top_k = scores.nlargest(k).index.tolist()
states_tr = M_train[top_k].mean(axis=1).values.reshape(-1, 1)
states_te = M_test[top_k].mean(axis=1).values.reshape(-1, 1)
null_scores.append(
float(obj.holdout_score(states_tr, y_shuf, states_te, y_test))
)
return null_scores
def permutation_p_value(observed: float, null_dist: list[float]) -> float:
"""Fraction of nulls >= observed, with a +1 / +1 add-one correction."""
null_arr = np.asarray(null_dist)
return float(((null_arr >= observed).sum() + 1) / (len(null_arr) + 1))
|