Skip to content
Research
Page 5 of the mood detection paper: the datasets table, the class equalisation results and the confusion matrices for four-class classification
A page from the paper2026

Mood change detection

Presented at IEEE CIBCB 2026March 2026 to July 2026

Mood changes in young people often go unnoticed for years, and heart data is too private to pool in one place. I built a pipeline that estimates whether someone feels positive or negative from their heart rhythm, tested it on 74 people it had never seen, and trained it across six Raspberry Pis without sharing anyone's raw data.

Download research PDF, 475 KB

Shared under CC BY, via arXiv.

Figure 1 from the mood detection paper: data acquisition from a Polar H10 chest strap and three datasets, ECG pre-processing, 45-second windows with nine heart rate variability features, model training and evaluation, and federated learning across five client nodes, with raw ECG never leaving the device
Figure 1 from the paper, CC BY

The problem

Mood disorders in young people are usually caught through self-report and booked appointments, and the average gap between the first signs and treatment is eight to twelve years. Most heart-rhythm models are tested on the same people they learned from, which flatters them, and pooling everyone's heart data raises real privacy concerns.

What I did

I built the whole pipeline in Python, from the raw heart signal to cross-participant tests on three public datasets, and set up the six-node Raspberry Pi cluster for federated training. It is meant as a personal awareness tool, not a clinical one.

How it works

  1. Record the heart

    The heart's electrical signal comes from three public research datasets, 74 people in all, or from a chest strap.

  2. Cut it up

    Each recording is cut into 45-second pieces.

  3. Measure the rhythm

    Nine standard measures describe how the gap between heartbeats varies in each piece.

  4. Guess, then vote

    A model guesses the feeling for each piece, and the pieces vote on the whole clip.

  5. Test on strangers

    Each test leaves one person out of training, so the model is judged on someone it has never seen.

  6. Train without pooling

    Six Raspberry Pis train together and share only the model's numbers, never anyone's heart data.

Signal to features

  1. 01Acquire

    ECG from DREAMER (23 people, 256 Hz), AMIGOS (15, 128 Hz) and EmoWear (36, 250 Hz), or live from a Polar H10 at 130 Hz.

    • DREAMER
    • AMIGOS
    • EmoWear
    • Polar H10
  2. 02Window

    Non-overlapping 45-second windows, chosen over 15, 30, 60 and 90 s because they scored above the other lengths under both protocols.

    45 s
  3. 03Features

    Nine HRV features per window. Nine standard features matched a 78-feature extended set under cross-participant evaluation.

    • RMSSD
    • SDNN
    • pNN50
    • MeanNN
    • HF
    • LF
    • LF/HF
    • SD1
    • SD2

Training and evaluation

  1. 04Classify

    Six classifiers under identical settings, a prediction per window and a majority vote per clip. Classes balanced by downsampling, not SMOTE, which would invent heart patterns between people.

    • Logistic Regression
    • Random Forest
    • SVM
    • XGBoost
    • LDA
    • KNN
  2. 05Evaluate

    Leave-one-participant-out cross-validation is the main benchmark: the held-out person's data never touches training.

    LOPO-CV

Federated cluster, six Raspberry Pi 4s

  1. 06Federate

    One server and five clients, each holding four or five participants. Each trains Logistic Regression locally; FedAvg averages the weights. Random Forest cannot be averaged this way, so it stays centralised.

    • Flower
    • FedAvg
    • Logistic Regression
Simplified. The window-length search, the feature set comparison and the four-class models are left out.

In numbers

  • 53.17%

    Binary valence, leave-one-participant-out, DREAMER, Logistic Regression

    Modest; 50% is chance

  • 56.3%

    Recall for the rarest class after balancing, up from 7.8%

    Within participant, four class, DREAMER

  • 2.7points

    Largest gap between federated and centralised training (AMIGOS, 55.04% against 57.76%)

  • 74

    Participants across three public datasets

  • 75%

    Binary valence in the Polar H10 pilot, against 52.81% across participants

    Pilot on one person, four clips

