Repository navigation
On device adaptation - #3
Merged
Merged
Conversation
trains a logistic regression on the arduino (pricking vs movement). host test checks the c++ matches the python reference.
There was a problem hiding this comment.
Pull request overview
Adds an “on-device adaptation” demo and supporting tooling for CAP detection/classification, including a NumPy reference model, offline model comparisons (linear/RF/CNN + ensemble), a raw-stream replay script for training/eval on the Arduino, and a C++ parity harness to validate the on-device training core against Python.
Changes:
- Introduces a shared dataset cache builder + deterministic within-rat temporal split utilities for comparable model evaluation.
- Adds an on-device streaming/adaptation workflow (host replay + Arduino sketch + C++ model core + host parity test).
- Adds documentation for running the demos and (separately) includes an article markdown export.
Reviewed changes
Copilot reviewed 19 out of 21 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/cap_pipeline/ondevice/task_data.py | Shared task definition, deterministic splits, and prediction save/load helpers for model comparisons |
| scripts/cap_pipeline/ondevice/stream_raw.py | Host-side raw replay streamer + offline self-test for on-device training/adaptation demo |
| scripts/cap_pipeline/ondevice/showcase.py | Offline demos of online learning, cross-rat adaptation, and channel dropout using the NumPy model |
| scripts/cap_pipeline/ondevice/README.md | Usage docs for the on-device pipeline |
| scripts/cap_pipeline/ondevice/model.py | NumPy reference feature extractor, running standardizer, and SGD logistic regression |
| scripts/cap_pipeline/ondevice/model_linear.py | sklearn logistic regression baseline using shared split/task |
| scripts/cap_pipeline/ondevice/model_random_forest.py | sklearn random forest baseline using shared split/task |
| scripts/cap_pipeline/ondevice/model_cnn.py | PyTorch two-stream CNN baseline using shared split/task |
| scripts/cap_pipeline/ondevice/model_ensemble.py | Soft-voting ensemble over saved per-sample probabilities |
| scripts/cap_pipeline/ondevice/build_dataset.py | Cache builder: reads .rhd, detects CAPs, saves 56×100 windows |
| scripts/Arduino/ondevice_train/test_host.cpp | Host-side C++ parity runner for the on-device model core |
| scripts/Arduino/ondevice_train/README.md | Instructions for generating parity data and running the host test |
| scripts/Arduino/ondevice_train/make_parity.py | Exports parity fixtures + Python reference outputs for the C++ test |
| scripts/Arduino/ondevice_train/.gitignore | Ignores generated parity artifacts/binaries |
| scripts/Arduino/ArduinoOnDeviceTrain/README.md | Arduino sketch usage documentation |
| scripts/Arduino/ArduinoOnDeviceTrain/ondevice_model.h | Arduino/host-shared model API (features, standardizer, SGD logreg) |
| scripts/Arduino/ArduinoOnDeviceTrain/ondevice_model.cpp | Arduino/host-shared model implementation |
| scripts/Arduino/ArduinoOnDeviceTrain/ArduinoOnDeviceTrain.ino | Full Arduino sketch: detection + feature extraction + online training + eval-only mode |
| articles/2022_Resource_efficient_Neural_Network_Architectures_for_Classifying_Nerve_Cuff_Recordings.md | Adds a markdown version of an external paper |
| .gitignore | Ignores generated caches and Torch weight files |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| float feat[OD_N_FEAT]; | ||
| double z[OD_N_FEAT]; | ||
| od_extract_features(od_window, feat); | ||
| if (!eval) od_std.update(feat); |
| trigs, _ = detect(raw, warmup=int(0.5 * FS)) | ||
| for t in trigs: | ||
| if t - LEAD >= 0 and t + TRAIL <= N: | ||
| events.append((raw[t - LEAD: t + TRAIL], cls)) |
Comment on lines
+20
to
+23
| HERE = pathlib.Path(__file__).resolve().parent | ||
| OND = HERE.parents[1] / "cap_pipeline" / "ondevice" | ||
| CACHE = HERE.parents[1] / "cap_pipeline" / "caches" / "cap_windows_rich.npz" | ||
| sys.path.insert(0, str(OND)) |
| Checks the C++ training core (ondevice_model.*) against the Python reference. | ||
| Run make_parity.py first to produce the data files, then: | ||
|
|
||
| g++ -O2 -std=c++17 test_host.cpp ondevice_model.cpp -o test_host && ./test_host |
| g++ -O2 -std=c++17 test_host.cpp ../ArduinoOnDeviceTrain/ondevice_model.cpp -o test_host | ||
| ./test_host | ||
| ``` | ||
| Should print all PASS (predictions identical, weights match to ~1e-15). |
Comment on lines
+7
to
+9
| We use this task because dorsi vs plantar basically can't be told apart in this | ||
| data (~50%, see `docs/replication_investigation_2026-06.md`), but pricking vs | ||
| movement works ok — around 70% when we stay within one rat. |
Comment on lines
+1
to
+4
| # Content from 2022.10.05.510983v1.full.pdf | ||
|
|
||
| bioRxiv preprint doi: https://doi.org/10.1101/2022.10.05.510983; this version posted October 7, 2022. The copyright holder for this preprint (which was not certified by peer review) is the author/funder. All rights reserved. No reuse allowed without permission. | ||
|
|
Comment on lines
+28
to
+30
| def load(): | ||
| d = np.load(CACHE) | ||
| X, y3, rat = d["X"].astype(np.float32), d["y"], d["rat"] |
Comment on lines
+16
to
+17
| ## How to run | ||
| Build the window cache once (takes a couple of minutes): |
| DATA_DIR = HERE.parents[2] / "data" # <repo>/data | ||
| CACHE = HERE.parent / "caches" / "cap_windows_rich.npz" | ||
|
|
||
| # Each recording folder and its class label. (RAT7 uses a 64-ch cuff -> skipped.) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.