All projects

In the lab

Modeling athlete and team performance

A cross-country analytics suite built with a coach: Athletic.net ingestion, individual 5K time prediction, team-scoring simulation, and a meet-field explorer. The implemented tools sit alongside a newer research model focused on race ranking and uncertainty.

Status
Active
Signal
Connects historical race results to athlete predictions, course comparisons, team-scoring simulations, and meet-field exploration, while keeping data preparation, research models, and coach-facing tools separate.
Focus
Machine learning · Data pipelines · Evaluation · Sports

The question

What can historical race data say about an individual athlete's next performance, and how should those estimates combine when two teams meet?

I am working with a cross-country coach to make those questions useful in practice. The project now includes implemented data collection, individual-time prediction, team simulation, and meet-field exploration, alongside a newer modeling effort. The goal is not just a predicted time: it is a workflow that preserves the context behind a result and helps a coach compare plausible scenarios.

Four components, distinct responsibilities

xc-scraper owns the data foundation. It ingests Athletic.net results into a canonical SQLite database, maintains the schema and migrations, and supports venue and weather enrichment. Ingestion preserves athlete, school, meet, division, distance, and date relationships rather than treating every finishing time as an interchangeable observation.

xc-predictor contains the first prediction application: a PyTorch time model with a local FastAPI and React dashboard. It exposes individual predictions, course comparisons, training metrics, and meet simulations. Its initial scope is Michigan girls' 5K cross-country racing, not an unrestricted model for every athlete or event.

xc-model is a separate research rewrite. It introduces season-based data splits, normalization fitted on training data, athlete-history encoding, explicit race offsets, and ranking and uncertainty objectives. Its first per-athlete stage is implemented; field-level interaction modeling, calibration, and the complete inference path remain work in progress. It should not be confused with the model already connected to the predictor dashboard.

xc-meets approaches a different coaching question: which nearby meets offer a useful competitive field? A Next.js interface submits date-and-radius searches through same-origin API routes. Supabase stores the jobs, and a private Python worker discovers meets and produces comparison reports. The worker reads the race database and rating snapshots; it can use a native baseline or a legacy bridge to xc-predictor. It does not directly run xc-scraper or the newer xc-model pipeline.

From individual predictions to team outcomes

The first predictor combines an attention-pooled athlete history with course and race-context representations to estimate log finishing time. At inference, athlete history is cut off before the prediction date, and weather inputs can use defaults or explicit overrides. This makes the question about a future race rather than a reconstruction using that race's result.

Team simulation then applies cross-country scoring to the predicted field: the first five runners score, the sixth runner breaks team-score ties, and rosters are capped at seven runners. Incomplete teams are left unscored. Individual time error and team ordering are related, but they are not the same evaluation problem.

Evaluation is part of the architecture

The research rewrite uses season-based splits, strictly earlier athlete history, and training-only normalization to address temporal leakage. The meet explorer has a separate rolling-origin backtest workflow with season-specific training cutoffs. It compares candidates on a shared cohort using team-place error and pairwise accuracy, recording model and runtime provenance alongside the selection.

These are evaluation mechanisms, not proof of a general predictive advantage. The newer model still needs baseline comparisons, uncertainty calibration, and more complete evaluation across different groups and race conditions. I am leaving quantitative performance claims out of this page until the metric, comparison baseline, held-out split, and uncertainty can be presented together.

What the project is teaching me

The durable work is in the boundaries: a canonical dataset, a prediction date that controls which history is available, scoring rules that match the sport, and a clear separation between experimental models and the tools a coach can actually use. Keeping those boundaries explicit makes it possible to improve the model without disguising research progress as a finished result.