Classify workout types (run / bike / mountain bike / walk) from real sensor data
Built on 50,000+ real Endomondo workouts
Given GPS + heart rate + altitude sensor data from a workout,
can we automatically classify what sport the athlete was doing?
This is a core feature in every fitness platform — Strava calls it "Sport Detection".
- Source: FitRec Dataset — Kaggle
- Origin: Real Endomondo user workouts (UCSD FitRec Project, WWW 2019)
- Raw size: 250,000+ workouts with time-series sensor arrays
- Used: 50,000 workouts, filtered to top 4 sport types
- Format: JSONL with single-quote encoding (required ast.literal_eval parser)
Raw data = time-series arrays per workout. Extracted statistical features:
| Feature Group | Features Extracted |
|---|---|
| Speed | mean, max, std, range |
| Heart Rate | mean, max, std, range |
| Altitude | mean, max, std, range |
| Workout Meta | duration, n_points, gender |
Total: 15 features extracted from time-series arrays
- JSONL with single quotes → used
ast.literal_evalinstead ofjson.loads - Pre-normalized version → switched to raw
endomondoHR.jsonfor real signal - Silent NaN bug →
[~np.isnan(a)]vsa[~np.isnan(a)]— one character, complete feature corruption - Class imbalance (run=52%, walk=2%) → SMOTE oversampling on training set only
- bike vs bike (transport) → merged as physically indistinguishable from sensor data
| Model | Accuracy | F1 (weighted) |
|---|---|---|
| Logistic Regression | 0.6911 | 0.6598 |
| K-Nearest Neighbors | 0.7808 | 0.7769 |
| SVM (RBF kernel) | 0.7611 | 0.7447 |
| Random Forest ✅ | 0.8641 | 0.8585 |
1. HR beats Speed as top predictor
hr_mean (0.159) outranked speed_mean (0.054).
A slow cyclist and fast runner have identical speeds — but very different heart rates.
2. Duration is almost as important as HR
Cyclists ride longer than runners on average. Duration encodes sport modality implicitly.
3. Mountain bike is the hardest class (41% recall)
MTB overlaps with both bike (cycling motion) and run (slow uphill speed).
Would require cadence or power meter data to fully separate.
4. Model mistakes are physically interpretable
Every misclassification pair makes real-world sense:
bike↔run (speed overlap), mtb→bike (both cycling), walk→run (slow jog overlap).
- Python, NumPy, Pandas
- Scikit-learn (RF, SVM, KNN, Logistic Regression)
- imbalanced-learn (SMOTE)
- Matplotlib, Seaborn
- Kaggle Notebooks