NBA Player Stat Prediction
An end-to-end Python pipeline for ingesting NBA data, engineering leakage-safe historical features, training gradient boosting models, and evaluating them against a rolling-average baseline on future games.
The problem
Predicting a player's next box-score line sounds simple until time enters the picture. A useful system has to learn only from information that would have actually been available before each game, and it has to be judged against a reasonable baseline rather than against nothing.
I built the project around that constraint: preserve chronology, avoid feature leakage, and make the evaluation reproducible from stored model artifacts.
From source data to reproducible evaluation.
Leakage prevention
Rolling statistics are shifted so that a row cannot use information from the game it is trying to predict. Training and validation also move forward through time rather than randomly shuffling past and future observations together.
That makes the reported holdout performance a more realistic test of how the system would behave on genuinely unseen future games.
Evaluation
The project compares tuned gradient boosting regressors with a 10-game rolling-average baseline on identical chronological holdout rows. For points, the model reached 4.85 MAE and outperformed the baseline in 23 of 28 trailing seven-day windows; the assists model won 22 of 28.
The visualizations below are rebuilt natively for this portfolio from the project's reporting data rather than embedded as exported chart images.
Trailing 7-day MAE
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
Recent scoring drives the model.
Holdout permutation importance measures how much prediction error increases when one feature is shuffled while the others stay intact. The player's 10-game scoring average dominates the points model, with recent minutes the strongest secondary signal.
Because several rolling features are correlated, these values describe the contribution of each feature given the others rather than a complete measure of the underlying basketball concept's importance.
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 in 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.
Open GitHub repository ↗