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 22: Vision and Multimodal: When You Need a VLM

Try the decision first

If the label signal sits low in the embedding's variance ranking, what does a PCA that keeps 90% of the variance leave for the second stage?

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

If the label signal sits low in the embedding's variance ranking, what does a PCA that keeps 90% of the variance leave for the second stage?

The chapter says PCA preserves variance under its fitted distribution, not necessarily task information, and that a percentage of lost predictive signal cannot be inferred from explained variance. Measuring a constructed case makes that concrete and shows the safer routine.

Constructed data. Where the signal sits is a choice made by the generator; the activity measures what each rule does for each choice and does not claim real embeddings look like this.

The experiment

Twenty-four constructed binary tasks per setting. A 40-dimensional embedding has directions with geometrically decaying variance. Five directions starting at the control's variance rank carry the class, each shifted by the same number of its own standard deviations, so the information is identical wherever the signal sits. A noisy soft label stands in for the VLM output. A logistic regression second stage is fitted on 600 rows and scored on 4,000 new rows with: the soft label alone, the soft label plus the raw embedding, the soft label plus k principal components (k from 2 to 32, PCA fitted on the training rows only), a 90% variance rule, and the candidate chosen by 5-fold cross-validation among all of these inside the 600 rows.

Calculation code
import numpy as np
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler

from kaggle_companion.activities._common import clean

SEED = 22
REPLICATES = 24            # independent constructed datasets; every estimate is their mean
D = 40                     # embedding dimension
VARIANCE = np.exp(-0.15 * np.arange(D))     # variance of each embedding direction, largest first
KS = [2, 4, 8, 16, 24, 32]  # candidate numbers of principal components
N_TRAIN, N_NEW, WIDTH = 600, 4000, 5
SEPARATION = 0.75          # class shift per signal direction, in standard deviations of that direction


def generate(n, rng, signal_rank):
    """Embedding plus a noisy VLM soft label. Five embedding directions, starting at variance rank `signal_rank`, carry the class.

    Every signal direction is shifted by the same number of its own standard deviations, so the information in the embedding
    is identical wherever the signal sits; only its place in the variance ranking changes."""
    y = rng.integers(0, 2, n)
    sign = 2 * y - 1
    z = rng.normal(size=(n, D)) * np.sqrt(VARIANCE)
    rows = np.arange(signal_rank, signal_rank + WIDTH)
    z[:, rows] += (SEPARATION / 2) * np.sqrt(VARIANCE[rows]) * sign[:, None]
    soft = sign * 0.55 + rng.normal(size=n)            # the VLM's output as a logit-like score, informative but noisy
    return z, soft, y


def second_stage(train_features, y_train, new_features):
    """Standardize, fit logistic regression and return predicted classes for the new features."""
    scaler = StandardScaler().fit(train_features)
    model = LogisticRegression(C=1.0, max_iter=500).fit(scaler.transform(train_features), y_train)
    return model.predict(scaler.transform(new_features))


def features(kind, z_fit, soft_fit, z_apply, soft_apply):
    """Second-stage inputs for one candidate: soft label only, soft label + raw embedding, or soft label + k principal components."""
    if kind == "soft":
        return soft_fit[:, None], soft_apply[:, None]
    if kind == "raw":
        return np.column_stack([soft_fit, z_fit]), np.column_stack([soft_apply, z_apply])
    pca = PCA(kind).fit(z_fit)                          # fitted on the fitting rows only
    return np.column_stack([soft_fit, pca.transform(z_fit)]), np.column_stack([soft_apply, pca.transform(z_apply)])


def one_dataset(signal_rank, seed):
    rng = np.random.default_rng(seed)
    z, soft, y = generate(N_TRAIN, rng, signal_rank)
    z_new, soft_new, y_new = generate(N_NEW, rng, signal_rank)
    candidates = ["soft"] + KS + ["raw"]
    new_accuracy = {}
    for kind in candidates:
        a, b = features(kind, z, soft, z_new, soft_new)
        new_accuracy[kind] = (second_stage(a, y, b) == y_new).mean()
    # Choose among the candidates by 5-fold cross-validation inside the development rows; ties keep the earlier (simpler) one.
    cv = {kind: 0.0 for kind in candidates}
    for fit, val in StratifiedKFold(5, shuffle=True, random_state=0).split(z, y):
        for kind in candidates:
            a, b = features(kind, z[fit], soft[fit], z[val], soft[val])
            cv[kind] += (second_stage(a, y[fit], b) == y[val]).mean() / 5
    chosen = max(candidates, key=lambda c: (round(cv[c], 6), -candidates.index(c)))
    # The habit the chapter warns about: keep enough components for 90% of the explained variance.
    k90 = PCA(0.90).fit(z).n_components_
    a, b = features(int(k90), z, soft, z_new, soft_new)
    variance90 = (second_stage(a, y, b) == y_new).mean()
    explained = np.cumsum(PCA(D).fit(z).explained_variance_ratio_)
    return new_accuracy, chosen, k90, variance90, explained


