Winning Kaggle the Reproducible Way

Interactive chapter

This page shows the chapter notebook with its saved results. Constructed examples do not measure competition gains.

Chapter 47: Medical Imaging Patterns

Try the decision first

How far does image-level cross-validation overstate the score on new patients, and does grouping by patient remove the error?

Write your expectation before opening the worked results. Use the chapter activity to compare supported inputs. To change the calculation itself, run the notebook on GitHub.

Your answers stay on this page until you download them. They are not sent to a server.

Open the chapter activity

Worked notebook and saved results

How far does image-level cross-validation overstate the score on new patients, and does grouping by patient remove the error?

Several images, slides or tiles usually share one patient. The chapter's rule is to keep each patient in one validation fold; the size of the error it prevents depends on how many images each patient contributes, which this demonstration varies.

Constructed data with patient-level labels; the sizes of these effects are properties of this generator, not a competition result.

The experiment

Constructed cohorts of 150 patients with a patient-level label (half positive). Each image has 12 features: the patient's own anatomy (shared by all of their images and larger than the within-patient noise), a weak disease signal on three features, and image noise. An extremely randomized trees classifier is scored by out-of-fold AUC pooled over five folds, split two ways: ordinary shuffled folds that treat each image alone, and GroupKFold by patient. Both are compared with the same model's AUC on 600 fresh patients, averaged over 8 cohorts. The control is the number of images per patient.

Calculation code
import numpy as np
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import GroupKFold, KFold

from kaggle_companion.activities._common import clean

SEED = 47
DRAWS = 8            # independent cohorts; every estimate is a mean over draws
PATIENTS = 150       # development patients; 600 further patients form the fresh test cohort
FRESH = 600
DIM = 12             # image features


def generate(n_patients, images_each, rng):
    """Patient-level label. Each image = the patient's own anatomy (shared by all their images) + a weak disease signal + image noise."""
    label = (rng.random(n_patients) < 0.5).astype(int)
    anatomy = 1.5 * rng.normal(size=(n_patients, DIM))
    patient = np.repeat(np.arange(n_patients), images_each)
    y = label[patient]
    X = anatomy[patient] + 0.8 * rng.normal(size=(len(patient), DIM))
    X[:, :3] += 0.5 * (2 * y[:, None] - 1)
    return X, y, patient


def model(seed=0):
    return ExtraTreesClassifier(n_estimators=40, max_features=0.5, random_state=seed, n_jobs=1)


def pooled_auc(X, y, splits):
    """Out-of-fold probabilities pooled over all folds, then one AUC."""
    oof = np.zeros(len(y))
    for fit, hold in splits:
        oof[hold] = model().fit(X[fit], y[fit]).predict_proba(X[hold])[:, 1]
    return roc_auc_score(y, oof)


def run(images_per_patient):
    rng = np.random.default_rng(SEED)
    X_new, y_new, _ = generate(FRESH, images_per_patient, rng)       # fresh patients: the truth the CV should predict
    rows = {k: [] for k in ("kfold", "grouped", "fresh", "overlap_kfold", "overlap_grouped")}
    for draw in range(DRAWS):
        X, y, patient = generate(PATIENTS, images_per_patient, rng)
        kfold = list(KFold(5, shuffle=True, random_state=draw).split(X))              # each image on its own
        grouped = list(GroupKFold(5).split(X, y, patient))                              # whole patients together
        rows["kfold"].append(pooled_auc(X, y, kfold))
        rows["grouped"].append(pooled_auc(X, y, grouped))
        rows["fresh"].append(roc_auc_score(y_new, model().fit(X, y).predict_proba(X_new)[:, 1]))
        # The chapter's check: do validation patients also appear in training? (share of validation images)
        rows["overlap_kfold"].append(np.mean([np.isin(patient[b], patient[a]).mean() for a, b in kfold]))
        rows["overlap_grouped"].append(np.mean([np.isin(patient[b], patient[a]).mean() for a, b in grouped]))
    mean = {k: float(np.mean(v)) for k, v in rows.items()}
    return clean({
        "images_per_patient": images_per_patient, **mean,
        "kfold_error": mean["kfold"] - mean["fresh"], "grouped_error": mean["grouped"] - mean["fresh"],
        "per_draw": {k: rows[k] for k in ("kfold", "grouped", "fresh")},
        "patients": PATIENTS, "images": PATIENTS * images_per_patient, "fresh_patients": FRESH, "draws": DRAWS,
    })

