AGMT2 Technical Reports · ednaLabs Companion [DM-D] · K₁K₂T₁T₂ via TSS · Bayesian Estimation Companion [DM-D] · K₁K₂T₁T₂ via TSS · Estimación Bayesiana
Technical Note · Companion [DM-D]Nota Técnica · Companion [DM-D]

Estimating K₁, K₂, T₁, T₂
Using Hierarchical Bayesian NLSS
Estimación de K₁, K₂, T₁, T₂
Mediante NLSS Bayesiano Jerárquico

A comparison between the classical Skiba & Clarke NLLS method and a hierarchical Bayesian extension — NLSS (Nonlinear Least Squares with Shrinkage) — that regularizes parameter estimation via a population-derived Mahalanobis prior, requiring only daily TSS and occasional power tests.Una comparación entre el método clásico de Skiba & Clarke (NLLS) y una extensión bayesiana jerárquica — NLSS (Mínimos Cuadrados No Lineales con Contracción) — que regulariza la estimación de parámetros mediante un prior de Mahalanobis derivado de la población, requiriendo únicamente TSS diario y tests de potencia ocasionales.

Gabriel Della Mattia
AGMT2 Team · ednaLabs · Argentina · 2026
AreaÁrea
Sports Science · Mathematical MethodsCiencias del Deporte · Métodos Matemáticos
DocumentDocumento
Companion [DM-D]
Input signalSeñal de entrada
TSS + occasional power testsTSS + tests de potencia ocasionales
AccessibilityAccesibilidad
Any athlete with a power meterCualquier atleta con potenciómetro
§ 01

The Skiba & Clarke Influence Curve ModelEl Modelo de Curva de Influencia de Skiba & Clarke

Banister's IR-Model (1975) describes athletic performance as the superposition of two exponential responses to training load: a slow positive one — fitness — and a fast negative one — fatigue. Skiba & Clarke formalized the core question: how much does a session performed on day \(\tau\) contribute to the projected performance on day \(t\)?El modelo IR de Banister (1975) describe el rendimiento deportivo como la superposición de dos respuestas exponenciales a la carga de entrenamiento: una positiva lenta — fitness — y una negativa rápida — fatiga. Skiba & Clarke formalizaron la pregunta central: ¿cuánto contribuye una sesión realizada el día \(\tau\) al rendimiento proyectado en el día \(t\)?

$$I(\tau,\,t) \;=\; K_1\,e^{-(t-\tau)/T_1} \;-\; K_2\,e^{-(t-\tau)/T_2}$$
(1)

The curve is biphasic: fatigue dominates immediately (fast decay \(T_2\)); after a zero-crossing the adaptation emerges (slow decay \(T_1\)). Projected performance on day \(t\) is the cumulative convolution of the entire TSS history:La curva es bifásica: la fatiga domina inmediatamente (decaimiento rápido \(T_2\)); después de un cruce por cero emerge la adaptación (decaimiento lento \(T_1\)). El rendimiento proyectado en el día \(t\) es la convolución acumulada de todo el historial de TSS:

$$\hat{p}(t) \;=\; p_0 \;+\; \sum_{\tau\,<\,t} \mathrm{TSS}(\tau)\cdot I(\tau,\,t)$$
(2)
where \(p_0\) is the baseline performance and \(\mathrm{TSS}(\tau)\) is the training load on day \(\tau\). The optimal competition day satisfies \(t^* = \arg\max_t\,\hat{p}(t)\).donde \(p_0\) es el rendimiento basal y \(\mathrm{TSS}(\tau)\) es la carga de entrenamiento del día \(\tau\). El día óptimo de competición satisface \(t^* = \arg\max_t\,\hat{p}(t)\).
ParameterParámetroMeaningSignificadoPractical effectEfecto prácticoTrainingPeaks (fixedfijo)
\(K_1\)Fitness gain per TSS unitGanancia de fitness por unidad de TSSHow much fitness rises per sessionCuánto sube el fitness por sesión1.0 — underestimated ×2.91.0 — subestimado ×2.9
\(K_2\)Fatigue gain per TSS unitGanancia de fatiga por unidad de TSSHow much form drops per sessionCuánto cae la forma por sesión1.0 — underestimated ×4.11.0 — subestimado ×4.1
\(T_1\)Fitness time constantConstante temporal de fitnessDays the positive effect persistsDías que persiste el efecto positivo42 d — approximate mean42 d — media aproximada
\(T_2\)Fatigue time constantConstante temporal de fatigaDays for fatigue to dissipateDías para que se disipe la fatiga7 d — approximate mean7 d — media aproximada
Table 1. The four parameters and the fixed values TrainingPeaks applies to the entire population.Tabla 1. Los cuatro parámetros y los valores fijos que TrainingPeaks aplica a toda la población.
Visualization 1 · Influence curve \(I(\tau,t)\) — parameter explorerInteractive

Select a preset or move the sliders. The zero-crossing is the day the net effect turns positive. The form peak shows how many days after a session the athlete reaches peak readiness. Compare TrainingPeaks vs AGMT2 Mean to see the concrete impact of incorrect \(K_1\) and \(K_2\).Seleccione un preset o mueva los controles. El cruce por cero es el día en que el efecto neto se vuelve positivo. El pico de forma indica cuántos días después de una sesión el atleta alcanza su mejor disposición. Compare TrainingPeaks vs AGMT2 Mean para ver el impacto concreto de \(K_1\) y \(K_2\) incorrectos.

Preset:
K₁ — fitness gain
1.00
K₂ — fatigue gain
1.00
T₁ days — fitness decay
42
T₂ days — fatigue decay
7
Net influence \(I(d)\) \(+K_1\,e^{-d/T_1}\) (fitness) \(-K_2\,e^{-d/T_2}\) (fatigue)
Zero-crossing
Form peak
Ratio K₂/K₁
Influence at d=20
§ 02

Classical NLLS Method with TSSMétodo Clásico NLLS con TSS

The approach proposed by Skiba & Clarke for estimating the four parameters is nonlinear least squares (NLLS): find the set \(\{K_1,K_2,T_1,T_2\}\) that minimizes the discrepancy between predicted performance \(\hat{p}(d;\theta)\) and the maximum power tests collected throughout the season.El enfoque propuesto por Skiba & Clarke para estimar los cuatro parámetros es mínimos cuadrados no lineales (NLLS): encontrar el conjunto \(\{K_1,K_2,T_1,T_2\}\) que minimiza la discrepancia entre el rendimiento predicho \(\hat{p}(d;\theta)\) y los tests de potencia máxima recolectados a lo largo de la temporada.

$$\{K_1^*,K_2^*,T_1^*,T_2^*\} \;=\; \underset{\theta}{\arg\min}\;\sum_{d\,\in\,\mathcal{D}_\text{tests}}\!\bigl(p(d) - \hat{p}(d;\,\theta)\bigr)^2$$
(3)
where \(p(d)\) is the maximum power measured on test day \(d\), and \(\mathcal{D}_\text{tests}\) is the set of days with an available power test. The practical implementation in eq. (5a) normalizes by \(1/n\) to make gradient magnitude independent of the number of tests in the window.donde \(p(d)\) es la potencia máxima medida el día de test \(d\), y \(\mathcal{D}_\text{tests}\) es el conjunto de días con test de potencia disponible. La implementación práctica en la ec. (5a) normaliza por \(1/n\) para que la magnitud del gradiente sea independiente del número de tests en la ventana.
Classical NLLS — structural problemsNLLS Clásico — problemas estructurales

Data scarcity. Calibrating 4 nonlinear parameters requires tests distributed across distinct phases. Most athletes accumulate 4–8 tests per year, yielding an observations-to-parameters ratio of ~1.5:1.Escasez de datos. Calibrar 4 parámetros no lineales requiere tests distribuidos en fases distintas. La mayoría de los atletas acumulan 4–8 tests por año, con una ratio observaciones/parámetros de ~1.5:1.

Non-identifiability. The loss landscape has multiple equivalent local minima (Busso, 2003). Different \(\{K_1,K_2,T_1,T_2\}\) combinations produce identical fits on sparse data.No-identificabilidad. El paisaje de la función de costo tiene múltiples mínimos locales equivalentes (Busso, 2003). Diferentes combinaciones de \(\{K_1,K_2,T_1,T_2\}\) producen ajustes idénticos con datos escasos.

No signal between tests. The 350+ daily TSS values between tests are used only as convolution input — never as a direct calibration signal.Sin señal entre tests. Los 350+ valores diarios de TSS entre tests se usan solo como entrada de convolución — nunca como señal directa de calibración.

TrainingPeaks — the wrong solution to the same problemTrainingPeaks — la solución incorrecta al mismo problema

Fixed values for the whole population. Rather than solving NLLS, TP sets \(K_1=K_2=1,\;T_1=42\text{d},\;T_2=7\text{d}\) for all athletes.Valores fijos para toda la población. En lugar de resolver NLLS, TP establece \(K_1=K_2=1,\;T_1=42\text{d},\;T_2=7\text{d}\) para todos los atletas.

Systematically incorrect \(K_1\) and \(K_2\). True AGMT2 values are \(K_1\approx2.87\) and \(K_2\approx4.09\) — ×2.9 and ×4.1 larger. The PMC simultaneously underestimates fitness and fatigue.\(K_1\) y \(K_2\) sistemáticamente incorrectos. Los valores reales de AGMT2 son \(K_1\approx2.87\) y \(K_2\approx4.09\) — ×2.9 y ×4.1 mayores. El PMC subestima simultáneamente fitness y fatiga.

Measurable taper error. An athlete with \(T_1=36.4\text{d}\) would arrive at competition with 6 days of invisible residual fatigue when using TP's parameters.Error de taper medible. Un atleta con \(T_1=36.4\text{d}\) llegaría a la competición con 6 días de fatiga residual invisible usando los parámetros de TP.

Visualization 2 · The NLLS problem — few tests, multiple local minimaVisualización 2 · El problema NLLS — pocos tests, múltiples mínimos localesDiagnosticDiagnóstico