def run(signal_rank):
    sets = [one_dataset(signal_rank, SEED * 1000 + i) for i in range(REPLICATES)]
    candidates = ["soft"] + KS + ["raw"]
    mean_new = {str(c): float(np.mean([s[0][c] for s in sets])) for c in candidates}
    chosen_accuracy = float(np.mean([s[0][s[1]] for s in sets]))
    explained = np.mean([s[4] for s in sets], axis=0)
    return clean({
        "signal_rank": signal_rank, "replicates": REPLICATES, "embedding_dimension": D, "train_rows": N_TRAIN, "new_rows": N_NEW,
        "soft_only": mean_new["soft"], "raw_embedding": mean_new["raw"],
        "pca_by_k": {str(k): mean_new[str(k)] for k in KS},
        "explained_by_k": {str(k): float(explained[k - 1]) for k in KS},
        "variance_rule": {"accuracy": float(np.mean([s[3] for s in sets])), "components": float(np.mean([s[2] for s in sets])),
                          "explained": float(explained[int(round(np.mean([s[2] for s in sets]))) - 1])},
        "cv_choice": {"accuracy": chosen_accuracy,
                      "share_soft_only": float(np.mean([s[1] == "soft" for s in sets])),
                      "share_raw": float(np.mean([s[1] == "raw" for s in sets]))},
    })

Measure it across the control

The control is variance rank where the label signal starts (0 is the largest-variance direction). Each value below runs the whole experiment from the generator up.

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

VALUES = [0, 10, 20, 30]
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     10     20     30
Soft label alone            0.707  0.707  0.707  0.707
Raw embedding               0.823  0.823  0.823  0.824
90% variance rule           0.835  0.834  0.695  0.696
Cross-validated choice      0.835  0.831  0.826  0.823
Components in the 90% rule     15     15     16     15

Look at it

The figure shows the default setting, variance rank where the label signal starts (0 is the largest-variance direction) = 20.

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

DEFAULT = 20
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 the signal starting at variance rank 20, the 90% rule keeps about 16 components (91% of the variance) and scores 0.695, against 0.707 for the soft label alone and 0.823 for the raw embedding: 0.695 - 0.707 = -0.012, so the reduced embedding has lost the signal. Choosing by cross-validation scores 0.826, and 0.826 - 0.695 = 0.131 is its margin over the rule.

Apply this to your competition

Book location: Chapter 22, When VLMs Beat Traditional CV Pipelines.

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.

Undo answer-option permutations before probability averaging

Conditions

  • multiple-choice VQA may be sensitive to answer position

Action

  • Proposed adaptation of source observation: Apply several option permutations and restore each probability vector to original answer identities before averaging.

Check

  • Proposed verification: Test permutation round-trips and compare original versus permuted accuracy under equal compute.

Limits

  • The source does not isolate the gain from training permutations versus inference permutations.

Find source links and value grades in the lesson atlas

Align external annotations and synthesize missing chart forms

Conditions

  • chart training sources have incompatible conventions or missing visual forms

Action

  • Proposed adaptation of source observation: Audit annotations against target rules and generate missing types such as error bars and multiline labels.

Check

  • Proposed verification: Use real held-out charts to evaluate each source and inspect sampled synthetic labels.

Limits

  • Manual correction is costly; synthetic diversity alone does not establish real-world transfer.

Find source links and value grades in the lesson atlas

Fuse visual and textual meme features before classification

Conditions

  • low-resolution meme images need captions to interpret hate

Action

  • Proposed conditional application: Combine pretrained image and text representations with a classification head and validate decision thresholds.

Check

  • Proposed check: Compare image-only, text-only and fused models on untouched paired examples; separate threshold tuning from final assessment and inspect error subgroups.

Limits

  • The README's0.723 accuracy is a final result, not an isolated fusion comparison; split details are absent.

Find source links and value grades in the lesson atlas

Compare late stacking with joint multimodal fusion

Conditions

  • house prediction has tabular features, photos and text descriptions

Action

  • Proposed conditional application: Compare a stack of modality-specific models with a single network sharing text embeddings and combining image and tabular inputs.

