Ghost-GK Sweeper v1 β€” Extended-Grid Goalkeeper Positioning (Rest-Defense)

Predicts where a league-average goalkeeper would position themselves, including the in-possession high-sweeper regime that the standard Ghost-GK v1 model cannot represent. Point-estimate (ghost_gk_x/y) served as the exact pickle-free boosted HistGradientBoostingRegressor mean.

Part of the silly-kicks soccer analytics library (TF-60 rest-defense; ADR-083).

Why a separate model

The bundled Ghost-GK default/full variants train on a fixed goal-relative box x ∈ [0, 30] m from the defended goal: a keeper who has swept far upfield falls outside it and is dropped as a "sweeper rush". That is correct for normal in-goal positioning, but it makes the model hard-saturate at 30 m β€” it cannot place an in-possession keeper who has pushed up to 30–45 m to blunt a counter-attack (the rest-defense regime). This sweeper variant lifts the label ceiling to x_max = 52.5 m so it represents the high-sweeper regime, for TF-60 rest-defense / TF-19 GKDV counterfactual arms.

The frozen default/position_only/full variants are unchanged β€” this is an additive variant; consumers opt in via from_variant("sweeper").

Variants

Variant Repo Features Use
sweeper (this repo) silly-kicks/ghost-gk-sweeper-v1 26 (velocity-bearing) Continuous tracking (Sportec, SkillCorner, Gradient Sports)
sweeper_position_only silly-kicks/ghost-gk-sweeper-position-only-v1 21 (5 velocity features dropped) Velocity-less StatsBomb-360 freeze-frames

Model description

  • Point estimate only. ghost_gk_x/y serve the exact boosted HGBR mean, reconstructed pickle-free (baseline + Σ_trees leaf_value; no sklearn at inference). The KDE density read-out (predict_density) is not supported on this extended grid and raises β€” the density path stays on the default 30 m grid (ADR-083). Use compute_ghost_gk / serve_ghost_gk_positions.
  • Grid: first-class per-model GhostGridSpec β€” x ∈ [0, 52.5] m, y ∈ [18, 50] m, 0.5 m resolution (105 Γ— 64 cells).
  • Parameters-only, pickle-free: npz (tree ensembles + baselines) + JSON metadata + SHA-256 checksums. No per-sample training data, no raw provider tracking data (ADR-044).
  • Hyperparameters: HistGradientBoostingRegressor, 500 trees, max depth 8, 5-fold CV.

Metrics

Metric Value
Held-out CV euclidean MAE 1.135 m (per-provider: Gradient Sports 1.071 / SkillCorner 1.166 / Sportec 1.717)
Boosted-reconstruction parity vs sklearn 1.14e-13 (exact β€” safe to publish)
> 30 m high-sweeper stratum MAE 1.96 m (the sweeper places high keepers where the default is blind)
Training corpus 179 games / 1048834 frames

The > 30 m (high-sweeper) coverage of the training corpus is IDSSE/Sportec-dominated (11.5 %); SkillCorner 0.24 %; Gradient Sports 0.0 % β€” see the data caveat below.

Both-axes goal-relative re-fit (silly-kicks 4.111.0 / ADR-089; training_commit=4bda048). These weights were re-fit after the ghost-GK feature extractor was corrected to apply the full 180Β° goal-relative point reflection (both axes) β€” the previous convention flipped only x, leaving the signed-y features and the target gk_y in absolute frame coordinates, mislocating away-team keepers in y. The served ghost_gk_x/y change (chiefly for away-team keepers) and the feature-contract + chirality fingerprints change, so pre-4.111.0 artifacts fail closed on load. The aggregate MAE is essentially unchanged (the correction affects the away-team subset).

Training data

179 matches / ~1.05M frames of licensed professional tracking (Sportec/DFL Bundesliga, SkillCorner, Gradient Sports FIFA World Cup 2022). Only the learned parameters are published; no raw provider tracking data is redistributed (parameters-only artifact). Trained from a clean, CI-green commit.

⚠ Gradient Sports goalkeeper clamp. Gradient Sports' tracking clamps the goalkeeper's position to a hard 27.5 m from goal (a source-data limitation, verified on the raw provider data; silly-kicks passes it through faithfully). Consequently GS contributes no high-sweeper training signal, and any GS goalkeeper-depth analysis is invalid past 27.5 m. The high-sweeper regime this model represents is learned from IDSSE/Sportec. silly-kicks flags this at conversion time via validate_gk_position_clamp / GoalkeeperClampWarning. See docs/research/gs_keeper_clamp/.

Usage

import silly_kicks.tracking as tracking

# The extended-grid sweeper (velocity-keyed within its family on velocity-less frames)
model = tracking.GhostGkModel.from_variant("sweeper")
out = tracking.compute_ghost_gk(frames, model=model, home_team_id=1)  # ghost_gk_x / ghost_gk_y

# predict_density is NOT supported on the extended grid (raises); use the mean/serve path above.

Input frames must be LTR-normalized (home attacks right). All coordinates are goal-relative.

Limitations

  • League-average positioning, not a specific keeper's style; no shot-stopping ability.
  • No KDE density on the extended grid (mean/serve path only).
  • Inherits tracking-system noise; Gradient Sports keeper positions are unusable past 27.5 m (above).
  • LTR normalization required; static per-frame estimate.

References

Le et al. 2017 (Data-Driven Ghosting, MIT Sloan); Dutta et al. 2024 (NFL Ghosts, arXiv:2406.17220); Pospisil & Lee 2018 (RFCDE, arXiv:1804.05753). See the silly-kicks NOTICE for full citations.

More information

  • License: MIT Β· Library: silly-kicks (v4.111.0+ for these both-axes weights) Β· GitHub Β· ADR-083 / ADR-089.

TF-65 velocity-gap re-fit (4.134.0)

TF-65 velocity-gap re-fit (silly-kicks 4.134.0 / ADR-120; training_commit=a34e992). Re-fit on the dense-grid-corrected floor velocities (TF-65 removed fabricated through-gap velocity on broadcast providers β€” the prior F1b float32 re-fit at 4.128.0 / ADR-106 is superseded); the metrics table above reflects this re-fit, and the mirror is republished to match the wheel.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Papers for silly-kicks/ghost-gk-sweeper-v1