"I cannot see the sleeper's brain waves, so I read the autonomic nervous system's diary instead. It turns out the heart keeps very detailed notes."
An Inferential AI Agent
Prerequisites
This section assumes the PPG waveform and beat detection from Section 30.1, and the heart-rate variability features of Section 30.3, whose RMSSD and LF/HF quantities are the raw material here. It builds on autonomic physiology and epoch-based labeling from Chapter 28, the person-level splitting discipline of Chapter 5, and the sequence models of Chapter 14. Comfort with a power spectrum (Chapter 7) is enough for the frequency-domain HRV features.
The Big Picture
Sleep stage and psychological stress look like two unrelated problems, but a wrist PPG solves both by reading the same hidden variable: the balance between the sympathetic and parasympathetic branches of the autonomic nervous system. A green LED cannot see cortical slow waves or a cortisol spike. What it can see is the heartbeat, and the heartbeat is exquisitely modulated by autonomic tone. Deep sleep is parasympathetic dominance (slow, steady heart, high vagal variability); REM and acute stress are sympathetic surges (faster, less variable heart). So the wearable never measures sleep or stress directly. It measures the autonomic proxy, then a model maps that proxy, plus motion and respiration, onto the label a clinician or a user actually wants. Understanding this indirection is the whole game: it explains both why consumer sleep staging works surprisingly well and why it will never match a polysomnogram.
One signal, two branches of the nervous system
The PPG carries three autonomic tracers at once. The first is instantaneous heart rate from the inter-beat interval (IBI) series. The second is heart-rate variability, the beat-to-beat fluctuation whose high-frequency band (0.15 to 0.4 Hz) reflects vagal, parasympathetic activity, and whose low-frequency band (0.04 to 0.15 Hz) blends sympathetic and baroreflex influence. The third is respiration: breathing amplitude-modulates and frequency-modulates the pulse, so the envelope of the PPG recovers a respiratory rate and its regularity without a chest strap.
These tracers move in a stereotyped way across the night. As a sleeper descends into slow-wave (deep, N3) sleep, the parasympathetic branch takes over: heart rate drops to its nightly minimum, RMSSD and high-frequency power climb, and breathing becomes slow and metronomic. REM sleep is the opposite and the giveaway: the brain is active, sympathetic tone surges in bursts, heart rate rises and becomes erratic, and respiration turns irregular. Wake carries gross body motion and a high, variable heart rate. That gives a four-way structure (Wake, Light, Deep, REM) that maps cleanly onto autonomic features, which is exactly the label set every consumer sleep tracker reports.
Key Insight
Stress detection and REM detection are, mechanistically, the same measurement: both are the sympathetic branch overriding the parasympathetic one, seen as a rising heart rate with collapsing high-frequency HRV. The model that scores daytime stress and the model that scores nighttime REM are reading the identical autonomic axis. This is why a single PPG feature set, IBI statistics plus HRV bands plus respiration, serves sleep staging, stress, and recovery scores alike. Learn the autonomic proxy once and you have built three products.
From gold standard to wrist: what the label really is
Sleep's ground truth is polysomnography (PSG): EEG, EOG, EMG, and more, scored by a technician into 30-second epochs under the AASM rules as Wake, N1, N2, N3, and REM. A wrist PPG has none of those electrodes, so it cannot recover the N1/N2 distinction that depends on cortical microstructure. The honest target is therefore a collapsed taxonomy: Wake / Light (N1+N2) / Deep (N3) / REM. Consumer devices (Oura, Fitbit, Apple Watch, Whoop) report exactly this four-class scheme, and the right way to score them is agreement against concurrent PSG using Cohen's \( \kappa \), not raw accuracy, because a "predict Light always" baseline already scores high on the majority class.
Stress has no EEG-grade gold standard at all, which is a deeper problem. Research protocols manufacture ground truth with a validated stressor, the Trier Social Stress Test, cold-pressor, or a mental-arithmetic task, and label the induced window as "stress." The WESAD dataset (chest and wrist signals with baseline, stress, and amusement conditions) is the reference corpus for wearable stress. The trap is construct validity: the label is really "sympathetic activation," and sympathetic activation is not the same thing as subjective distress. Physical exertion, caffeine, and a happy surprise all light up the same PPG features, so a naive stress model cheerfully flags a brisk walk as anxiety. Distinguishing stress from mere arousal is the open, hard part, and it is why serious deployments gate on motion and context rather than trusting HRV alone.
A smart-ring recovery score that mistook a hot bath for anxiety
A wearable startup shipped a nightly "recovery" score derived from resting heart rate and HRV in the first hours of sleep, on the sound physiology that low HRV predicts poor recovery. Field data surfaced a cluster of users whose scores cratered on random nights with no reported stress. The common factor, recovered from motion and skin-temperature channels, was a hot bath or a heavy late meal before bed: peripheral vasodilation and digestion raise heart rate and suppress HRV exactly as psychological stress does. The autonomic proxy was behaving correctly; the label "poor recovery" was overreaching. The fix was not a better HRV algorithm but a context gate: require low motion, a stable skin temperature, and a settled sleep onset before trusting the HRV window, and widen the estimate's uncertainty when the context is ambiguous, the calibration discipline of Chapter 18. Reported false stress episodes fell by more than half with the model untouched.
Features, then a sequence model
A working pipeline computes autonomic features on a sliding window (30 seconds for sleep epochs, 60 to 300 seconds for stress), then feeds the feature sequence to a temporal model. The reason the model must be temporal, not per-epoch, is that stages have strong grammar: REM follows deep sleep, not wake; a single deviant epoch is more likely a mislabel than a real one-epoch stage. A model that scores each epoch independently throws away this structure, so recurrent and temporal-convolutional networks (Chapter 14) that see a context window of neighboring epochs consistently beat per-epoch classifiers by a wide margin. The snippet below computes the core features from an IBI series so the mechanism is concrete before any network sees them.
import numpy as np
def autonomic_features(ibi_ms, fs=4.0):
"""Time- and frequency-domain HRV from an inter-beat-interval series (ms)."""
ibi = np.asarray(ibi_ms, float)
hr = 60000.0 / ibi.mean() # mean heart rate (bpm)
rmssd = np.sqrt(np.mean(np.diff(ibi) ** 2)) # vagal / parasympathetic index
# Resample the irregular IBI tachogram to a uniform grid for a spectrum.
t = np.cumsum(ibi) / 1000.0
grid = np.arange(t[0], t[-1], 1.0 / fs)
x = np.interp(grid, t, ibi) - ibi.mean()
f = np.fft.rfftfreq(len(x), 1.0 / fs)
p = np.abs(np.fft.rfft(x * np.hanning(len(x)))) ** 2
lf = p[(f >= 0.04) & (f < 0.15)].sum() # sympathetic + baroreflex
hf = p[(f >= 0.15) & (f < 0.40)].sum() # parasympathetic (respiration)
return dict(hr=hr, rmssd=rmssd, lf_hf=lf / (hf + 1e-9))
deep_sleep = np.random.default_rng(0).normal(1050, 45, 200) # slow, variable heart
stress = np.random.default_rng(1).normal(720, 12, 200) # fast, rigid heart
print("deep :", {k: round(v, 2) for k, v in autonomic_features(deep_sleep).items()})
print("stress:", {k: round(v, 2) for k, v in autonomic_features(stress).items()})
Running it prints the autonomic signature directly: deep sleep gives low hr, high rmssd, low lf_hf; the stress window inverts all three. A real staging model stacks these features per epoch across the night and lets a sequence network learn the transition grammar on top. Person-level splits are non-negotiable: resting heart rate and HRV are strongly individual, so any window from a subject in training must never appear in the test set, or the reported \( \kappa \) is measuring memorized physiology, not generalization (Chapter 5).
Right Tool: HRV and respiration features
Hand-rolling a robust HRV suite (Lomb-Scargle spectra for the irregular tachogram, ectopic-beat correction, geometric and nonlinear indices such as SD1/SD2, plus a PPG-derived respiratory rate) is several hundred lines and full of edge cases around artifact rejection. The neurokit2 library reduces the whole feature stage to about three lines: signals, info = nk.ppg_process(ppg, sampling_rate=fs) then nk.hrv(info, sampling_rate=fs) returns a labeled table of dozens of validated HRV features, and nk.ppg_rate plus nk.rsp_rate recover respiration. You supply the raw PPG and a sampling rate; the library handles peak detection, artifact correction, and the spectral bookkeeping.
What the proxy can and cannot promise
Set expectations by the physiology. On the four-class collapsed scheme, well-built PPG plus actigraphy staging reaches epoch agreement with PSG around \( \kappa \approx 0.5 \) to \( 0.6 \), roughly "moderate," with Deep and REM easier than the Light/Wake boundary, where quiet wakefulness mimics light sleep autonomically. That is genuinely useful for tracking trends and sleep architecture over weeks, and genuinely insufficient to diagnose a sleep disorder, which is why these devices carry wellness rather than diagnostic labeling (Chapter 34). Two structural limits bound everything: the N1/N2 boundary is invisible without EEG, and sympathetic arousal is polysemous, so stress, exertion, and excitement are not separable from HRV alone. The most reliable systems therefore fuse the PPG proxy with accelerometry, skin temperature, and time-of-day, and they report calibrated uncertainty rather than a single confident stage.
Research Frontier
The frontier is self-supervised wearable foundation models that pretrain on millions of unlabeled overnight PPG and accelerometer recordings, then fine-tune sleep staging and stress with far fewer labeled nights. Google's Large Sensor Model line and Apple's and Oura's internal PPG encoders point this way, learning autonomic representations once and serving many downstream heads (see Chapter 20). Publicly, the MESA and SHHS PSG cohorts anchor sleep benchmarking, and contrastive pretraining on the raw pulse (Chapter 17) is closing the gap to per-epoch PSG agreement. The unsolved problem remains construct validity for stress: no wearable label yet cleanly separates distress from arousal, and building a dataset that does, with concurrent cortisol or validated affect ratings, is the bottleneck rather than the model.
Exercise
Using a public PSG-plus-PPG cohort (or the MESA overnight recordings): (1) Extract per-30-second-epoch autonomic features (mean HR, RMSSD, LF/HF, respiratory rate) from the PPG. (2) Train a per-epoch classifier and a sequence model (a small temporal CNN or LSTM over a context window of neighboring epochs) to predict the four-class collapsed stage, using a strict subject-level split. (3) Report Cohen's \( \kappa \), not accuracy, and a confusion matrix; confirm the sequence model improves the Light/Wake and REM boundaries. (4) Ablation: shuffle the epoch order before feeding the sequence model and show the \( \kappa \) collapses, demonstrating that the transition grammar, not the per-epoch features, carries much of the gain.
Self-Check
- A wrist PPG cannot see cortical activity, yet it stages sleep. What hidden physiological variable does it actually measure, and how do deep sleep and REM differ along it?
- Why is Cohen's \( \kappa \) the right metric for PPG sleep staging, and what naive baseline does raw accuracy flatter?
- Your stress model flags a subject as highly stressed, but they were climbing stairs. Explain, in autonomic terms, why HRV alone cannot resolve this, and name one extra channel that would.
What's Next
In Section 30.6, we confront the assumption every method in this section quietly made: that the pulse is clean. Real wrist PPG is wrecked by motion artifact, and both the HRV features and the sleep and stress inferences built on them are only as trustworthy as the signal-quality gate that decides when to compute them at all.