From f4ed9ba1ba178856bcf026bea0abd894e261f79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20C=C3=ADfka?= <550433@mail.muni.cz> Date: Thu, 8 Oct 2026 18:23:50 +0200 Subject: [PATCH] chore: default to stratified_group kfold everywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Point both kfold run ids at the splits recomputed over the corrected filter_tiles output (#20). The kfold convention was inconsistent: the base tasks defaulted to plain stratified, while train_*_group_kfold and final_linear_provgigapath_* overrode to stratified_group. final_linear_virchow2_* overrode nothing, so it read stratified_kfold_run_id while its probe used the group split. That mismatch did not change the final training data — final_embedding_tiles sets neither include_folds nor exclude_folds, so the final fit uses every row of kfold_tiles.parquet and ignores the fold column, and both artifacts hold the same tile set. It mattered because the two run ids have to be kept current independently: the stratified one still pointed at a split built over the pre-fix filter_tiles, so the final virchow2 fit would have trained on the old tile set, missing the 30% of annotated tiles the scale bug dropped. The run also recorded a kfold run id its probe never used. Make stratified_group the default in both base tasks and drop the now redundant per-experiment overrides, so one run id drives every experiment. All nine ml experiments resolve to the same kfold run id, verified by composing each config. Plain stratified folds remain available by overriding kfold_strategy and kfold_run_id together. Co-Authored-By: Claude Opus 5 --- configs/data/dataset.yaml | 4 ++-- .../experiment/ml/final_linear_provgigapath_adamw.yaml | 2 -- .../experiment/ml/final_linear_provgigapath_lbfgs.yaml | 2 -- .../ml/train_linear_virchow2_adamw_group_kfold.yaml | 3 --- configs/ml/task/final_linear_classifier.yaml | 8 ++++++-- configs/ml/task/kfold_linear_classifier.yaml | 8 ++++++-- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/configs/data/dataset.yaml b/configs/data/dataset.yaml index 7299c1d3..1f2e0cd8 100644 --- a/configs/data/dataset.yaml +++ b/configs/data/dataset.yaml @@ -14,8 +14,8 @@ dataset: test_split_filename: "split_mapping/test_split.csv" tiling_run_id: "fdf7550a2004474f8c7a05dc0cf1fd86" filter_tiles_run_id: "9a844082b48d47bfa5d3e7a37d7de268" - stratified_kfold_run_id: "850c81506684450b9af92296acfd045a" - stratified_group_kfold_run_id: "382b41d2fa894514908e8067949c4326" + stratified_kfold_run_id: "e2132cd681e04892b2bfe837a7295b55" + stratified_group_kfold_run_id: "9c2618576b89453893788a7401fef393" embedding_run_ids: virchow2: "262d680f52374614baaf19f1e4d05940" provgigapath: "5099ce57e886411dababfc1234a88b23" diff --git a/configs/experiment/ml/final_linear_provgigapath_adamw.yaml b/configs/experiment/ml/final_linear_provgigapath_adamw.yaml index fb54dc66..6319e25b 100644 --- a/configs/experiment/ml/final_linear_provgigapath_adamw.yaml +++ b/configs/experiment/ml/final_linear_provgigapath_adamw.yaml @@ -7,8 +7,6 @@ defaults: embedding_model_name: ProvGigaPath embedding_dim: 1536 embedding_run_id: ${dataset.mlflow_artifacts.embedding_run_ids.provgigapath} -kfold_strategy: stratified_group -kfold_run_id: ${dataset.mlflow_artifacts.stratified_group_kfold_run_id} mlflow_artifact_path: linear_classifier_final_provgigapath # Set after Stage 1 from ProvGigaPath's own AdamW sweep selected by diff --git a/configs/experiment/ml/final_linear_provgigapath_lbfgs.yaml b/configs/experiment/ml/final_linear_provgigapath_lbfgs.yaml index 85c81719..8481053b 100644 --- a/configs/experiment/ml/final_linear_provgigapath_lbfgs.yaml +++ b/configs/experiment/ml/final_linear_provgigapath_lbfgs.yaml @@ -7,8 +7,6 @@ defaults: embedding_model_name: ProvGigaPath embedding_dim: 1536 embedding_run_id: ${dataset.mlflow_artifacts.embedding_run_ids.provgigapath} -kfold_strategy: stratified_group -kfold_run_id: ${dataset.mlflow_artifacts.stratified_group_kfold_run_id} mlflow_artifact_path: linear_classifier_final_provgigapath # Set after Stage 1 from ProvGigaPath's own LBFGS sweep selected by diff --git a/configs/experiment/ml/train_linear_virchow2_adamw_group_kfold.yaml b/configs/experiment/ml/train_linear_virchow2_adamw_group_kfold.yaml index 86f56479..8f342d0e 100644 --- a/configs/experiment/ml/train_linear_virchow2_adamw_group_kfold.yaml +++ b/configs/experiment/ml/train_linear_virchow2_adamw_group_kfold.yaml @@ -4,9 +4,6 @@ defaults: - /ml/task: kfold_linear_classifier - _self_ -kfold_strategy: stratified_group -kfold_run_id: ${dataset.mlflow_artifacts.stratified_group_kfold_run_id} - model: optimizer: adamw learning_rate: 1.0e-4 diff --git a/configs/ml/task/final_linear_classifier.yaml b/configs/ml/task/final_linear_classifier.yaml index a33638e0..be6189fd 100644 --- a/configs/ml/task/final_linear_classifier.yaml +++ b/configs/ml/task/final_linear_classifier.yaml @@ -13,8 +13,12 @@ mode: fit embedding_model_name: Virchow2 embedding_dim: 2560 embedding_run_id: ${dataset.mlflow_artifacts.embedding_run_ids.virchow2} -kfold_strategy: stratified -kfold_run_id: ${dataset.mlflow_artifacts.stratified_kfold_run_id} +# stratified_group is the default: plain stratified splits tiles from one slide +# across folds, so validation scores are inflated by slide-level leakage. The two +# fields must stay in sync — kfold_strategy only labels the run, kfold_run_id picks +# the data. To use plain stratified folds, override both. +kfold_strategy: stratified_group +kfold_run_id: ${dataset.mlflow_artifacts.stratified_group_kfold_run_id} filter_tiles_run_id: ${dataset.mlflow_artifacts.filter_tiles_run_id} train_embedding_uri: runs:/${embedding_run_id}/train/tiles diff --git a/configs/ml/task/kfold_linear_classifier.yaml b/configs/ml/task/kfold_linear_classifier.yaml index dd0a05d0..06166be0 100644 --- a/configs/ml/task/kfold_linear_classifier.yaml +++ b/configs/ml/task/kfold_linear_classifier.yaml @@ -13,8 +13,12 @@ mode: fit embedding_model_name: Virchow2 embedding_dim: 2560 embedding_run_id: ${dataset.mlflow_artifacts.embedding_run_ids.virchow2} -kfold_strategy: stratified -kfold_run_id: ${dataset.mlflow_artifacts.stratified_kfold_run_id} +# stratified_group is the default: plain stratified splits tiles from one slide +# across folds, so validation scores are inflated by slide-level leakage. The two +# fields must stay in sync — kfold_strategy only labels the run, kfold_run_id picks +# the data. To use plain stratified folds, override both. +kfold_strategy: stratified_group +kfold_run_id: ${dataset.mlflow_artifacts.stratified_group_kfold_run_id} filter_tiles_run_id: ${dataset.mlflow_artifacts.filter_tiles_run_id} train_embedding_uri: runs:/${embedding_run_id}/train/tiles