Training¶
The model is a BiLSTM-CNN with attention trained via Leave-One-Subject-Out (LOSO) cross-validation.
Quick start¶
1. Smoke test with synthetic data (no hardware needed)¶
cd wearable_har_v2
.venv/bin/python -m host.train_model --synthetic --epochs 2 --output /tmp/test_model.pt
This generates random data mimicking the 11 classes, trains for 2 epochs, exports a TorchScript model, and prints a validation accuracy for each subject.
2. Train on real data¶
.venv/bin/python -m host.train_model \
--data_dir recordings/ \
--output models/worker_har_best.pt \
--loso \
--epochs 50 \
--batch_size 32
CLI flags¶
| Flag | Default | Description |
|---|---|---|
--data_dir |
(required) | Directory of .h5 recordings |
--output |
models/model.pt |
TorchScript export path |
--synthetic |
False |
Generate random training data instead of loading .h5 files |
--loso |
False |
Leave-One-Subject-Out CV (splits by subject_id HDF5 attr) |
--epochs |
30 | Training epochs per fold |
--batch_size |
32 | Mini-batch size |
--lr |
0.001 | Adam learning rate |
--hidden_dim |
128 | BiLSTM hidden dimension |
--num_layers |
2 | BiLSTM layers |
Model architecture¶
Input (328-dim feature)
→ LayerNorm
→ Conv1d (kernel=3, 64 filters) → ReLU → MaxPool1d
→ Conv1d (kernel=3, 128 filters) → ReLU → MaxPool1d
→ BiLSTM (2 layers, hidden=128) → attention pooling
→ Linear(256 → 64) → ReLU → Dropout(0.3)
→ Linear(64 → 11) → softmax
LOSO cross-validation¶
For N subjects, the script runs N folds. Each fold holds out one subject for validation and trains on the remaining N−1. Final reported metrics are the mean ± std across all folds. The exported model is trained on all subjects (full dataset) — this is the model used for live inference.
Outputs¶
| File | Contents |
|---|---|
models/worker_har_best.pt |
Self-contained TorchScript module (normalization baked in) |
models/worker_har_best.meta.pkl |
Labels + feature names (Python pickle) |
models/training_log.json |
Per-epoch loss, per-fold accuracy |
Export format¶
The model exports via torch.jit.script (NOT torch.jit.trace). Tracing
baked CPU-initialized hidden tensors into the LSTM graph, breaking GPU
inference. torch.jit.script preserves the LSTM's runtime hidden-state
creation, so the model runs on any device: CPU, CUDA, or Jetson.
import torch
model = torch.jit.load("models/worker_har_best.pt")
feats = torch.randn(1, 328) # batch × feature_dim
output = model(feats)
print(output.shape) # torch.Size([1, 11])
Feature names & labels¶
import pickle
with open("models/worker_har_best.meta.pkl", "rb") as f:
meta = pickle.load(f)
print(meta["labels"]) # ['standing', 'walking', ..., 'troweling']
print(meta["feature_names"]) # ['imu0_quat_w_mean', 'imu0_quat_w_std', ..., 'fsr_ratio_right']