NBA Player Stat Prediction
Predicting how many points, assists, and rebounds an NBA player will record in his next game, using only what was known before tipoff. An end-to-end Python pipeline covering data collection, feature engineering, model training, and evaluation against a simple baseline on games the model never saw during training.
Evaluated on the 2025–26 regular season. The chronological holdout begins March 11, 2026.
The question
How well can you predict an NBA player's next box score (points, assists, rebounds) from only what was known before tipoff? The answer is: not perfectly. In the games set aside for testing, players averaging 19–21 points over their previous ten games went on to score anywhere from 0 to 41. Recent scoring, minutes, rest, and matchup history all carry useful signal, but individual game outcomes remain highly variable.
A low error can still be easy to fake if a feature quietly peeks at the game being predicted. So useful performance has to survive an honest test: past information only, games evaluated in order, and a simpler method under the same conditions.
From source data to reproducible evaluation.
Keeping the test honest
A model that sees any part of the result it is supposed to predict will look accurate for the wrong reason. That failure is called data leakage, and preventing it is why every historical feature uses a strict date cutoff. Jamal Murray’s 5-game and 10-game scoring averages, recent minutes, rest, and team form can only be derived from information available before the game being predicted. Numbering his appearances in order, a prediction for Game 11 can use Games 1–10 but nothing from Game 11 itself. The database query enforces this by requiring each source game to have an earlier date than the game being predicted. Games he did not play are excluded from the averages rather than counted as zero.
Chronology also governs tuning and evaluation. The most recent 20% of game dates are reserved for the final test. On the earlier data, expanding-window cross-validation divides the dates into four consecutive blocks, producing three rounds that train on the past and validate on the next block. Later games never inform earlier predictions.
Evaluation
A model can look accurate on its own terms and still add nothing if a much simpler rule does the same job. To test whether the added complexity is actually worthwhile, the tuned gradient boosting models are compared head-to-head with a simple 10-game rolling-average baseline, where the player’s average over their previous 10 games is used as the predicted value for that stat in their next game.
The final test contains 5,645 player-game rows that were never used in training. Across that chronological holdout, the points model’s mean absolute error is 4.85 — a little under five points per prediction on average. Across the 5,612 rows for which both methods produced predictions, the model achieved a 4.841 MAE compared to 4.883 for the 10-game baseline. Assists showed the same small edge, 1.407 against 1.417, while rebounds were effectively tied.
The 10-game baseline already captures much of the signal in a player’s recent performance, leaving less room for a more complex model to improve the overall error. The model’s advantage was small in aggregate, but it was consistent over time: it outperformed the baseline in 23 of 28 trailing seven-day windows for points and 22 of 28 for assists.
The NBA model visualizations across this site are rebuilt natively from the project’s generated reporting data.
Trailing 7-day MAE
View rolling error data
Mean absolute error (MAE) is the average size of a prediction error, in points. Lower is better. Each row covers the seven days ending on the listed date.
Scroll the table sideways to see all columns.
| Window end | Model MAE | Baseline MAE | Lower error |
|---|---|---|---|
| 2026-03-17 | 4.854 | 4.868 | Model |
| 2026-03-18 | 4.898 | 4.927 | Model |
| 2026-03-19 | 4.810 | 4.807 | Baseline |
| 2026-03-20 | 4.795 | 4.792 | Baseline |
| 2026-03-21 | 4.764 | 4.761 | Baseline |
| 2026-03-22 | 4.710 | 4.721 | Model |
| 2026-03-23 | 4.613 | 4.627 | Model |
| 2026-03-24 | 4.774 | 4.786 | Model |
| 2026-03-25 | 4.626 | 4.633 | Model |
| 2026-03-26 | 4.586 | 4.602 | Model |
| 2026-03-27 | 4.618 | 4.644 | Model |
| 2026-03-28 | 4.631 | 4.638 | Model |
| 2026-03-29 | 4.621 | 4.616 | Baseline |
| 2026-03-30 | 4.638 | 4.637 | Baseline |
| 2026-03-31 | 4.513 | 4.521 | Model |
| 2026-04-01 | 4.586 | 4.595 | Model |
| 2026-04-02 | 4.735 | 4.756 | Model |
| 2026-04-03 | 4.600 | 4.655 | Model |
| 2026-04-04 | 4.663 | 4.749 | Model |
| 2026-04-05 | 4.655 | 4.744 | Model |
| 2026-04-06 | 4.652 | 4.715 | Model |
| 2026-04-07 | 4.733 | 4.812 | Model |
| 2026-04-08 | 4.727 | 4.823 | Model |
| 2026-04-09 | 4.706 | 4.782 | Model |
| 2026-04-10 | 4.770 | 4.799 | Model |
| 2026-04-11 | 4.873 | 4.915 | Model |
| 2026-04-12 | 5.018 | 5.076 | Model |
| 2026-04-13 | 5.310 | 5.419 | Model |
Useful signal, with a visible ceiling.
The chronological holdout contains 5,645 player-game observations. The model tracks typical scoring outcomes reasonably well, but predictions compress toward the middle instead of following extreme performances all the way up.
That limitation is especially clear on ceiling games: every one of the 188 holdout performances of 30+ points was underpredicted, with an average underprediction of 13.9 points.
Actual vs. predicted
View prediction density data
Each row corresponds to one occupied cell in the chart. Two-point ranges include the lower bound and exclude the upper bound, except the final 58–60 range, which includes 60. Averages describe the observations within that cell.
Scroll the table sideways to see all columns.
| Actual range | Predicted range | Actual avg | Predicted avg | Observations |
|---|---|---|---|---|
| 0–2 | 2–4 | 0.1 | 3.1 | 288 |
| 0–2 | 4–6 | 0.1 | 4.9 | 155 |
| 0–2 | 6–8 | 0.1 | 6.8 | 85 |
| 0–2 | 8–10 | 0.1 | 8.9 | 40 |
| 0–2 | 10–12 | 0.1 | 11.0 | 19 |
| 0–2 | 12–14 | 0.1 | 13.1 | 9 |
| 0–2 | 14–16 | 0.0 | 14.8 | 6 |
| 0–2 | 16–18 | 0.0 | 16.5 | 1 |
| 0–2 | 20–22 | 0.0 | 20.9 | 1 |
| 2–4 | 2–4 | 2.3 | 3.2 | 186 |
| 2–4 | 4–6 | 2.4 | 4.9 | 133 |
| 2–4 | 6–8 | 2.5 | 7.0 | 141 |
| 2–4 | 8–10 | 2.5 | 9.0 | 100 |
| 2–4 | 10–12 | 2.5 | 11.0 | 55 |
| 2–4 | 12–14 | 2.5 | 12.6 | 15 |
| 2–4 | 14–16 | 2.3 | 15.1 | 9 |
| 2–4 | 16–18 | 2.0 | 16.2 | 1 |
| 2–4 | 18–20 | 2.5 | 18.6 | 2 |
| 2–4 | 20–22 | 2.0 | 21.4 | 2 |
| 4–6 | 0–2 | 5.0 | 1.9 | 1 |
| 4–6 | 2–4 | 4.4 | 3.2 | 86 |
| 4–6 | 4–6 | 4.5 | 5.0 | 108 |
| 4–6 | 6–8 | 4.5 | 7.0 | 124 |
| 4–6 | 8–10 | 4.5 | 8.9 | 96 |
| 4–6 | 10–12 | 4.7 | 10.9 | 51 |
| 4–6 | 12–14 | 4.6 | 13.1 | 29 |
| 4–6 | 14–16 | 4.5 | 15.1 | 15 |
| 4–6 | 16–18 | 4.8 | 16.8 | 5 |
| 4–6 | 18–20 | 5.0 | 18.9 | 5 |
| 4–6 | 20–22 | 4.3 | 20.5 | 3 |
| 4–6 | 24–26 | 5.0 | 25.0 | 1 |
| 6–8 | 2–4 | 6.4 | 3.2 | 57 |
| 6–8 | 4–6 | 6.5 | 5.1 | 87 |
| 6–8 | 6–8 | 6.5 | 7.0 | 111 |
| 6–8 | 8–10 | 6.5 | 9.0 | 101 |
| 6–8 | 10–12 | 6.5 | 10.9 | 73 |
| 6–8 | 12–14 | 6.4 | 13.0 | 34 |
| 6–8 | 14–16 | 6.5 | 15.0 | 30 |
| 6–8 | 16–18 | 6.5 | 17.0 | 12 |
| 6–8 | 18–20 | 6.4 | 19.2 | 12 |
| 6–8 | 20–22 | 6.5 | 21.8 | 2 |
| 6–8 | 24–26 | 6.0 | 25.3 | 2 |
| 8–10 | 2–4 | 8.4 | 3.3 | 53 |
| 8–10 | 4–6 | 8.4 | 5.2 | 71 |
| 8–10 | 6–8 | 8.4 | 6.9 | 125 |
| 8–10 | 8–10 | 8.4 | 8.9 | 111 |
| 8–10 | 10–12 | 8.5 | 10.9 | 67 |
| 8–10 | 12–14 | 8.3 | 12.7 | 38 |
| 8–10 | 14–16 | 8.5 | 15.0 | 29 |
| 8–10 | 16–18 | 8.8 | 17.0 | 25 |
| 8–10 | 18–20 | 8.8 | 19.0 | 12 |
| 8–10 | 20–22 | 8.4 | 20.6 | 7 |
| 8–10 | 22–24 | 8.0 | 22.3 | 1 |
| 8–10 | 24–26 | 8.3 | 25.2 | 3 |
| 8–10 | 28–30 | 8.0 | 28.4 | 2 |
| 10–12 | 2–4 | 10.4 | 3.2 | 23 |
| 10–12 | 4–6 | 10.5 | 5.1 | 47 |
| 10–12 | 6–8 | 10.5 | 7.0 | 81 |
| 10–12 | 8–10 | 10.6 | 9.0 | 90 |
| 10–12 | 10–12 | 10.6 | 11.0 | 85 |
| 10–12 | 12–14 | 10.5 | 13.0 | 55 |
| 10–12 | 14–16 | 10.6 | 15.1 | 44 |
| 10–12 | 16–18 | 10.5 | 16.8 | 29 |
| 10–12 | 18–20 | 10.7 | 18.5 | 6 |
| 10–12 | 20–22 | 10.4 | 20.9 | 9 |
| 10–12 | 22–24 | 10.7 | 22.9 | 3 |
| 10–12 | 24–26 | 10.6 | 25.1 | 5 |
| 12–14 | 2–4 | 12.6 | 3.1 | 14 |
| 12–14 | 4–6 | 12.5 | 5.3 | 35 |
| 12–14 | 6–8 | 12.5 | 7.0 | 59 |
| 12–14 | 8–10 | 12.5 | 9.0 | 82 |
| 12–14 | 10–12 | 12.5 | 10.7 | 79 |
| 12–14 | 12–14 | 12.4 | 13.0 | 65 |
| 12–14 | 14–16 | 12.5 | 15.0 | 46 |
| 12–14 | 16–18 | 12.5 | 17.0 | 26 |
| 12–14 | 18–20 | 12.6 | 18.7 | 16 |
| 12–14 | 20–22 | 12.5 | 20.9 | 21 |
| 12–14 | 22–24 | 12.7 | 22.8 | 3 |
| 12–14 | 24–26 | 13.0 | 24.5 | 1 |
| 12–14 | 26–28 | 12.0 | 26.1 | 1 |
| 12–14 | 28–30 | 12.0 | 28.9 | 1 |
| 14–16 | 2–4 | 14.4 | 3.3 | 12 |
| 14–16 | 4–6 | 14.4 | 5.1 | 20 |
| 14–16 | 6–8 | 14.4 | 7.2 | 43 |
| 14–16 | 8–10 | 14.5 | 9.1 | 61 |
| 14–16 | 10–12 | 14.5 | 11.0 | 66 |
| 14–16 | 12–14 | 14.4 | 12.9 | 57 |
| 14–16 | 14–16 | 14.4 | 15.2 | 49 |
| 14–16 | 16–18 | 14.5 | 17.0 | 37 |
| 14–16 | 18–20 | 14.5 | 19.0 | 22 |
| 14–16 | 20–22 | 14.5 | 21.0 | 24 |
| 14–16 | 22–24 | 14.4 | 22.7 | 5 |
| 14–16 | 24–26 | 15.0 | 24.3 | 2 |
| 14–16 | 26–28 | 14.3 | 27.2 | 4 |
| 14–16 | 28–30 | 15.0 | 28.9 | 1 |
| 14–16 | 30–32 | 14.0 | 31.7 | 1 |
| 16–18 | 2–4 | 16.8 | 3.4 | 8 |
| 16–18 | 4–6 | 16.5 | 5.3 | 17 |
| 16–18 | 6–8 | 16.5 | 7.1 | 36 |
| 16–18 | 8–10 | 16.6 | 9.1 | 45 |
| 16–18 | 10–12 | 16.5 | 11.0 | 51 |
| 16–18 | 12–14 | 16.6 | 13.0 | 29 |
| 16–18 | 14–16 | 16.5 | 15.0 | 41 |
| 16–18 | 16–18 | 16.6 | 17.0 | 22 |
| 16–18 | 18–20 | 16.4 | 18.9 | 29 |
| 16–18 | 20–22 | 16.8 | 20.9 | 15 |
| 16–18 | 22–24 | 16.5 | 22.2 | 4 |
| 16–18 | 24–26 | 16.7 | 25.1 | 6 |
| 16–18 | 26–28 | 17.0 | 27.3 | 2 |
| 16–18 | 28–30 | 16.0 | 29.6 | 1 |
| 18–20 | 2–4 | 18.5 | 3.4 | 2 |
| 18–20 | 4–6 | 18.3 | 5.2 | 6 |
| 18–20 | 6–8 | 18.5 | 6.8 | 18 |
| 18–20 | 8–10 | 18.4 | 9.2 | 23 |
| 18–20 | 10–12 | 18.4 | 10.9 | 52 |
| 18–20 | 12–14 | 18.4 | 12.9 | 39 |
| 18–20 | 14–16 | 18.5 | 15.2 | 35 |
| 18–20 | 16–18 | 18.4 | 16.8 | 30 |
| 18–20 | 18–20 | 18.5 | 18.9 | 31 |
| 18–20 | 20–22 | 18.3 | 21.0 | 25 |
| 18–20 | 22–24 | 18.5 | 22.8 | 12 |
| 18–20 | 24–26 | 18.2 | 24.8 | 6 |
| 18–20 | 26–28 | 18.8 | 27.5 | 4 |
| 20–22 | 2–4 | 20.5 | 2.9 | 2 |
| 20–22 | 4–6 | 20.3 | 5.2 | 8 |
| 20–22 | 6–8 | 20.6 | 7.2 | 14 |
| 20–22 | 8–10 | 20.5 | 8.9 | 24 |
| 20–22 | 10–12 | 20.5 | 11.0 | 33 |
| 20–22 | 12–14 | 20.5 | 13.1 | 22 |
| 20–22 | 14–16 | 20.6 | 15.0 | 34 |
| 20–22 | 16–18 | 20.4 | 17.0 | 30 |
| 20–22 | 18–20 | 20.4 | 19.1 | 18 |
| 20–22 | 20–22 | 20.5 | 21.0 | 28 |
| 20–22 | 22–24 | 20.5 | 23.0 | 12 |
| 20–22 | 24–26 | 20.0 | 24.6 | 7 |
| 20–22 | 26–28 | 20.5 | 26.8 | 4 |
| 20–22 | 28–30 | 20.0 | 28.6 | 4 |
| 22–24 | 2–4 | 22.7 | 3.5 | 3 |
| 22–24 | 4–6 | 22.5 | 5.5 | 4 |
| 22–24 | 6–8 | 22.5 | 7.1 | 11 |
| 22–24 | 8–10 | 22.5 | 8.8 | 8 |
| 22–24 | 10–12 | 22.5 | 10.9 | 18 |
| 22–24 | 12–14 | 22.6 | 13.0 | 13 |
| 22–24 | 14–16 | 22.7 | 15.4 | 23 |
| 22–24 | 16–18 | 22.5 | 17.1 | 22 |
| 22–24 | 18–20 | 22.4 | 19.1 | 28 |
| 22–24 | 20–22 | 22.7 | 20.8 | 16 |
| 22–24 | 22–24 | 22.4 | 22.6 | 7 |
| 22–24 | 24–26 | 22.8 | 24.5 | 5 |
| 22–24 | 26–28 | 22.3 | 26.8 | 4 |
| 22–24 | 28–30 | 22.6 | 28.3 | 7 |
| 22–24 | 30–32 | 23.0 | 30.1 | 1 |
| 24–26 | 4–6 | 24.4 | 5.3 | 5 |
| 24–26 | 6–8 | 24.5 | 6.6 | 2 |
| 24–26 | 8–10 | 24.0 | 8.7 | 5 |
| 24–26 | 10–12 | 24.3 | 11.1 | 15 |
| 24–26 | 12–14 | 24.4 | 13.3 | 7 |
| 24–26 | 14–16 | 24.9 | 15.0 | 14 |
| 24–26 | 16–18 | 24.6 | 17.0 | 22 |
| 24–26 | 18–20 | 24.5 | 19.0 | 21 |
| 24–26 | 20–22 | 24.4 | 20.9 | 18 |
| 24–26 | 22–24 | 24.7 | 22.8 | 7 |
| 24–26 | 24–26 | 24.6 | 24.9 | 10 |
| 24–26 | 26–28 | 24.8 | 27.5 | 4 |
| 24–26 | 28–30 | 25.0 | 28.4 | 2 |
| 24–26 | 30–32 | 24.0 | 30.6 | 1 |
| 26–28 | 2–4 | 27.0 | 3.5 | 1 |
| 26–28 | 4–6 | 26.5 | 4.9 | 4 |
| 26–28 | 6–8 | 26.0 | 7.0 | 4 |
| 26–28 | 8–10 | 26.4 | 9.1 | 5 |
| 26–28 | 10–12 | 26.0 | 10.8 | 1 |
| 26–28 | 12–14 | 26.3 | 13.0 | 9 |
| 26–28 | 14–16 | 26.5 | 15.2 | 14 |
| 26–28 | 16–18 | 26.5 | 16.8 | 12 |
| 26–28 | 18–20 | 26.7 | 18.8 | 15 |
| 26–28 | 20–22 | 26.4 | 21.0 | 14 |
| 26–28 | 22–24 | 26.4 | 22.8 | 11 |
| 26–28 | 24–26 | 26.2 | 24.8 | 5 |
| 26–28 | 26–28 | 26.3 | 27.5 | 3 |
| 26–28 | 28–30 | 26.0 | 28.5 | 3 |
| 28–30 | 6–8 | 28.0 | 7.9 | 1 |
| 28–30 | 8–10 | 29.0 | 9.5 | 3 |
| 28–30 | 10–12 | 28.0 | 10.7 | 1 |
| 28–30 | 12–14 | 28.1 | 12.5 | 7 |
| 28–30 | 14–16 | 28.4 | 14.9 | 10 |
| 28–30 | 16–18 | 28.6 | 16.9 | 5 |
| 28–30 | 18–20 | 28.3 | 19.4 | 4 |
| 28–30 | 20–22 | 28.5 | 21.0 | 8 |
| 28–30 | 22–24 | 28.8 | 23.1 | 5 |
| 28–30 | 24–26 | 28.8 | 24.9 | 4 |
| 28–30 | 26–28 | 28.3 | 27.3 | 8 |
| 28–30 | 28–30 | 29.0 | 29.0 | 1 |
| 30–32 | 2–4 | 31.0 | 3.7 | 1 |
| 30–32 | 6–8 | 30.0 | 7.8 | 1 |
| 30–32 | 8–10 | 30.0 | 9.4 | 3 |
| 30–32 | 12–14 | 30.4 | 12.6 | 5 |
| 30–32 | 14–16 | 30.3 | 15.1 | 6 |
| 30–32 | 16–18 | 30.5 | 17.0 | 11 |
| 30–32 | 18–20 | 30.1 | 19.3 | 9 |
| 30–32 | 20–22 | 31.0 | 21.0 | 4 |
| 30–32 | 22–24 | 30.3 | 22.9 | 11 |
| 30–32 | 24–26 | 30.6 | 25.2 | 8 |
| 30–32 | 26–28 | 30.0 | 27.5 | 1 |
| 30–32 | 28–30 | 30.7 | 28.5 | 3 |
| 30–32 | 30–32 | 31.0 | 30.3 | 1 |
| 32–34 | 2–4 | 33.0 | 3.8 | 1 |
| 32–34 | 10–12 | 32.4 | 11.0 | 5 |
| 32–34 | 12–14 | 32.5 | 13.4 | 2 |
| 32–34 | 14–16 | 32.3 | 15.1 | 4 |
| 32–34 | 16–18 | 32.5 | 16.8 | 2 |
| 32–34 | 18–20 | 32.2 | 19.1 | 6 |
| 32–34 | 20–22 | 32.0 | 20.9 | 1 |
| 32–34 | 22–24 | 32.1 | 23.1 | 7 |
| 32–34 | 24–26 | 32.7 | 25.3 | 3 |
| 32–34 | 26–28 | 32.7 | 27.8 | 3 |
| 32–34 | 28–30 | 32.5 | 28.7 | 2 |
| 34–36 | 6–8 | 34.0 | 7.7 | 1 |
| 34–36 | 10–12 | 34.7 | 11.3 | 3 |
| 34–36 | 12–14 | 35.0 | 12.8 | 1 |
| 34–36 | 16–18 | 34.7 | 17.3 | 3 |
| 34–36 | 18–20 | 34.0 | 19.5 | 1 |
| 34–36 | 20–22 | 34.5 | 20.8 | 4 |
| 34–36 | 22–24 | 34.3 | 22.7 | 4 |
| 34–36 | 24–26 | 34.0 | 25.0 | 3 |
| 34–36 | 26–28 | 34.3 | 27.1 | 4 |
| 34–36 | 28–30 | 34.8 | 28.4 | 4 |
| 36–38 | 6–8 | 36.0 | 7.8 | 1 |
| 36–38 | 10–12 | 36.0 | 11.4 | 1 |
| 36–38 | 12–14 | 36.0 | 13.8 | 1 |
| 36–38 | 16–18 | 36.5 | 17.4 | 2 |
| 36–38 | 18–20 | 36.0 | 19.1 | 4 |
| 36–38 | 20–22 | 36.0 | 21.0 | 5 |
| 36–38 | 22–24 | 37.0 | 23.1 | 1 |
| 36–38 | 24–26 | 36.7 | 24.9 | 3 |
| 36–38 | 26–28 | 36.0 | 26.5 | 2 |
| 36–38 | 28–30 | 36.0 | 29.2 | 1 |
| 38–40 | 14–16 | 39.0 | 14.4 | 1 |
| 38–40 | 16–18 | 38.0 | 17.2 | 2 |
| 38–40 | 18–20 | 39.0 | 19.1 | 1 |
| 38–40 | 22–24 | 38.7 | 22.5 | 3 |
| 38–40 | 24–26 | 39.0 | 24.5 | 1 |
| 40–42 | 16–18 | 40.8 | 17.0 | 4 |
| 40–42 | 18–20 | 41.0 | 18.9 | 2 |
| 40–42 | 20–22 | 41.0 | 20.3 | 1 |
| 40–42 | 22–24 | 40.5 | 22.1 | 2 |
| 40–42 | 24–26 | 40.5 | 25.4 | 4 |
| 40–42 | 26–28 | 40.0 | 26.8 | 1 |
| 40–42 | 28–30 | 40.3 | 28.8 | 4 |
| 42–44 | 22–24 | 43.0 | 23.8 | 1 |
| 42–44 | 24–26 | 42.0 | 24.1 | 1 |
| 42–44 | 26–28 | 42.7 | 27.3 | 3 |
| 42–44 | 28–30 | 42.0 | 29.1 | 1 |
| 44–46 | 24–26 | 45.0 | 24.4 | 1 |
| 44–46 | 26–28 | 45.0 | 26.1 | 1 |
| 46–48 | 26–28 | 47.0 | 27.9 | 1 |
| 50–52 | 22–24 | 51.0 | 22.4 | 1 |
| 50–52 | 28–30 | 51.0 | 28.9 | 1 |
| 52–54 | 18–20 | 53.0 | 19.9 | 1 |
| 58–60 | 28–30 | 60.0 | 29.0 | 1 |
Recent scoring drives the model.
Holdout permutation importance measures how much prediction error increases when the values of one feature are randomly rearranged across the holdout data, breaking its relationship with the outcome while leaving the other features unchanged. The player’s 10-game scoring average is by far the strongest signal in the points model, with recent minutes being the strongest secondary signal.
As some of the features contain overlapping information, the importance attributed to any one feature can be reduced because other features may still preserve part of the same signal. These values therefore represent how much the model relies on each feature beyond what is already captured by the other features, rather than the total predictive value of the broader signal that feature represents.
Permutation importance
Engineering, not just modeling
Reproducible artifacts
Serialized model pipelines include evaluation-window metadata so reported metrics can be reproduced later.
Automated testing
A pytest suite runs in GitHub Actions CI to catch regressions across the data and modeling pipeline.
CLI workflow
Evaluation reports are regenerated from saved models in one command instead of relying on a notebook-only workflow.
Database-backed pipeline
SQLAlchemy and SQLite provide a structured persistence layer for game and player-level records.
See the implementation.
The repository contains the data pipeline, feature engineering, model training, automated tests, evaluation CLI, and generated reporting workflow.
GitHub repo