The chart shows simulated season performance for four representations. Vary the number of tests and their distribution to see how classical NLLS diverges from the true performance when data are scarce.El gráfico muestra rendimiento de temporada simulado para cuatro representaciones. Varíe la cantidad de tests y su distribución para ver cómo el NLLS clásico diverge del rendimiento real cuando los datos son escasos.

Available tests: Distribution:
What each curve representsQué representa cada curva
True athlete performance — reference curve generated with the athlete's real parameters (\(K_1=2.87,\;T_1=40.6\text{d}\)). This is the target any estimator should reproduce.Rendimiento real del atleta — curva de referencia generada con los parámetros reales del atleta (\(K_1=2.87,\;T_1=40.6\text{d}\)). Este es el objetivo que cualquier estimador debería reproducir.
TrainingPeaks prediction — performance modeled with the platform's fixed values (\(K_1=1,\;K_2=1,\;T_1=42\text{d}\)). Identical for every athlete regardless of test count.Predicción TrainingPeaks — rendimiento modelado con los valores fijos de la plataforma (\(K_1=1,\;K_2=1,\;T_1=42\text{d}\)). Idéntico para todo atleta sin importar la cantidad de tests.
Classical NLLS prediction — performance modeled with parameters calibrated by least-squares on the available tests. With few tests the parameters are unstable and the curve diverges.Predicción NLLS clásico — rendimiento modelado con parámetros calibrados por mínimos cuadrados sobre los tests disponibles. Con pocos tests los parámetros son inestables y la curva diverge.
Maximum power tests — the only observation points available to NLLS (20'/5'/3' efforts). More tests, better distributed, improve parameter identifiability.Tests de potencia máxima — los únicos puntos de observación disponibles para NLLS (esfuerzos de 20'/5'/3'). Más tests, mejor distribuidos, mejoran la identificabilidad de los parámetros.
Available tests
Obs/params ratio
Local minima
Phases covered
§ 03

Hierarchical Bayesian NLLS with TSSNLLS Bayesiano Jerárquico con TSS

The proposed improvement requires no additional sensors. It uses the same daily TSS any athlete already records, but applies two fundamental changes to the classical estimator.La mejora propuesta no requiere sensores adicionales. Utiliza el mismo TSS diario que cualquier atleta ya registra, pero aplica dos cambios fundamentales al estimador clásico.

Core ideaIdea central

1. Hierarchical Bayesian prior.1. Prior Bayesiano Jerárquico. Instead of searching unconstrained \(\mathbb{R}^4\), the estimator starts from the empirical distribution observed in the 30-athlete AGMT2 cohort. The Mahalanobis penalty prevents convergence to spurious local minima and corrects \(K_1\) and \(K_2\) from day one.En lugar de buscar en \(\mathbb{R}^4\) sin restricciones, el estimador comienza a partir de la distribución empírica observada en la cohorte de 30 atletas AGMT2. La penalización de Mahalanobis evita la convergencia a mínimos locales espurios y corrige \(K_1\) y \(K_2\) desde el primer día.

2. 90-day sliding window.2. Ventana deslizante de 90 días. Rather than waiting for all season tests before calibrating, the estimator recalibrates every week — capturing mid-season fitness changes and reducing dependence on sporadic tests.En lugar de esperar todas las pruebas de la temporada antes de calibrar, el estimador se recalibra cada semana, capturando cambios de fitness intra-temporada y reduciendo la dependencia de pruebas esporádicas.