Measure it across the control

The control is images per patient. Each value below runs the whole experiment from the generator up.

Calculation code
import pandas as pd
from kaggle_companion.activities.ch47 import explain

VALUES = [1, 2, 4, 8]
results = {value: run(value) for value in VALUES}
table = pd.DataFrame({str(v): explain(results[v], v)['metrics'] for v in VALUES})
print(table.to_string())
                                                 1       2       4       8
Image-level 5-fold AUC                       0.700   0.791   0.874   0.924
Grouped AUC                                  0.701   0.683   0.674   0.667
AUC on fresh patients                        0.716   0.689   0.707   0.706
Image-level error                           -0.016  +0.101  +0.167  +0.218
Grouped error                               -0.015  -0.006  -0.033  -0.039
Patients shared across folds (image-level)    0.0%   81.4%   98.8%  100.0%

Look at it

The figure shows the default setting, images per patient = 4.

Calculation code
import matplotlib.pyplot as plt
from kaggle_companion.activities.ch47 import draw, NCOLS, HEIGHT

DEFAULT = 4
fig, axes = plt.subplots(1, NCOLS, figsize=(6.6 if NCOLS == 1 else 10.4, HEIGHT), layout='constrained')
draw(axes, results[DEFAULT], DEFAULT)
plt.show()
Saved figure from this chapter calculation

What the result says

With 4 images per patient the same model scores AUC 0.707 on fresh patients. Image-level folds report 0.874: 0.874 - 0.707 = 0.167 (their error). Grouped folds report 0.674, which is -0.033 from the fresh score. 98.8% of image-level validation images belong to a patient that is also in training, against 0.0% when grouped. The image-level number measures how well the model recognises patients it has already seen.

Apply this to your competition

Book location: Chapter 47, Keep all images from each patient in one validation fold.

Technical corrections

Apply a lesson from this chapter

Select a lesson whose conditions match your project. State how you would test it and what would make you reject it.

Measure resolution and ensemble returns on medical images

Conditions

  • small medical features suggest expensive higher-resolution or multi-view inference

Action

  • Proposed conditional application: Check whether resolution beyond radius 270 and multi-view/multi-network ensembles improve enough to justify cost.

Check

  • Proposed check: Sweep resolution and separately ensemble size on patient holdouts; plot metric versus training/inference cost.

Limits

  • 270 is a historical setup result, not universal sufficient resolution; subtle pathology may require higher detail.

Find source links and value grades in the lesson atlas

Compare breast-to-patient aggregation before final ensembling

Conditions

  • breast-level mammography probabilities require a patient-level score
  • one patient outcome is predicted from multiple breast-level scores

Action

  • Proposed conditional application: Compare mean and maximum breast probabilities when computing patient-level scores within the same ensemble.
  • Proposed adaptation of source observation: Compare mean and maximum aggregation on patient-level predictions.

Check

  • Proposed check: Compare mean and maximum breast-to-patient aggregation with a fixed ensemble and patient-grouped validation, including unilateral and bilateral cases.
  • Proposed verification: Use identical breast predictions and patient labels for the paired AUC comparison.

Limits

  • Public AUC comparison may reflect leaderboard tuning; the maximum rule may overreact to a noisy breast score.
  • This is a source-reported comparison; the aggregation rule should match the target outcome and is not a universal medical rule.

Find source links and value grades in the lesson atlas

