The problem in brief
You receive 10 000 grey-scale images of handwritten digits, pixels each, and must print the digit on each one. No training data is given: the statement explicitly invites you to find your own on the internet, and even links to MNIST tutorials. The Kattis program runs offline, so in practice you train at home and submit a program that prints your 10 000 answers. This is the Swedish AI Olympiad qualifier 2025 (problem by Arvid Kristoffersson and Joshua Andersson).
About evaluation. The slips look exactly like MNIST: the average image correlates at 0.9995 with the MNIST test average, and the share of black pixels is the same (80.8 % against 80.7 %). They are not the MNIST test set, though: no slip is pixel-identical to an MNIST test image, nor to a QMNIST test image, and only 2 match MNIST training images. Their labels are private. We therefore report accuracy on the official MNIST test set (10 000 digits never used for training or tuning), which is the natural proxy, and we check that our model is just as confident on the slips as on that set.
How you are scored
With the percentage of correct digits,
so random guessing (10 %, the provided baseline) scores 0 and every percent of accuracy is worth points. The contest graded 30 % of the slips live and the other 70 % at the end.
What to aim for. The Kattis statistics page shows two scores of 100 and then 99.59, 99.22 and 99.0, which correspond to about 99.6 %, 99.3 % and 99.1 % accuracy.
First look at the data
The input file is 10 000 blocks of integers between 0 and 255: white ink on black, centred, with the same size and thickness as MNIST digits. The match is so close that any MNIST classifier should transfer without a domain shift. Here is the check: after training, the mean top-class probability of our ensemble is 0.9515 on MNIST test and 0.9528 on the slips (it is below 1 because we train with label smoothing). A simpler kNN model agrees with the CNN on 98.6 % of the slips, against 97.6 % on MNIST test. The slips are, if anything, slightly easier.
A first baseline
Download MNIST training data (60 000 labelled digits, from Hugging Face ylecun/mnist) and fit classical models on the raw pixels:
| model | MNIST test accuracy | score |
|---|---|---|
| random digits (provided baseline) | 10 % | 0 |
| logistic regression on pixels | 92.6 % | 91.8 |
| 3-nearest neighbours on 50 PCA components | 97.5 % | 97.2 |
kNN is surprisingly good, but each lost percent costs more than a point, and the top of the leaderboard is beyond 99.5 %.
The key idea
Two things matter: convolutions and augmentation.
A convolutional network applies the same small filters everywhere in the image, so a stroke detector learnt in one place works everywhere, and pooling makes the response tolerant to small shifts. That is the right inductive bias for handwriting. Augmentation goes further. Each training batch is randomly rotated (up to ±12°), scaled (±10 %), sheared and shifted (±2 pixels) with an affine warp:
The network then never sees the same image twice and has to learn what makes a 4 a 4, whatever the writer's slant and size. Averaging the predicted probabilities of 3 networks trained with different seeds smooths out the errors of each one.
The full solution
- Download MNIST from Hugging Face (two parquet files, 18 MB) and decode the PNGs.
- CNN: two blocks of [conv 3x3, batch norm, ReLU] x 2 then max-pooling (32 then 64 channels), then dropout 0.3, a dense layer of 256 units and 10 outputs. That is about 0.9 M parameters.
- Training: AdamW, one-cycle learning rate peaking at 0.003, 8 epochs, batches of 128, label smoothing 0.05, on-the-fly affine augmentation with
affine_gridandgrid_sample. On Apple MPS it takes about 2 minutes per seed. - Ensemble the softmax outputs of 3 seeds, predict the 10 000 slips, and write a one-line Kattis program,
print('2959912745...').

The top row shows the remaining MNIST test mistakes: a 6 drawn lying down, a broken 8, a 4 that looks like a 9. Many of them would make a human hesitate. The bottom row shows the slips where the ensemble is least confident, with its two top guesses. They are hard in the same way (a 0 or a 7 with a tail, a 6 or an 8 with a filled loop). These are cases where we would expect to lose points on Kattis too.
Results
Accuracy on the official MNIST test set (the slips' labels are private; score computed with the Kattis formula).
| approach | MNIST test accuracy | score |
|---|---|---|
| random (baseline.py) | 10 % | 0 |
| logistic regression | 92.60 % | 91.8 |
| kNN on PCA-50 | 97.52 % | 97.2 |
| CNN, no augmentation, 4 epochs | 99.58 % | 99.53 |
| CNN + augmentation, single seed | 99.56 to 99.69 % | 99.51 to 99.66 |
| ensemble of 3 augmented CNNs (final) | 99.64 % | 99.60 |
With augmentation, single seeds already range from 99.56 to 99.69 %, so the differences between the CNN rows are within seed noise. The ensemble is chosen for stability rather than for a measured gain. If the slips behave like MNIST test (the confidence check says they do), this places the solution at the level of the third Kattis score.
What to remember
- "No training data" does not mean "no data": find the public dataset the task was obviously drawn from, and check that it matches (pixel statistics, mean images, model confidence).
- When the test labels are hidden, check the shift directly: compare the model's confidence, or the agreement between two models, on the official proxy and on the real inputs.
- For images, convolutions plus geometric augmentation beat pixel models by a wide margin. Ensembling seeds removes the luck of one run.
- Near 99.6 %, seed-to-seed variation (±0.07 %) is as large as most architecture tweaks. Do not over-read small differences.