Model Training Stages

Detailed walkthrough of the three-stage modeling path for predicting per-stroke force curves from video-derived biomechanics. Each stage builds on the last; earlier stages establish floors and baselines that later stages must clear.

← Full pipeline overview
T Target Representation — How Force Curves Are Encoded

Before any model is trained, force curves must be encoded into a learnable form. Two representations are maintained in parallel: direct curve bins (full fidelity) and a low-dimensional shape (compact, smooth, interpretable). The low-dimensional target is either standard PCA on peak-normalized curves or functional PCA (B-spline basis → PCA on coefficients), selectable at dataset-build time via --target-representation {standard, fpca, both}. Stage A models predict the chosen coefficients; Stage B models predict full curves directly.

RAW FORCE CURVES F(s) s = 0.0 s = 1.0 N strokes × 64 bins on s-grid peak-norm PEAK-NORMALIZED F(s) / max(F) all curves scaled to [0, 1] PCA PCA DECOMPOSITION PC1 PC2 PC3 ... PC20 c1 c2 c3 .. c20 20 coefficients per stroke Reconstruction: F̂(s) = peak × Σ c_k · PC_k(s) Stage A predicts c_1 ... c_k   •   Stage B predicts F(s) directly

Force curve target encoding: raw curves → peak-normalized → PCA coefficients (20 components)

Direct bins
Full-fidelity force values at each s-grid point. Used by Stage B sequence models. Masked loss handles variable stroke lengths.
PCA shape
~20 coefficients capture >95% of curve variance. Compact target for Stage A scalar models. Smooth, denoised reconstruction.
Functional PCA option
functional_pca.py projects each curve onto a cubic B-spline basis, then runs PCA on the basis coefficients. Drop-in replacement for standard PCA; chosen per-run with --target-representation fpca.
Artifacts
Either pca_model.joblib or fpca_model.joblib is written alongside s_grid.npy in the training dataset and copied into the inference model bundle.

0 Sanity Baselines — The Floor Every Model Must Clear

Before training any biomechanics model, establish two baselines. 0a measures how reproducible force curves are within the same conditions (the irreducible floor). 0b tests how much simple metadata alone can predict. Any model using kinematics must beat 0b on all metrics.

0a — FORCE REPRODUCIBILITY FLOOR Condition bin same athlete similar stroke rate similar stroke length ⇒ group of comparable strokes Pairwise comparison how much do they vary? Reproducibility metrics median pairwise curve distance coefficient of variation (peak force) coefficient of variation (impulse) ⇒ this is the irreducible variability floor 0b — METADATA-ONLY BASELINE Scalar metadata stroke_rate_spm stroke_length_cm drive_ratio no kinematics Linear regression Ridge / OLS PCA c_1 ... c_k predicted coeffs ↓ reconstruct curve Baseline prediction predicted vs actual GATE: all later models must beat 0b on curve error + rowing metrics

Stage 0: establish the reproducibility floor (0a) and metadata-only prediction baseline (0b)

Why this matters
If force curves are already very consistent within conditions, even a naive model looks good. The reproducibility floor prevents us from over-claiming.
Baseline gate
Stroke rate and length alone explain some force curve shape. Any biomechanics model that fails to beat metadata-only has no justification for its complexity.

A Interpretable Kinematic Models — Do Biomechanics Add Value?

Use stroke-level scalar features (summary statistics + coordination) to predict force-curve PCA (or fPCA) coefficients. Classical ML models that support feature importance analysis. The goal is to verify biomechanics add value beyond metadata and to identify which features dominate. The canonical feature contract (6 unilateral/central angles including head_vs_trunk_deg with mirror normalization) lives in inference/feature_contract.py; Stage A summaries and coordination scalars are assembled in inference/build_training_dataset.py.

INPUT: SCALAR FEATURES (per stroke) Kinematic summary knee_active_deg_min knee_active_deg_max knee_active_deg_range knee_active_deg_mean knee_active_deg_s_at_max … ×6 angles = 30 features min, max, range, mean, s-position of peak build_training_dataset.py Coordination onset_knee_s onset_trunk_s onset_arms_s lag_knee_to_trunk_s lag_trunk_to_arms_s knee_range_frac hip_range_frac elbow_range_frac _compute_coordination_features Context stroke_rate_spm stroke_length_cm drive_ratio same features as Stage 0 metadata baseline x ∈ R^~41 (per stroke) Models Ridge regression Lasso regression Random Forest Gradient Boosted Trees PCA / fPCA coeffs ĉ_1, ĉ_2, … ĉ_k ↓ reconstruct F̂(s) ↓ evaluate vs Stage 0 Key output: feature importance ranking — which biomechanics explain force?

