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.

TargetPredictorMAERMSER²
PointsLightGBM model4.7646.1600.457
Last-10-game mean4.9086.3930.415
Season-to-date mean4.9466.4670.401
ReboundsLightGBM model1.9422.5270.402
Last-10-game mean2.0092.6440.346
Season-to-date mean2.0082.6590.338
AssistsLightGBM model1.4311.9090.461
Last-10-game mean1.4601.9670.427
Season-to-date mean1.4561.9730.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.

TargetModel MAELast-10 MAELower error
Points4.8644.679last-10 baseline
Rebounds2.0231.939last-10 baseline
Assists1.4031.374last-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.

TargetHoldout MAEReplayed MAEDifferenceModel MAE, all rows
Points4.76444.7665+0.00214.8639
Rebounds1.94211.9429+0.00082.0228
Assists1.43101.4320+0.00101.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.