NBA Stat Predictor
A batch pipeline that predicts a player's points, rebounds, and assists for a game from that player's history before the game. One LightGBM regressor per target is trained on four seasons of box scores and evaluated on a full held-out season against two simple baselines. Every number on this site is read from files published by the pipeline; nothing is typed in by hand.
Holdout results (training population)
Trained on 2021-22, 2022-23, 2023-24, 2024-25 (2021-10-19 to 2025-04-13, 88,257 player-games). Held out: all of 2025-26 (2025-10-21 to 2026-04-12). Rows are limited to games where the player logged at least 10 minutes; all three predictors are scored on the same 22,244 holdout rows.
| Target | Predictor | MAE | RMSE | R² |
|---|---|---|---|---|
| Points | LightGBM model | 4.764 | 6.160 | 0.457 |
| Last-10-game mean | 4.908 | 6.393 | 0.415 | |
| Season-to-date mean | 4.946 | 6.467 | 0.401 | |
| Rebounds | LightGBM model | 1.942 | 2.527 | 0.402 |
| Last-10-game mean | 2.009 | 2.644 | 0.346 | |
| Season-to-date mean | 2.008 | 2.659 | 0.338 | |
| Assists | LightGBM model | 1.431 | 1.909 | 0.461 |
| Last-10-game mean | 1.460 | 1.967 | 0.427 | |
| Season-to-date mean | 1.456 | 1.973 | 0.424 |
Population: players with at least 10 minutes and both baselines defined (the training population). Source: metrics.json for model commit 50a3b2e / HF fb427de, trained 2026-09-12, dataset hf:b20b5601de213fa8e704ebffaafd18f182ea68c3. Warehouse cross-check (gold/mart_holdout_metrics.json in the dataset repo (the warehouse's gold export, exported 2026-10-11 on target motherduck), population min10 on the replay rows, n 22,075): model MAE points 4.766, rebounds 1.943, assists 1.432; the dbt test assert_holdout_metrics_reconcile_to_metrics_json holds these within 0.005 of the table above (the replay never slated 169 of the holdout rows).
All rows (replay population)
The same model and the last-10-game baseline on every replayed player-game with a box score and a last-10 baseline for every target (all rows): 26,031 rows of 2025-26, row-weighted in the warehouse. This population is wider than the headline one (it includes games under 10 minutes), and on it the last-10 baseline has the lower MAE on every target.
| Target | Model MAE | Last-10 MAE | Lower error |
|---|---|---|---|
| Points | 4.864 | 4.679 | last-10 baseline |
| Rebounds | 2.023 | 1.939 | last-10 baseline |
| Assists | 1.403 | 1.374 | last-10 baseline |
Population: every replayed player-game with a box score and a last-10 baseline for every target (all rows). Source: gold/mart_holdout_metrics.json in the dataset repo (the warehouse's gold export, exported 2026-10-11 on target motherduck), population all on the 2025-26 replay rows; the warehouse test assert_daily_metrics_reconcile_to_all_rows_report holds these rows to the committed report reports/replay_all_rows_2025-26.json, which is the fallback. The same numbers drive the replay page.
Replay equivalence
The nightly slate was replayed for every game date of 2025-26 using only data available before each date (164 dates, 38,372 slated player-games, 26,031 with a box score), with model commit 50a3b2e / HF fb427de. On the same population as the holdout report (the training population, 22,075 rows) the replayed MAE matches within the 0.05 tolerance: passed.
| Target | Holdout MAE | Replayed MAE | Difference | Model MAE, all rows |
|---|---|---|---|---|
| Points | 4.7644 | 4.7665 | +0.0021 | 4.8639 |
| Rebounds | 1.9421 | 1.9429 | +0.0008 | 2.0228 |
| Assists | 1.4310 | 1.4320 | +0.0010 | 1.4029 |
Populations: the first three columns use the training population; the last column uses every replayed row with a box score (26,031 rows; its baseline is in the table above). 617 actual player-games (367 with 10+ minutes) were never slated because the player had not appeared in his team's previous ten games. Daily chart and a sample slate. A tool-using analyst writes a nightly brief from these files.