pre-refactor 041426

This commit is contained in:
rpotter6298
2026-04-14 19:42:16 +02:00
parent eb9eafe715
commit 13290575d5
75 changed files with 8900 additions and 77 deletions
+59
View File
@@ -83,6 +83,65 @@ def build_patient_split_plans(
return plans
class EyeLevelSplitManager:
"""
Eye-level (leaky) splitter — splits on individual eye rows, ignoring
patient grouping. Same patient's eyes can appear in different folds.
Used to demonstrate the effect of data leakage.
"""
def __init__(
self,
*,
patient_col: str = "Patient ID",
label_col: Optional[str] = None,
) -> None:
self.patient_col = patient_col
self.label_col = label_col
def build_plans(
self,
*,
clinical: Any,
args: Any,
profile: Optional[Any] = None,
) -> list[PatientSplit]:
profile_label_col = getattr(profile, "label_col", None) if profile is not None else None
label_col = self.label_col or profile_label_col or getattr(clinical, "label_col", None)
if label_col is None:
raise ValueError("Could not resolve label column")
if not hasattr(clinical, "df"):
raise ValueError("Clinical object must expose a dataframe at .df")
df_full = clinical.df.copy().reset_index(drop=True)
eval_mode = str(getattr(args, "eval_mode", "multiclass")).lower()
if eval_mode == "binary":
df_full = df_full[df_full[label_col].isin([0, 1])].reset_index(drop=True)
n_splits = int(getattr(args, "n_splits", 5))
fold_seed = int(getattr(args, "fold_seed", 42))
labels = df_full[label_col].to_numpy()
eye_ids = df_full.index.to_numpy()
# Reuse build_patient_split_plans with eye-row IDs as the "patients"
plans = build_patient_split_plans(
patient_ids=eye_ids,
patient_labels=labels,
n_splits=n_splits,
seed=fold_seed,
)
out: list[PatientSplit] = []
for plan in plans:
train_df = df_full[df_full.index.isin(plan.train_patient_ids)].reset_index(drop=True)
val_df = df_full[df_full.index.isin(plan.val_patient_ids)].reset_index(drop=True)
test_df = df_full[df_full.index.isin(plan.test_patient_ids)].reset_index(drop=True)
out.append(PatientSplit(train=train_df, val=val_df, test=test_df))
return out
class PatientFirstSplitManager:
"""Patient-level splitter for V3. Outer/inner k-fold, no holdout."""