The 90-Minute Colab Round
Round 2 strategy: one dataset, one notebook, a model to export, and marks for code quality as well as performance.
Round 2 strategy: one dataset, one notebook, a model to export, and marks for code quality as well as performance.
11 multiple choice at 2 marks and 1 fill-in-the-blank at 5, marked exactly as Round 1 marks them. Each answer is explained as soon as you check it. The clock is shown, not enforced.
Round 2 gives you ninety minutes, a dataset, and Google Colab. You submit a trained model and the code that produced it, and you are marked on both model performance and code quality. That second criterion changes the optimal strategy.
| Minutes | What | | --- | --- | | 0 to 10 | Load, inspect, understand the target and the metric | | 10 to 20 | Build a complete pipeline and produce a first saved model | | 20 to 60 | Iterate: features, model choice, light tuning | | 60 to 75 | Cross-validate the best two candidates, pick one, refit on all data | | 75 to 90 | Clean up the notebook, re-run top to bottom, verify the saved artefact |
The last fifteen minutes are not slack. A notebook that does not run from a clean state, or a model file that was never written, scores far below what the work deserved.
Within the first twenty minutes you should have written a model to disk, however crude. This proves the whole path works - loading, fitting, saving - while there is still time to fix it.
import joblib
joblib.dump(model, "model.joblib")
# Verify the artefact actually round-trips.
loaded = joblib.load("model.joblib")
assert (loaded.predict(X_valid[:5]) == model.predict(X_valid[:5])).all()
That assertion catches the case where a pipeline holds something unpicklable - a lambda, a local function - which is a genuinely common way to lose the round.
Concretely, what a marker can see:
Pipeline rather than a sequence of loose transformations. It reads better and it prevents leakage.random_state so the result reproduces.None of this costs meaningful time if you work that way from the start. Retrofitting it in the last ten minutes does.
For tabular data, HistGradientBoostingClassifier or its regressor: strong defaults, native missing-value handling, no scaling needed, built-in early stopping. Fit it first, and only look further if the problem is clearly not tabular.
from sklearn.ensemble import HistGradientBoostingClassifier
model = HistGradientBoostingClassifier(
max_iter=300, learning_rate=0.08,
early_stopping=True, validation_fraction=0.15, random_state=0,
)
Tune the learning rate and iteration count, and nothing else. A grid search over five hyperparameters will consume the round and gain almost nothing.
Save your work as you go - a disconnected runtime loses unsaved state. Restart and run all before submitting, so that hidden state from cells you edited cannot produce a notebook that only works in your session. If a GPU would help, enable it at the start rather than after building everything on CPU.
Produce a saved, verified model within twenty minutes. Marks come from code quality too - use a pipeline and write it cleanly from the start.
Tune the learning rate and iteration count; leave the rest alone. Restart and run all before submitting; check the artefact round-trips.
What should joblib.dump receive?
The judges load one object and call predict on a raw row. If the transformers are not inside that object, the row cannot be scored.
Select an answer
Write opening_steps() so it returns the leak-free order as four strings.
Inspect, then cut the holdout, then fit only on train, then export. Scaling the whole frame before the cut is the leak.