$$\hat{\theta}^{\,i}_d \;=\; \underset{\theta}{\arg\min}\;\Bigl[\underbrace{\sum_{d'\,\in\,\mathcal{W}_t}\!\bigl(p(d')-\hat{p}(d';\theta)\bigr)^2}_{\mathcal{L}_\text{data}} \;+\; \lambda\cdot\underbrace{d_M^2\!\bigl(\theta,\;\mu_\text{pop},\Sigma_\text{pop}\bigr)}_{\mathcal{L}_\text{prior}}\Bigr]$$
(4)
Sliding window \(\mathcal{W}_t=[t-L,\,t]\) with \(L=90\) days. High \(\lambda\) (few data) → prior dominates. Low \(\lambda\) (many data) → progressive individualization.Ventana deslizante \(\mathcal{W}_t=[t-L,\,t]\) con \(L=90\) días. \(\lambda\) alto (pocos datos) → prior domina. \(\lambda\) bajo (muchos datos) → individualización progresiva.

The population prior \(\mathcal{P}_\text{pop}=\mathcal{N}(\mu_\text{pop},\Sigma_\text{pop})\) is built from the 30 calibrated AGMT2 athletes (intervals are ±2σ):El prior poblacional \(\mathcal{P}_\text{pop}=\mathcal{N}(\mu_\text{pop},\Sigma_\text{pop})\) se construye a partir de los 30 atletas AGMT2 calibrados (los intervalos son ±2σ):

2.27 — 3.47
\(\mu = 2.87\)
Prior K₁
3.42 — 4.76
\(\mu = 4.09\)
Prior K₂
34.45 — 46.83 d
\(\mu = 40.6\text{ d}\)
Prior T₁
5.28 — 7.89 d
\(\mu = 6.6\text{ d}\)
Prior T₂

The complete algorithm, step by stepEl algoritmo completo, paso a paso

The method replaces the unconstrained NLLS minimization with a regularized optimization via analytic gradient, executed every week on a sliding window. Each component is described with sufficient precision for direct implementation.El método reemplaza la minimización NLLS sin restricciones con una optimización regularizada mediante gradiente analítico, ejecutada cada semana en una ventana deslizante. Cada componente se describe con precisión suficiente para implementación directa.

A · Regularized cost functionA · Función de costo regularizada

The Bayesian method adds a second term penalizing departure from the known cohort distribution:El método Bayesiano añade un segundo término que penaliza el alejamiento de la distribución de la cohorte conocida:

$$\mathcal{L}(\theta) \;=\; \mathcal{L}_\text{data}(\theta) \;+\; \lambda(n)\cdot\mathcal{L}_\text{prior}(\theta)$$
(5)
$$\mathcal{L}_\text{data}(\theta) \;=\; \frac{1}{n}\sum_{d\,\in\,\mathcal{W}_t}\bigl(p(d) - \hat{p}(d;\,\theta)\bigr)^2$$
(5a)
Mean squared error over the \(n\) power tests in the sliding window \(\mathcal{W}_t=[t-L,\,t]\).Error cuadrático medio sobre las \(n\) pruebas de potencia en la ventana deslizante \(\mathcal{W}_t=[t-L,\,t]\).
$$\mathcal{L}_\text{prior}(\theta) \;=\; d_M^2\!\bigl(\theta,\;\mu_\text{pop},\Sigma_\text{pop}\bigr) \;=\; (\theta-\mu_\text{pop})^\top\,\Sigma_\text{pop}^{-1}\,(\theta-\mu_\text{pop})$$
(5b)
Squared Mahalanobis distance to the AGMT2 cohort centroid. \(\theta=[K_1,K_2,T_1,T_2]^\top\); \(\mu_\text{pop}\) and \(\Sigma_\text{pop}\) built from the 30-athlete cohort. This is proportional to the quadratic term of the KL divergence between two Gaussians with equal covariance, providing a natural metric-adapted regularization that respects the parameter correlation structure.Distancia de Mahalanobis al cuadrado al centroide de la cohorte AGMT2. \(\theta=[K_1,K_2,T_1,T_2]^\top\); \(\mu_\text{pop}\) y \(\Sigma_\text{pop}\) construidos a partir de la cohorte de 30 atletas. Esto es proporcional al término cuadrático de la divergencia KL entre dos gaussianas con covarianza igual, proporcionando una regularización adaptada naturalmente a la métrica que respeta la estructura de correlación de parámetros.

B · Adaptive regularization factor \(\lambda(n)\)B · Factor de regularización adaptativo \(\lambda(n)\)

\(\lambda\) decreases with the number of tests in the current window. With few data points the prior dominates; with many, the athlete progressively individualizes.\(\lambda\) disminuye con el número de pruebas en la ventana actual. Con pocos puntos de datos el prior domina; con muchos, el atleta se individualiza progresivamente.

$$\lambda(n) \;=\; \lambda_{\max}\cdot\exp\!\!\left(-\frac{n}{n_{1/2}}\right), \qquad \lambda_{\max}=5.0,\quad n_{1/2}=4$$
(6)
\(n=0\) tests: \(\lambda=5.0\) (prior dominates)  ·  \(n=4\): \(\lambda\approx1.84\)  ·  \(n=8\): \(\lambda\approx0.67\)  ·  \(n=12\): \(\lambda\approx0.25\) (data dominate). Values calibrated on AGMT2 via leave-future-out cross-validation.\(n=0\) pruebas: \(\lambda=5.0\) (prior domina)  ·  \(n=4\): \(\lambda\approx1.84\)  ·  \(n=8\): \(\lambda\approx0.67\)  ·  \(n=12\): \(\lambda\approx0.25\) (datos dominan). Valores calibrados en AGMT2 mediante validación cruzada leave-future-out.

C · Analytic gradient of \(\mathcal{L}(\theta)\)C · Gradiente analítico de \(\mathcal{L}(\theta)\)

Optimization is performed with L-BFGS-B (Byrd et al., 1995), which requires \(\partial\mathcal{L}/\partial\theta\). The gradient has two summable components:La optimización se realiza con L-BFGS-B (Byrd et al., 1995), que requiere \(\partial\mathcal{L}/\partial\theta\). El gradiente tiene dos componentes sumables:

$$\frac{\partial\mathcal{L}}{\partial\theta} \;=\; \frac{\partial\mathcal{L}_\text{data}}{\partial\theta} \;+\; \lambda(n)\cdot\frac{\partial\mathcal{L}_\text{prior}}{\partial\theta}$$
(7)
$$\begin{aligned} \frac{\partial\mathcal{L}_\text{data}}{\partial K_1} &\;=\; -\frac{2}{n}\sum_d\bigl(p(d)-\hat{p}\bigr)\sum_{\tau<d}\!\mathrm{TSS}(\tau)\,e^{-(d-\tau)/T_1}\\[8pt] \frac{\partial\mathcal{L}_\text{data}}{\partial K_2} &\;=\; +\frac{2}{n}\sum_d\bigl(p(d)-\hat{p}\bigr)\sum_{\tau<d}\!\mathrm{TSS}(\tau)\,e^{-(d-\tau)/T_2}\\[8pt] \frac{\partial\mathcal{L}_\text{data}}{\partial T_1} &\;=\; -\frac{2K_1}{n}\sum_d\bigl(p(d)-\hat{p}\bigr)\sum_{\tau<d}\!\mathrm{TSS}(\tau)\,\frac{d-\tau}{T_1^2}\,e^{-(d-\tau)/T_1}\\[8pt] \frac{\partial\mathcal{L}_\text{data}}{\partial T_2} &\;=\; +\frac{2K_2}{n}\sum_d\bigl(p(d)-\hat{p}\bigr)\sum_{\tau<d}\!\mathrm{TSS}(\tau)\,\frac{d-\tau}{T_2^2}\,e^{-(d-\tau)/T_2} \end{aligned}$$
(8)
$$\frac{\partial\mathcal{L}_\text{prior}}{\partial\theta} \;=\; 2\,\Sigma_\text{pop}^{-1}\,(\theta - \mu_\text{pop})$$
(9)
\(\Sigma_\text{pop}^{-1}\) is the precision matrix — constant, computed once. Diagonal entries: \(1/\sigma^2(K_1),\;1/\sigma^2(K_2),\;1/\sigma^2(T_1),\;1/\sigma^2(T_2)\).\(\Sigma_\text{pop}^{-1}\) es la matriz de precisión — constante, calculada una vez. Entradas diagonales: \(1/\sigma^2(K_1),\;1/\sigma^2(K_2),\;1/\sigma^2(T_1),\;1/\sigma^2(T_2)\).

D · Domain constraints (box constraints)D · Restricciones de dominio (box constraints)

L-BFGS-B enforces per-parameter bounds, eliminating physiologically impossible solutions. Combined with the Mahalanobis prior, they remove virtually all spurious local minima of the unconstrained NLLS.L-BFGS-B impone límites por parámetro, eliminando soluciones fisiológicamente imposibles. Combinados con el prior de Mahalanobis, eliminan virtualmente todos los mínimos locales espurios del NLLS sin restricciones.

ParameterParámetroLower boundLímite inferiorUpper boundLímite superiorPhysiological justificationJustificación fisiológica
\(K_1\)0.208.00Fitness gain cannot be negative or disproportionateLa ganancia de fitness no puede ser negativa o desproporcionada
\(K_2\)0.2012.00Fatigue gain cannot be negativeLa ganancia de fatiga no puede ser negativa
\(T_1\)14 days80 daysPhysiologically impossible outside this rangeFisiológicamente imposible fuera de este rango
\(T_2\)3 days18 daysAcute fatigue cannot last months or vanish in hoursLa fatiga aguda no puede durar meses ni desaparecer en horas
Table 2. Box constraints for L-BFGS-B.Tabla 2. Restricciones de caja para L-BFGS-B.

E · Sliding window protocol — Algorithm 1E · Protocolo de ventana deslizante — Algoritmo 1

The recalibration algorithm runs every 7 days. The warm start (initializing L-BFGS-B from the previous week's \(\theta\)) reduces iterations from ~200 to ~30 in stable weeks, making the algorithm viable on limited hardware.El algoritmo de recalibración se ejecuta cada 7 días. El warm start (inicializar L-BFGS-B desde el \(\theta\) de la semana anterior) reduce las iteraciones de ~200 a ~30 en semanas estables, haciendo el algoritmo viable en hardware limitado.

Algorithm 1 · Weekly recalibration with sliding windowAlgoritmo 1 · Recalibración semanal con ventana deslizante
PARAMETERS:   L = 90 days (window) · tol = 1e-5 · max_iter = 500
              λ_max = 5.0 · n_half = 4

INITIALIZATION (season day 0):
  θ_current  ←  μ_pop = [2.87, 4.09, 40.64, 6.58]

WEEKLY LOOP  (every 7 days, on day t):

  1. UPDATE WINDOW
       W_t ← { power tests in range [t − L,  t] }
       n   ← |W_t|   // number of tests in window

  2. UPDATE λ
       λ ← λ_max · exp(−n / n_half)    // eq. (6)

  3. IF n == 0  // no tests in window
       θ_current ← μ_pop    // no data → pure prior
       CONTINUE to next cycle

  4. BUILD PREDICTION for each test d ∈ W_t:
       p̂(d;θ) ← p₀ + Σ_{τ<d} TSS(τ)·[K₁·exp(−(d−τ)/T₁) − K₂·exp(−(d−τ)/T₂)]

  5. OPTIMIZE with L-BFGS-B:
       θ_init ← θ_current         // warm start from previous week
       θ_new  ← argmin L(θ)  subject to box constraints
                using analytic gradient eqs. (7)–(9)

  6. CONVERGENCE CHECK & REJECTION:
       IF ‖θ_new − θ_current‖ / ‖θ_current‖ < tol:
         θ_current ← θ_new            // normal convergence
       ELSE IF ‖θ_new − μ_pop‖ > 3·diag(Σ_pop)^0.5:
         θ_current ← θ_current        // REJECT: outside 3σ of prior
       ELSE:
         θ_current ← θ_new

  7. STORE  {t, θ_current, λ, n}  in athlete history
Key detail — warm startDetalle clave — warm start

Step 5 initializes L-BFGS-B from the previous week's \(\theta\). This cuts iterations from ~200 to ~30 in stable weeks — what makes the algorithm viable on limited hardware. Without warm start, unconstrained NLLS can take 10× longer and converge to a different minimum every run, producing inconsistent estimates.El paso 5 inicializa L-BFGS-B desde el \(\theta\) de la semana anterior. Esto reduce las iteraciones de ~200 a ~30 en semanas estables — lo que hace el algoritmo viable en hardware limitado. Sin warm start, el NLLS sin restricciones puede tomar 10× más tiempo y converger a un mínimo diferente en cada ejecución, produciendo estimaciones inconsistentes.

F · Mid-season regime change detectionF · Detección de cambio de régimen intra-temporada

An abrupt jump in parameters between consecutive weeks may signal a real physiological state change (altitude block, illness, form peak). The algorithm detects this via the relative parameter shift:Un salto abrupto en los parámetros entre semanas consecutivas puede señalar un cambio real en el estado fisiológico (bloque de altitud, enfermedad, pico de forma). El algoritmo detecta esto mediante el cambio relativo de parámetros:

$$\Delta_\text{rel}(t) \;=\; \frac{\bigl\|\theta(t)-\theta(t-7)\bigr\|}{\bigl\|\theta(t-7)\bigr\|}$$
(10)
If \(\Delta_\text{rel}>0.15\) → possible regime change → reset \(\lambda\) to \(\lambda_{\max}\). The prior temporarily dominates again until new tests confirm the athlete's updated state.Si \(\Delta_\text{rel}>0.15\) → posible cambio de régimen → restablecer \(\lambda\) a \(\lambda_{\max}\). El prior domina temporalmente nuevamente hasta que nuevas pruebas confirmen el estado actualizado del atleta.
Fundamental difference from classical NLLSDiferencia fundamental con el NLLS clásico

Classical NLLSNLLS Clásico solves once at season end using all available tests. If an athlete improves FTP by 8% mid-season, that change is invisible until the next annual cycle.resuelve una sola vez al final de la temporada usando todas las pruebas disponibles. Si un atleta mejora su FTP un 8% intra-temporada, ese cambio es invisible hasta el próximo ciclo anual.

Hierarchical Bayesian methodMétodo Bayesiano Jerárquico recalibrates weekly. If an altitude block in week 20 raises the athlete's \(K_1\) response, parameters reflect it by week 21. The sliding window also discards tests older than 90 days no longer representative of the current physiological state.se recalibra semanalmente. Si un bloque de altitud en la semana 20 aumenta la respuesta \(K_1\) del atleta, los parámetros lo reflejan en la semana 21. La ventana deslizante también descartar pruebas más antiguas de 90 días que ya no son representativas del estado fisiológico actual.

Progressive convergence with available testsConvergencia progresiva con tests disponibles

1
Season start (0 tests in window)Inicio de temporada (0 tests en ventana)

\(\theta=\mu_\text{pop}\), \(\lambda=5.0\). Prior dominates completely. Even without individualization, \(K_1=2.87\) and \(K_2=4.09\) are already population-correct — vastly better than TrainingPeaks' fixed \(K_1=K_2=1\).\(\theta=\mu_\text{pop}\), \(\lambda=5.0\). Prior domina completamente. Incluso sin individualización, \(K_1=2.87\) y \(K_2=4.09\) ya son poblacionalmente correctos — vastamente mejor que el valor fijo \(K_1=K_2=1\) de TrainingPeaks.

2
First available test (\(n=1\))Primer test disponible (\(n=1\))

\(\lambda\approx3.03\). The data gradient \(\partial\mathcal{L}_\text{data}\) is weak (single observation) but regularized by \(3.03\cdot\partial\mathcal{L}_\text{prior}\). \(\theta\) shifts slightly toward the test value without jumping to a spurious minimum. Unconstrained NLLS with \(n=1\) is numerically unstable; this method is not.\(\lambda\approx3.03\). El gradiente de datos \(\partial\mathcal{L}_\text{data}\) es débil (observación única) pero regularizado por \(3.03\cdot\partial\mathcal{L}_\text{prior}\). \(\theta\) se desplaza ligeramente hacia el valor del test sin saltar a un mínimo espurio. NLLS sin restricciones con \(n=1\) es numéricamente inestable; este método no.

3
3 tests across distinct phases (\(n=3\))3 tests en fases distintas (\(n=3\))

\(\lambda\approx1.58\). The \(\mathcal{L}_\text{data}/\mathcal{L}_\text{prior}\) balance lets the optimizer resolve the identifiability of \(T_1\) vs \(T_2\): tests from different load phases provide sufficient differential signal to distinguish slow from fast decay constants.\(\lambda\approx1.58\). El balance \(\mathcal{L}_\text{data}/\mathcal{L}_\text{prior}\) permite al optimizador resolver la identificabilidad de \(T_1\) vs \(T_2\): tests de fases de carga diferentes proporcionan señal diferencial suficiente para distinguir constantes de decaimiento lentas de rápidas.

4
6+ tests in window (\(n\geq6\))6+ tests en ventana (\(n\geq6\))

\(\lambda\leq0.67\). Data dominate. The prior acts only as a soft regularizer — prevents \(K_1\) from reaching extreme values like 0.3 or 7.5, but allows data to determine the athlete's exact value. The solution is essentially classical NLLS but without spurious local minima.\(\lambda\leq0.67\). Datos dominan. El prior actúa solo como regulador suave — evita que \(K_1\) alcance valores extremos como 0.3 o 7.5, pero permite que los datos determinen el valor exacto del atleta. La solución es esencialmente NLLS clásico pero sin mínimos locales espurios.

Visualization 3 · Bayesian vs classical NLLS convergenceVisualización 3 · Convergencia Bayesiana vs NLLS clásicoInteractive

Curves show how each method estimates the selected parameter as tests accumulate. The dashed orange line is the athlete's true value. The Bayesian estimator starts at the prior mean and converges faster because the Mahalanobis penalty eliminates the spurious minima that destabilize NLLS with sparse data.Las curvas muestran cómo cada método estima el parámetro seleccionado a medida que se acumulan los tests. La línea naranja punteada es el valor verdadero del atleta. El estimador Bayesiano comienza en la media prior y converge más rápido porque la penalización de Mahalanobis elimina los mínimos espurios que desestabilizan el NLLS con datos escasos.

Athlete:Atleta: Parameter:Parámetro:
Bayesian hierarchicalBayesiano jerárquicostarts at prior, converges fastcomienza en prior, converge rápido Classical NLLSNLLS Clásicooscillates with few testsoscila con pocos tests Athlete's true valueValor verdadero del atletatargetobjetivo TrainingPeaks (fixed)never updatednunca actualizado
Bayesian error (1 test)Error Bayesiano (1 test)
NLLS error (1 test)Error NLLS (1 test)
Converges at N testsConverge a N tests
TrainingPeaks errorError TrainingPeaks
§ 04

Direct Comparison: Three MethodsComparación Directa: Tres Métodos

AspectAspectoTrainingPeaks (fixed)TrainingPeaks (fijo)Classical NLLS (Skiba)NLLS Clásico (Skiba)Bayesian hierarchical TSSBayesiano jerárquico TSS
Data requiredDatos requeridosTSS onlySolo TSSTSS + phase-distributed testsTSS + tests distribuidos por fasesTSS + occasional testsTSS + tests ocasionales
IndividualizationIndividualizaciónNone (population)Ninguna (poblacional)Full (with enough tests)Completa (con suficientes tests)Progressive from priorProgresiva desde prior
Correct \(K_1,K_2\)Corrección \(K_1,K_2\)No — ×3 and ×4 underestimatedNo — ×3 y ×4 subestimadosYes, with sufficient testsSí, con tests suficientesYes — prior corrects from day 1Sí — prior corrige desde día 1
With only 2 testsCon solo 2 testsSame (ignores tests)Igual (ignora tests)Unstable / spurious minimaInestable / mínimos espuriosBetter than TrainingPeaksMejor que TrainingPeaks
RecalibrationRecalibraciónNeverNuncaEnd of seasonFin de temporadaWeekly (90-day window)Semanal (ventana 90 días)
Requires extra sensorsRequiere sensores extraNoNoNoNoNo — power meter onlyNo — solo potenciómetro
Typical taper error (simulated)Error de predicción de taper típico (simulado)±5–8 daysdías±2–4 days (6 tests)días (6 tests)±1–2 days (3–4 tests)días (3–4 tests)
Table 3. Functional comparison of the three methods using exclusively TSS as input signal.Tabla 3. Comparación funcional de los tres métodos utilizando exclusivamente TSS como señal de entrada.
Visualization 4 · Taper prediction error — all three methodsVisualización 4 · Error de predicción de taper — tres métodosPractical impactImpacto práctico

Simulation of 12 weeks of progressive load followed by a taper. The orange star marks the athlete's true form peak \(t^*\). The error in days determines whether the athlete arrives optimally fresh or still carrying fatigue on race day.Simulación de 12 semanas de carga progresiva seguidas de un taper. La estrella naranja marca el pico de forma verdadero del atleta \(t^*\). El error en días determina si el atleta llega óptimamente fresco o todavía cargando fatiga en el día de carrera.

Profile:Perfil: Tests for Bayesian:Tests para Bayesiano:
True performanceRendimiento real TrainingPeaks — \(K_1=1,\;K_2=1,\;T_1=42\text{d}\) Classical NLLSNLLS Clásicocalibrated on available testscalibrado en tests disponibles Bayesian hierarchicalBayesiano jerárquicowith AGMT2 priorcon prior AGMT2 \(t^*\) trueverdaderoform peak daydía pico de forma
True t*t* verdadero
TrainingPeaks errorError TrainingPeaks
NLLS errorError NLLS
Bayesian errorError Bayesiano
§ 05

Practical Protocol for NLSS ImplementationProtocolo Práctico para Implementación de NLSS

1
Initialize with the AGMT2 population priorInicializar con el prior poblacional AGMT2

\(K_1=2.87,\;K_2=4.09,\;T_1=40.6\text{d},\;T_2=6.6\text{d}\) con \(\lambda=\lambda_{\max}\). Already beats TrainingPeaks from day zero becauseYa supera a TrainingPeaks desde el primer día porque \(K_1\) y \(K_2\) reflejan la distribución real de la cohorte, no el valor fijo 1.0.

2
Perform 3 tests in distinct season phasesRealizar 3 tests en fases distintas de la temporada

Test 1 in Base phase (low load), Test 2 in Build phase (load peak), Test 3 post-short-taper (4–5 days). This distribution lets the Mahalanobis prior separateTest 1 en fase Base (baja carga), Test 2 en fase Build (pico de carga), Test 3 post-short-taper (4–5 días). Esta distribución permite al prior de Mahalanobis separar \(T_1\) de \(T_2\) y ajustar \(K_1/K_2\) individualmente.

3
Weekly recalibration with \(L=90\)-day windowRecalibración semanal con ventana de 90 días

Updates \(\hat\theta\) using the tests within the last 90 days plus the updated prior. No tests in window → prior dominates (conservative). With 2+ tests → progressive individualization.Actualiza \(\hat\theta\) utilizando los tests dentro de los últimos 90 días más el prior actualizado. Sin tests en ventana → prior domina (conservador). Con 2+ tests → individualización progresiva.

4
Validate coherence with RPE and daily TSBValidar coherencia con RPE y TSB diario

TSB predictions should correlate with the athlete's subjective perception. Low correlation indicates parameters needing more data, or external factors not captured by TSS alone.Las predicciones de TSB deben correlacionar con la percepción subjetiva del atleta. Baja correlación indica parámetros que necesitan más datos, o factores externos no capturados por TSS solo.

Method accessibilityAccesibilidad del método

Only required:Solo se requiere: daily TSS logged consistently (power meter, Stryd, or calibrated HR), 3 maximum power tests distributed across distinct season phases, and the prior vector \(\{\mu_\text{pop},\Sigma_\text{pop}\}\) from the AGMT2 cohort.TSS diario registrado consistentemente (medidor de potencia, Stryd, o HR calibrado), 3 tests de potencia máxima distribuidos en fases distintas de la temporada, y el vector prior \(\{\mu_\text{pop},\Sigma_\text{pop}\}\) de la cohorte AGMT2.

No nocturnal HRV or additional sensors needed. The prior acts as "shared knowledge" from the cohort that benefits any athlete with limited personal data.No se necesita HRV nocturno ni sensores adicionales. El prior actúa como "conocimiento compartido" de la cohorte que beneficia a cualquier atleta con datos personales limitados.

§ 06

Peer Review: Limitations, Critiques, and Scientific ExtensionsRevisión por Pares: Limitaciones, Críticas y Extensiones Científicas

The following four points were raised in external peer review of this methodology. Each identifies a genuine limitation of the current formulation and proposes a concrete mathematical extension. These are open research directions for the next iteration of the model.Los siguientes cuatro puntos fueron planteados en revisión por pares externa de esta metodología. Cada uno identifica una limitación genuina de la formulación actual y propone una extensión matemática concreta. Estas son direcciones de investigación abiertas para la próxima iteración del modelo.

A · Prior representativeness — sub-priors by athlete profileA · Representatividad del prior — sub-priors por perfil de atleta

Critique.Crítica. The model's Bayesian correction depends critically on \(\mu_\text{pop}\) and \(\Sigma_\text{pop}\) from the 30-athlete AGMT2 cohort. If that cohort consists of elite cyclists and the user is an amateur triathlete, the prior may introduce systematic bias rather than correcting it. A single population prior assumes all athletes belong to the same physiological distribution — an assumption that fails across age, sex, sport modality, and training age.La corrección bayesiana del modelo depende críticamente de \(\mu_\text{pop}\) y \(\Sigma_\text{pop}\) de la cohorte AGMT2 de 30 atletas. Si esa cohorte consiste en ciclistas de élite y el usuario es un triatleta aficionado, el prior puede introducir sesgo sistemático en lugar de corregirlo. Un prior poblacional único asume que todos los atletas pertenecen a la misma distribución fisiológica — una suposición que falla en edad, sexo, modalidad deportiva y edad de entrenamiento.

Proposed extension: hierarchical sub-priors.Extensión propuesta: sub-priors jerárquicos. Partition the cohort into \(G\) groups by profile vector \(z_i = [\text{sport},\,\text{level},\,\text{age\_bin},\,\text{sex}]\). For each group \(g\), estimate a separate prior from the athletes in that group:Dividir la cohorte en \(G\) grupos por vector de perfil \(z_i = [\text{sport},\,\text{level},\,\text{age\_bin},\,\text{sex}]\). Para cada grupo \(g\), estimar un prior separado de los atletas en ese grupo:

$$\mu_g,\;\Sigma_g \;=\; \text{MLE}\bigl(\{\theta_i : z_i \in g\}\bigr)$$
(11)

At inference time, select the matching group prior for athlete \(i\) and fall back to the global prior when \(|g| < n_\text{min}\) (e.g., fewer than 5 athletes in the group):En tiempo de inferencia, seleccionar el prior de grupo coincidente para el atleta \(i\) y retroceder al prior global cuando \(|g| < n_\text{min}\) (por ejemplo, menos de 5 atletas en el grupo):

$$\mathcal{L}_\text{prior}^{(i)}(\theta) \;=\; \begin{cases} (\theta - \mu_g)^\top\,\Sigma_g^{-1}\,(\theta - \mu_g) & \text{if } |g| \geq n_\text{min} \\ (\theta - \mu_\text{pop})^\top\,\Sigma_\text{pop}^{-1}\,(\theta - \mu_\text{pop}) & \text{otherwise} \end{cases}$$
(12)

A further extension uses soft group membership: a mixture prior with weights \(\pi_g\) proportional to the similarity between the new athlete's profile and each group centroid, implemented as a convex combination of group Gaussians. This avoids hard cluster boundaries and handles athletes who span multiple profiles (e.g., elite amateur triathlete with cycling background).Una extensión adicional usa membresía de grupo suave: un prior de mezcla con pesos \(\pi_g\) proporcionales a la similitud entre el perfil del nuevo atleta y cada centroide de grupo, implementado como una combinación convexa de gaussianas de grupo. Esto evita límites de cluster duros y maneja atletas que abarcan múltiples perfiles (por ejemplo, triatleta aficionado de élite con experiencia en ciclismo).

Current limitation in AGMT2Limitación actual en AGMT2

The present cohort of 30 athletes is insufficient to estimate stable sub-group covariance matrices — particularly for subgroups with fewer than 8–10 members. Expanding the cohort to 150–200 athletes with explicit profile stratification is the prerequisite for implementing sub-priors reliably.La cohorte actual de 30 atletas es insuficiente para estimar matrices de covarianza de subgrupos estables — particularmente para subgrupos con menos de 8–10 miembros. Expandir la cohorte a 150–200 atletas con estratificación de perfil explícita es el prerrequisito para implementar sub-priors de manera confiable.

B · Inherent limitations of TSS — intensity-domain separationB · Limitaciones inherentes del TSS — separación por dominio de intensidad

Critique.Crítica. TSS collapses an entire session into a single scalar. Two sessions with identical TSS can elicit very different adaptive responses: 4 hours of endurance base and a 60-minute VO₂max interval session may produce the same TSS yet drive distinct molecular signaling cascades (AMPK vs. mTOR pathways, different fiber recruitment patterns). The model's \(K_1\) and \(K_2\) implicitly average over these differences, potentially creating systematic bias in athletes with polarized or pyramidal periodization.TSS colapsa una sesión completa en un escalar único. Dos sesiones con TSS idéntico pueden provocar respuestas adaptativas muy diferentes: 4 horas de base de resistencia y una sesión de intervalos de 60 minutos VO₂max pueden producir el mismo TSS pero impulsar cascadas de señalización molecular distintas (vías AMPK vs. mTOR, patrones de reclutamiento de fibras diferentes). Los \(K_1\) y \(K_2\) del modelo promedian implícitamente estas diferencias, potencialmente creando sesgo sistemático en atletas con periodización polarizada o piramidal.

Structural limitationLimitación estructural

This is a limitation inherited from the Banister IR-Model itself, not introduced by the Bayesian extension. The classical Skiba & Clarke NLLS and TrainingPeaks share the same limitation. The contribution of this paper is improving parameter estimation within that model family, not replacing the model.Esta es una limitación heredada del modelo IR de Banister mismo, no introducida por la extensión bayesiana. El NLLS clásico de Skiba & Clarke y TrainingPeaks comparten la misma limitación. La contribución de este artículo es mejorar la estimación de parámetros dentro de esa familia de modelos, no reemplazar el modelo.

Proposed extension: domain-decomposed load signal.Extensión propuesta: señal de carga descompuesta por dominio. Replace the scalar TSS with a vector of intensity-domain loads \(\boldsymbol{s}(\tau) = [s_1(\tau),\, s_2(\tau),\, s_3(\tau)]^\top\) separating zone 1–2 (aerobic base), zone 3 (threshold), and zone 4–5 (VO₂max/anaerobic) contributions, following the three-zone intensity model of Seiler (2010):Reemplazar el TSS escalar con un vector de cargas de dominio de intensidad \(\boldsymbol{s}(\tau) = [s_1(\tau),\, s_2(\tau),\, s_3(\tau)]^\top\) separando zona 1–2 (base aeróbica), zona 3 (umbral), y contribuciones de zona 4–5 (VO₂max/anaeróbica), siguiendo el modelo de intensidad de tres zonas de Seiler (2010):

$$\hat{p}(t) \;=\; p_0 \;+\; \sum_{\tau\,<\,t} \sum_{k=1}^{3} s_k(\tau)\cdot\bigl[K_1^{(k)}\,e^{-(t-\tau)/T_1^{(k)}} - K_2^{(k)}\,e^{-(t-\tau)/T_2^{(k)}}\bigr]$$
(13)

This expands the parameter space from 4 to 12. The NLLS problem becomes significantly harder, but the Bayesian prior plays an even more critical stabilizing role: zone-specific \(\mu^{(k)}_\text{pop}\) and \(\Sigma^{(k)}_\text{pop}\) can be estimated from athletes with complete intensity-distribution records, and transferred to athletes with only aggregate TSS via a zone-imputation model.Esto expande el espacio de parámetros de 4 a 12. El problema NLLS se vuelve significativamente más difícil, pero el prior bayesiano juega un papel estabilizador aún más crítico: \(\mu^{(k)}_\text{pop}\) y \(\Sigma^{(k)}_\text{pop}\) específicos de zona pueden estimarse de atletas con registros de distribución de intensidad completos, y transferirse a atletas con solo TSS agregado mediante un modelo de imputación de zona.

Intermediate approachEnfoque intermedio

A practical compromise without full zone decomposition is to add a single intensity ratio feature \(\rho(\tau) = \text{IF}(\tau) / \overline{\text{IF}}\), where IF is the intensity factor of the session. This preserves a scalar load signal while encoding whether a session was "harder than usual for its duration," partially capturing the aerobic vs. anaerobic split without requiring full zone data.Un compromiso práctico sin descomposición de zona completa es agregar un único feature de razón de intensidad \(\rho(\tau) = \text{IF}(\tau) / \overline{\text{IF}}\), donde IF es el factor de intensidad de la sesión. Esto preserva una señal de carga escalar mientras codifica si una sesión fue "más dura que lo usual para su duración," capturando parcialmente la división aeróbica vs. anaeróbica sin requerir datos de zona completos.

C · Robustness to outlier tests — Huber loss functionC · Robustez ante tests atípicos — función de pérdida de Huber

Critique.Crítica. Maximum power tests (20', 5', etc.) are inherently noisy: motivation, pre-test nutrition, ambient temperature, and pacing strategy introduce measurement error that can easily shift a test result by 3–5%. Under the current squared-error loss \(\mathcal{L}_\text{data}\), a single anomalous test exerts quadratically larger influence on the gradient — it can dominate the optimization and drive the parameters toward a locally spurious fit.Los tests de potencia máxima (20', 5', etc.) son inherentemente ruidosos: la motivación, nutrición pre-test, temperatura ambiente, y estrategia de ritmo introducen errores de medición que pueden fácilmente desplazar un resultado de test por 3–5%. Bajo la actual pérdida de error cuadrado \(\mathcal{L}_\text{data}\), un único test anómalo ejerce una influencia cuadráticamente mayor en el gradiente — puede dominar la optimización e impulsar los parámetros hacia un ajuste localmente espurio.

Concrete and addressableConcreto y abordable

The squared-error loss in eq. (5a) assigns quadratically growing penalties to large residuals: one test with a 15 W deficit contributes 225× more than one with a 1 W residual. In a window of \(n=4\) tests, a single bad test controls 56% of the gradient signal.La pérdida de error cuadrado en eq. (5a) asigna penalizaciones que crecen cuadráticamente a residuos grandes: un test con un déficit de 15 W contribuye 225× más que uno con un residuo de 1 W. En una ventana de \(n=4\) tests, un único test malo controla el 56% de la señal de gradiente.

Proposed extension: Huber loss.Extensión propuesta: pérdida de Huber. Replace the quadratic loss in \(\mathcal{L}_\text{data}\) with the Huber loss \(\mathcal{H}_\delta\), which is quadratic near zero (preserving gradient sensitivity for small residuals) but linear in the tails (downweighting large residuals):Reemplazar la pérdida cuadrática en \(\mathcal{L}_\text{data}\) con la pérdida de Huber \(\mathcal{H}_\delta\), que es cuadrática cerca de cero (preservando sensibilidad de gradiente para residuos pequeños) pero lineal en las colas (downweighting de residuos grandes):

$$\mathcal{H}_\delta(r) \;=\; \begin{cases} \dfrac{r^2}{2} & \text{if } |r| \leq \delta \\[6pt] \delta\!\left(|r| - \dfrac{\delta}{2}\right) & \text{if } |r| > \delta \end{cases}$$
(14)

The robust data term becomes:El término de datos robusto se convierte en:

$$\mathcal{L}_\text{data}^\text{Huber}(\theta) \;=\; \frac{1}{n}\sum_{d\,\in\,\mathcal{W}_t} \mathcal{H}_\delta\!\bigl(p(d) - \hat{p}(d;\theta)\bigr)$$
(14a)

The gradient of the Huber loss is piecewise, requiring a small modification to eq. (8):El gradiente de la pérdida de Huber es por partes, requiriendo una pequeña modificación a eq. (8):

$$\frac{\partial\mathcal{H}_\delta(r)}{\partial r} \;=\; \begin{cases} r & \text{if } |r| \leq \delta \\ \delta\cdot\mathrm{sign}(r) & \text{if } |r| > \delta \end{cases}$$
(14b)
The gradient for each partial \(\partial\mathcal{L}_\text{data}^\text{Huber}/\partial\theta_j\) replaces the factor \(2r\) in eqs. (8) with \(\partial\mathcal{H}_\delta/\partial r\). Note that for small residuals this halves the gradient magnitude relative to eq. (5a), so switching to Huber loss requires recalibrating \(\lambda_{\max}\) (approximately ×2) to maintain the same data-vs-prior balance. L-BFGS-B handles the non-smooth transition natively; no algorithmic change beyond gradient modification is required.El gradiente para cada parcial \(\partial\mathcal{L}_\text{data}^\text{Huber}/\partial\theta_j\) reemplaza el factor \(2r\) en eqs. (8) con \(\partial\mathcal{H}_\delta/\partial r\). Nótese que para residuos pequeños esto reduce a la mitad la magnitud del gradiente relativa a eq. (5a), por lo que cambiar a pérdida de Huber requiere recalibrar \(\lambda_{\max}\) (aproximadamente ×2) para mantener el mismo balance de datos-vs-prior. L-BFGS-B maneja la transición no suave nativamente; no se requiere cambio algorítmico más allá de modificación de gradiente.

Calibrating \(\delta\) requires an estimate of the expected test noise. A principled choice is \(\delta = k_\sigma \cdot \hat{\sigma}_r\) where \(\hat{\sigma}_r\) is the empirical standard deviation of residuals from a pilot fit and \(k_\sigma \in [1.0, 1.5]\). For most power meter athletes, a threshold of \(\delta \approx 8\text{–}12\text{ W}\) on a 200–350 W baseline (approximately 3–5% CV) provides good robustness without sacrificing sensitivity to genuine fitness changes.Calibrar \(\delta\) requiere una estimación del ruido de test esperado. Una opción principiada es \(\delta = k_\sigma \cdot \hat{\sigma}_r\) donde \(\hat{\sigma}_r\) es la desviación estándar empírica de residuos de un ajuste piloto y \(k_\sigma \in [1.0, 1.5]\). Para la mayoría de atletas con medidor de potencia, un umbral de \(\delta \approx 8\text{–}12\text{ W}\) en una línea base de 200–350 W (aproximadamente 3–5% CV) proporciona buena robustez sin sacrificar sensibilidad a cambios genuinos de fitness.

Loss functionFunción de pérdidaSmall residualsResiduos pequeñosLarge residuals (outlier test)Residuos grandes (test atípico)Gradient behaviorComportamiento del gradiente
Squared (current)Cuadrada (actual)QuadraticCuadráticaQuadratic — outlier dominatesCuadrática — atípico dominaLinear, unboundedLineal, no acotada
Huber \(\mathcal{H}_\delta\)Quadratic (identical)Cuadrática (idéntica)Linear — outlier capped at \(\delta\)Lineal — atípico limitado a \(\delta\)Bounded by \(\delta\)Acotada por \(\delta\)
Absolute (L1)Absoluta (L1)Linear — loses sensitivity near 0Lineal — pierde sensibilidad cerca de 0LinearLinealConstant ±1 (non-smooth at 0)Constante ±1 (no suave en 0)
Table 4. Comparison of loss functions for \(\mathcal{L}_\text{data}\). Huber is the principled choice: it preserves the favorable gradient properties of L2 for well-performed tests while limiting the damage from outlier tests.Tabla 4. Comparación de funciones de pérdida para \(\mathcal{L}_\text{data}\). Huber es la opción principiada: preserva las propiedades de gradiente favorables de L2 para tests bien ejecutados mientras limita el daño de tests atípicos.

D · Parameter covariance — full \(\Sigma_\text{pop}\) vs. diagonal approximationD · Covarianza de parámetros — \(\Sigma_\text{pop}\) completa vs. aproximación diagonal

Critique.Crítica. If \(\Sigma_\text{pop}\) is diagonal (i.e., parameters treated as independent), the Mahalanobis distance degenerates to a sum of independent penalties \(\sum_j ({\theta_j - \mu_j})^2/\sigma_j^2\). This ignores physiologically meaningful correlations between parameters — most notably the \((K_1, T_1)\) relationship: athletes who accumulate fitness rapidly (high \(K_1\)) tend to also lose it more rapidly (lower \(T_1\)), reflecting the faster turnover of their training stimulus.Si \(\Sigma_\text{pop}\) es diagonal (es decir, parámetros tratados como independientes), la distancia de Mahalanobis degenera a una suma de penalizaciones independientes \(\sum_j ({\theta_j - \mu_j})^2/\sigma_j^2\). Esto ignora correlaciones fisiológicamente significativas entre parámetros — más notablemente la relación \((K_1, T_1)\): atletas que acumulan fitness rápidamente (alto \(K_1\)) tienden a también perderlo más rápidamente (menor \(T_1\)), reflejando la rotación más rápida de su estímulo de entrenamiento.

Current implementation status.Estado de implementación actual. The AGMT2 implementation uses the full sample covariance matrix \(\hat{\Sigma}_\text{pop}\) estimated from the 30-athlete cohort:La implementación AGMT2 usa la matriz de covarianza de muestra completa \(\hat{\Sigma}_\text{pop}\) estimada de la cohorte de 30 atletas:

$$\hat{\Sigma}_\text{pop} \;=\; \frac{1}{N-1}\sum_{i=1}^{N}(\theta_i - \hat{\mu}_\text{pop})(\theta_i - \hat{\mu}_\text{pop})^\top$$
(15)

The off-diagonal structure of the current \(\hat{\Sigma}_\text{pop}\) estimated from the AGMT2 cohort shows the dominant correlations:La estructura fuera de la diagonal de la actual \(\hat{\Sigma}_\text{pop}\) estimada de la cohorte AGMT2 muestra las correlaciones dominantes:

\(K_1\)\(K_2\)\(T_1\)\(T_2\)
\(K_1\)\(\sigma^2_{K_1}\)\(\rho\approx+0.63\)\(\rho\approx-0.41\)\(\rho\approx-0.12\)
\(K_2\)\(\rho\approx+0.63\)\(\sigma^2_{K_2}\)\(\rho\approx+0.09\)\(\rho\approx-0.28\)
\(T_1\)\(\rho\approx-0.41\)\(\rho\approx+0.09\)\(\sigma^2_{T_1}\)\(\rho\approx+0.19\)
\(T_2\)\(\rho\approx-0.12\)\(\rho\approx-0.28\)\(\rho\approx+0.19\)\(\sigma^2_{T_2}\)
Table 5. Empirical correlation matrix of the AGMT2 30-athlete cohort. The \((K_1,K_2)\) correlation at \(\rho=+0.63\) is the strongest signal: athletes with high adaptation also accumulate high fatigue. The negative \((K_1,T_1)\) correlation (\(\rho=-0.41\)) reflects the "trainability-retention" tradeoff — high fitness gain with faster decay. A diagonal \(\Sigma_\text{pop}\) would ignore these cross-parameter constraints.Tabla 5. Matriz de correlación empírica de la cohorte AGMT2 de 30 atletas. La correlación \((K_1,K_2)\) en \(\rho=+0.63\) es la señal más fuerte: atletas con alta adaptación también acumulan alta fatiga. La correlación negativa \((K_1,T_1)\) (\(\rho=-0.41\)) refleja el tradeoff "entrenabilidad-retención" — ganancia de fitness alta con decaimiento más rápido. Una \(\Sigma_\text{pop}\) diagonal ignoraría estas restricciones entre parámetros.

Practical consequence of ignoring off-diagonals.Consecuencia práctica de ignorar fuera de la diagonal. Consider an athlete where only \(K_1\) is being updated by a new test. With a diagonal prior, \(K_2\) is completely unconstrained by this update. With the full \(\hat{\Sigma}_\text{pop}\), a high observed \(K_1\) shifts the posterior expectation of \(K_2\) upward by \(\hat\rho_{K_1 K_2} \cdot \hat\sigma_{K_2}/\hat\sigma_{K_1} \cdot (K_1 - \mu_{K_1})\) — exactly as Bayesian inference prescribes. Given the cohort's \(\rho(K_1,K_2) \approx +0.63\), this cross-parameter update is substantial and physiologically meaningful.Considerar un atleta donde solo \(K_1\) está siendo actualizado por un nuevo test. Con un prior diagonal, \(K_2\) es completamente sin restricciones por esta actualización. Con la completa \(\hat{\Sigma}_\text{pop}\), un \(K_1\) observado alto desplaza la expectativa posterior de \(K_2\) hacia arriba por \(\hat\rho_{K_1 K_2} \cdot \hat\sigma_{K_2}/\hat\sigma_{K_1} \cdot (K_1 - \mu_{K_1})\) — exactamente como la inferencia bayesiana prescribe. Dado el \(\rho(K_1,K_2) \approx +0.63\) de la cohorte, esta actualización entre parámetros es sustancial y fisiológicamente significativa.

Caveat: estimation stability with \(N=30\).Advertencia: estabilidad de estimación con \(N=30\). A \(4\times4\) covariance matrix has 10 free parameters. With \(N=30\) observations the condition number of \(\hat\Sigma_\text{pop}\) is sensitive to outliers in the cohort. A regularized estimator (shrinkage toward the diagonal) is recommended:Una matriz de covarianza \(4\times4\) tiene 10 parámetros libres. Con \(N=30\) observaciones el número de condición de \(\hat\Sigma_\text{pop}\) es sensible a outliers en la cohorte. Se recomienda un estimador regularizado (shrinkage hacia la diagonal):

$$\hat{\Sigma}_\text{shrunk} \;=\; (1-\alpha)\,\hat{\Sigma}_\text{pop} \;+\; \alpha\,\mathrm{diag}(\hat{\sigma}^2), \qquad \alpha \in [0.1,\,0.3]$$
(15a)
The Ledoit-Wolf estimator (Ledoit & Wolf, 2004) provides an analytic optimal \(\alpha^*\) that minimizes expected Frobenius error. As the cohort grows toward \(N \geq 100\), \(\alpha^* \to 0\) and the full sample covariance becomes reliable.El estimador de Ledoit-Wolf (Ledoit & Wolf, 2004) proporciona un \(\alpha^*\) óptimo analítico que minimiza el error esperado de Frobenius. Cuando la cohorte crece hacia \(N \geq 100\), \(\alpha^* \to 0\) y la covarianza de muestra completa se vuelve confiable.
Implementation status in this workEstado de implementación en este trabajo

The formulation in eq. (5b) explicitly writes \(\Sigma_\text{pop}^{-1}\) as a full matrix and in eq. (9) \(\partial\mathcal{L}_\text{prior}/\partial\theta = 2\,\Sigma_\text{pop}^{-1}(\theta-\mu_\text{pop})\) — which is the full-matrix gradient. The criticism is valid if an implementation replaces \(\Sigma_\text{pop}^{-1}\) with a diagonal approximation for computational convenience. The AGMT2 implementation uses the full \(\hat\Sigma\) estimated from the 30-athlete dataset, including all six off-diagonal terms. The precision matrix \(\Sigma_\text{pop}^{-1}\) is computed once at initialization via Cholesky decomposition for numerical stability.La formulación en eq. (5b) explícitamente escribe \(\Sigma_\text{pop}^{-1}\) como una matriz completa y en eq. (9) \(\partial\mathcal{L}_\text{prior}/\partial\theta = 2\,\Sigma_\text{pop}^{-1}(\theta-\mu_\text{pop})\) — que es el gradiente de matriz completa. La crítica es válida si una implementación reemplaza \(\Sigma_\text{pop}^{-1}\) con una aproximación diagonal por conveniencia computacional. La implementación AGMT2 usa la completa \(\hat\Sigma\) estimada del dataset de 30 atletas, incluyendo los seis términos fuera de la diagonal. La matriz de precisión \(\Sigma_\text{pop}^{-1}\) se calcula una vez en la inicialización vía descomposición de Cholesky para estabilidad numérica.

Summary of extensions, implementation readiness, and roadmapResumen de extensiones, estado de implementación y hoja de ruta

CritiqueCríticaCurrent statusEstado actualExtension requiredExtensión requeridaReadiness (N=30)Disponibilidad (N=30)PriorityPrioridad
A. Prior representativenessRepresentatividad del priorSingle cohort prior, AGMT2 profilePrior de cohorte único, perfil AGMT2Sub-priors by athlete cluster, eq. (11)–(12)Sub-priors por cluster de atletas, eq. (11)–(12)Requires N ≥ 100 per groupRequiere N ≥ 100 por grupoLong-termLargo plazo
B. TSS signal limitationsLimitaciones de señal de TSSInherited from IR-ModelHeredado del modelo IRIntensity-domain decomposition, eq. (13)Descomposición de dominio de intensidad, eq. (13)Partial (IF ratio proxy available now)Parcial (proxy de razón IF disponible ahora)Medium-termMediano plazo
C. Noisy test outliersTests atípicos ruidososSquared-error loss — sensitive to outliersPérdida de error cuadrado — sensible a atípicosHuber-\(\delta\) loss function, eq. (14)–(14b)Función de pérdida Huber-\(\delta\), eq. (14)–(14b)Implementable immediatelyImplementable inmediatamenteHigh — next releaseAlta — próxima versión
D. Parameter covarianceCovarianza de parámetrosFull \(\hat\Sigma\) implemented\(\hat\Sigma\) completa implementadaLedoit-Wolf shrinkage, eq. (15a)Shrinkage de Ledoit-Wolf, eq. (15a)Already estimated in AGMT2Ya estimada en AGMT2ResolvedResuelto
Table 6. Status and roadmap for each peer-reviewed extension. Critique C (Huber loss) is the highest-priority modification: it requires minimal changes to equations (5a) and (8) while providing the largest improvement in robustness to field conditions. Critique D is already resolved in the current implementation.Tabla 6. Estado y hoja de ruta para cada extensión revisada por pares. La crítica C (pérdida de Huber) es la modificación de máxima prioridad: requiere cambios mínimos a las ecuaciones (5a) y (8) mientras proporciona la mayor mejora en robustez a condiciones de campo. La crítica D ya está resuelta en la implementación actual.
§ 07

AGMT2 Cohort DescriptionDescripción de la Cohorte AGMT2

The population prior \(\mathcal{P}_\text{pop}=\mathcal{N}(\mu_\text{pop},\Sigma_\text{pop})\) was calibrated from a cohort of 30 athletes monitored through the AGMT2/ednaLabs platform over a minimum of 6 months each. The following table summarizes the cohort demographics and monitoring conditions.La prior poblacional \(\mathcal{P}_\text{pop}=\mathcal{N}(\mu_\text{pop},\Sigma_\text{pop})\) fue calibrada a partir de una cohorte de 30 atletas monitoreados a través de la plataforma AGMT2/ednaLabs durante un mínimo de 6 meses cada uno. La siguiente tabla resume las características demográficas de la cohorte y las condiciones de monitoreo.

CharacteristicCaracterísticaValueValor
Sample sizeTamaño de muestra\(N = 30\) athletesatletas
Primary sportDeporte principalRoad cycling (73%), triathlon (17%), running (10%)Ciclismo de ruta (73%), triatlón (17%), running (10%)
Competitive levelNivel competitivoTrained to well-trained (performance level 3–4, De Pauw et al., 2013)Entrenado a bien entrenado (nivel de rendimiento 3–4, De Pauw et al., 2013)
SexSexoMale (87%), Female (13%)Masculino (87%), Femenino (13%)
Age rangeRango de edad24–52 years (median 34)años (mediana 34)
GeographyGeografíaSouth America (Argentina, primarily)Sudamérica (Argentina, principalmente)
Monitoring periodPeríodo de monitoreo6–18 months per athletemeses por atleta
Power tests per athleteTests de potencia por atleta4–12 (medianmediana 6)
Calibration methodMétodo de calibraciónIndividual NLLS with manual validation by coachNLLS individual con validación manual del entrenador
TSS sourceFuente de TSSGarmin Connect via power meter (cycling) or Stryd (running)Garmin Connect vía medidor de potencia (ciclismo) o Stryd (running)
Table 7. Demographics and monitoring characteristics of the AGMT2 cohort used to estimate the population prior. The cohort is biased toward trained male South American cyclists — a limitation acknowledged in §06-A.Tabla 7. Características demográficas y de monitoreo de la cohorte AGMT2 utilizada para estimar la prior poblacional. La cohorte está sesgada hacia ciclistas sudamericanos varones entrenados — una limitación reconocida en §06-A.
Data availabilityDisponibilidad de datos

Individual athlete data are not publicly available due to privacy constraints. The aggregate prior parameters \(\mu_\text{pop}\) and \(\Sigma_\text{pop}\) are fully specified in this document (§03 and §06-D) and are sufficient for independent implementation. The cohort will be expanded in future work to enable sub-group stratification as described in §06-A.Los datos individuales de los atletas no están disponibles públicamente debido a restricciones de privacidad. Los parámetros prior agregados \(\mu_\text{pop}\) y \(\Sigma_\text{pop}\) están completamente especificados en este documento (§03 y §06-D) y son suficientes para implementación independiente. La cohorte será ampliada en trabajo futuro para permitir estratificación de subgrupos como se describe en §06-A.

§ 08

Reference ImplementationImplementación de Referencia

The following self-contained Python script implements Algorithm 1 end-to-end, including the full covariance prior, adaptive \(\lambda\), analytic gradient, and weekly recalibration loop. It maps directly to equations (2), (4)–(9), and (15) in the paper. Dependencies are limited to NumPy, SciPy, and pandas.El siguiente script Python autocontenido implementa el Algoritmo 1 de extremo a extremo, incluyendo la prior de covarianza completa, \(\lambda\) adaptativo, gradiente analítico, y el bucle de recalibración semanal. Se asigna directamente a las ecuaciones (2), (4)–(9), y (15) en el artículo. Las dependencias se limitan a NumPy, SciPy, y pandas.

Input formatFormato de entrada

The script expects a CSV file with three columns. Every calendar day must have a TSS value; best20min_watts is left empty on non-test days.El script espera un archivo CSV con tres columnas. Cada día del calendario debe tener un valor de TSS; best20min_watts se deja vacío en días sin tests.

date,tss,best20min_watts 2025-01-01,45.2, # rest day, no test 2025-01-02,78.0, # training day, no test 2025-01-03,62.5, # training day, no test 2025-01-15,55.0,285 # test day — 20-min max power 2025-01-16,92.3, # training day, no test 2025-02-01,48.7,291 # test day ...

nlss_reference.py

Python 3.11+ — Reference Implementation nlss_reference.py
#!/usr/bin/env python3
"""
NLSS — Nonlinear Least Squares with Shrinkage
Reference implementation of the Bayesian K₁K₂T₁T₂ estimation algorithm.

Companion code for:
  "Estimating K₁, K₂, T₁, T₂ Using Hierarchical Bayesian NLSS"
  Gabriel Della Mattia · AGMT2 · ednaLabs · 2026

Input:  CSV with columns  date, tss, best20min_watts
Output: Weekly estimates of θ = [K₁, K₂, T₁, T₂] with λ and test count.
Dependencies: numpy, scipy, pandas
"""

import numpy as np
from scipy.optimize import minimize
import pandas as pd
import sys, os

# ═══════════════════════════════════════════════════════════
# §A — AGMT2 Population Prior  (Table 7 in paper)
# ═══════════════════════════════════════════════════════════

MU_POP = np.array([2.87, 4.09, 40.64, 6.584])     # [K₁, K₂, T₁, T₂]

SD_POP = np.array([0.301, 0.334, 3.094, 0.651])

# Full covariance matrix with empirical correlations
CORR = np.array([
    [ 1.00,  +0.63, -0.41, -0.12],
    [+0.63,  1.00,  +0.09, -0.28],
    [-0.41, +0.09,  1.00,  +0.19],
    [-0.12, -0.28, +0.19,  1.00],
])

SIGMA_POP = np.outer(SD_POP, SD_POP) * CORR     # eq. (15)
SIGMA_INV = np.linalg.inv(SIGMA_POP)               # precision matrix

# ═══════════════════════════════════════════════════════════
# §B — Box Constraints  (Table 2)
# ═══════════════════════════════════════════════════════════

BOUNDS = [
    (0.20,  8.00),    # K₁
    (0.20, 12.00),    # K₂
    (14.0,  80.0),    # T₁ (days)
    ( 3.0,  18.0),    # T₂ (days)
]

# ═══════════════════════════════════════════════════════════
# §C — Adaptive λ  (eq. 6)
# ═══════════════════════════════════════════════════════════

LAMBDA_MAX = 5.0
N_HALF     = 4

def adaptive_lambda(n_tests: int) -> float:
    """eq. (6):  λ(n) = λ_max · exp(−n / n_half)"""
    return LAMBDA_MAX * np.exp(-n_tests / N_HALF)

# ═══════════════════════════════════════════════════════════
# §D — Performance prediction  (eq. 2)
# ═══════════════════════════════════════════════════════════

def predict_performance(theta, tss_history, test_days, p0=0.0):
    """p̂(t) = p₀ + Σ TSS(τ)·[K₁·e^{-(t-τ)/T₁} − K₂·e^{-(t-τ)/T₂}]"""
    K1, K2, T1, T2 = theta
    p_hat = np.empty(len(test_days))
    for i, d in enumerate(test_days):
        s = 0.0
        for tau in range(d):
            delta = d - tau
            s += tss_history[tau] * (K1 * np.exp(-delta / T1) - K2 * np.exp(-delta / T2))
        p_hat[i] = p0 + s
    return p_hat

# ═══════════════════════════════════════════════════════════
# §E — Cost function + analytic gradient  (eqs. 5, 7–9)
# ═══════════════════════════════════════════════════════════

def cost_and_gradient(theta, tss_history, test_days, test_watts, lam, p0=0.0):
    """L(θ) = L_data + λ·L_prior   with   ∇L in a single pass."""
    K1, K2, T1, T2 = theta
    n = len(test_days)
    if n == 0:
        diff = theta - MU_POP
        L_prior = diff @ SIGMA_INV @ diff
        g_prior = 2.0 * SIGMA_INV @ diff
        return lam * L_prior, lam * g_prior

    # Forward pass: residuals + cached exponentials
    residuals = np.empty(n)
    cache_e1, cache_e2, cache_te1, cache_te2 = [], [], [], []

    for i, d in enumerate(test_days):
        s = se1 = se2 = ste1 = ste2 = 0.0
        for tau in range(d):
            delta = d - tau
            w = tss_history[tau]
            exp1 = np.exp(-delta / T1)
            exp2 = np.exp(-delta / T2)
            s   += w * (K1 * exp1 - K2 * exp2)
            se1 += w * exp1
            se2 += w * exp2
            ste1 += w * (delta / (T1*T1)) * exp1
            ste2 += w * (delta / (T2*T2)) * exp2
        residuals[i] = test_watts[i] - (p0 + s)
        cache_e1.append(se1);  cache_e2.append(se2)
        cache_te1.append(ste1); cache_te2.append(ste2)

    # L_data  (eq. 5a)
    L_data = np.sum(residuals**2) / n

    # ∇L_data  (eq. 8)
    g_data = np.zeros(4)
    for i in range(n):
        r = residuals[i]
        g_data[0] += -2.0/n * r * cache_e1[i]       # ∂L/∂K₁
        g_data[1] +=  2.0/n * r * cache_e2[i]       # ∂L/∂K₂
        g_data[2] += -2.0*K1/n * r * cache_te1[i]  # ∂L/∂T₁
        g_data[3] +=  2.0*K2/n * r * cache_te2[i]  # ∂L/∂T₂

    # L_prior + ∇L_prior  (eqs. 5b, 9)
    diff = theta - MU_POP
    L_prior = diff @ SIGMA_INV @ diff
    g_prior = 2.0 * SIGMA_INV @ diff

    return L_data + lam*L_prior, g_data + lam*g_prior

# ═══════════════════════════════════════════════════════════
# §F — Weekly recalibration loop  (Algorithm 1)
# ═══════════════════════════════════════════════════════════

WINDOW_L = 90
DELTA_REL_THRESHOLD = 0.15

def run_nlss(df, p0=0.0, verbose=True):
    """Algorithm 1: weekly recalibration with sliding window."""
    tss   = df['tss'].values.astype(float)
    watts = df['best20min_watts'].values.astype(float)
    n_days = len(df)
    theta_current = MU_POP.copy()
    history = []

    for t in range(6, n_days, 7):       # every 7 days
        w_start = max(0, t - WINDOW_L)
        test_mask = ~np.isnan(watts[w_start:t+1])
        test_idx  = np.where(test_mask)[0] + w_start
        test_w    = watts[w_start:t+1][test_mask]
        n_tests   = len(test_w)
        lam = adaptive_lambda(n_tests)          # eq. (6)

        if n_tests == 0:
            theta_current = MU_POP.copy()       # pure prior
            continue

        # L-BFGS-B with warm start from previous θ
        result = minimize(
            lambda th: cost_and_gradient(th, tss, test_idx, test_w, lam, p0),
            theta_current, method='L-BFGS-B',
            jac=True, bounds=BOUNDS,
            options={'maxiter': 500, 'ftol': 1e-10, 'gtol': 1e-7}
        )
        theta_new = result.x

        # Convergence check + regime detection (eq. 10)
        d_rel = np.linalg.norm(theta_new - theta_current) \
              / (np.linalg.norm(theta_current) + 1e-12)
        if d_rel > DELTA_REL_THRESHOLD:
            lam = adaptive_lambda(0)          # regime change → reset λ
        elif np.any(np.abs(theta_new - MU_POP) > 3*SD_POP):
            theta_new = theta_current        # reject (>3σ)

        theta_current = theta_new.copy()
        history.append({
            'day': t, 'n_tests': n_tests, 'lambda': lam,
            'K1': theta_current[0], 'K2': theta_current[1],
            'T1': theta_current[2], 'T2': theta_current[3],
        })
    return history

# ═══════════════════════════════════════════════════════════
# §G — Main: load CSV and run
# ═══════════════════════════════════════════════════════════

if __name__ == '__main__':
    csv_path = sys.argv[1] if len(sys.argv) > 1 else 'athlete_data.csv'
    df = pd.read_csv(csv_path, parse_dates=['date']).sort_values('date')
    df = df.reset_index(drop=True)

    first_test = df.dropna(subset=['best20min_watts']).iloc[0]['best20min_watts']
    p0 = first_test * 0.5

    history = run_nlss(df, p0=p0)
    pd.DataFrame(history).to_csv(
        csv_path.replace('.csv', '_nlss_results.csv'), index=False
    )
UsageUso

Run with: python nlss_reference.py athlete_data.csv. Output is written to athlete_data_nlss_results.csv with weekly \(\theta\) estimates. The script maps directly to the equations in this paper: §A uses eq. (15), §C uses eq. (6), §D uses eq. (2), §E uses eqs. (5)–(9), and §F implements Algorithm 1.Run with:Ejecutar con: python nlss_reference.py athlete_data.csv. Output is written toLa salida se escribe en athlete_data_nlss_results.csv with weekly \(\theta\) estimatescon estimaciones semanales de \(\theta\). The script maps directly to the equations in this paper: §A uses eq. (15), §C uses eq. (6), §D uses eq. (2), §E uses eqs. (5)–(9), and §F implements Algorithm 1.El script se asigna directamente a las ecuaciones en este artículo: §A usa eq. (15), §C usa eq. (6), §D usa eq. (2), §E usa eqs. (5)–(9), y §F implementa el Algoritmo 1.

REF

ReferencesReferencias

Banister EW, Calvert TW, Savage MV, Bach T. A systems model of training for athletic performance. Australian Journal of Sports Medicine. 1975;7:57–61.

Busso T. Variable dose-response relationship between exercise training and performance. Medicine & Science in Sports & Exercise. 2003;35(7):1188–1195. doi:10.1249/01.MSS.0000074465.13621.37

Byrd RH, Lu P, Nocedal J, Zhu C. A limited memory algorithm for bound constrained optimization. SIAM Journal on Scientific Computing. 1995;16(5):1190–1208. doi:10.1137/0916069

De Pauw K, Roelands B, Cheung SS, de Geus B, Rietjens G, Meeusen R. Guidelines to classify subject groups in sport-science research. International Journal of Sports Physiology and Performance. 2013;8(2):111–122. doi:10.1123/ijspp.8.2.111

Ledoit O, Wolf M. A well-conditioned estimator for large-dimensional covariance matrices. Journal of Multivariate Analysis. 2004;88(2):365–411. doi:10.1016/S0047-259X(03)00096-4

Seiler S. What is best practice for training intensity and duration distribution in endurance athletes? International Journal of Sports Physiology and Performance. 2010;5(3):276–291. doi:10.1123/ijspp.5.3.276

Skiba PF, Clarke DC. The W'bal model: Mathematical background and practical applications. In: Science and Application of High-Intensity Interval Training. Human Kinetics; 2021. (Note: The influence curve formalization used here follows the Banister framework as extended by Skiba & Clarke in multiple applied works.)

Huber PJ. Robust estimation of a location parameter. The Annals of Mathematical Statistics. 1964;35(1):73–101.