Can machine learning predict who wins the NBA's most prestigious individual award? This paper investigates that question using 16 seasons of game data spanning over 400 players. We trained seven models — from simple K-Nearest Neighbors to ensemble methods like Random Forest and Gradient Boosting — to predict each player's MVP vote share.
The results showed that SVM and Random Forest consistently outperformed the field, tracking actual vote shares within 3–5% for top candidates. KNN and AdaBoost systematically underestimated dominant MVP seasons — Jokic's 2021–22 campaign showed actual share 0.875 but KNN predicted only 0.700.
The model combines three sources to build a complete picture of each player's season: raw game performance, physical attributes, and historical voting outcomes.
Per-game stats covering PTS, FG%, 3P%, AST, STL, BLK, and minutes played across 16 NBA seasons from 2006–2022.
Height, weight, age, wingspan, and body composition data for contextualizing performance metrics relative to physical profile.
Historical MVP vote shares (0.0–1.0) as the regression target. Captures the full distribution of votes, not just the winner's binary outcome.
A 9-step pipeline transforms three raw datasets into model-ready training and test splits.
Scrape game stats, physiological data, and MVP voting records from Basketball Reference and NBA.com.
Handle missing values, remove duplicates, and standardize player name formatting across all three sources.
Join datasets on player ID and season year to create a unified player-season record per row.
Feature selection retains 8 most predictive metrics: PTS, MP, FG%, 3P%, 2P%, AST, STL, BLK.
StandardScaler normalizes all features to zero mean and unit variance — critical for SVM and KNN.
Train on 2006–2020, test on 2020–21 and 2021–22 to prevent any data leakage.
Fit all 7 models on the training set with hyperparameters tuned via cross-validation.
Run each model on the test seasons to generate predicted MVP vote shares for all eligible players.
Compare predictions to actual vote shares using MAE and R². Rank all 7 models by accuracy.
Core training pipeline from the GitHub repository. Features are standardized before fitting — critical for SVM and KNN, whose predictions are distance-based and scale-sensitive.
from sklearn.preprocessing import StandardScaler from sklearn.svm import SVR from sklearn.ensemble import RandomForestRegressor, AdaBoostRegressor from sklearn.neighbors import KNeighborsRegressor from sklearn.linear_model import ElasticNet from lightgbm import LGBMRegressor from xgboost import XGBRegressor FEATURES = ['PTS', 'MP', 'FG%', '3P%', '2P%', 'AST', 'STL', 'BLK'] TARGET = 'MVP_Vote_Share' # Normalize features — required for distance-based models (SVM, KNN) scaler = StandardScaler() X_train = scaler.fit_transform(df_train[FEATURES]) X_test = scaler.transform(df_test[FEATURES]) y_train, y_test = df_train[TARGET], df_test[TARGET] models = { "SVM": SVR(kernel='rbf', C=1.0), "RandomForest": RandomForestRegressor(n_estimators=100, random_state=42), "KNN": KNeighborsRegressor(n_neighbors=5), "AdaBoost": AdaBoostRegressor(random_state=42), "ElasticNet": ElasticNet(alpha=0.01), "LightGBM": LGBMRegressor(n_estimators=100), "XGBoost": XGBRegressor(n_estimators=100), } for name, model in models.items(): model.fit(X_train, y_train) preds = model.predict(X_test) evaluate(name, y_test, preds)
Feature Importance (Random Forest)
Uses a radial basis function kernel to map player stats into high-dimensional space, finding the hyperplane that best predicts vote share. Excels at capturing non-linear scoring-voting relationships.
Ensemble of 100 decision trees. Each tree votes on predicted vote share; the forest averages them. Naturally handles feature interactions and provides interpretable feature importances.
Predicts vote share by averaging the 5 most similar player-seasons. Struggles with outlier seasons — dominant years have no close neighbors, causing systematic underestimation.
Sequentially boosts weak learners by focusing on previously misclassified samples. Performs worst on runaway MVP seasons — the training distribution underweights extreme vote share values.
Tested on the 2020–21 and 2021–22 NBA seasons. The gap between models was largest for dominant MVP seasons with historically high vote shares.
Model Accuracy Ranking
How the best models tracked against actual vote shares for each MVP winner from 2013–22.
| Season | MVP Winner | Actual | SVM | RF | Best |
|---|---|---|---|---|---|
| 2021–22 | Nikola Jokic | 0.875 | 0.848 | 0.862 | RF |
| 2020–21 | Nikola Jokic | 0.731 | 0.710 | 0.688 | SVM |
| 2019–20 | Giannis Antetokounmpo | 0.960 | 0.932 | 0.944 | RF |
| 2018–19 | Giannis Antetokounmpo | 0.781 | 0.740 | 0.758 | RF |
| 2017–18 | James Harden | 0.712 | 0.695 | 0.672 | SVM |
| 2016–17 | Russell Westbrook | 0.822 | 0.778 | 0.800 | RF |
| 2015–16 | Stephen Curry | 1.000 | 0.956 | 0.972 | RF |
| 2013–14 | Kevin Durant | 0.921 | 0.893 | 0.907 | RF |
Both models tracked within 3–5% for dominant MVP seasons. Their ability to model non-linear relationships between raw stats and voting behaviour gave them a consistent edge over linear and distance-based approaches.
Both methods systematically underpredicted runaway winners like Jokic and Giannis. KNN averages nearest neighbors — which underweights unprecedented seasons. AdaBoost reweights toward historically common outcomes, missing historical outliers.
Points per game and minutes played held the highest feature importance across all ensemble models. This matches intuition — voters reward availability and scoring volume simultaneously.
Win percentage is historically significant in real-world MVP voting — no player has won from a losing team in decades — but it was absent from this dataset. Adding team-level context would likely improve every model.
Paper, source code, and published writeup in Curieux Review.