My part

  1. Pipeline

    I built every stage in Python: pre-processing, windowing, heart rate variability features, the classifiers and the evaluation.

    All of it

  2. Federated cluster

    I deployed the federated training on six Raspberry Pi 4s with Flower.

    All of it

  3. Research

    I did all of it: the coding, the experiments, the analysis and the writing. I am first author, and colleagues at the university are co-authors.

    All of it

Built with

Python
The whole pipeline
Flower
Federated training
Raspberry Pi 4
Six-node cluster
Logistic Regression and Random Forest
The main classifiers
XGBoost, SVM, LDA and KNN
The comparison
Polar H10
The pilot recording

In pictures

A Polar H10 heart rate chest strap, the sensor unit clipped to its fabric strap
A Polar H10, the strap used in the pilot on one person. Photo: Tiia Monto, CC BY-SA 3.0
Me at my desk with code on a large monitor, a laptop and a small desktop computer beside it
At my desk. Photo, 2026

From the work

These are pictures of the project's own code running on simulated input. They show how it works, not what it found.

The ECG pipeline on a synthetic heart signal: one window kept by the R-peak quality gate and one dropped
The ECG pipeline and its quality gateRendered from the project's code, simulated input2026
A federated learning round on three synthetic clients: each trains on its own data and the server averages their models
A federated round on three simulated clientsRendered from the project's code, simulated input2026
The live session app's self-report screen, with valence and arousal scales, during a session driven by a synthetic heart signal
The self-report screenScreenshot, simulated input2026

Where it stands

Accepted on 1 June 2026 and presented at IEEE CIBCB 2026 in Athens.

What it found

The feeling closest to low mood, low energy and negative, was nearly invisible: the model found 7.8% of it. With the training data balanced, it found 56.3%. That test used the same people for training and testing.

Asked only whether someone felt positive or negative, on people it had never seen, it was right at most 53.17% of the time. That is modest. All six models I tried landed between 49.9% and 53.2%, which suggests the limit is in the signal, not the model.

Training across the six Raspberry Pis gave results comparable to training in one place, within 2.7 points on all three datasets.

In a pilot on one person with a Polar H10 chest strap, it was right 75% of the time for positive or negative, against 52.81% across participants. One person is not a study: it is promising, pending a wider one.

Class imbalance was the main thing holding back low-arousal, low-valence detection: 109 windows against 304 for the largest class. Downsampling every class to 109 raised its recall from 7.8% to 56.3% within participant, while the other classes moved by less.

Six classifiers converge between 49.9% and 53.2% on binary valence across participants. The paper reads that ceiling as physiological rather than algorithmic, which points to personalisation over time.

Federated against centralised Logistic Regression: DREAMER 53.99% against 53.17%, AMIGOS 55.04% against 57.76%, EmoWear 50.87% against 50.96%. Comparable, with no raw features shared; no significance test was run.

What went wrong

  • Too little data per person

    One dataset had only about 24 pieces per person, so each test trained on very little, and four-way accuracy started at 28.82%.

    AMIGOS: 15 participants, about 24 windows each, so each LOPO-CV fold trained on fewer than 336 examples against about 70 windows per participant in DREAMER; 28.82% four-class before equalisation.

  • Feelings did not follow the script

    In the pilot, each clip was chosen to stir one feeling, but what the participant reported did not always match.

    Self-reported valence and arousal did not always fall in the intended quadrant, so the pilot was scored against the self-reports.

  • The live validation is one participant, a study author, and four clips. Federated training used dataset partitions, not months of one person's data, and assumed a shared local network.

  • Four-class accuracy across participants is 24.02%. The contribution is the imbalance finding and private training, not accurate mood detection.

What comes next

Add EEG alongside the heart signal in the federated setup, and run live validation on a wider group of people, which needs ethics approval and informed consent first.

The paper is being extended into a journal paper.

Explanation

Hi. Tell me your name and I will use it now and then as you look around. It stays on this device. I never collect it, so not even I will know.