Skip to content

Latest commit

 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GradePrediction

Wearable Stress Modeling for Academic Performance Prediction

Marissa Crevecoeur · David Juarez · Sumaiyah Rahman


Overview

This project investigates whether physiological stress signals recorded from wearable devices during controlled lab sessions can be used to build a generalizable stress model, and whether that model's predictions correlate with academic performance when applied to real exam recordings.

The pipeline has two stages:

  1. Train a stress classification model on a controlled stress-induction dataset using self-reported stress labels
  2. Apply the trained model to physiological data recorded during real university exams and test whether predicted stress correlates with exam grades

Research Question

How can stress be modeled as a continuous physiological signal from wearable sensor data, and to what extent does this stress representation exhibit meaningful associations with academic performance?


Datasets

Source Dataset — Stress Training Data

Wearable Device Dataset from Induced Stress and Structured Exercise Sessions Hongn et al., PhysioNet 2025. DOI: 10.13026/he0v-tf17

  • 35 participants (18 V1 protocol, 17 V2 protocol)
  • Empatica E4 wristband recordings
  • Controlled stress induction protocol: Baseline, Stroop, TMCT, Opinion tasks, Subtract
  • Self-reported stress scores (1–10 scale) per protocol stage
  • Signals: EDA, BVP, HR, TEMP, ACC, IBI

Target Dataset — Exam Stress Data

Wearable Exam Stress Dataset for Predicting Cognitive Performance Amin et al., PhysioNet 2022. DOI: 10.13026/kvkb-aj90

  • 10 students across 3 exams (Midterm 1, Midterm 2, Final)
  • Same Empatica E4 wristband
  • Linked to actual exam grades
  • Signals: EDA, BVP, HR, TEMP, ACC, IBI

Methodology

Source Dataset                    Target Dataset
(Lab stress sessions)             (Real exam recordings)
        │                                  │
        ▼                                  ▼
  feat_eng.py                       new_feat_eng.py
  (feature extraction)              (same features)
        │                                  │
        ▼                                  │
  train.py                                 │
  (model training +                        │
   cross-validation)                       │
        │                                  │
        ▼                                  ▼
  Saved Model  ──────────────▶  Inference + Grade
  (gb_class3_z)                  Correlation

Feature Engineering (feat_eng.py)

  • 60-second sliding windows with 30-second overlap
  • Features extracted per window across all signals:
    • EDA: mean, std, min, max, range, slope, SCL mean/slope, SCR peak count/amplitude
    • Temperature: mean, std, min, max, slope
    • Heart Rate: mean, std, min, max
    • HRV (IBI-derived): mean IBI, SDNN, RMSSD, pNN50
    • BVP: mean, std, LF power, HF power, LF/HF ratio
    • Accelerometer: magnitude mean, std, max
  • Tonic/phasic EDA decomposition via 0.05 Hz Butterworth low-pass filter
  • Artifact flagging: EDA flatline, EDA dropout, motion, HR missing
  • Per-subject z-score normalization

Model Training (train.py)

  • Label schemes: 3-class stress (Low: 1–3, Medium: 4–6, High: 7–10)
  • Algorithms: Random Forest, Gradient Boosting
  • Feature schemes: raw features, per-subject z-scored features
  • Validation: nested subject-grouped cross-validation
    • Outer: StratifiedGroupKFold (5 splits)
    • Inner: StratifiedGroupKFold (5 splits) with RandomizedSearchCV (50 iterations)
  • Class imbalance: class_weight="balanced" for RF; compute_sample_weight for GB
  • Imputation: median imputation for missing signal windows

Data Quality Decisions

Decision Rationale
Exclude S02 Duplicated raw signal values from E4 Connect download
Invalidate f07 BVP/HR/IBI/TEMP Protection dock never removed — PPG sensor blocked
Split f14 into f14_a / f14_b Bluetooth loss mid-session; baseline in f14_a
Flat-responder filter (std < 0.8) Subjects with near-zero label variance add noise

Results

Stress Classification (Source Dataset)

Model Accuracy Balanced Accuracy Macro F1
RF — raw features 0.562 0.382 0.377
RF — z-scored features 0.481 0.376 0.375
GB — raw features 0.533 0.363 0.364
GB — z-scored features 0.481 0.387 0.383

Best model: Gradient Boosting on z-scored features (gb_class3_z)

Chance level for balanced 3-class classification = 0.333 macro F1. All models are above chance, with the performance ceiling attributed to self-reported label noise rather than feature poverty.

Iteration History

Iteration Best Model Macro F1 Balanced Accuracy
Basic Features RF 0.384 0.398
Trend Features RF 0.437 0.444
HR Variability + Motion RF 0.439 0.462
Baseline Normalization RF 0.421 0.449
Clean EDA + Feature Selection (ANOVA-50) RF 0.473 0.492

Limitations

Limitation Mitigation
Small sample size (27 training subjects) Effect sizes + confidence intervals reported
Domain shift: lab vs. exam stress Within-subject z-score normalization; baseline-relative scoring
Self-reported labels are noisy Flat-responder filtering; 3-class rather than 10-class binning
V1/V2 protocol differences Protocol version tracked as metadata
Single wearable device Empatica E4 is validated research-grade hardware

Repository Structure

GradePrediction/
├── feat_eng.py              # Feature extraction pipeline
├── train.py                 # Model training and evaluation
├── features_stress.csv      # Generated feature table (not tracked if large)
├── models/                  # Saved model pipelines (.joblib)
│   ├── stress_rf_class3_raw.joblib
│   ├── stress_rf_class3_z.joblib
│   ├── stress_gb_class3_raw.joblib
│   └── stress_gb_class3_z.joblib
├── reports/                 # Evaluation outputs
│   ├── summary.json         # Full results across all configs
│   ├── summary_partial.json # Incremental results (crash-safe)
│   ├── feature_importance.csv
│   └── *.txt / *_confusion.csv
├── CHANGES.md               # Branch-level change documentation
└── README.md                # This file

Setup and Usage

Requirements

pip install numpy pandas scipy scikit-learn joblib

1. Generate Features

python feat_eng.py

Reads from wearable-data/Wearable_Dataset/STRESS/ and writes features_stress.csv.

2. Train Models

python train.py

Reads features_stress.csv, runs nested cross-validation across 4 configurations, saves models to models/ and reports to reports/.

Expected runtime: 1–3 hours on a standard CPU instance.

On Google Cloud VM

source venv/bin/activate
nohup python3 train.py > training_log.txt 2>&1 &
tail -f training_log.txt

Branches

Branch Description
main Stable pipeline
feature/cv-fixes-flat-filter CV leakage fix, flat-responder filter, class10 removed

References

  1. Hongn, A., Bosch, F., Prado, L., & Bonomini, P. (2025). Wearable Device Dataset from Induced Stress and Structured Exercise Sessions (version 1.0.1). PhysioNet. https://doi.org/10.13026/he0v-tf17

  2. Amin, M.R., Wickramasuriya, D., & Faghih, R.T. (2022). A Wearable Exam Stress Dataset for Predicting Cognitive Performance in Real-World Settings (version 1.0.0). PhysioNet. https://doi.org/10.13026/kvkb-aj90

  3. Çöpürkaya Ç., et al. (2023). Investigating the effects of stress on achievement: BIOSTRESS dataset. Data in Brief, 49, 109297. https://doi.org/10.1016/j.dib.2023.109297

  4. Hsu, A. (2023). Quantifying Exam Stress Progressions Using Electrodermal Activity and Machine Learning. IEEE BIBE 2023, pp. 434–438. https://doi.org/10.1109/BIBE60311.2023.00077

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages