raj5517/ppg-heart-rate-estimator
116
PPG Heart Rate Estimator — CNN/LSTM with TFLite Deployment
Lightweight CNN/LSTM for heart rate estimation from raw PPG signals. Deployed as TensorFlow Lite for mobile and embedded targets.
Results
- Median error: 0.34 BPM
- P95 error: 1.86 BPM
- Max error: 4.36 BPM
Architecture
Input (1000, 1) — 8 sec @ 125Hz
→ Conv1D(16,k=7) → BN → MaxPool(2)
→ Conv1D(32,k=5) → BN → MaxPool(2)
→ Conv1D(64,k=3) → BN → MaxPool(2)
→ LSTM(32, return_sequences=True) → Dropout
→ LSTM(16)
→ Dense(32) → Dropout
→ Dense(1) — BPM regressionTotal params: 25,505 (~100KB FP32)
Predicted vs True
Error Distribution
MAE by HR Range
Training Curves
Usage
import tensorflow as tf
import numpy as np
interpreter = tf.lite.Interpreter(
model_path="ppg_hr_dynamic.tflite",
experimental_delegates=[tf.lite.load_delegate('tensorflowlite_flex')]
)
interpreter.allocate_tensors()
inp = interpreter.get_input_details()
out = interpreter.get_output_details()
# sample: (1, 1000, 1) float32 — normalized PPG window
sample = np.random.randn(1, 1000, 1).astype(np.float32)
interpreter.set_tensor(inp[0]['index'], sample)
interpreter.invoke()
hr_bpm = interpreter.get_tensor(out[0]['index'])[0][0]
print(f"Estimated HR: {hr_bpm:.1f} BPM")Notes
LSTM layers require the Flex delegate for TFLite inference. On Android: add tensorflow-lite-select-tf-ops dependency.
Links
- GitHub: https://github.com/RAj5517/ppgheartrate_estimator
