This page shows the chapter notebook with its saved results. Constructed examples do not measure competition gains.
Chapter 50: LLM Fine-Tuning for Kaggle
Try the decision first
How does the rank of a LoRA-style update change held-out error against the original checkpoint and a full update when target data is small?
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.
Worked notebook and saved results
How does the rank of a LoRA-style update change held-out error against the original checkpoint and a full update when target data is small?
The chapter says parameter efficiency does not guarantee a quality gain and asks for the adapted model to be compared with the original checkpoint under matched data. A rank sweep with both comparators shows where a low-rank update helps, where it stops helping, and how much a full update gains over leaving the model alone.
A linear stand-in with an exactly low-rank change; the sizes of these effects are properties of this generator, not a competition result.
The experiment
A constructed linear layer W0 (40 inputs, 20 outputs, 800 weights) stands in for a frozen pretrained layer. The target task is W0 plus a hidden rank-2 change, observed through 100 noisy target rows. Three adaptations are trained with the same Adam optimiser, 300 steps and learning rate: a full update of all 800 weights, and a LoRA update W0 + B A with B starting at zero, A random, scaling alpha / r = 1 and the control's rank r. Error is the mean squared difference from the noiseless target on 4,000 held-out rows, averaged over 20 tasks. The original layer, with no adaptation, is the comparator.
Calculation code
import numpy as np
from kaggle_companion.activities._common import clean
SEED = 50
DRAWS = 20 # independent tasks; every estimate is a mean over draws
D_IN, D_OUT = 40, 20 # one frozen "pretrained" linear layer W0 of 800 weights
TRUE_RANK = 2 # the target task differs from the pretrained task by a rank-2 change
N_TARGET, STEPS, LR = 100, 300, 0.01
CURVE_RANKS = [1, 2, 3, 4, 6, 8, 12, 16]
def make_task(draw):
"""Pretrained layer W0, a rank-2 shift to the target task, 100 noisy target rows and 4,000 clean held-out rows."""
rng = np.random.default_rng([SEED, draw])
W0 = rng.normal(size=(D_IN, D_OUT)) / np.sqrt(D_IN)
shift = rng.normal(size=(D_IN, TRUE_RANK)) @ rng.normal(size=(TRUE_RANK, D_OUT)) / np.sqrt(D_IN * TRUE_RANK)
X, X_held = rng.normal(size=(N_TARGET, D_IN)), rng.normal(size=(4000, D_IN))
Y = X @ (W0 + shift) + rng.normal(size=(N_TARGET, D_OUT))
return W0, X, Y, X_held, X_held @ (W0 + shift)
def adam(params, gradients, steps=STEPS, lr=LR):
"""Plain Adam on a list of arrays; every method below gets the same optimiser, steps and learning rate."""
m1 = [np.zeros_like(p) for p in params]
m2 = [np.zeros_like(p) for p in params]
for t in range(1, steps + 1):
for i, g in enumerate(gradients(params)):
m1[i] = 0.9 * m1[i] + 0.1 * g
m2[i] = 0.999 * m2[i] + 0.001 * g * g
params[i] -= lr * (m1[i] / (1 - 0.9 ** t)) / (np.sqrt(m2[i] / (1 - 0.999 ** t)) + 1e-8)
return params
def full_update(W0, X, Y):
"""Fine-tune every weight: W = W0 + Delta, with Delta trained from zero."""
grad = lambda p: [X.T @ (X @ (W0 + p[0]) - Y) * 2 / Y.size]
return W0 + adam([np.zeros_like(W0)], grad)[0]
def lora_update(W0, X, Y, rank, seed):
"""LoRA: W = W0 + B A with B (D_IN x r) starting at zero, A (r x D_OUT) random, scaling alpha / r = 1. Only A and B train."""
A = np.random.default_rng(seed).normal(size=(rank, D_OUT)) / np.sqrt(D_OUT)
def grad(p):
G = X.T @ (X @ (W0 + p[1] @ p[0]) - Y) * 2 / Y.size # gradient with respect to the whole update
return [p[1].T @ G, G @ p[0].T]
A, B = adam([A, np.zeros((D_IN, rank))], grad)
return W0 + B @ A
def run(rank):
ranks = sorted(set(CURVE_RANKS) | {rank})
original, full, curve = [], [], {r: [] for r in ranks}
for draw in range(DRAWS):
W0, X, Y, X_held, Y_held = make_task(draw)
mse = lambda W: float(np.mean((X_held @ W - Y_held) ** 2)) # held-out error against the noiseless target
original.append(mse(W0))
full.append(mse(full_update(W0, X, Y)))
for r in ranks:
curve[r].append(mse(lora_update(W0, X, Y, r, seed=1000 * draw + r)))
chosen = np.array(curve[rank])
saved = np.array(full) - chosen
return clean({
"rank": rank, "original": np.mean(original), "full": np.mean(full), "lora": chosen.mean(),
"gain_over_full": saved.mean(), "gain_over_full_se": saved.std(ddof=1) / np.sqrt(DRAWS),
"curve_ranks": ranks, "curve": [np.mean(curve[r]) for r in ranks],
"per_draw_lora": chosen, "per_draw_full": full, "per_draw_original": original,
"lora_parameters": rank * (D_IN + D_OUT), "full_parameters": D_IN * D_OUT, "true_rank": TRUE_RANK,
"target_rows": N_TARGET, "draws": DRAWS,
})
Measure it across the control
The control is lora rank r (trainable parameters: 60 r). Each value below runs the whole experiment from the generator up.
Calculation code
import pandas as pd
from kaggle_companion.activities.ch50 import explain
VALUES = [1, 2, 4, 16]
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 16 Original layer error 1.015 1.015 1.015 1.015 Full update error 0.682 0.682 0.682 0.682 LoRA error, rank 1 0.364 NaN NaN NaN Gain over full (SE) +0.319 (0.035) +0.588 (0.015) +0.438 (0.010) +0.032 (0.001) Trainable parameters 60 120 240 960 Best rank in the sweep 2 2 2 2 LoRA error, rank 2 NaN 0.095 NaN NaN LoRA error, rank 4 NaN NaN 0.245 NaN LoRA error, rank 16 NaN NaN NaN 0.651
Look at it
The figure shows the default setting, lora rank r (trainable parameters: 60 r) = 4.
Calculation code
import matplotlib.pyplot as plt
from kaggle_companion.activities.ch50 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()What the result says
At rank 4 (240 trainable parameters against 800 for a full update) the adapted layer has held-out error 0.245. The original layer scores 1.015 and the full update 0.682, so the LoRA update is 0.682 - 0.245 = 0.437 better than the full update (paired standard error 0.010) and 1.015 - 0.245 = 0.770 better than doing nothing. Across the ranks tried the lowest error is 0.095 at rank 2; the hidden change has rank 2.
- Gain over the original layer: 1.015 - 0.245 = +0.770.
- Gain over the full update: 0.682 - 0.245 = +0.437 (standard error 0.010).
- Trainable parameters: 240 of 800 (30.0%).
- Best rank in the sweep: 2 with held-out error 0.095.
Apply this to your competition
- Record the rank, scaling, target modules and trainable parameter count with every adapter you compare.
- Compare each adapter with the original checkpoint and a full update at the same data, steps and learning rate.
- Sweep the rank on development rows and prefer the smallest rank whose error is within noise of the best.
- Expect full updates to overfit when target data is small, and re-check the comparison when the data grows.
Book location: Chapter 50, Why LoRA Changes the Game.
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.
Reject stronger reasoning models that exhaust execution limits
Conditions
- stronger validation models generate longer answers
Action
- Proposed conditional application: Account for answer length and timeouts before selecting a reasoning model.
Check
- Proposed check: Evaluate the stronger and shorter models under the identical end-to-end deadline; report attempted questions, completed answers and accuracy together.
Limits
- Longer generation was a suspected timeout explanation; source does not isolate causality.
- A longer model may remain useful with a different deadline or decoding policy.
Evaluate quantization and speculative drafting together
Conditions
- long reasoning inference is limited by time and memory
Action
- Proposed adaptation of source observation: Benchmark quantization; train a drafting head on target-model generations; measure accepted draft tokens and end-to-end speed.
Check
- Proposed verification: Compare accuracy, memory and time on identical problems and hardware, including failed draft alternatives.
Limits
- Custom integration was needed; throughput and accuracy depend on hardware and model.
Bootstrap tool reasoning through iterative generation and filtering
Conditions
- a reasoning model does not follow the desired tool-call format
Action
- Proposed adaptation of source observation: Bootstrap tool-call examples from an instruction-following model; alternate fine-tuning, generation and quality filtering.
Check
- Proposed verification: Check parseable tool calls, correct answers and usefulness of executions on held-out problems.
Limits
- Failure was local to this prompting attempt; iterative synthetic data can amplify errors and costs.
Reuse a shared question prefix cache across answer scoring
Conditions
- decoder-only models score several answers with the same context and question
Action
- Proposed conditional application: Cache past key values for context plus question once, then score five answer continuations in a batch.
Check
- Proposed check: Check cached/noncached logits parity with identical prefix tokens/positions; benchmark per-question latency and KV memory.
Limits
- Shared prefix must be byte/token identical; changing attention positions invalidates cache.
Stop parallel reasoning after sufficient consensus
Conditions
- multiple asynchronous reasoning samples share a time budget
Action
- Proposed conditional application: Cancel remaining generations when four of the first five answers agree; also stop after ten of twelve completions to avoid stragglers.
Check
- Proposed check: Replay the same question set with and without each stopping rule; compare accuracy, cancellation rate and tail latency.
Limits
- Correlated generations may agree on a wrong answer.
- Four-of-five and ten-of-twelve are source-specific examples; calibrate on the target workload.
Approximate subgroup metric emphasis in training loss
Conditions
- toxicity evaluation combines subgroup and background performance
Action
- Proposed conditional application: Combine overall BCE with power-mean subgroup, background-positive/subgroup-negative and reverse-mask BCE terms.
Check
- Proposed check: Compare plain/mimic BCE on subgroup and background AUC; test empty subgroup masks and numerical gradients.
Limits
- BCE surrogate does not equal AUC metric; sparse subgroup estimates and fairness tradeoffs remain.
Adapt language pretraining to the task corpus
Conditions
- question-answer labeling shares domain text with an external unlabeled corpus
Action
- Proposed: compare domain language-model fine-tuning and supervised pseudo-label training before blending distinct model families.
Check
- Proposed: audit external data overlap and pseudo-label teacher/validation separation, then compare domain-pretrained and original checkpoints on the same held-out folds.
Limits
- Native first-place label is not independent rank verification. The source does not isolate either adaptation gain or establish leakage prevention from the no-leak artifact filename.
Restrict language-model fine-tuning to adapters under limited GPU resources
Conditions
- large pretrained text classifiers exceed full-tuning resources
Action
- Proposed adaptation of source observation: Compare projection-targeted LoRA with a small baseline and track trainable parameters and memory.
Check
- Proposed verification: Check class-stratified held-out quality and reproducibility across seeds.
Limits
- No full-tuning comparison or memory amount is supplied.
Compare decoding speed together with answer quality
Conditions
- reasoning inference must fit a strict runtime budget
Action
- Proposed conditional application: Compare quantization and speculative decoding jointly; the source trained a ReDrafter head from 100k target-model solutions and reports approximately 1.8X speedup.
Check
- Proposed check: On the same math questions and seeds compare base decoding, each quantization, and quantization plus drafting; measure answer accuracy, throughput and total evaluation time.
Limits
- Draft head training used 100k target-model solutions and required custom TensorRT changes.
- Benchmark speed and accuracy depend on GPU configuration, batching, quantization and reasoning length.
Keep multiple valid answers when training extractive QA
Conditions
- identical context/question pairs have different legitimate answers
Action
- Proposed conditional application: Compare retaining all answer examples with choosing only the shortest answer.
Check
- Proposed check: Group identical question/context pairs within one split; compare all-answer and shortest-answer training using edit distance and EM.
Limits
- Repeated answers change example weighting; single split and length-sensitive metric limit certainty.
Compare step-wise seed averaging against costly beam search
Conditions
- sequence decoding has a tight runtime budget and mixed-precision training
Action
- Compare step-wise seed-logit averaging with beam search using the same examples and inference budget.
Check
- Measure edit distance, total latency and memory for each decoding strategy.
Limits
- The source found beam search too costly in its setting; ensemble averaging adds component inference cost.
- AWP instability and auxiliary CTC failure are separate training observations, not decoding comparisons.
Mask chat-template tokens from binary classification loss
Conditions
- LLM chat templates surround the useful Yes/No target
Action
- Proposed conditional application: Compute loss only on the Yes/No answer token and exclude irrelevant template suffixes and whitespace.
Check
- Proposed check: Inspect tokenizer offsets/loss masks and compare label accuracy plus training time with unmasked suffix loss.
Limits
- Multi-token labels need all relevant tokens; tokenizer/template changes can break mask positions.
Bootstrap language specialists from multilingual teachers
Conditions
- multilingual target text has viable language-specific pretrained models
Action
- Proposed adaptation of source observation: Create language-specific pseudo-label subsets, fine-tune specialists from original weights and compare native-language routing with translated cross-language routing.
Check
- Proposed verification: Evaluate each language separately and audit teacher/validation isolation.
Limits
- Repeated improvements are author-reported; language detection and translation errors can change behavior.
Cache repository structure across localization stages
Conditions
- repeated code-agent stages rebuild the same structure
Action
- Proposed conditional application: Extract repository files, symbols and line ranges once and reuse them across localization stages.
Check
- Proposed check: Compare cached/fresh symbol maps and runtime; invalidate affected entries after edits or checkout changes.
Limits
- Stale line ranges after edits mislocalize fixes; timing baseline details unspecified.
Sample supplemental sequence data by unique target phrase
Conditions
- supplemental sequences contain many repetitions of few target phrases
Action
- Proposed adaptation of source observation: Group supplemental examples by target phrase and sample one per phrase each epoch rather than adding all duplicates.
Check
- Proposed verification: Compare phrase-disjoint evaluation and full versus group-balanced supplemental sampling.
Limits
- The author’s memorization explanation is a hypothesis; the gain is small and source-specific.
Compare general and domain checkpoints at matched tuning budgets
Conditions
- domain-specific checkpoint names may not predict molecular task quality
Action
- Proposed adaptation of source observation: Include general/code-pretrained models in a matched fine-tuning comparison rather than defaulting to a domain model.
Check
- Proposed verification: Use identical molecular splits, tuning budgets and target metrics.
Limits
- The source’s code-data explanation is a hypothesis and model comparisons do not establish broad superiority.
Encode paired texts as tokenizer pairs
Conditions
- classification depends on the relationship between two text snippets
Action
- Proposed: pass both snippets through the pretrained tokenizer pair interface and collate with dynamic padding.
Check
- Proposed: verify pair boundaries, truncation coverage and order behavior; use document/author-group separation if snippets recur across pairs.
Limits
- The source uses random pair-level splitting, so author/document leakage is not excluded; baseline label polarity also needs validation.
Record visual-token limits and precision as distinct inference settings
Conditions
- a multimodal run can silently use a different memory fallback
Action
- Proposed adaptation of source observation: Persist actual precision and visual-token settings in the run record and treat fallback outputs as separate experiments.
Check
- Proposed verification: Assert loaded precision and token budget and compare output probabilities after any fallback.
Limits
- No gain or equivalence for 8-bit fallback is reported.
Repeat language-model comparisons across seeds
Conditions
- fine-tuned text classifiers have seed variability
Action
- Proposed conditional application: Repeat each comparison across five seeds while keeping other per-model hyperparameters fixed.
Check
- Proposed check: Pair seeds and fixed validation membership; report mean, spread and paired gains.
Limits
- Five long GPU fits per variant are costly; repeated seeds do not assess distribution shift.
Preserve IDs through length-sorted inference
Conditions
- evaluation examples are reordered for efficient text batching
Action
- Proposed: save prediction IDs from the reordered dataset or restore original order before archiving.
Check
- Proposed: compare archived IDs against the sorted dataset and assert ID-label pairs before joining OOF features.
Limits
- This is proposed correction: test outputs use test_ds IDs consistently, whereas OOF output uses val_df IDs.
Add span-boundary auxiliary targets
Conditions
- token classification predicts contiguous clinical spans
Action
- Proposed conditional application: Train extra start/end channels alongside the normal token target.
Check
- Proposed check: Ablate boundary channels with the same tokenizer and folds and examine exact span boundaries as well as token scores.
Limits
- Improvement was slight; pseudo-label ensemble benefit was an author's hypothesis.
Separate long reasoning pretraining from lightweight tool refinement
Conditions
- training long reasoning responses and a much smaller tool dataset
Action
- Proposed adaptation of source observation: Train reasoning on packed sequences, then run a separately budgeted short tool fine-tuning phase; evaluate intermediate checkpoints.
Check
- Proposed verification: Measure held-out accuracy versus cumulative compute and tool-phase steps.
Limits
- The reported resource scale is inaccessible to many readers and the 20% claim is not an exact equivalent-quality guarantee.
Score binary LLM labels with forward logits and variant aggregation
Conditions
- the task needs a classification probability rather than generated text
Action
- Proposed conditional application: Use a forward pass at the answer position and aggregate Yes/No token variants into log-odds, sorting inputs by length.
Check
- Proposed check: Verify answer-position/variant IDs per tokenizer; compare forward scoring with generation accuracy, calibration and latency.
Limits
- Multi-token variants and probability outside chosen set affect semantics; not universal calibrated probability.
Share unused time across sequential inference questions
Conditions
- question difficulty and completion time vary under a global deadline
Action
- Proposed conditional application: Use a shared buffer with 350 seconds base time per question and up to 210 additional seconds from previous savings.
Check
- Proposed check: Replay questions in several orders with fixed per-question limits versus buffered limits; count completions and enforce the total deadline.
Limits
- Question order can change who receives spare time.
- The later global-time smoothed strategy was explicitly not used; numerical budgets require retuning.