Skip to content
karim.semaan(open to work)
WorkExperienceAboutSkillsContactResume ↓
← All work
KickCast preview
ML / Data ScienceLive2026

KickCast

2026 World Cup prediction · calibration-first ML

Turns a 21,371-match feature matrix into 10,000-run Monte-Carlo odds for every one of the 104 games of the 2026 World Cup: full probability distributions, not a single guess.

Monte-Carlo simulator · 8,000-run in-browser sample

Runs in your browser on synthetic data. Deterministic (seeded), so the same inputs always give the same forecast.

Press Run simulation to run 8,000 synthetic knockout tournaments (in-browser sample) and rank teams by how often they lift the trophy.

Synthetic, illustrative ratings, not the live KickCast model or a published forecast. The real product uses a 7-model ensemble over decades of match data.

Real model outputtop 6 of 48 teams
  1. 1Spain20.52%
  2. 2France18.71%
  3. 3England15.34%
  4. 4Brazil10.27%
  5. 5Argentina9.00%
  6. 6Portugal5.68%

Published KickCastNet_v3 forecast: 10,000-run Monte Carlo. Same data as the live dashboard, not produced by the simulator above.

8,000-run in-browser sample on synthetic data. The published model ran 10,000 iterations.

KickCast, a graduate machine-learning course project, turns historical match data into tournament odds: an ensemble of classifiers predicts each match, and the class probabilities drive a 10,000-iteration Monte-Carlo simulation that samples goals via Poisson and runs the full group + knockout bracket into per-team advancement odds, served as a deployed Next.js dashboard.

The pipeline is leakage-safe: it loads Elo, FIFA rankings, market values, manager records, injuries, form and head-to-head history into a 21,371-row × 38-feature matrix with chronological train/val/test splits (test = the 2022 World Cup).

Modeling covers seven classical models (Logistic Regression, KNN, Random Forest, XGBoost, HistGradientBoosting, SVM-RBF and a stacking ensemble) alongside LightGBM/CatBoost variants and a custom PyTorch 'KickCastNet' tuned with Optuna, handling class imbalance with balanced weights and SMOTE. SHAP attributes the signal (Elo difference is the single strongest predictor, |r|=0.504).

  • Python
  • scikit-learn
  • XGBoost
  • LightGBM
  • PyTorch
  • Optuna
  • SHAP
  • Monte Carlo
  • Next.js
  • Vercel

Architecture · notebook → tournament odds

  1. 01

    Feature engineering

    Elo, FIFA rankings, market values, form, injuries and head-to-head → a 21,371 × 38 matrix with leakage-safe chronological splits (test = the 2022 World Cup).

  2. 02

    Model ensemble

    Seven classical models + LightGBM/CatBoost + a PyTorch net (KickCastNet), tuned with Optuna; class imbalance handled with balanced weights + SMOTE.

  3. 03

    Explainability

    SHAP attributes the signal: Elo difference is the single strongest predictor (|r| = 0.504).

  4. 04

    Monte-Carlo simulation

    3-class probabilities drive 10,000 iterations that sample goals via Poisson through the full 48-team group + knockout bracket.

  5. 05

    Live dashboard

    Per-team advancement odds served as a deployed Next.js dashboard.

Log-loss (holdout)
1.347 → 1.093 (calibrated)
calibration study↗︎
Feature matrix
21,371 matches × 38 feat.
repo↗︎
Models
7 classifiers + PyTorch net
Monte Carlo
10,000 iterations

