Model card β opencgm_stateevent encoder (v0.1.0)
License
| Component | License |
|---|---|
Encoder (glucofm_encoder.onnx) |
CC-BY-NC-4.0 (research / non-commercial) |
Probe heads (glucofm_heads.json) |
CC-BY-NC-SA-4.0 β share-alike inherited from CGMacros (D025) |
| Source code (this repo, the Python trainer, the Next.js demo) | Apache-2.0 |
HF Hub license: tag |
other β the repo holds two artefacts under two licences |
See LICENSE-WEIGHTS for the full text and LICENSE_NOTES.md for the decision record.
A commercial license for the weights can be negotiated with the maintainer
(@sfourdrinier on GitHub).
Summary
A 435,633-parameter dual-stream JEPA-style encoder for 24-hour continuous glucose
monitoring windows. Trained on a public-data corpus; not derived from any Google
implementation or checkpoint. See LICENSE_NOTES.md for weights licensing and
manifests/sources/registry.yaml for the data record.
Intended use
- In scope: research on CGM-derived phenotypes (glycemic variability, insulin
resistance proxies, beta-cell dysfunction proxies, glucotype clustering,
hyperlipidaemia proxies, obesity proxies, diabetes risk, hypoglycaemia).
Embeddings compose across days (
n_days = 1..7) for cohort-level phenotypes. - Out of scope: clinical diagnosis, treatment decisions, dosing recommendations, real-time insulin titration, alarm generation. Not a medical device.
Training data
The encoder was pretrained on Lane A only β the four public cohorts the GlucoFM paper names. These are the windows that are actually inside the released weights.
| Source | Windows | Subjects | Hours | Licence |
|---|---|---|---|---|
| stanford | 171,140 | 56 | 8,761 | source repository states none |
| shanghai_t2dm | 159,119 | 100 | 12,414 | CC-BY-4.0 |
| big_ideas | 13,167 | 16 | 3,017 | ODC-By-1.0 |
| colas | 9,701 | 68 | 9,544 | CC-BY-4.0 |
| total | 353,127 | 240 | 33,736 | 30.9% of the paper's 109,066 h |
Windows overlap, so the window count is much larger than hours Γ· 24; hours are the non-overlapping quantity and are what the 30.9% refers to.
No other lane entered pretraining. Hall (Lane B) and the Lane C and D cohorts are used for downstream evaluation and for the PPG teacher-student pilot, not for training the encoder. Lane E β cgmacros, uchtt1dm, glucofm_bench β is evaluation-only under non-commercial, share-alike or no-derivatives terms.
The full corpus audit is in manifests/sources/registry.yaml; the lane rules are in
DECISIONS.md D002 and bundle/BLUEPRINT_AMENDMENTS.md A4.
Architecture
| value | |
|---|---|
| Parameters | 435,633 in this released encoder; 732,593 trainable in the full pretraining model (encoder + predictor + transition heads) |
| Input | 24 h Γ 5 min grid (288 positions, 24 hourly patches Γ 12 steps) |
| Streams | state + event (causal Gaussian decomposition, learnable Ο) |
| Embedding | 64 β 128-d fused physiological token, gated with circadian time embedding |
| Backbone | 3-layer, 4-head Transformer (paper Β§3.3; our D019) |
| Training objective | JEPA-style masked-token prediction + temporal-dynamics loss |
| Masking | 50-60 % of patches, sampled uniformly per window, masked before normalisation and filtering |
| EMA target | linear ramp 0.997 β 0.9994 per epoch |
| Reported in paper | 0.72 M β within 1.7 % |
Provenance of this artifact
The weights in this repository are one checkpoint, not the five-seed ensemble the evaluation below is computed over. Read this section before quoting a number against the file you downloaded.
| value | |
|---|---|
| Checkpoint | runs_5090/rawstats120/ckpt_ep040.pt |
| Seed | 17 |
| Epoch | 40, not 120 |
zero_empty_patches |
false β as trained (see below) |
| Exported file | glucofm_encoder.onnx, opset 17, 1,991,782 bytes |
| SHA-256 | b1349deffd15ab62a5a98d7c7c4a7e143bcf1dee7ad745b1e05533ff54f34768 |
Why epoch 40 and not 120. Epoch 40 is the measured transfer peak at 30.9 % of the paper's
corpus; epoch 120 is mildly worse (β0.005 ROC, about 1 sd of the seed spread). That is the
expected consequence of giving a model more capacity than a reduced corpus can use, and it is
reported rather than hidden. See D024 and findings/results_section.md.
Why zero_empty_patches is false here. D020 β an empty patch emits nothing rather than a
learned bias β is tagged PAPER_EXACT and is now the repo default (True). This checkpoint
predates that change, so it was trained with the learned bias and is exported faithfully as
such. D020 was measured to be neutral (0.6780 vs 0.6818, well inside the seed sd), so the
released weights are not disadvantaged by it β but if you rebuild the architecture from the
current repo defaults, you will not get an architecture that matches this file. Construct it
with zero_empty_patches=False, or read the flags from glucofm_encoder.onnx.meta.json, which
records the exact architecture this artifact was exported under.
Which probe heads are distributed
All 18 probe heads are published; 14 clear the signal floor. The bundle
(glucofm_heads.json) is licensed CC-BY-NC-SA-4.0, one step stricter than the encoder.
Eight heads are fitted on CGMacros, whose registry entry reads CC-BY-NC-SA-4.0 with
license_confidence: unverified (open question Q4). Share-alike obliges an adapted work to be
offered under the same licence, so the bundle carries it. Keeping the heads as a separate
artefact from the encoder stops that term reaching the encoder, which never saw CGMacros and
stays CC-BY-NC-4.0.
Three heads are fitted on Stanford. They are published: Stanford is Lane A and already inside the encoder, so withholding classifiers fitted on its labels would protect nothing.
Anything fitted on UCHTT1DM would stay out permanently β its no-derivatives term has no labelling remedy. No such head exists today; the filter enforces it regardless.
See D025. Enforced by
tests/unit/test_source_rights.py::test_published_heads_bundle_declares_the_licence_its_sources_impose.
Evaluation (the headline numbers)
The table below is the five-seed, 120-epoch protocol β the scientific result of the project. It characterises the method, not the single file above. A single ep40 checkpoint will land near, but not exactly on, these numbers.
5 seeds Γ 120 epochs, subject-disjoint 5Γ10-fold probe, macro across 14 dataset-task probes (18 task-source combinations β two cohorts are measured on two sensors each):
| Method | ROC-AUC (mean Β± sd) | PR-AUC (mean Β± sd) |
|---|---|---|
clinical_metrics baseline |
0.643 | β |
raw_masked baseline |
0.607 | β |
opencgm_mean (this model) |
0.670 Β± 0.003 | 0.588 Β± 0.003 |
| CGM-JEPA (the paper's central comparator) | 0.643 Β± 0.004 | 0.566 Β± 0.003 |
The paper reports 0.74 ROC across 14 tasks on its full corpus; we measure 0.670 on
30.9 % of the corpus. Direction and ordering of effects survive; absolute magnitude
is smaller. See findings/results_section.md Β§8βΒ§9 for the gap analysis.
Ablation evidence
The 30-run Tier-1 ablation (3 seeds Γ 10 conditions Γ 40 epochs) confirms the
load-bearing role of the dual-stream decomposition: removing the event stream costs
β0.050 ROC (largest single ablator), removing the state stream costs β0.014, and, the
circadian embedding costs β0.015. Single-stream baselines (abl_raw, abl_event,
abl_state) are the only ablations beyond β0.02.
The abl_dense arm (forced interpolation, which the production rule forbids) is
statistically indistinguishable from the observed mask at 40 epochs (+0.0005). The
never-interpolate rule is not a hair-shirt; it is the principled choice that does not
also need ablation to defend it.
Caveats and limits
- 30.9 % of paper pretraining hours. Wear-CGM (two unreleased Google/Fitbit cohorts corpus) is non-public. The released encoder cannot match the paper's absolute scores.
- Stanford's source repository states no licence. It is in the released weights, and
recorded as such in
manifests/sources/registry.yaml. - Single-seed multi-day, cross-dataset, and few-shot extensions. These are
documented in
findings/results_section.mdand will gain error bars when the multi-seed sweep finishes. - No real-time inference. The encoder expects 24-hour windows; real-time per-reading inference is out of scope.
Citation
@software{opencgm_stateevent_2026,
title = {OpenCGM-StateEvent: independent public-data reconstruction of GlucoFM},
author = {Fourdrinier, Stephane},
year = {2026},
url = {https://github.com/sfourdrinier/opencgm-stateevent},
note = {Apache-2.0; see CITATION.cff}
}
Plus cite the original method:
@article{glucofm_2026,
title = {GlucoFM: A Dual-Stream Foundation Model for Continuous Glucose Monitoring},
url = {https://arxiv.org/abs/2605.30865v2}
}