Skip to main content

PPG-Bench - A Unified Evaluation Framework for PPG Foundation Models

Official code for PPG-Bench. Benchmark your PPG encoder on nine datasets with linear probes, random forests, frozen MLP probes and end-to-end finetuning.

Paper

Install

Use Python 3.11 or newer. Create an environment:

python -m venv .venv
source .venv/bin/activate

Install PyTorch inside this environment for your CPU/CUDA setup using the PyTorch installer, then:

pip install ppg-bench
ppg-bench list
ppg-bench init

ppg-bench init creates configs/ and examples/ in your working directory. It preserves existing directories; use --output another-directory if needed.

For the random-forest backend, a supported NVIDIA GPU and RAPIDS cuML are required:

pip install --extra-index-url https://pypi.nvidia.com 'ppg-bench[rf]'

Check RAPIDS installation requirements for your CUDA environment. Linear probing, MLP probing and finetuning can also run on CPU. Model-specific dependencies belong to your encoder's environment.

1. Download datasets

ppg-bench download ppgbp bidmc
ppg-bench download all --physionet-user YOUR_USERNAME

Downloads go to data/raw/<dataset>. Interrupted downloads can be resumed by rerunning the command.

Name Source/version Raw layout recognized by preprocessing
dalia UCI PPG-DaLiA S1/S1.pkl, …
dreamt PhysioNet 2.1.0 data_64Hz/S*_whole_df.csv
wesad WESAD authors S2/S2.pkl, …
ecsmp Mendeley v2 E4/, EEG_downsample/, scale.xlsx
ppgbp Figshare v5 PPG-BP dataset.xlsx, signal text files
bidmc PhysioNet 1.0.0 bidmc_csv/
butppg PhysioNet 2.0.0 subject-info.csv, quality-hr-ann.csv, record directories
realworldppg Mendeley v1 train8.xlsx, test8.xlsx
wildppg WildPPG authors WildPPG_Part_*.mat

DREAMT requires an approved PhysioNet account and signed data-use agreement.

2. Quickstart: your own model

After downloading a dataset, preprocess it at your encoder's sampling rate:

ppg-bench preprocess ppgbp --fs 125

Use preprocess all --fs 125 to prepare the full benchmark. For existing raw files, add --raw-root /path/to/dataset when preprocessing one dataset.

Edit examples/model.py, created by ppg-bench init, to implement two methods:

import torch
from ppg_bench.models import ModelPort
from your_model import Encoder  # Your model's architecture.


class MyModel(ModelPort):
    def load_encoder(self):
        encoder = Encoder()
        weights = torch.load(
            self.model_init_cfg["ckpt_path"], map_location="cpu", weights_only=True
        )
        encoder.load_state_dict(weights)
        return encoder

    def prepare_batch(self, batch, model_cfg, device):
        x = batch["x"].float().to(device)  # [batch, samples]
        # Apply your model's filtering and normalization here.
        return x.unsqueeze(1)  # Example: [batch, 1, samples]

load_encoder() must return a fresh encoder with pretrained weights whose forward pass produces [batch, embedding_dim]. Adapt checkpoint loading to your model's format. prepare_batch() applies the input formatting, filtering and normalization used during pretraining; the benchmark supplies resampled PPG windows. For finetuning, keep gradients enabled through the encoder.

Set examples/model.yaml to match your model:

name: MyModel
port: model.py:MyModel
fs: 125
embedding_dim: 512
init:
  ckpt_path: ../checkpoints/my_encoder.pt

Paths are relative to the YAML file. Set fs and embedding_dim to your encoder's sampling rate and output size. The benchmark handles downstream heads, training, hyperparameter selection and scoring.

Configs for the paper's external models are also created in configs/. Download their weights separately; AnyPPG and SigmaPPG also require the authors' source code, with init.source_root pointing to the downloaded repository.

3. Run a task, a dataset, or everything

Start with a single fold and seed to check your adapter:

ppg-bench run --model examples/model.yaml --datasets ppgbp-sysbp \
  --methods linear --seeds 42 --folds 0 --device cpu --output results/check

Evaluate every task on one dataset with the full seeds and folds:

ppg-bench run --model examples/model.yaml --datasets dalia \
  --methods linear --output results/dalia

Run the full benchmark:

ppg-bench run --model examples/model.yaml --output results/my-model

The full suite evaluates 17 primary tasks with all four methods and nine secondary tasks with linear and RF probes: 2,150 outer evaluations per model. Models and folds run sequentially to keep execution simple (it is recommended to add parallelization if possible on your local machine). This command is interrupt-resume-friendly. Remember to change the output dir between runs to avoid overwriting results. Results run with this command will be directly comparable to those in the paper, so you do not need to rerun any external models.

Protocol and results

The protocol in ppg_bench.protocol specifies:

  • Five outer folds and four inner folds for exhaustive linear/RF grid search.
  • A 20% group-disjoint validation holdout for neural methods, repeated for subject-level tasks, with repeat-specific seeds.
  • 48 TPE trials, eight startup trials and Hyperband pruning: 25 maximum epochs for MLP probes and 15 for finetuning.
  • Mean subject aggregation for regression; mean, median and top-10% aggregation candidates for subject-level classification.

Groups are subjects, except closed-set RealWorldPPG identification, where groups are individual records and participant IDs remain shared class labels. PPG-BP targets are scored at subject level. Selection uses MAE for regression, AUROC for binary linear/RF/MLP tasks, and balanced accuracy for multiclass tasks and finetuning classification. Secondary ECSMP emotion estimates six questionnaire scores and reports balanced accuracy of their argmax.

Each run saves:

results/my-model/
  run.json          # models, data identity, protocol, planned jobs
  summary.csv       # task/method means and Student-t 95% CIs
  status.json       # completed/planned counts
  jobs/             # per-fold metrics, splits, predictions and HPO records
  features/         # reusable frozen embeddings

License

PPG-Bench's own code is licensed under the GNU General Public License v3.0 only (GPL-3.0-only); see LICENSE. Bundled PaPaGei and PulsePPG code retains its BSD-3-Clause and MIT licenses, respectively, with the full notices in ppg_bench/encoders/NOTICE. External model code, weights and datasets remain subject to their authors' terms.

Metadata

Release files for ppg-bench 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ppg-bench 0.1.0
File Size Uploaded Provenance Actions
ppg_bench-0.1.0.tar.gz 83.0 kB Without provenance Details for ppg_bench-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ppg-bench 0.1.0
File Interpreter ABI Platform Actions
ppg_bench-0.1.0-py3-none-any.whl Python 3 none any Details for ppg_bench-0.1.0-py3-none-any.whl

Total release size: 169.1 kB

Release files / ppg_bench-0.1.0.tar.gz

Download URL ppg_bench-0.1.0.tar.gz
Size 83.0 kB
Tags Source
SHA-256 checksum
How to use checksums
b95f330802d0d9282623636566bb69f3f6943e83b37c84f247ad0f6b1cf689bf
BLAKE2b-256 checksum
How to use checksums
d02543503585c215384d7bb10e6d1193669d5a4d813f52cb371d61a2431d3493
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / ppg_bench-0.1.0-py3-none-any.whl

Download URL ppg_bench-0.1.0-py3-none-any.whl
Size 86.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
794a2d7849021cfb32bb89e41fa54b25856b89bec97b9259c6db004bb1f79dfc
BLAKE2b-256 checksum
How to use checksums
eb7402ffcc924c141dfe03eba3e391348cf0461eda14be8a27ae967e6e2b6d1a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for ppg-bench 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page