Stage A: stroke-level scalar features → classical ML → PCA / fPCA force-curve coefficients

Interpretability
Ridge/Lasso coefficients and tree feature importances directly reveal which biomechanics features drive force curve shape changes.
Must-beat gate
If Stage A cannot beat Stage 0b (metadata-only), there is no evidence that kinematics explain force beyond what stroke rate/length already capture.

B Sequence Models — Capturing Full Stroke Dynamics

Use the full progress-aligned kinematic sequences as input. The model sees how joint angles and their derivatives evolve continuously over the drive, capturing nonlinear cross-joint interactions that scalar summaries lose.

INPUT: KINEMATIC SEQUENCES ON s-GRID s = 0.00 0.02 0.03 ... 0.98 1.00 —————————————————————————— knee(s) hip(s) elbow(s) trunk(s) spine(s) d_knee/ds d_hip/ds ... handle_vel(s) handle_acc(s) shape: (64, 12) 64 s-grid points × 12 kinematic channels SEQUENCE MODEL Temporal Conv Network causal dilated convolutions or Transformer Encoder self-attention over s positions + scalar conditioning stroke rate, length, ratios OUTPUT F̂(s) direct prediction shape: (64,) force at each s bin Loss function Masked pointwise MSE — bins beyond stroke length masked out. Shape regularizers / derivative losses only if validation shows pathological curves. Why sequences > scalars Captures when and how joints interact during the drive. Learns nonlinear dynamics that summary stats cannot encode. Stage B predicts the full force curve — no PCA bottleneck — evaluated against same metrics as Stages 0 and A

Stage B: full kinematic sequence (64×12) → temporal model → predicted force curve (64 bins)

No PCA bottleneck
Stage B predicts the full force curve directly. No information is lost to PCA truncation. The model can capture subtle curve details that PCA misses.
Scalar conditioning
Stroke rate, drive ratio, and (optionally, via --stageB-use-coordination) onset/lag/range-fraction scalars are broadcast as constant extra channels over the s-axis, giving the sequence model global context without a separate head.
Masked + derivative losses
Pointwise MSE is masked to the per-stroke valid force bins; an optional derivative regularizer (--stageB-lambda-deriv) penalizes jaggy predictions when curve smoothness is pathological.
Portable artifacts
Every Stage B run saves state.pt + arch_config.json + feature_norm.npz + target_norm.npz. export_model_bundle.py combines these with the (f)PCA model and Stage A estimator into a self-describing model_bundle/ consumed by predict_force_cli.py.

E Evaluation Protocol — Validation Splits and Metrics

All stages are evaluated on the same held-out strokes using the same metrics. Curve-level statistics (RMSE, correlation) catch gross errors; rowing-relevant metrics (peak force, peak position, impulse) validate that the model gets the things coaches care about right.

DATA SPLIT STRATEGY Current phase (limited athletes) train fold 1 train fold 2 held-out Session-held-out or time-block splits within athlete. Results labeled as provisional; no generalization claims. Future phase (multi-athlete) athlete A athlete B athlete C ath. D ath. E Leave-one-athlete-out or grouped folds. True generalization test: unseen biomechanics. EVALUATION METRICS (all stages, same held-out set) Curve-level RMSE(F, F̂) over all valid bins MAE(F, F̂) over all valid bins Pearson r per-stroke correlation Does the predicted curve match the overall shape and magnitude? Rowing-relevant peak force error (N) peak position error (%) impulse error (N·s) Downstream quantities that coaches use for technique feedback. Phase-specific early drive mid drive late drive RMSE per phase segment Reveals where the model struggles: catch, peak, or finish.

Evaluation: consistent splits and metrics across all stages for fair comparison

Stage progression gate: each stage must improve on the previous stage's metrics. If Stage A fails to beat Stage 0, Stage B is not justified.
Cross-representation report
Every run annotates its metrics with target_representation (standard / fpca) and stage_b_arch (tcn / transformer). write_evaluation_report groups and compares results across representations and architectures, merging prior-run artifacts in the same output directory for cumulative comparison.
Architecture-suffixed artifacts
Stage B saves architecture-suffixed copies (e.g. stage_b_tcn.pt, stage_b_transformer.pt) alongside canonical names, so the report can compare TCN and Transformer on the same held-out strokes without clobbering either.
0 Sanity Baselines metadata → PCA coefficients = the floor to beat must beat A Kinematic Baselines scalar features → PCA coefficients interpretable + feature importance must beat B Sequence Models full sequences → full force curve captures nonlinear dynamics Best model Each stage strictly must beat all previous stages on curve error + rowing-relevant metrics