Keep a simplified detector pipeline as a cost benchmark

Conditions

  • a large medical detection ensemble has substantial setup cost

Action

  • Proposed conditional application: Compare the full ensemble with the supplied one-classifier plus five-relation-network variant.

Check

  • Proposed check: Reproduce small and full pipelines on the same validation, then compare detection quality, model loading, latency and memory.

Limits

  • Smaller model count suggests a cost experiment but no measured cost saving is provided; setup still includes several detectors.

Find source links and value grades in the lesson atlas

Limit degrees of freedom in leaderboard experiments

Conditions

  • competition feedback is noisy and repeated submissions are limited

Action

  • Proposed adaptation of source observation: Evaluate seed pairs and use coarse hyperparameter changes; proposed adaptation also maintains independent validation.

Check

  • Proposed verification: Estimate seed variance and track the number of feedback-driven decisions.

Limits

  • Public-only selection can still overfit; coarse search does not guarantee reliability.

Find source links and value grades in the lesson atlas

Aggregate detected lesions while accounting for missed lesions

Conditions

  • case-level cancer prediction depends on multiple detected nodules

Action

  • Proposed conditional application: Extract features from detector proposals and combine lesion probabilities with a learned dummy-nodule probability for missed disease.

Check

  • Proposed check: Ablate dummy term on patient-held-out log loss/calibration, stratified by detection misses.

Limits

  • Noisy-or dependence assumptions and missed-lesion interpretation need validation; full training reported 8 GPUs over days.
  • Competition cancer prediction does not establish clinical utility.

Find source links and value grades in the lesson atlas

Combine paired anatomical predictions in a second stage

Conditions

  • two eyes belong to the same case and are available together at inference

Action

  • Proposed conditional application: Fit a second-stage Random Forest using predictions from both eyes before mapping to integer labels.

Check

  • Proposed check: Train the RF on out-of-fold paired-eye predictions, group folds by patient, and test one-eye missingness and ordinal-label mapping.

Limits

  • Both eyes must be available together; patient overlap and in-sample base predictions would bias stacking evaluation.

Find source links and value grades in the lesson atlas

Budget the diagnostic model before label-cleaning retraining

Conditions

  • an out-of-fold noise audit requires its own model training

Action

  • Proposed adaptation of source observation: Include the diagnostic folds and prediction pass in the compute budget before committing to a label-cleaning pipeline.

Check

  • Proposed verification: Measure one complete fold and estimate total audit plus retraining wall time.

Limits

  • These timings are author estimates on a stated setup and do not transfer directly to other hardware.

Find source links and value grades in the lesson atlas

Audit image-hash duplicate groups before assigning folds

Conditions

  • histology slides may include visually duplicated images

Action

  • Proposed adaptation of source observation: Inspect image-hash groups before constructing fixed folds and keep confirmed duplicates together.

Check

  • Proposed verification: Verify group disjointness across folds and inspect threshold-boundary pairs manually.

Limits

  • The README does not establish that its grouping is actually enforced by its split script; grouping enforcement is a proposed check.

Find source links and value grades in the lesson atlas

Keep all images from each patient in one validation fold

Conditions

  • Microscopy tiles share patient origin.
  • multiple medical images belong to one patient

Action

  • Assign all slides and tiles from a patient to one validation fold.
  • Proposed adaptation of source observation: Keep all images of each patient in one validation fold.

Check

  • Audit patient disjointness, slide ancestry and held-out segmentation quality.
  • Proposed verification: Assert that patient IDs never overlap between training and validation.

Limits

  • Patient grouping requires accurate provenance and enough independent patients.
  • Balanced mask-area sampling is a separate training decision that alters prevalence.
  • The source reports the split choice without comparing against an image-level split.

Find source links and value grades in the lesson atlas

Harmonize external ordinal labels before pseudo-label training

Conditions

  • external image datasets use different ordinal grading conventions

Action

  • Proposed adaptation of source observation: Keep external label sources distinct; evaluate smoothing labels with stage-one predictions and group-based label harmonization before retraining.

Check

  • Proposed verification: Use trusted held-out grades to check calibration and the incremental contribution of each external source.

Limits

  • Model-based relabeling can reinforce bias; threshold changes and added data occur together, so no isolated gain is established.

Find source links and value grades in the lesson atlas

Treat cross-year validation disagreement as unresolved evidence

Conditions

  • historical and current image datasets give conflicting validation feedback

Action

  • Proposed adaptation of source observation: Proposed: diagnose cross-year distribution and labeling differences before abandoning an independent holdout.

Check

  • Proposed verification: Compare year-held-out and within-year splits, documenting leaderboard disagreement.

Limits

  • The source actually used public-only validation; this is a proposed safer adaptation, not their validated solution.

Find source links and value grades in the lesson atlas

Treat auxiliary-task CV gains as provisional

Conditions

  • an age or other auxiliary task appears helpful in cross-validation

Action

  • Proposed adaptation of source observation: Require an independent target-task check before retaining an auxiliary loss.

Check

  • Proposed verification: Compare matched target-task models and test whether auxiliary labels induce shortcut learning.

Limits

  • Overfitting is the author’s hypothesis; the excerpt supplies no controlled diagnosis.

Find source links and value grades in the lesson atlas

Keep a credible local small-data baseline despite weak public score

Conditions

  • public evaluation is noisy for a small MRI dataset

Action

  • Proposed conditional application: Retain a simple Gaussian-process classifier supported by leave-one-out validation rather than discarding it solely for weak public score.

Check

  • Proposed check: Audit subject independence and preprocessing within LOOCV, compare simple baselines, and quantify uncertainty before reacting to public scores.

Limits

  • LOOCV score and kernel are absent; a later private success is not proof the local protocol was unbiased.

Find source links and value grades in the lesson atlas

Preserve a raw-image branch when cropping mammograms

Conditions

  • large medical images include substantial non-breast background

Action

  • Proposed adaptation of source observation: Retain raw conversions and a separately indexed cropped-resized branch for controlled preprocessing comparison.

Check

  • Proposed verification: Inspect border lesions and verify identical image IDs and intensity handling across branches.

Limits

  • Cropping quality and a raw-versus-cropped ablation are not reported.

Find source links and value grades in the lesson atlas

Normalize retinal scale and lighting

Conditions

  • retinal photographs vary in scale and lighting

Action

  • Proposed conditional application: Scale retinal photographs to a common radius and subtract local average color before fitting the image model.

Check

  • Proposed check: Ablate scale and color correction on patient-held-out grading metrics; inspect lesion visibility and acquisition subgroups.

Limits

  • Normalization can erase subtle lesions; no clinical benefit or isolated numerical gain established.

Find source links and value grades in the lesson atlas

Aggregate informative slide tiles with attention

Conditions

  • slide labels supervise a selected subset of histology tiles

Action

  • Proposed conditional application: Select sixteen darkest tiles and train slide-level attention pooling instead of average pooling.

Check

  • Proposed check: Compare average and attention pooling on identical patient-grouped folds and tile sets; measure tile selection sensitivity and inference cost.

Limits

  • More tiles and stain normalization failed in this source; the reported comparison is author evidence on small-data folds.

Find source links and value grades in the lesson atlas

Assess fold dispersion when selecting small-data medical models

Conditions

  • a small public leaderboard cannot distinguish tiny gains

Action

  • Proposed conditional application: Use patient-grouped stratified folds and track both mean score and fold deviation; compare self-supervised pretraining by stability.

Check

  • Proposed check: Repeat pretraining comparisons on fixed patient-grouped folds and seeds; report mean, dispersion and uncertainty rather than only the best fold.

Limits

  • Fold deviation from five folds is imprecise and does not guarantee unseen-patient stability; pretraining adds cost.

Find source links and value grades in the lesson atlas