Check

  • Proposed check: Compare late and joint fusion on property-held-out RMSE with identical modality inputs and training budget.

Limits

  • Availability and correlated duplicate properties can leak; architecture/validation details partial.

Find source links and value grades in the lesson atlas

Add permutation-invariant cross-option information to a binary head

Conditions

  • independent multiple-choice scoring misses relations among alternatives

Action

  • Proposed conditional application: Concatenate target-option logits with mean logits of all other options before the classifier head.

Check

  • Proposed check: Permute answer order and assert invariant scores; compare independent/augmented heads on unseen questions.

Limits

  • Mean loses option-specific relations; source qualitative gain does not isolate architecture changes.

Find source links and value grades in the lesson atlas

Validate detector-based coordinate refinement for VLM boxes

Conditions

  • VLM localization predictions can be refined against detector proposals

Action

  • Proposed recipe: compare the blend alone with a detector-based bounding-box snap step.

Check

  • Proposed check: Compare snap/no-snap on fixed held-out VLM predictions, inspecting object identity swaps, missed proposals, timing and coordinate error.

Limits

  • A detector proposal may snap to the wrong object; detailed matching rule is absent and extra inference cost is not isolated.

Find source links and value grades in the lesson atlas

Condition base-model blending on confident disagreement

Conditions

  • a fine-tuned VQA model and its base model disagree on low-margin cases

Action

  • Proposed adaptation of source observation: Evaluate a gated base-model blend using the source’s confidence and agreement conditions as candidate thresholds.

Check

  • Proposed verification: Measure changed answers and paired held-out accuracy before adjusting thresholds.

Limits

  • The rules were selected for this competition and can overfit a public leaderboard; multicrop is explicitly unnecessary for this final candidate.

Find source links and value grades in the lesson atlas

Keep a fallback when grounding can fail

Conditions

  • single-frame visual grounding follows temporal localization

Action

  • Proposed: extract the event frame and retain coarse coordinates when frame extraction or grounding fails.

Check

  • Proposed: log extraction and grounding failure rates, then compare localization error with and without refinement.

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

Allocate extra VQA inference to uncertain questions

Conditions

  • additional VQA inference is expensive

Action

  • Proposed adaptation of source observation: Rank uncertainty using margin, entropy, confidence and permutation disagreement, then reserve extra permutations and visual tokens for a limited subset.

Check

  • Proposed verification: Compare selective versus uniform compute at the same total inference budget.

Limits

  • The adaptive notebook is missing from the published two-file package; counts and blend weights are source-specific.

Find source links and value grades in the lesson atlas

Choose modality inputs separately for contact subtypes

Conditions

  • player-player and player-ground contact cues differ

Action

  • Proposed conditional application: Train separate subtype models and retain tracking-image inputs only for player-player contact.

Check

  • Proposed check: Ablate each modality per contact subtype on shared folds and compare performance, missing-modality behavior and memory cost.

Limits

  • The tracking failure is specific to ground contacts in this setup; input length also changed because of GPU limits.
  • Tracking input is documented for player-player modeling, but the source provides no player-player ablation establishing a tracking benefit.

Find source links and value grades in the lesson atlas

Match target serialization to pretrained decoder conventions

Conditions

  • pretrained structured decoder conventions differ from evaluation annotation rules

Action

  • Proposed adaptation of source observation: Train using compatible serialization and translate axis conventions explicitly at output.

Check

  • Proposed verification: Round-trip known charts through serialization and output conversion.

Limits

  • These changes are combined in the report; no independent format ablation is shown.

Find source links and value grades in the lesson atlas

Route geometric chart types to detection plus coordinate conversion

Conditions

  • numeric scatter charts permit coordinate reconstruction

Action

  • Proposed adaptation of source observation: Use detected tick positions and values to map plot-point coordinates to data values, with a specialized scatter branch.

Check

  • Proposed verification: Check axis orientation, scale, label-to-box mapping and missing detections on held-out charts.

Limits

  • The source used crude extreme-label matching and ignored rare count mismatches; robust mismatch handling is proposed.

Find source links and value grades in the lesson atlas

Choose ensemble components separately for distinct output types

Conditions

  • a multimodal model predicts time, location and event class

Action

  • Proposed recipe: test output-specific blending instead of applying one rule to every output.

Check

  • Proposed check: Ablate output-specific versus uniform blends using held-out videos, evaluate each output and composite score, and audit label/coordinate alignment.

Limits

  • Two large VLMs have high compute requirements;9:1and single-model type choice are tuned source settings.

Find source links and value grades in the lesson atlas