Ten years of runs, one index
A random forest reads every workout since 2016, plus the hour-by-hour weather at each run's GPS point, and answers one question: how fast is a mile at heart rate 150 in standard conditions?
The fitness curve
Each month the model is asked the same question, a flat 5-miler at heart rate 150, 59°F, and answers with a pace. Training load is the rust area underneath; the pace line follows it with a lag.
| Year | Pace @ HR 150 | Avg CTL |
|---|---|---|
| 2019 | 9:24 | 4 |
| 2020 | 9:17 | 22 |
| 2021 | 9:18 | 18 |
| 2022 | 8:51 | 51 |
| 2023 | 8:10 | 84 |
| 2024 | 8:13 | 85 |
| 2025 | 8:17 | 77 |
| 2026 | 8:16 | 52 |
The 2022 to 2023 block is the whole story: training load went from 51 to 84 and bought back 41 seconds per mile at the same heart rate. The February 2026 layoff cost the index 7 seconds; the June rebuild has already recovered most of it.
What a hot day costs
Residuals from a weather-blind model, binned by apparent temperature: how much faster or slower each easy run was than the model expected, given effort, terrain, and training state.
The measured penalty is gentler than the textbook 10 seconds per 10°F, and the data shows why: July runs start four to five hours earlier in the day than January runs. The heat you never run in costs nothing.
What moves the needle
Permutation importance: how much prediction error rises when the model is denied each input. Heart rate dominates, as it should; training load is the strongest signal you can actually change.
Model & data
| Model | Forecast MAE | Interp MAE | Interp R² |
|---|---|---|---|
| Predict the mean | 0.225 | n/a | n/a |
| Ridge regression | 0.194 | 0.178 | 0.31 |
| Gradient boosting | 0.191 | 0.161 | 0.39 |
| Random forest | 0.181 | 0.158 | 0.42 |
MAE of 0.16 m/s is roughly 27 seconds per mile on a single run. The index averages over a month, which is where the signal lives. This is a fitness tracker, not a race predictor.
- Workouts pulled from Final Surge2,168
- Raw files downloaded (FIT + Apple Health)2,163
- Runs passing quality filters1,126
- Joined to hourly ERA5 weather98%
- Location-year weather cells71
- Max heart rate, verified 2024187
- Load model: Banister TRIMP, EWMA42 / 7 day