How to use AI models to detect plateau points in training
Plateaus are not just a feeling; they show up in your data. With a small, sensible AI toolkit, you can spot diminishing returns early and adjust before motivation and fitness slip. The idea is simple: relate training load to performance and recovery, then flag when extra work stops moving the needle on your key metrics like FTP, power-duration curve, or submax endurance.
What a plateau looks like in your data
Think of a plateau as a period where performance is flat while load stays high, or where the cost of holding the same watts keeps rising. Typical signs include:
- FTP or 20-minute power stalls despite increasing weekly TSS or hours.
- Endurance decoupling (power vs. heart rate) worsens at the same steady pace.
- RPE drifts up for the same watts and duration.
- HRV trends down and morning heart rate creeps up.
- Training becomes monotonous (too similar day-to-day) and recovery lags.
| Signal | What it means | Typical threshold |
|---|---|---|
| FTP/20-min power trend | Output not rising | <1–2% gain over 4–6 weeks while weekly TSS is +10–15% |
| Endurance decoupling (Pa:Hr) | Inefficient aerobic base | >5–7% on a 60–90 min zone 2 ride |
| RPE at fixed watts | More cost for same work | +2 points vs. baseline at same watts and duration |
| HRV (rMSSD) | Strain outpacing recovery | 7-day avg >1 SD below 60-day mean |
| Training monotony | Lack of variation | >2.0 for 2 consecutive weeks (mean load / SD) |
| TSB (CTL–ATL) | Responsiveness check | TSB near 0 but performance flat for 2+ weeks |
None of these alone proves a plateau. AI helps combine them, quantify the trend, and give you a clear, timely nudge.
Model approaches that work for riders
1) Baseline and change-point detection
- Rolling slope: Fit a short rolling regression to your key metric (e.g., 20-min power or 95% of 20-min as FTP proxy). Flag when the slope is near zero while training load slope is positive.
- Change-point: Use cumulative sum (CUSUM) or Bayesian change-point methods to find when improvement flattens after a period of growth.
- Power-duration curve drift: If gains across your curve (e.g., 1, 5, 20, 60 min) are <1% over 21 days while CTL rises >3 points per week, you likely have diminishing returns.
2) Dose–response with training load
- Impulse–response (Banister) models: Use ATL (7-day EMA of TSS) and CTL (42-day EMA of TSS) to predict performance. When predicted performance gains per unit added load (marginal benefit) fall below a small threshold for several weeks, you are at a plateau.
- TSB responsiveness: If TSB returns to neutral or slightly positive and your 20-min or 5-min power does not rebound, your recent load is not translating into performance.
3) Machine learning predictors for small datasets
- Lightweight models: Gradient boosting or random forest can predict next-week performance using features such as CTL, ATL, TSB, monotony, zone distribution (time in zone 1/2/3+), HRV, sleep, and RPE.
- Uncertainty-aware: Gaussian process regression provides a prediction and confidence interval. Plateau risk rises when the model predicts little improvement with high confidence despite higher planned load.
- Feature importance: Use model explanations (e.g., SHAP) to see whether lack of easy volume, too much intensity in high zones, or poor sleep is driving the stall.
Keep it practical: start with rolling slopes and a dose–response fit. Add ML when you have consistent data over 12+ weeks.
A simple workflow you can implement this week
- Collect and align
Daily: power (watts), TSS or similar load, heart rate, HRV (morning rMSSD), RPE (0–10), sleep hours, and a short note on fueling and stress. Mark key tests (e.g., 20-min bests, 5-min VO2max efforts).
- Engineer features
- CTL (42-day EMA of TSS), ATL (7-day EMA), TSB = CTL − ATL.
- Training monotony = mean 7-day load / SD.
- Zone distribution: time in zone 1, 2, and 3+ (or 7-zone if you prefer).
- Endurance decoupling: compare first vs second half of a steady zone 2 ride.
- Fit a simple model
- Rolling slope of 20-min power and of PD-curve area (e.g., sum of best powers at 1–60 min).
- Optional: impulse–response model using CTL/ATL to predict 20-min power.
- Define plateau rules
- Performance slope >= 0% and < 0.25% per week for 21 days while CTL increases > 3 per week.
- Endurance decoupling > 5% in two consecutive submax tests.
- RPE at fixed watts +2 for two or more similar sessions.
- HRV 7-day avg >1 SD below 60-day mean for 5+ days.
- Validate the signal
- Require persistence for at least 7 days.
- Check confidence: if your model’s prediction interval overlaps zero change, be cautious.
- Cross-check context: heat, altitude, illness, travel, and menstrual cycle phase can shift baselines temporarily.
- Decide and adjust
When the plateau flag is on, act for 7–14 days, then retest:
- Deload: reduce volume by 30–50% for 3–5 days; keep 1 short high-intensity session to stay sharp.
- Change stimulus: swap threshold-heavy for VO2max micro-intervals (e.g., 30/15s), or move from polarized to pyramidal distribution for a block.
- Add strength: 2 sessions/week of lower-body lifts (e.g., squats, RDLs) in the general prep or base phases.
- Fuel recovery: 8–10 g/kg/day carbs in heavy weeks; 0.7–1.0 g/kg carbs plus 20–30 g protein within 60 minutes post-ride.
- Sleep target: 7–9 hours; add a 20–30 min nap on hard days if possible.
- Retest: after deload, do a 60–90 min zone 2 decoupling ride and a 5-min or 20-min benchmark within a week.
- Iterate monthly
Re-tune thresholds to your response. As FTP rises, the same absolute watts feel easier; your model should follow that evolution.
# Pseudocode: simple plateau flag
for each day:
CTL = ema(TSS, span=42)
ATL = ema(TSS, span=7)
TSB = CTL - ATL
monotony_7d = mean(TSS_last_7) / std(TSS_last_7)
# Weekly update
perf = rolling_best(power_20min, window=7)
perf_slope_21d = slope(last_21_days(perf))
ctl_slope_21d = slope(last_21_days(CTL))
plateau = (
perf_slope_21d >= 0 and perf_slope_21d < 0.0025 and
ctl_slope_21d > 0.1 and
decoupling_recent > 0.05 or
rpe_drift_recent >= 2 or
hrv_7d < (hrv_60d_mean - 1*hrv_60d_sd)
)
if plateau persists >= 7 days:
suggest(["deload", "change_stimulus", "fuel_sleep_focus"])
The goal is not perfect prediction. It is timely, defensible decisions: notice when more load is no longer buying you better watts, then change the input so adaptation resumes.