Skip to content

Run sklearn baselines on the GNN features and folds with one global configuration - #143

Open
cornelislouisa wants to merge 1 commit into
louisa/kfold-b-five-fold-defaultfrom
louisa/kfold-c-baselines
Open

cornelislouisa wants to merge 1 commit into
louisa/kfold-b-five-fold-defaultfrom
louisa/kfold-c-baselines

Conversation

@cornelislouisa

Copy link
Copy Markdown
Collaborator

Third of five stacked PRs bringing the k-fold work from guille/kfold_relaunch (the code behind the October k-fold results) into main. Targets #142. Draft until the whole stack passes a reproducibility check against kfold_relaunch. Supersedes #137.

Why

The baselines should answer one question: how much does the graph add over a classifier on the same input? On main they did not see the same input or the same protocol as the GNNs:

  • Different features. Standard baselines ran their own SelectKBest on the full matrix instead of the GNN node selection, and method=random could pick different genes from the GNN cache.
  • Different hyperparameter protocol. Each fold ran its own grid search, while every GNN Optuna trial uses one configuration for all five folds.
  • Stale description. The README described "GNN-learned embeddings", which the code never used.

Changes

ogbench/baseline.py (from kfold_relaunch)

  • load_and_prepare_data (standard baselines svm, elastic_net) rebuilds the GNN input from the pinned Hub revision: the same split and fold via compute_omics_split_indices and resolve_split_groups (so grouped datasets get grouped folds), the same train-only corrections (covariate adjustment, ComBat, promoter probe pick, median centering), imputation, and the same node selection. method=random uses selection_seed, so it picks exactly the GNN cache's genes. No graph is built.
  • load_and_prepare_data_gnn_features (svm_gnn_features, elastic_net_gnn_features) reads the GNN cache (selected_data.parquet, split_info.json).
  • Global k-fold selection. With split_type=k-fold, every grid configuration is scored on the validation fold of all k folds and the best mean is kept (baseline_hparam_selection: global_kfold_mean_validation; any other value raises). The choice is cached as JSON under baseline_hparam_cache_dir with a file lock, so the other folds reuse it. Each fold is then refit on its training split and evaluated on its test fold. Fixed splits score the grid on their single train/validation cut.
  • Baselines log to cfg.logger.wandb.entity, the same setting GNN runs use.

Configs

  • configs/baseline.yaml: baseline_hparam_selection and baseline_hparam_cache_dir.
  • configs/logger/wandb.yaml: entity: null # optional W&B team or organization replaces the commented-out key. With null, W&B logs to the user's own account as before.
  • configs/dataset/*.yaml: remove SelectKBest and feature_selection__k from the baseline grids, since the features are now the GNN node selection.

Scripts

  • run_baselines.sh runs the standard baselines over all six datasets, folds 0 to 4, ratios 1.0/0.8/0.5/0.3 and all four selection methods. DATASETS, FOLDS, NODE_RATIOS, METHODS and PYTHON can narrow it from the environment, and extra arguments pass through as Hydra overrides.
  • scripts/verify_baseline_features.py checks that the standard baselines select exactly the features stored in every cached GNN fold. Two fixes over kfold_relaunch: its path pattern matches the cache layout from Make leak-free 5-fold cross-validation the default for omics datasets #142 (hf_<revision>/.../impute_<method>/), which it previously did not match at all, and it now exits with an error when it finds no cached folds instead of reporting 0/0 as success.

Docs

  • README section renamed to "Sklearn Baselines", describing both baseline families, the global selection, the cache requirement for gnn_features, and the run_baselines.sh environment variables.

Differences from #137

#137 introduced global selection; this PR is the later version from kfold_relaunch:

  • grouped folds through resolve_split_groups, so Parkinson's (and tuberculosis in the next PR) baselines use the same grouped folds as the GNNs
  • seeded random selection shared with the GNN cache
  • the historical per_fold mode is removed; k-fold always uses global selection, fixed splits use their single validation cut
  • W&B entity support and the extended run_baselines.sh

Tests

test_baseline_global_hparams.py (selection, caching, rejection of other modes), test_no_preprocessing_leakage.py (corrections, imputation and selection only see training samples), test_composed_config_parity.py (GNN and baseline configs compose to the same data settings).

Checks

  • pytest -m "not slow": 272 passed; pre-commit clean
  • DATASETS=motrpac FOLDS=0,1 NODE_RATIOS=0.5 METHODS=random bash run_baselines.sh: the global selection is computed once and reused by the second fold
  • Fixed-split standard baselines on MotrPAC run
  • After a 5-fold GNN multirun with method=random, the gnn_features baselines run, and verify_baseline_features.py reports 5/5 folds identical to the GNN cache
  • Without all folds cached, gnn_features fails with a clear "run the GNN pipeline first" error

…onfiguration

- Standard baselines rebuild the GNN input from the Hub data: the same split
  and fold (including grouped folds), train-only corrections and imputation,
  and the same node selection, with seeded random selection
- K-fold runs score every grid configuration on all validation folds, keep the
  best mean, cache that choice, and refit each fold on its training split
- Remove SelectKBest from the dataset baseline grids; features are the GNN
  node selection
- Baselines log to logger.wandb.entity, now an explicit optional setting
- run_baselines.sh covers all six datasets, five folds and ratios down to 0.3,
  reads its axes from the environment and passes extra Hydra overrides
- verify_baseline_features.py checks the baseline features against every
  cached GNN fold and fails when it finds none

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants