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 3: Building a CV That Matches the Test Set

Try the decision first

When the relationship between features and outcomes changes from season to season, how far does each validation scheme's Brier score sit from the score on the next season?

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

When the relationship between features and outcomes changes from season to season, how far does each validation scheme's Brier score sit from the score on the next season?

Leave-one-season-out is a respectable group assessment, but its training set contains seasons from after the held-out one. For a competition that forecasts a future season, the estimate you use to choose models then describes a different question from the one the leaderboard asks.

Constructed data with a random-walk relationship; the sizes are properties of this generator, not a competition result. Past-only is closer to the next season, not exact.

The experiment

A constructed league of 8 seasons with 400 games each and 4 features. A logistic model gives win odds from season-specific weights; the weights take a random step from one season to the next, and the size of the step is the control (0 means no drift). Seasons 1 to 7 are development. Both schemes score seasons 5 to 7 (1,200 games, pooled into one Brier score): leave-one-season-out trains on the other six development seasons, past-only trains on earlier seasons only. The reference is the final recipe, fitted on all seven development seasons, scored on 4,000 fresh games of season 8. Every number is the mean of 100 independent histories.

Calculation code
import numpy as np
from sklearn.linear_model import LogisticRegression

from kaggle_companion.activities._common import clean

SEED = 3
REPLICATES = 100      # independent constructed histories; every estimate is their mean
SEASONS, GAMES, FEATURES = 8, 400, 4
FIRST_SCORED = 4      # score seasons 5, 6 and 7 (0-based 4, 5, 6); season 8 is the future
FUTURE_GAMES = 4000


def generate(drift, seed):
    """Seven development seasons and a large season 8. The weights that turn features into win odds
    wander from season to season; `drift` is the size of the wander (their length stays constant)."""
    rng = np.random.default_rng(seed)
    weights = np.zeros((SEASONS, FEATURES))
    weights[0] = rng.normal(0, 1.0, FEATURES)
    for s in range(1, SEASONS):
        step = weights[s - 1] + rng.normal(0, drift, FEATURES)
        weights[s] = step * np.linalg.norm(weights[0]) / np.linalg.norm(step)

    def games(s, n):
        x = rng.normal(size=(n, FEATURES))
        win = rng.random(n) < 1 / (1 + np.exp(-x @ weights[s]))
        return x, win.astype(int)

    dev = [games(s, GAMES) for s in range(SEASONS - 1)]
    return dev, games(SEASONS - 1, FUTURE_GAMES)


def fit(seasons):
    X = np.vstack([s[0] for s in seasons])
    y = np.concatenate([s[1] for s in seasons])
    return LogisticRegression(max_iter=500).fit(X, y)


def brier(y, p):
    return float(np.mean((y - p) ** 2))


def one_history(drift, seed):
    dev, (X_next, y_next) = generate(drift, seed)
    held, loso, past = [], [], []
    for s in range(FIRST_SCORED, SEASONS - 1):
        X, y = dev[s]
        held.append(y)
        # Leave-one-season-out: train on every other development season, later ones included.
        loso.append(fit([d for k, d in enumerate(dev) if k != s]).predict_proba(X)[:, 1])
        # Past-only: train on the seasons before s, as a real forecast would.
        past.append(fit(dev[:s]).predict_proba(X)[:, 1])
    y = np.concatenate(held)
    # Truth: the final recipe (all seven development seasons) on the next season, 4,000 fresh games.
    truth = brier(y_next, fit(dev).predict_proba(X_next)[:, 1])
    return brier(y, np.concatenate(loso)), brier(y, np.concatenate(past)), truth


def run(drift):
    runs = np.array([one_history(drift, SEED * 1000 + i) for i in range(REPLICATES)])
    loso, past, truth = runs.T
    return clean({
        "drift": drift,
        "loso": float(loso.mean()), "past_only": float(past.mean()), "next_season": float(truth.mean()),
        # optimism = Brier on the next season minus the estimate (positive: the estimate looked better than reality)
        "optimism": {"loso": float((truth - loso).mean()), "past_only": float((truth - past).mean())},
        "per_history": {"loso": (truth - loso).tolist(), "past_only": (truth - past).tolist()},
        "loso_more_optimistic": float(np.mean((truth - loso) > (truth - past))),
        "replicates": REPLICATES, "scored_games": GAMES * (SEASONS - 1 - FIRST_SCORED), "future_games": FUTURE_GAMES,
    })

Measure it across the control

The control is season-to-season drift (standard deviation of the weight step). Each value below runs the whole experiment from the generator up.

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

VALUES = [0, 0.25, 0.5, 1.0]
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())
                                    0   0.25    0.5    1.0
Leave-one-season-out Brier      0.159  0.167  0.184  0.217
Past-only Brier                 0.159  0.170  0.190  0.229
Next-season Brier               0.159  0.173  0.196  0.235
Optimism, leave-one-season-out  0.000  0.006  0.012  0.017
Optimism, past-only             0.000  0.003  0.006  0.006

Look at it

The figure shows the default setting, season-to-season drift (standard deviation of the weight step) = 0.5.

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

DEFAULT = 0.5
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

At drift 0.5 the final recipe scores a Brier of 0.196 on the next season. Leave-one-season-out reports 0.184, so 0.196 - 0.184 = 0.012 of optimism. Past-only reports 0.190, 0.196 - 0.190 = 0.006. Leave-one-season-out is the more optimistic scheme. Leave-one-season-out was the more optimistic in 85% of 100 histories.

Apply this to your competition

Book location: Chapter 3, March Mania as a Special Case.

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.

Resample entity-level validation when AUC estimates are noisy

Conditions

  • small imbalanced entity labels create uncertain AUC differences

Action

  • Proposed adaptation of source observation: Aggregate events to prediction entities and repeat entity-disjoint splits before deciding whether a change matters.

Check

  • Proposed verification: Report AUC dispersion and compare it with proposed change magnitude.

Limits

  • Repeated splits do not create new independent labels and can remain optimistic after many experiments.

Find source links and value grades in the lesson atlas

Verify that training and validation loaders refer to different datasets

Conditions

  • training scripts load separate train and validation tensors

Action

  • Proposed: assert loader dataset identity and split membership before starting optimization.

Check

  • Proposed: assert training loader uses train_dataset, validation uses val_dataset and sample IDs are disjoint; assess the loss tensor axes and padded-target handling separately.

Limits

  • This is a proposed correction to an observed source assignment. It is not evidence of a valid held-out score or an executed successful training run.

Find source links and value grades in the lesson atlas

Check local validation’s directional agreement with evaluation early

Conditions

  • local validation has not yet been checked against the evaluation distribution
  • model selection relies on local validation

Action

  • Proposed adaptation of author advice: Compare the direction of a small set of predeclared model changes across local holdout and available external evaluation.
  • Proposed adaptation of author advice: Track whether a few materially different changes improve both independent validation and competition feedback.

Check

  • Proposed verification: Investigate split mismatch if candidate rankings disagree and retain an untouched local check.
  • Proposed verification: Check repeated change directions rather than inferring reliability from one good submission.

Limits

  • Leaderboard agreement is descriptive and repeated checking can overfit it; stable behavior is not guaranteed on future datasets.
  • Leaderboard correlation is evidence about one contest and cannot prove deployment validity.

Find source links and value grades in the lesson atlas

Tune inside training resamples before a separate final holdout

Conditions

  • several regression model families share a held-out test split

Action

  • Proposed: choose hyperparameters with training folds and assess the finalized workflow on the reserved split.

Check

  • Proposed: keep final holdout results out of tuning decisions and select predictors rather than outcomes in recipe normalization/correlation steps.

Limits

  • The initial split and folds are random stratified splits; temporal or entity dependence is not checked. Recipe1 selects all_numeric rather than explicitly numeric predictors. Repeated cross-family inspection of the holdout can still bias selection.

Find source links and value grades in the lesson atlas

Reject public-leaderboard-only ensemble gains

Conditions

  • forward ensemble selection beats public score but worsens CV

Action

  • Proposed conditional application: Compare ensemble selection on nested score-stratified validation rather than selecting only the best public score.

Check

  • Proposed check: Choose ensemble weights under nested validation, compare competing ensembles on untouched folds, and log public, local, and final scores separately.

Limits

  • The source demonstrates one public/private disagreement; score-stratified folds need auditing for the intended deployment split.

Find source links and value grades in the lesson atlas

Check fold-count sensitivity before high-fold stacking

Conditions

  • small data support a proposed high-fold stack

Action

  • Proposed adaptation of source observation: Compare fold counts and score dispersion before using a high-fold stack; nest feature selection in validation as proposed.

Check

  • Proposed verification: Evaluate the same model under several splits and inspect fold sample counts and variance.

Limits

  • More folds did not automatically mean more reliable CV in this source.

Find source links and value grades in the lesson atlas

Use component removal to prioritize scientific-model improvements

Conditions

  • a scientific pipeline combines physical assumptions and correction stages

Action

  • Proposed adaptation of source observation: Compare targeted component removals under a fixed pipeline and prioritize high-impact dependencies.

Check

  • Proposed verification: Record the same metric and baseline for each ablation and inspect interactions between PCA and GP components.

Limits

  • Reported drops are conditional on the complete pipeline and do not establish independent additive effects.

Find source links and value grades in the lesson atlas

Match validation exclusions to partially labeled evaluation

Conditions

  • sparse-label articles are excluded from scoring

Action

  • Proposed conditional application: Exclude those articles from local false-positive accounting to reproduce the official metric.

Check

  • Proposed check: Reproduce official article exclusions on known examples, report both official and complete-label metrics, and inspect error families.

Limits

  • Matching incomplete labels reproduces the benchmark rather than proving complete extraction quality.

Find source links and value grades in the lesson atlas

Audit teacher provenance before cross-validating a stack

Conditions

  • a meta-model uses outputs from an already trained supervised checkpoint

Action

  • Proposed: generate teacher features out of fold or prove teacher training excludes validation recipients.

Check

  • Proposed: record the loaded checkpoint training IDs and regenerate fold-safe teacher logits before assessing the stack.

Limits

  • Teacher training data are unknown; leakage is a risk requiring evidence, not a proven result. Text length counts truncated token IDs and sentence count is a dot count.

Find source links and value grades in the lesson atlas

Split simulations before constructing overlapping windows

Conditions

  • overlapping windows come from distinct simulation IDs

Action

  • Proposed: hold out whole simulation IDs before building training and validation datasets.

Check

  • Proposed: assert disjoint simulation IDs across train and validation and inspect errors per held-out simulation.

Limits

  • This source shows an implementation, without an isolated gain, execution result, or confirmed final-submission provenance. Historical dependencies and dataset assumptions require local checks.

Find source links and value grades in the lesson atlas

Evaluate the complete validation iterator

Conditions

  • validation may contain more examples than a single batch

Action

  • Proposed: iterate until the validation dataset is exhausted and aggregate by processed example count.

Check

  • Proposed: assert processed validation IDs equal the manifest and handle the final partial batch explicitly.

Limits

  • Complete iteration is proposed correction; the source gives no guarantee its fixed batch is the whole validation set.

Find source links and value grades in the lesson atlas

Avoid supervised corpus statistics leaking into OOF base models

Conditions

  • text preprocessing uses target-derived vectors

Action

  • Proposed conditional application: Keep approximate Naive Bayes vectors fold-local rather than adding whole-training labels to out-of-fold predictors.

Check

  • Proposed check: Fit label-dependent text statistics only on each fold's training rows and trace validation-label exclusion.

Limits

  • Unsupervised and target-derived statistics differ; source did not adopt the rejected whole-data vectors.

Find source links and value grades in the lesson atlas

Investigate leaderboard disagreement against independent benchmarks

Conditions

  • public feedback disagrees with a independently constructed task benchmark

Action

  • Proposed adaptation of source observation: Keep the benchmark and investigate disagreement before chasing public score.

Check

  • Proposed verification: Compare multiple held-out benchmarks and inspect their distribution overlap with target tasks.

Limits

  • This is proposed response to an observed mismatch; the source does not establish the cause or a universally superior split.

Find source links and value grades in the lesson atlas

Hold out whole events when predicting a new event

Conditions

  • observations share event-level conditions and the target is a new event

Action

  • Proposed adaptation of source observation: Partition by complete event and build every statistic on the remaining events.

Check

  • Proposed verification: Compare event-level error and, as proposed, chronological backtesting where future events are unavailable.

Limits

  • Leave-one-event-out can train on future events relative to older tests; chronological checks are proposed for forecasting use.

Find source links and value grades in the lesson atlas

Rotate overused meta-model folds and investigate score plateaus

Conditions

  • many ensemble decisions reuse the same validation predictions

Action

  • Proposed adaptation of source observation: Recheck finalists across new fold partitions and investigate unexpected feedback patterns by comparing train/test feature calculations.

Check

  • Proposed verification: Verify identical interaction formulas and fold-level score changes on controlled fixtures.

Limits

  • New partitions of fixed OOF predictions are not fully independent fresh data; leaderboard diagnosis cannot prove generalization.

Find source links and value grades in the lesson atlas

Prune candidate reconstructions using past score consistency

Conditions

  • a reconstruction puzzle permits lawful use of score observations to constrain candidate assignments

Action

  • Proposed adaptation of source observation: Score prior predictions against candidate reconstructions and reject candidates inconsistent with score ranges and order.

Check

  • Proposed verification: Verify constraints on known labels and distinguish necessary constraints from a unique solution.

Limits

  • Necessary but insufficient conditions; depends on competition rules and feedback behavior, and risks leaderboard overfitting.

Find source links and value grades in the lesson atlas

Account for skipped validation examples

Conditions

  • validation code skips batches with invalid loss

Action

  • Proposed: track and report excluded IDs and compute denominators from processed examples.

Check

  • Proposed: fail or explicitly report incomplete validation and gather predictions across processes before computing full-set metrics.

Limits

  • Accounting and cross-process gathering are proposed corrections. The source skips only NaNs, not all nonfinite values, and has no measured stability benefit.

Find source links and value grades in the lesson atlas

Audit feedback-driven postprocessing with a paired unprocessed submission

Conditions

  • postprocessing uses repeated competition feedback to adjust predictions

Action

  • Proposed adaptation of source observation: Treat successful-submission delta adjustment as a competition-specific experiment and retain an untweaked comparator.

Check

  • Proposed verification: Proposed: simulate selection on independent held-out data and quantify sensitivity to feedback reuse.

Limits

  • High leaderboard-overfitting risk; this is not a general production calibration method.

Find source links and value grades in the lesson atlas

Maintain comparable folds and restore best checkpoints

Conditions

  • heterogeneous image models need comparable OOF predictions

Action

  • Proposed adaptation of source observation: Use shared folds and save best checkpoints by the target metric; choose full-fit duration from CV.

Check

  • Proposed verification: Audit fold alignment and compare full-fit duration against fold-optimal epochs.

Limits

  • Exact durations and schedulers are source-specific and may change with full-data size.

Find source links and value grades in the lesson atlas

Separate stopping selection from final performance estimation

Conditions

  • early stopping chooses an epoch using labeled validation

Action

  • Proposed conditional application: Use training, stopping-validation and separate performance-holdout partitions, or a fixed fold-robust epoch count.

Check

  • Proposed check: Reserve final untouched scoring partition after choosing epochs; compare selection score with independent estimate.

Limits

  • Three-way splits reduce training/scoring sample sizes; early stopping itself is legitimate.

Find source links and value grades in the lesson atlas