Where the numbers come from

  • ›Four accuracy figures, one story…

    Four accuracy figures, one story (so a spot-check, or the chatbot, never reads them as a wobble): 45.3% (29/64) is top-1 on the 64-match 2022 World Cup holdout BEFORE recalibration; 50.0% is the SAME holdout AFTER per-class isotonic recalibration (a monotone side-effect of calibrating, documented in the calibration study); 56.25% is raw accuracy on the separate 3,552-match chronological test split, which recalibration nudges to 58.3%. All four are real and consistent, not a contradiction, and accuracy is deliberately not the headline: the calibration study optimizes log-loss and ECE (proper scoring), not top-1.

  • ›38 vs 31 features: 38 counts every column of the released 21,371-row…

    38 vs 31 features: 38 counts every column of the released 21,371-row master matrix (repo LESSONS.md); the report models on the 31 engineered delta features inside it.

  • ›7 vs 14 models: the card's seven are the core classical classifiers…

    7 vs 14 models: the card's seven are the core classical classifiers; the report's fourteen add the majority-class baseline, LightGBM and CatBoost, an isotonic-calibrated weighted ensemble, and three KickCastNet generations.

  • ›Two simulation runs exist: the committed course-submission run (Spain 16.5%)…

    Two simulation runs exist: the committed course-submission run (Spain 16.5%) and a later calibrated-ensemble run baked into the live dashboard (Spain 20.5%). The repo's simulation-results README documents which is which; the README attributes the committed run to the tuned XGBoost while the report abstract describes it as KickCastNet v3-calibrated.

  • ›The demo's 'Real model output' panel republishes the live dashboard's own data…

    The demo's 'Real model output' panel republishes the live dashboard's own data (Spain 20.52%): the published KickCastNet v3 run, 10,000 Monte-Carlo iterations, dashboard data generated 2026-04-16, traceable to the model artifact and simulation script behind the live dashboard. The in-page simulator itself remains a simplified, illustrative Elo-style model on synthetic ratings and never produces those numbers.

KickCast tournament dashboard: a 48-team win-probability bar chart grouped by confederation with Spain favoured at 20.5%, from 10,000 Monte Carlo simulations of the calibrated ensemble.
The live KickCast dashboard (kickcast-dashboard.vercel.app): a 48-team forecast from a 10,000-run Monte-Carlo simulation of the calibrated ensemble. Spain leads at 20.5% (the earlier committed course-submission run had Spain at 16.5%; this dashboard runs the later calibrated ensemble, and the public repo commits the 16.5% run).
Reliability diagram before recalibration: predicted probability vs observed frequency in 10 bins on the 64-match 2022 World Cup holdout, under-confident at low probabilities and over-confident above 0.6
Before recalibration: pooled one-vs-rest reliability over 192 match-class pairs, 10 uniform bins (ECE 0.157, log-loss 1.347).
Reliability diagram after per-class isotonic recalibration: the same 10-bin plot with points pulled toward the diagonal
After per-class isotonic recalibration on the same holdout (ECE 0.120, log-loss 1.093). Calibrator fit only on the 2,324-match validation split.

What I'd improve

Honest read on the 64-match 2022 holdout: the 45.3% top-1 (29/64) sits about at the always-home rate (~44%) and below a naive Elo-favorite (~52%), precisely because the model predicts draws the favorite baselines never do.

So the lever isn't top-1 accuracy, it's calibration, and that is what the project optimizes: it scores on log-loss (a proper scoring rule) with a stacking ensemble and calibration plots. That recalibration is now done and measured in the follow-up calibration study: per-class isotonic regression (fit on the validation split, holdout untouched) cuts holdout log-loss from 1.347 to 1.093 and 10-bin ECE from 0.157 to 0.120 on the 64-match 2022 holdout, and full-test ECE from 0.098 to 0.017 (n=3,552).

Still open: backtesting more tournaments so the probabilities are decision-grade for the Monte-Carlo simulation.

Open live↗︎View source↗︎Live 2026 scoreboard→Project report (PDF)↗︎
Want something like this? Get in touch →

Measured:30/30 chatbot evals·20-case Bastion eval·Serving·Calibration Lab

© 2026 Karim SemaanBuilt with Next.js, Tailwind & Supabase.LinkedIn ↗︎GitHub ↗︎