RAPM Base Predictions
The RAPM + Transformer model does not estimate its additive baseline inside the network. It consumes frozen possession predictions produced from the canonical stint-weighted ridge RAPM model. The analytical mart makes every base-model fit and prediction boundary explicit.
Location
data/analytical/rapm_base_predictions/<season>/regular/
_manifest.json
part-00000.parquet
rapm_player_coefficients.parquet
stage_parameters.parquet
The 2025-26 mart contains 929,003 stage-possession rows for 218,810 distinct eligible possessions. Rows repeat across stages because each model-selection or refit stage has its own RAPM training cutoff.
Stages
| Stage | RAPM training games | Prediction roles |
|---|---|---|
cv_0 |
677 | Train and validation |
cv_1 |
798 | Train and validation |
cv_2 |
920 | Train and validation |
final |
1,044 | Train and untouched test |
all_season |
1,230 | Train |
Every stage reuses the lambda selected by the source one-year RAPM run. It refits coefficients and the home-court intercept on only that stage's training stints.
Prediction conversion
For stage \(k\), RAPM predicts home net rating
Let \(s_i=+1\) for home offense and \(-1\) for away offense. The offense-oriented possession prediction is
where \(\overline y_k\) is mean offense margin among the stage's training possessions. The residual target is
Leakage boundary
Each row records stage, role, base_train_game_count, and
base_is_out_of_sample.
- Training rows use predictions from the RAPM fitted on that same stage's training games. This is ordinary residual fitting, analogous to fitting a second learner to a first learner's training residuals.
- Validation and test rows are predicted only by a RAPM fitted on earlier
games. Their
base_is_out_of_samplevalue must betrue. - The final 186 regular-season games and all playoff games remain absent from every model-selection fit.
The Transformer therefore never receives a base prediction from a RAPM model that used that evaluation game's outcome. This does not make training-row base predictions cross-fitted; that stricter stacking variant remains a future ablation.
Prediction rows
part-00000.parquet contains:
| Column | Meaning |
|---|---|
stage |
cv_0, cv_1, cv_2, final, or all_season |
role |
train, validation, or test |
base_is_out_of_sample |
Whether the game's outcome was excluded from RAPM fitting |
base_train_game_count |
Number of games available to that RAPM state |
rapm_home_net_rating |
Raw home-oriented RAPM prediction |
prediction_rapm |
Converted offense-margin prediction |
prediction_rapm_home_margin |
Converted home-margin prediction |
residual_target |
Actual offense margin minus prediction_rapm |
The remaining columns preserve the possession key, time, target, and home-offense sign.
Fitted states
rapm_player_coefficients.parquet contains one coefficient per stage and
player. stage_parameters.parquet records lambda, scikit-learn alpha,
intercept, training mean, train and prediction counts, and the exact training
cutoff.
The manifest hashes the source RAPM run, current RAPM stints, neural possessions, all three Parquet files, and the builder code. Existing RAPM-stint and neural-possession partitions are validated and reused rather than rewritten merely because a model command was invoked.
Correctness tests
tests/test_transformer_modeling.py perturbs validation outcomes and verifies
that their fold-specific RAPM predictions do not change. Runtime validation
also requires:
- identical chronological game splits between stints and possessions;
- prediction keys unique within stage;
- every non-training row marked out of sample;
- every evaluation game strictly after its stage's training cutoff;
- exact residual arithmetic;
- one retained coefficient per stage and player.
Run the focused checks with:
uv run pytest -q tests/test_transformer_modeling.py