train_38 LSTM + smooth expected-goals calibrator — 28 KO matches fully out-of-sample (training cutoff 2026-06-29)
predict_match CLI tool does not exist — our model runs via Docker + Python.
Brier-loss (deterministic): 0.179 — 5 wrong winner predictions
Brier-loss (deterministic): 0.286 — 8 wrong winner predictions
| # | Match | Model | ELO5 | Result | Pts Model | Pts ELO5 | MAE |
|---|---|---|---|---|---|---|---|
| Last 32 (w73–w88) | |||||||
| 73 | South Africa – Canada | 1-3 | 1-3 | 0-1 | 75 | 75 | 3 |
| 74 | Germany – Paraguay | 2-1 | 2-1 | 1-1 pen.↗ | 20 | 20 | 1 |
| 75 | Netherlands – Morocco | 2-1 | 2-1 | 1-1 pen.↗ | 20 | 20 | 1 |
| 76 | Brazil – Japan | 2-1 | 2-1 | 2-1 ✓✓ | 200 ✓ | 200 ✓ | 0 |
| 77 | France – Sweden | 3-1 | 3-1 | 3-0 | 95 | 95 | 1 |
| 78 | Ivory Coast – Norway | 1-2 | 1-3 | 1-2 ✓✓ | 200 ✓ | 95 | 0 |
| 79 | Mexico – Ecuador | 2-1 | 1-1 p. | 2-0 | 95 | 0 | 1 |
| 80 | England – DR Congo | 2-1 | 3-1 | 2-1 ✓✓ | 200 ✓ | 95 | 0 |
| 81 | USA – Bosnia | 2-1 | 2-1 | 2-0 | 95 | 95 | 1 |
| 82 | Belgium – Senegal | 2-1 | 1-1 p. | 3-2 | 75 | 0 | 2 |
| 83 | Portugal – Croatia | 2-1 | 1-1 p. | 2-1 ✓✓ | 200 ✓ | 20 | 0 |
| 84 | Spain – Austria | 3-1 | 3-1 | 3-0 | 95 | 95 | 1 |
| 85 | Switzerland – Algeria | 2-1 | 2-1 | 2-0 | 95 | 95 | 1 |
| 86 | Argentina – Cape Verde | 2-0 | 3-1 | 3-2 | 75 | 95 | 3 |
| 87 | Colombia – Ghana | 2-0 | 3-1 | 1-0 | 95 | 75 | 1 |
| 88 | Australia – Egypt | 2-1 | 1-1 p. | 1-1 pen.↗ | 20 | 200 ✓ | 1 |
| Last 16 (w89–w96) | |||||||
| 89 | Canada – Morocco | 1-2 | 1-2 | 0-3 | 75 | 75 | 2 |
| 90 | Paraguay – France | 1-2 | 1-3 | 0-1 | 75 | 75 | 2 |
| 91 | Brazil – Norway | 1-1 p. | 1-1 p. | 1-2 | 20 | 20 | 1 |
| 92 | Mexico – England | 1-2 | 1-2 | 2-3 | 75 | 75 | 2 |
| 93 | Portugal – Spain | 1-2 | 1-2 | 0-1 | 75 | 75 | 2 |
| 94 | USA – Belgium | 1-2 | 1-2 | 1-4 | 95 | 95 | 2 |
| 95 | Argentina – Egypt | 3-1 | 3-1 | 3-2 | 95 | 95 | 1 |
| 96 | Switzerland – Colombia | 1-1 p. | 1-1 p. | 0-0 pen. | 100 D | 100 D | 2 |
| Quarter-finals (w97–w100) | |||||||
| 97 | France – Morocco | 2-0 | 3-1 | 2-0 ✓✓ | 200 ✓ | 75 | 0 |
| 98 | Spain – Belgium | 2-1 | 3-1 | 2-1 ✓✓ | 200 ✓ | 95 | 0 |
| 99 | Norway – England | 1-2 | 1-2 | 1-2 ✓✓ | 200 ✓ | 200 ✓ | 0 |
| 100 | Argentina – Switzerland | 2-1 | 3-1 | 3-1 | 95 | 200 ✓ | 1 |
| TOTAL (28 matches) | 2960 / 105.7 | 2455 / 87.7 | 1.14 | ||||
| Phase | N | Model pts | ELO5 pts | Model/match | ELO5/match | MAE Model | MAE ELO5 |
|---|---|---|---|---|---|---|---|
| Last 32 | 16 | 1655 | 1275 | 103.4 | 79.7 | 1.06 | 1.31 |
| Last 16 | 8 | 610 | 610 | 76.2 | 76.2 | 1.75 | 1.88 |
| Quarter-finals | 4 | 695 | 570 | 173.8 | 142.5 | 0.25 | 0.75 |
| TOTAL | 28 | 2960 | 2455 | 105.7 | 87.7 | 1.14 | 1.39 |
* Scoreboard value = 2990/28 = 106.8. Difference of 30 pts (<1%) due to minor data entry differences for 1–2 model outputs.
worldcup2018_test.csv GitHub URL does not existpredict_match CLI does not exist (→ Docker + Python)
train_38 + calibrator is robustly validated on 28 genuine out-of-sample matches (WK 2026 KO phase).
Winner accuracy: 82.1% vs. ELO benchmark 71.4%.
Pool score: 105.7 pts/match vs. baseline 89.7 pts/match (+16.0 improvement from calibrator).
Exact scores: 25% of matches — in line with the expected distribution.
Zero matches fully wrong (0 pts) — model always predicts at least the winner or one score correctly.
Note: the Last 16 scores lower (76.2/match) because actual results sometimes deviated strongly from expectations (e.g. Brazil 1-2 Norway). This is expected in KO phases with penalty shootouts.