A machine-learning F1 podium predictor built on real FastF1 data (2021–2024, 1,799 driver-races). For any Grand Prix it gives every driver a podium probability and ranks the field — then lets you force a wet race, tweak track conditions, or hand out grid penalties and watch the podium re-shuffle live in a custom dark-themed dashboard.
Race outcomes hinge on changing factors — grid position, qualifying pace, form, reliability, weather — that a static standings table doesn't capture.
The starting grid alone is already a very strong predictor, so any model has to prove it adds signal beyond it.
Sports prediction models routinely leak future data into training; evaluation had to be strictly time-ordered.
Predictions should be explorable — what happens if it rains, or a driver takes a grid penalty?
System Overview
FastF1 race data (2021–2024)→Feature engineering→XGBoost + SHAP→FastAPI service layer→Interactive dark-themed dashboard
Dataset builder pulls four seasons of real F1 data via FastF1 and engineers 1,799 driver-race rows: grid position, qualifying gap, recent form, race pace, reliability, constructor strength, and weather.
XGBoost model outputs a podium probability for every driver, evaluated with an expanding-window scheme so each season is predicted only from earlier seasons (AUC 0.918 vs 0.902 for a grid-only baseline).
FastAPI backend is organized into a service layer (f1_data_service, prediction_service, weather_service) behind a thin routing layer.
Vanilla HTML/CSS/JS dashboard supports what-if scenarios: force wet races, tweak temperature and wind, apply grid penalties, and watch the podium re-shuffle live.
Optional live-weather integration pulls current conditions at the circuit from OpenWeatherMap for runtime what-if predictions only — never for training or evaluation.
SHAP explainability confirms the model learned racing logic (grid, quali pace, form, constructor), backed by a 29-test pytest suite at ~96% coverage including a no-leakage check.
What I Built
Feature-engineering pipeline over real FastF1 data: grid position, gap to pole, 5-race driver form, race-pace (places gained/lost), driver and constructor DNF rates, constructor strength, and weather.
XGBoost model with expanding-window evaluation — each season predicted using only earlier seasons, pooled over 68 out-of-sample races.
ROC-AUC 0.918 vs 0.902 for a grid-only baseline on full-field ranking, with the honest caveat that it only ties the grid on exact top-3 picks (Precision@3 0.60 vs 0.61).
FastAPI backend organised into a service layer (f1_data_service, prediction_service, weather_service) with a thin routing layer.
Custom no-build-step HTML/CSS/JS dashboard: predicted podium vs actual result, full-grid probability bars, constructor points, and live what-if controls (wet race, temperature, wind, grid penalties).
Optional live-weather integration: one click pulls current conditions at the circuit from OpenWeatherMap and predicts on them.
SHAP explainability showing the model learned grid → qualifying pace → championship form → constructor strength, in that order.
29 pytest tests at ~96% coverage, including a no-leakage check; Dockerized and deployed on Render with committed model + dataset so the app never retrains at serve time.
Screenshots
SHAP summary — the model learned grid position, qualifying pace, form, and constructor strength, in that order
Key Decisions & Tradeoffs
Expanding-window evaluation so no future season ever informs a prediction — the honest way to score a time-series sports model.
Reported the grid-only baseline beside the model and acknowledged where it merely ties — the model's edge is calibrated full-field ranking, not exact podium picks.
Live weather is a runtime what-if input only — it never enters training or evaluation, so metrics stay clean.
Committed the trained model and dataset so the deployed app needs no F1 API access or retraining; heavy deps (fastf1, shap) are dev-only.
Vanilla-JS frontend with no build step, keeping the deploy a single lightweight web service.
Why It Matters
It shows disciplined time-series ML — leak-free evaluation against a strong baseline — packaged as a genuinely interactive product rather than a notebook.
What I'd Improve Next
Extend the dataset to current seasons and automate periodic retraining so predictions stay up to date as the grid evolves.
Add probability calibration reporting (reliability curves, Brier score) to strengthen the calibrated-probability claim.
Model pit strategy, tyre choice, and safety-car likelihood as additional changing factors beyond grid, form, and weather.
Support pre-race predictions for upcoming Grands Prix using scheduled qualifying results as they land, not just historical races.
Quantify prediction uncertainty per driver (e.g. bootstrap or conformal intervals) alongside point probabilities.