/
βββ *.h5 # one or more pandas HDFStore files
```
Each key in an HDF5 store is one recording, stored as a pandas DataFrame with the EDA channels as columns (mixed, phasic, tonic, sampled at 4 Hz). An optional `Timestamp` column is dropped. Each key's storer has an `attrs.metadata` dict with `user`, `session`, `dataset_name` and `len_data` (number of samples). The loader cuts 60 s windows (240 samples) on the fly with a stride of `shift` samples, and splits train and validation by recording, so windows from one recording never end up in both.
---
## ποΈ UME Architecture (Base)
UME is an EfficientNet-inspired 1D encoder for contrastive learning:
```
Input (N, T, C)
-> Stem Conv1D + BN + Swish
-> MBConv1D blocks (repeated)
-> Head Conv1D + Global Pool
-> Linear embedding
-> Contrastive loss on two augmented views
```
Base preset (default), set through the `model_size` presets in [`configs/conf-ume.yaml`](configs/conf-ume.yaml):
| Parameter | Base Value |
|-----------|------------|
| `stem_channels` | `64` |
| `mbconv_channels` | `64` |
| `num_mbconv_blocks` | `16` |
| `head_channels` | `248` |
| `embedding_dim` | `64` |
| `kernel_size` | `3` |
| `dropout` | `0.1` |
| `loss temperature` | `0.1` |
| optimizer | Adam, lr `5e-4`, weight decay `1e-3` |
Contrastive training setup (augmentations, optimizer, scheduler):
- [`configs/pretrain/contrastive.yaml`](configs/pretrain/contrastive.yaml)
- [`configs/pretrain/engine/contrastive.yaml`](configs/pretrain/engine/contrastive.yaml)
---
## π§ͺ UME Configurations
We recommend the **base UME** preset, and only its weights are released. The other presets and the pretraining-data subsamples used in our ablations can be retrained with the configs below.
### UME model-size presets
Defined in [`configs/conf-ume.yaml`](configs/conf-ume.yaml):
| Preset | Stem | MBConv | Blocks | Head | Embedding | Kernel | Dropout |
|--------|------|--------|--------|------|-----------|--------|---------|
| `tiny` | `32` | `32` | `4` | `96` | `32` | `5` | `0.1` |
| `small`| `48` | `48` | `8` | `160` | `48` | `7` | `0.1` |
| `base` | `64` | `64` | `16` | `248` | `64` | `3` | `0.1` |
| `large`| `96` | `96` | `24` | `384` | `96` | `11` | `0.1` |
Sweeps over model size and pretraining-data size: [`sweep-ume-ablation-size.yaml`](configs/sweep-ume-ablation-size.yaml) and [`sweep-ume-ablation-subsample.yaml`](configs/sweep-ume-ablation-subsample.yaml).
---
## πΎ Checkpoints and Weights
Three files hold the same base UME weights:
| File | Contents | Use it for |
|------|----------|------------|
| [`model.safetensors`](model.safetensors) + [`config.json`](config.json) | Encoder weights in [safetensors](https://huggingface.co/docs/safetensors) format, with the model config. Holds tensors only, so loading never runs code. This is what `from_pretrained()` downloads from the Hugging Face Hub. | Inference and fine-tuning (recommended). |
| [`artifacts/ume_base_inference.pt`](artifacts/ume_base_inference.pt) | Encoder `state_dict` and model config in one PyTorch file. Loads with `torch.load(..., weights_only=True)`. | Same as above, without the safetensors dependency. |
| [`artifacts/ume_base_training.ckpt`](artifacts/ume_base_training.ckpt) | Full PyTorch Lightning checkpoint, including optimizer and scheduler state. Needs `weights_only=False`. | Resuming or inspecting training. |
**Are they the same model?** Yes. All three hold the same 366 encoder tensors, bit-for-bit, and give identical embeddings. They differ only in what else they contain:
- `ume_base_training.ckpt` is about 3Γ larger because it also stores the training state (mostly the Adam optimizer state, plus epoch, step, callback and hyperparameter records). Its weight keys carry a `model.` prefix, which `from_pretrained` strips.
- `ume_base_training.ckpt` has no model config: `from_pretrained` infers the architecture from the tensor shapes and gets the same model. The other two files include the config.
- Only `ume_base_training.ckpt` needs `weights_only=False`, which can run code stored in the file, so load it only from a source you trust.
Use `ume_base_training.ckpt` only to resume pretraining. For inference and fine-tuning, use `model.safetensors` or `ume_base_inference.pt`.
`UMEPipeline.from_pretrained` accepts any of them through `weights_path`. With no `weights_path`, it downloads `model.safetensors` and `config.json` from the Hub repo given by `repo_id` (default: the released base UME); `revision` and `cache_dir` are passed to the download.
---
## π Citation
If you use UME, please cite the paper ([doi.org/10.1145/3857981](https://doi.org/10.1145/3857981)):
```bibtex
@article{alchieri2026foundation,
author = {Alchieri, Leonardo and Garzon, Matteo and Alecci, Lidia and Bombassei De Bona, Francesco and Gjoreski, Martin and De Felice, Giovanni and Santini, Silvia},
title = {A Foundation Model for Electrodermal Activity Data},
journal = {Proc. ACM Interact. Mob. Wearable Ubiquitous Technol.},
volume = {10},
number = {4},
articleno = {202},
numpages = {40},
year = {2026},
month = dec,
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
doi = {10.1145/3857981},
url = {https://doi.org/10.1145/3857981}
}
```
---
## π License
This project is licensed under the MIT License. See [`LICENSE`](LICENSE).
---
People Centered Computing Lab @ USI, Switzerland.