Instructions to use mobility-model-zoo/pace-cnn with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use mobility-model-zoo/pace-cnn with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
- Pace (CNN): activity recognition from IMU windows on a microcontroller
Pace (CNN): activity recognition from IMU windows on a microcontroller
Version 0.1.0 · 2026-10-20 · status: experimental · topic: Condition monitoring · task: activity
Usage: Commercial use permitted · licence Apache-2.0.
Experimental. The output format may change in a minor version before 1.0.0.
Summary
A small int8 convolutional network that classifies 2.56-second windows of accelerometer and gyroscope signals into six activities (walking, walking upstairs, walking downstairs, sitting, standing, lying). It runs on the zoo's int8 engine on microcontrollers.
pace-cnn belongs to the topic Condition monitoring (condition-monitoring), task activity, variant cnn. Trained from scratch.
Not for:
- Monitoring, evaluating or profiling persons
- Fall detection or other uses people rely on for their safety
- Transport-mode or vehicle classes
Quality
Quality is measured against the labels of the datasets named below, on test data not used for training. Reference: labels of the uci-har dataset. Benchmark: uci-har-v1.
| Metric | Value | What it measures | Reference | Benchmark | Items | Date |
|---|---|---|---|---|---|---|
int8_macro_f1 |
0.9229 | int8 macro-F1 over the six activities, test subjects | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
int8_accuracy |
0.923 | int8 accuracy, test subjects | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
int8_f1_min_class |
0.81 | lowest int8 F1 of the six activities | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
int8_f1_walking |
0.9867 | int8 F1 of activity walking | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
int8_f1_walking_upstairs |
0.9333 | int8 F1 of activity walking upstairs | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
int8_f1_walking_downstairs |
0.9589 | int8 F1 of activity walking downstairs | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
int8_f1_sitting |
0.81 | int8 F1 of activity sitting | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
int8_f1_standing |
0.8636 | int8 F1 of activity standing | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
int8_f1_laying |
0.9849 | int8 F1 of activity laying | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
int8_macro_f1_worst_subject |
0.6671 | int8 macro-F1 of the worst test subject | labels of the uci-har dataset | uci-har-v1 | 9 | 2026-10-20 |
int8_macro_f1_subject_range |
0.3329 | best minus worst test subject, int8 macro-F1 | labels of the uci-har dataset | uci-har-v1 | 9 | 2026-10-20 |
int8_macro_f1_seed_min |
0.9156 | lowest int8 macro-F1 over the five seeds | labels of the uci-har dataset | uci-har-v1 | 5 | 2026-10-20 |
int8_macro_f1_seed_mean |
0.925 | mean int8 macro-F1 over the five seeds | labels of the uci-har dataset | uci-har-v1 | 5 | 2026-10-20 |
int8_macro_f1_seed_max |
0.93 | highest int8 macro-F1 over the five seeds | labels of the uci-har dataset | uci-har-v1 | 5 | 2026-10-20 |
float_macro_f1 |
0.9224 | float macro-F1 of the same model before quantisation (informative) | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
float_accuracy |
0.9226 | float accuracy before quantisation (informative) | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
tflite_interpreter_mismatches |
0 | test windows where the int8 host reference and the TFLite reference interpreter disagree (deterministic check) | labels of the uci-har dataset | uci-har-v1 | 2947 | 2026-10-20 |
Speed and memory
Budget: 32 KB RAM, 128 KB flash on ESP32.
| Metric | Value | Unit | What it measures | Measured on | Items | Date |
|---|---|---|---|---|---|---|
latency_us |
55034 | us | Median latency per inference over 100 samples (100 inferences, device BENCH timer) | ESP32-D0WDQ6-V3 rev3 cores=2, 240 MHz (target esp32, board esp32-1) (real board) | 100 | 2026-10-21 |
latency_mean_us |
5.503e+04 | us | Mean latency per inference over 100 samples (100 inferences, device BENCH timer) | ESP32-D0WDQ6-V3 rev3 cores=2, 240 MHz (target esp32, board esp32-1) (real board) | 100 | 2026-10-21 |
latency_p99_us |
55041 | us | 99th percentile latency per inference over 100 samples (device BENCH timer) | ESP32-D0WDQ6-V3 rev3 cores=2, 240 MHz (target esp32, board esp32-1) (real board) | 100 | 2026-10-21 |
flash_kb |
18 | KiB | Model footprint in flash from the ELF symbols: model constant data (17018 B: weights, bias, multipliers, shifts, layer table, self-test vectors) plus int8 engine code (1399 B) | ESP32-D0WDQ6-V3 rev3 cores=2, 240 MHz (target esp32, board esp32-1) (real board) | 2026-10-21 | |
ram_kb |
5.2 | KiB | Model footprint in RAM: tensor arena (4096 B), input (1152 B) and output (6 B) buffers, engine static data (0 B) | ESP32-D0WDQ6-V3 rev3 cores=2, 240 MHz (target esp32, board esp32-1) (real board) | 2026-10-21 | |
arena_bytes |
4096 | bytes | Tensor arena of the model (two ping-pong buffers, QModel.arena_size) | ESP32-D0WDQ6-V3 rev3 cores=2, 240 MHz (target esp32, board esp32-1) (real board) | 2026-10-21 | |
device_bit_exact_vectors |
1 | share | Share of the model's golden vectors whose device output equals the bit-exact host reference (device SELFTEST) | ESP32-D0WDQ6-V3 rev3 cores=2, 240 MHz (target esp32, board esp32-1) (real board) | 8 | 2026-10-21 |
flash_kb_image_esp32 |
312.1 | KiB | Flash used by the whole firmware image (bench app, inference engine and all bench models incl. this one), from the PlatformIO build | ESP32-D0WDQ6-V3 rev3 cores=2, 240 MHz (target esp32, board esp32-1) (real board) | 2026-10-21 | |
ram_kb_image_esp32 |
28.81 | KiB | Static RAM used by the whole firmware image (data + bss, incl. the shared tensor arena), from the PlatformIO build | ESP32-D0WDQ6-V3 rev3 cores=2, 240 MHz (target esp32, board esp32-1) (real board) | 2026-10-21 | |
latency_us_esp32_qemu |
2690 | us | Median latency per inference over 100 samples (100 inferences, device BENCH timer) | ESP32-D0WDQ6 rev0 cores=2, 240 MHz in QEMU (emulator, target esp32) (emulator) | 100 | 2026-10-21 |
latency_mean_us_esp32_qemu |
2705 | us | Mean latency per inference over 100 samples (100 inferences, device BENCH timer) | ESP32-D0WDQ6 rev0 cores=2, 240 MHz in QEMU (emulator, target esp32) (emulator) | 100 | 2026-10-21 |
latency_us_esp8266 |
159315 | us | Median latency per inference over 100 samples (100 inferences, device BENCH timer) | ESP8266 flash=4096KB, 80 MHz (target esp8266, board esp8266-1) (real board) | 100 | 2026-10-21 |
latency_mean_us_esp8266 |
1.593e+05 | us | Mean latency per inference over 100 samples (100 inferences, device BENCH timer) | ESP8266 flash=4096KB, 80 MHz (target esp8266, board esp8266-1) (real board) | 100 | 2026-10-21 |
latency_us_host |
106 | us | Median latency per inference over 100 samples (100 inferences, device BENCH timer) | host simulator (native build, Darwin arm64) (simulator) | 100 | 2026-10-20 |
latency_mean_us_host |
163.7 | us | Mean latency per inference over 100 samples (100 inferences, device BENCH timer) | host simulator (native build, Darwin arm64) (simulator) | 100 | 2026-10-20 |
Limitations and risks
Experimental: not ready for production use.
Not met yet:
- S5 Transfer to mobility data tested: not tested: trained and measured on UCI HAR only
Known limits in short:
- Waist-worn sensor only; no vehicle or transport-mode classes.
- Sitting and standing are often confused (int8 F1 0.81 and 0.8636).
- Results vary between persons: worst test subject macro-F1 0.6671.
All limitations:
- Trained and measured on UCI HAR only: a smartphone worn at the waist by the volunteers of one study. Other placements, sensors, sample rates and populations are untested, and the model cannot detect a wrong input; it always returns six scores.
- No vehicle or transport-mode classes. Whether waist-worn activity windows are a useful base for micromobility and manoeuvre detection (the task's riskiest assumption) is not tested, which keeps this release experimental.
- Sitting and standing are the classes most often confused: int8 F1 0.81 for sitting and 0.8636 for standing.
- Results vary between persons: the worst test subject reaches an int8 macro-F1 of 0.6671, against 0.9229 over all test subjects.
- The input preparation values the dataset leaves open (median length, gravity filter order, causal filtering) were chosen by the zoo; windows prepared differently can change the results.
- Energy use was not measured; emulator and host values in the speed table are informative only.
Intended use
A research and teaching baseline for classifying windows of a waist-worn accelerometer and gyroscope into six activities on a microcontroller, and a first step towards pedestrian, micromobility and manoeuvre detection with the same int8 pipeline. Use it to study motion classification on small devices, to test an IMU pipeline end to end, or as a measured reference for your own models.
Out-of-scope use
- Monitoring or evaluating persons at work, or decisions about access to insurance, credit or services based on a person's movement.
- Identifying or profiling persons from their movement.
- Fall detection or any other use that people rely on for their safety; the model was not developed or tested for that.
- Transport-mode or vehicle classes (car, bus, bicycle, e-scooter): the training data has none.
- Sensors worn elsewhere than the waist, other sample rates or units without the preparation of the input contract.
How to run it
Requires Python 3.12 or newer.
pip install "mobility-model-zoo[edge] @ git+https://github.com/mhabedank/mobility-model-zoo@pace-cnn/v0.1.0"
import json
import numpy as np
from huggingface_hub import hf_hub_download
from mobility_model_zoo.edge.int8.model import QModel
from mobility_model_zoo.edge.int8.reference import run_model
repo, revision = "mobility-model-zoo/pace-cnn", "v0.1.0"
model = QModel.load(hf_hub_download(repo, "pace-cnn.npz", revision=revision))
example = json.load(open(hf_hub_download(repo, "examples/example-1.json", revision=revision)))
scores = run_model(model, np.asarray(example["input"], dtype=np.int8))
# The example input is synthetic: it checks the int8 arithmetic, not an activity.
print(scores.tolist(), scores.tolist() == example["expected"])
Output:
[-128, -107, 116, -77, -96, -21] True
On the device (C, int8 engine of the zoo):
/* Sources from mobility-model-zoo/pace-cnn at v0.1.0: c/pace_cnn_model.c and c/microinfer.c with their headers. */
#include "pace_cnn_model.h"
static int8_t arena[PACE_CNN_ARENA_SIZE];
int8_t window[PACE_CNN_IN_SIZE]; /* 128 x 9 int8, prepared as config.json describes */
int8_t scores[PACE_CNN_OUT_SIZE]; /* six int8 scores in label order */
mi_invoke(&mi_model_pace_cnn, window, scores, arena, sizeof arena);
The tag v0.1.0 always points to this version. For strict reproducibility, pin the commit hash of that tag instead (revision="<commit>").
Input and output
Input: one window of 2.56 s of a 6-axis IMU worn at the waist, sampled at 50 Hz: 128 samples x 9 channels in the order body_acc xyz, body_gyro xyz, total_acc xyz, as 1,152 int8 values (row-major, sample t then channel c). Acceleration is in g (1 g = 9.80665 m/s²), angular velocity in rad/s. Consecutive windows overlap by 50 % (step 64 samples).
Preparation from raw readings (host reference mobility_model_zoo.condition_monitoring.activity.prepare, coefficients in config.json):
- a causal median filter over 3 samples, per axis;
- a causal 3rd-order Butterworth low-pass at 20 Hz, per axis (noise filter, as the dataset documents);
- gravity separation of the acceleration with a causal 3rd-order Butterworth low-pass at 0.3 Hz; body_acc = total_acc - gravity;
- per-channel normalisation with the mean and std of the training subjects (
config.json,normalisation); - int8 quantisation with the model's input scale and zero point (
config.json,quantisation).
The median length, the order of the gravity filter and causal filtering are not stated by the dataset; the zoo chose them. The model itself was trained on the dataset's own preparation.
Output: six int8 scores in the label order walking, walking upstairs, walking downstairs, sitting, standing, laying (lying); the highest score is the predicted activity.
Examples
Example 1: example-1.json
Source: synthetic. Input (1152 int8 values; the first 24 of 1,152 are shown; the full input is examples/example-1.json):
[2, 89, 107, 35, 87, 2, 61, -59, 104, -50, -67, -118, 112, -109, -89, -124, -47, -84, -6, 80, -100, 38, -39, 105]
Expected output (bit-exact on the host reference and on the device):
[-128, -107, 116, -77, -96, -21]
Example 2: example-2.json
Source: synthetic. Input (1152 int8 values; the first 24 of 1,152 are shown; the full input is examples/example-2.json):
[-65, 23, -27, 18, 83, 98, -68, -104, 124, -59, 1, -28, 31, 106, 48, -110, 35, -13, -109, -7, -95, -125, 69, -19]
Expected output (bit-exact on the host reference and on the device):
[-98, -69, 113, -94, -112, -50]
Example 3: example-3.json
Source: synthetic. Input (1152 int8 values; the first 24 of 1,152 are shown; the full input is examples/example-3.json):
[-41, -16, -21, 109, 55, 127, -127, -22, 84, -29, -117, -30, -90, -37, 109, 28, -9, 35, -77, 42, -2, 71, 98, 41]
Expected output (bit-exact on the host reference and on the device):
[-128, -75, 127, -95, -128, -56]
Training data and attribution
pace-cnn 0.1.0 was trained on 1 published dataset, credited below as its licence requires.
| Dataset | Creators | Source | DOI | Licence |
|---|---|---|---|---|
| Human Activity Recognition Using Smartphones | J. Reyes-Ortiz, D. Anguita, A. Ghio, L. Oneto, X. Parra | https://archive.ics.uci.edu/dataset/240/human+activity+recognition+using+smartphones | 10.24432/C54S4K | CC BY 4.0 |
- Attribution: Human Activity Recognition Using Smartphones by J. Reyes-Ortiz, D. Anguita, A. Ghio, L. Oneto, X. Parra, UCI Machine Learning Repository, doi:10.24432/C54S4K (CC BY 4.0) Modifications: Converted to the common frame or feature format for training; not redistributed. The datasets are not published or redistributed with the model; download them from their providers. Their licences and attribution apply to them (project constitution, Principle VI); see the copyright policy.
Teacher and labeling models
None. The model learned only from the labels of its training dataset; no teacher or labeling model was used.
Privacy and personal data
The model was trained on motion signals (accelerometer and gyroscope) of 30 volunteers that the dataset authors published under numbers only. No data, no window and no subject number is part of this release, and per-subject results are reported by rank only, never under a subject number. The model returns scores for the inputs you give it and contains no training data. How the training data were processed and how to object: privacy notice. AI Act classification: pace-cnn 0.1.0. Contact: privacy@miskatonic-analytics.com.
Training recipe
- Recipe: topics/condition-monitoring/tasks/activity.md
- Configuration: configs/condition-monitoring/activity/pace-cnn.yaml
- Commit:
f359d5064df0927a3ab4f9e30253a8c0a10f591b
Version history
| Version | Date | Status | Change | Changes | int8_macro_f1 |
int8_accuracy |
int8_f1_min_class |
|---|---|---|---|---|---|---|---|
| 0.1.0 | 2026-10-20 | experimental | initial | First release (feature 021): trained on the frozen benchmark uci-har-v1 with pre-registered criteria and five seeds; int8 results on the bit-exact host reference; experimental because the transfer to mobility data is not tested. | 0.9229 | 0.923 | 0.81 |
License
Apache-2.0 Commercial use permitted · licence Apache-2.0.
Citation
@misc{mobility-model-zoo-pace-cnn,
title = {Pace (CNN): activity recognition from IMU windows on a microcontroller, mobility-model-zoo},
author = {Habedank, Martin},
year = {2026},
url = {https://huggingface.co/mobility-model-zoo/pace-cnn}
}
About the zoo
Part of mobility-model-zoo, a collection of small, fast mobility models grouped by topic. Topic collection: Condition monitoring. Source code, recipes and release records: https://github.com/mhabedank/mobility-model-zoo.
- Downloads last month
- 5
Collection including mobility-model-zoo/pace-cnn
Evaluation results
- int8 macro-F1 over the six activities, test subjects on uci-har-v1 (frozen)self-reported0.923
- int8 accuracy, test subjects on uci-har-v1 (frozen)self-reported0.923
- lowest int8 F1 of the six activities on uci-har-v1 (frozen)self-reported0.810
- int8 F1 of activity walking on uci-har-v1 (frozen)self-reported0.987
- int8 F1 of activity walking upstairs on uci-har-v1 (frozen)self-reported0.933
- int8 F1 of activity walking downstairs on uci-har-v1 (frozen)self-reported0.959
- int8 F1 of activity sitting on uci-har-v1 (frozen)self-reported0.810
- int8 F1 of activity standing on uci-har-v1 (frozen)self-reported0.864