anonymous-4FAD commited on
Commit
c4135cc
·
verified ·
1 Parent(s): d143a39

Upload 8 files

Browse files
README.md ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ tags:
4
+ - cgm
5
+ - time-series
6
+ - glucose-forecasting
7
+ - ridge-regression
8
+ - metabonet
9
+ library_name: transformers
10
+ pipeline_tag: time-series-forecasting
11
+ ---
12
+
13
+ # Ridge multi-horizon CGM forecaster (MetaboNet)
14
+
15
+ A `sklearn`-trained Ridge regressor (with `StandardScaler`) re-packaged as a
16
+ `transformers`-compatible Hub model. One repo holds four feature ablations
17
+ selectable at load time:
18
+
19
+ - `cgm` — 24 CGM lags + `hour_sin`/`hour_cos` (26 features).
20
+ - `insulin` — `cgm` features + 24 Insulin lags (50 features).
21
+ - `carbs` — `cgm` features + 24 Carbs lags (50 features).
22
+ - `all` — `cgm` features + 24 Insulin lags + 24 Carbs lags (74 features).
23
+
24
+ History length is 24 (= 2 hours at 5-minute sampling). Output is 12 future
25
+ CGM values (5–60 min horizons).
26
+
27
+ ## Files
28
+
29
+ - `config.json` — `auto_map` wiring + per-ablation feature lists.
30
+ - `model.py` — `RidgeMultiHorizonConfig` / `RidgeMultiHorizonModel`
31
+ (`trust_remote_code=True`).
32
+ - `model_<ablation>.safetensors` — one per ablation, holding `scaler_mean`,
33
+ `scaler_scale`, `coef` (12 × F), `intercept` (12).
34
+
35
+ ## Usage
36
+
37
+ ```python
38
+ from transformers import AutoConfig, AutoModel
39
+
40
+ cfg = AutoConfig.from_pretrained(
41
+ "anonymous-4FAD/Ridge", trust_remote_code=True, ablation="cgm"
42
+ )
43
+ model = AutoModel.from_pretrained(
44
+ "anonymous-4FAD/Ridge", trust_remote_code=True, config=cfg
45
+ )
46
+
47
+ # Inputs match the MetaboNet benchmark.py contract:
48
+ # timestamps: int64 ns, shape (B, T_in)
49
+ # cgm/insulin/carbs: float, shape (B, T_in); only the last 24 steps are used
50
+ preds = model.predict(timestamps, cgm, insulin, carbs) # -> (B, 12)
51
+ ```
52
+
53
+ The thin local wrapper in
54
+ [`models/ridge.py`](https://github.com/njeffrie/MetaboNet-Bench/blob/main/models/ridge.py)
55
+ exposes the same API used by `benchmark.py`.
56
+
57
+ ## Feature convention
58
+
59
+ `CGM_t<i>` denotes the i-th sample within the last `history_length` steps,
60
+ ordered oldest -> newest (`CGM_t0` is the oldest of the 24, `CGM_t23` is the
61
+ newest). The same convention applies to `Insulin_t<i>` and `Carbs_t<i>`.
62
+ `hour_sin` / `hour_cos` are derived from the most recent input timestamp.
63
+
64
+ ## Provenance
65
+
66
+ Trained via
67
+ [`other_models/results/train_ridge.py`](https://github.com/njeffrie/MetaboNet-Bench/blob/main/other_models/results/train_ridge.py)
68
+ on the public MetaboNet train split. The `safetensors` checkpoints are produced
69
+ by [`scripts/build_other_models_hub.py`](https://github.com/njeffrie/MetaboNet-Bench/blob/main/scripts/build_other_models_hub.py)
70
+ from the original sklearn pickles.
config.json ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "ridge_multihorizon",
3
+ "auto_map": {
4
+ "AutoConfig": "model.RidgeMultiHorizonConfig",
5
+ "AutoModel": "model.RidgeMultiHorizonModel"
6
+ },
7
+ "architectures": [
8
+ "RidgeMultiHorizonModel"
9
+ ],
10
+ "ablation": "all",
11
+ "ablations": [
12
+ "cgm",
13
+ "insulin",
14
+ "carbs",
15
+ "all"
16
+ ],
17
+ "history_length": 24,
18
+ "horizon_length": 12,
19
+ "feature_names_by_ablation": {
20
+ "cgm": [
21
+ "CGM_t0",
22
+ "CGM_t1",
23
+ "CGM_t2",
24
+ "CGM_t3",
25
+ "CGM_t4",
26
+ "CGM_t5",
27
+ "CGM_t6",
28
+ "CGM_t7",
29
+ "CGM_t8",
30
+ "CGM_t9",
31
+ "CGM_t10",
32
+ "CGM_t11",
33
+ "CGM_t12",
34
+ "CGM_t13",
35
+ "CGM_t14",
36
+ "CGM_t15",
37
+ "CGM_t16",
38
+ "CGM_t17",
39
+ "CGM_t18",
40
+ "CGM_t19",
41
+ "CGM_t20",
42
+ "CGM_t21",
43
+ "CGM_t22",
44
+ "CGM_t23",
45
+ "hour_sin",
46
+ "hour_cos"
47
+ ],
48
+ "insulin": [
49
+ "CGM_t0",
50
+ "CGM_t1",
51
+ "CGM_t2",
52
+ "CGM_t3",
53
+ "CGM_t4",
54
+ "CGM_t5",
55
+ "CGM_t6",
56
+ "CGM_t7",
57
+ "CGM_t8",
58
+ "CGM_t9",
59
+ "CGM_t10",
60
+ "CGM_t11",
61
+ "CGM_t12",
62
+ "CGM_t13",
63
+ "CGM_t14",
64
+ "CGM_t15",
65
+ "CGM_t16",
66
+ "CGM_t17",
67
+ "CGM_t18",
68
+ "CGM_t19",
69
+ "CGM_t20",
70
+ "CGM_t21",
71
+ "CGM_t22",
72
+ "CGM_t23",
73
+ "Insulin_t0",
74
+ "Insulin_t1",
75
+ "Insulin_t2",
76
+ "Insulin_t3",
77
+ "Insulin_t4",
78
+ "Insulin_t5",
79
+ "Insulin_t6",
80
+ "Insulin_t7",
81
+ "Insulin_t8",
82
+ "Insulin_t9",
83
+ "Insulin_t10",
84
+ "Insulin_t11",
85
+ "Insulin_t12",
86
+ "Insulin_t13",
87
+ "Insulin_t14",
88
+ "Insulin_t15",
89
+ "Insulin_t16",
90
+ "Insulin_t17",
91
+ "Insulin_t18",
92
+ "Insulin_t19",
93
+ "Insulin_t20",
94
+ "Insulin_t21",
95
+ "Insulin_t22",
96
+ "Insulin_t23",
97
+ "hour_sin",
98
+ "hour_cos"
99
+ ],
100
+ "carbs": [
101
+ "CGM_t0",
102
+ "CGM_t1",
103
+ "CGM_t2",
104
+ "CGM_t3",
105
+ "CGM_t4",
106
+ "CGM_t5",
107
+ "CGM_t6",
108
+ "CGM_t7",
109
+ "CGM_t8",
110
+ "CGM_t9",
111
+ "CGM_t10",
112
+ "CGM_t11",
113
+ "CGM_t12",
114
+ "CGM_t13",
115
+ "CGM_t14",
116
+ "CGM_t15",
117
+ "CGM_t16",
118
+ "CGM_t17",
119
+ "CGM_t18",
120
+ "CGM_t19",
121
+ "CGM_t20",
122
+ "CGM_t21",
123
+ "CGM_t22",
124
+ "CGM_t23",
125
+ "Carbs_t0",
126
+ "Carbs_t1",
127
+ "Carbs_t2",
128
+ "Carbs_t3",
129
+ "Carbs_t4",
130
+ "Carbs_t5",
131
+ "Carbs_t6",
132
+ "Carbs_t7",
133
+ "Carbs_t8",
134
+ "Carbs_t9",
135
+ "Carbs_t10",
136
+ "Carbs_t11",
137
+ "Carbs_t12",
138
+ "Carbs_t13",
139
+ "Carbs_t14",
140
+ "Carbs_t15",
141
+ "Carbs_t16",
142
+ "Carbs_t17",
143
+ "Carbs_t18",
144
+ "Carbs_t19",
145
+ "Carbs_t20",
146
+ "Carbs_t21",
147
+ "Carbs_t22",
148
+ "Carbs_t23",
149
+ "hour_sin",
150
+ "hour_cos"
151
+ ],
152
+ "all": [
153
+ "CGM_t0",
154
+ "CGM_t1",
155
+ "CGM_t2",
156
+ "CGM_t3",
157
+ "CGM_t4",
158
+ "CGM_t5",
159
+ "CGM_t6",
160
+ "CGM_t7",
161
+ "CGM_t8",
162
+ "CGM_t9",
163
+ "CGM_t10",
164
+ "CGM_t11",
165
+ "CGM_t12",
166
+ "CGM_t13",
167
+ "CGM_t14",
168
+ "CGM_t15",
169
+ "CGM_t16",
170
+ "CGM_t17",
171
+ "CGM_t18",
172
+ "CGM_t19",
173
+ "CGM_t20",
174
+ "CGM_t21",
175
+ "CGM_t22",
176
+ "CGM_t23",
177
+ "Insulin_t0",
178
+ "Insulin_t1",
179
+ "Insulin_t2",
180
+ "Insulin_t3",
181
+ "Insulin_t4",
182
+ "Insulin_t5",
183
+ "Insulin_t6",
184
+ "Insulin_t7",
185
+ "Insulin_t8",
186
+ "Insulin_t9",
187
+ "Insulin_t10",
188
+ "Insulin_t11",
189
+ "Insulin_t12",
190
+ "Insulin_t13",
191
+ "Insulin_t14",
192
+ "Insulin_t15",
193
+ "Insulin_t16",
194
+ "Insulin_t17",
195
+ "Insulin_t18",
196
+ "Insulin_t19",
197
+ "Insulin_t20",
198
+ "Insulin_t21",
199
+ "Insulin_t22",
200
+ "Insulin_t23",
201
+ "Carbs_t0",
202
+ "Carbs_t1",
203
+ "Carbs_t2",
204
+ "Carbs_t3",
205
+ "Carbs_t4",
206
+ "Carbs_t5",
207
+ "Carbs_t6",
208
+ "Carbs_t7",
209
+ "Carbs_t8",
210
+ "Carbs_t9",
211
+ "Carbs_t10",
212
+ "Carbs_t11",
213
+ "Carbs_t12",
214
+ "Carbs_t13",
215
+ "Carbs_t14",
216
+ "Carbs_t15",
217
+ "Carbs_t16",
218
+ "Carbs_t17",
219
+ "Carbs_t18",
220
+ "Carbs_t19",
221
+ "Carbs_t20",
222
+ "Carbs_t21",
223
+ "Carbs_t22",
224
+ "Carbs_t23",
225
+ "hour_sin",
226
+ "hour_cos"
227
+ ]
228
+ },
229
+ "n_features_by_ablation": {
230
+ "cgm": 26,
231
+ "insulin": 50,
232
+ "carbs": 50,
233
+ "all": 74
234
+ },
235
+ "target_names": [
236
+ "CGM_t+1",
237
+ "CGM_t+2",
238
+ "CGM_t+3",
239
+ "CGM_t+4",
240
+ "CGM_t+5",
241
+ "CGM_t+6",
242
+ "CGM_t+7",
243
+ "CGM_t+8",
244
+ "CGM_t+9",
245
+ "CGM_t+10",
246
+ "CGM_t+11",
247
+ "CGM_t+12"
248
+ ],
249
+ "transformers_version": "4.54.0"
250
+ }
model.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Ridge multi-horizon CGM forecaster, packaged for the HF Hub.
2
+
3
+ One repo holds four feature ablations (``cgm``, ``insulin``, ``carbs``, ``all``)
4
+ as separate ``model_<ablation>.safetensors`` files. The active ablation is
5
+ selected at load time via the ``ablation=`` kwarg passed through ``AutoConfig``
6
+ or ``AutoModel`` ``from_pretrained``.
7
+
8
+ Usage::
9
+
10
+ from transformers import AutoConfig, AutoModel
11
+ cfg = AutoConfig.from_pretrained(
12
+ "anonymous-4FAD/Ridge", trust_remote_code=True, ablation="cgm")
13
+ model = AutoModel.from_pretrained(
14
+ "anonymous-4FAD/Ridge", trust_remote_code=True, config=cfg)
15
+ preds = model.predict(timestamps_ns, cgm, insulin, carbs) # (B, 12)
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import math
21
+ import os
22
+ from typing import Optional
23
+
24
+ import numpy as np
25
+ import torch
26
+ import torch.nn as nn
27
+ from huggingface_hub import hf_hub_download
28
+ from safetensors.torch import load_file
29
+ from transformers import PretrainedConfig, PreTrainedModel
30
+
31
+
32
+ _HUB_DOWNLOAD_KWARGS = (
33
+ "cache_dir",
34
+ "force_download",
35
+ "local_files_only",
36
+ "proxies",
37
+ "revision",
38
+ "subfolder",
39
+ "token",
40
+ )
41
+
42
+
43
+ class RidgeMultiHorizonConfig(PretrainedConfig):
44
+ """Config for the multi-horizon Ridge forecaster.
45
+
46
+ The same repo serves four ablations (``cgm``, ``insulin``, ``carbs``,
47
+ ``all``); the currently active one is ``self.ablation``.
48
+ """
49
+
50
+ model_type = "ridge_multihorizon"
51
+
52
+ def __init__(
53
+ self,
54
+ ablation: str = "all",
55
+ ablations: Optional[list] = None,
56
+ history_length: int = 24,
57
+ horizon_length: int = 12,
58
+ feature_names_by_ablation: Optional[dict] = None,
59
+ n_features_by_ablation: Optional[dict] = None,
60
+ target_names: Optional[list] = None,
61
+ **kwargs,
62
+ ):
63
+ if ablations is None:
64
+ ablations = ["cgm", "insulin", "carbs", "all"]
65
+ if ablation not in ablations:
66
+ raise ValueError(
67
+ f"ablation must be one of {ablations}, got {ablation!r}"
68
+ )
69
+ self.ablation = ablation
70
+ self.ablations = list(ablations)
71
+ self.history_length = int(history_length)
72
+ self.horizon_length = int(horizon_length)
73
+ self.feature_names_by_ablation = feature_names_by_ablation or {}
74
+ self.n_features_by_ablation = n_features_by_ablation or {}
75
+ self.target_names = list(target_names or [])
76
+ super().__init__(**kwargs)
77
+
78
+ @property
79
+ def n_features(self) -> int:
80
+ if self.n_features_by_ablation:
81
+ return int(self.n_features_by_ablation[self.ablation])
82
+ return len(self.feature_names_by_ablation[self.ablation])
83
+
84
+ @property
85
+ def feature_names(self) -> list:
86
+ return list(self.feature_names_by_ablation[self.ablation])
87
+
88
+
89
+ class RidgeMultiHorizonModel(PreTrainedModel):
90
+ """Multi-output Ridge regressor over standardized tabular features.
91
+
92
+ Holds only buffers (``scaler_mean``, ``scaler_scale``, ``coef``,
93
+ ``intercept``); there are no trainable parameters.
94
+ """
95
+
96
+ config_class = RidgeMultiHorizonConfig
97
+ main_input_name = "features"
98
+ _tied_weights_keys: dict = None
99
+ _no_split_modules: list = []
100
+
101
+ def __init__(self, config: RidgeMultiHorizonConfig):
102
+ super().__init__(config)
103
+ n_feat = config.n_features
104
+ n_horiz = config.horizon_length
105
+ self.register_buffer("scaler_mean", torch.zeros(n_feat))
106
+ self.register_buffer("scaler_scale", torch.ones(n_feat))
107
+ self.register_buffer("coef", torch.zeros(n_horiz, n_feat))
108
+ self.register_buffer("intercept", torch.zeros(n_horiz))
109
+
110
+ def _init_weights(self, module):
111
+ # No trainable parameters; values come from safetensors.
112
+ pass
113
+
114
+ def forward(self, features: torch.Tensor) -> torch.Tensor:
115
+ x = (features.to(self.coef.dtype) - self.scaler_mean) / self.scaler_scale
116
+ return x @ self.coef.T + self.intercept
117
+
118
+ @classmethod
119
+ def from_pretrained(
120
+ cls,
121
+ pretrained_model_name_or_path,
122
+ *model_args,
123
+ config=None,
124
+ ablation: Optional[str] = None,
125
+ **kwargs,
126
+ ):
127
+ # Drop transformers-internal markers we don't need to act on.
128
+ kwargs.pop("trust_remote_code", None)
129
+ kwargs.pop("_from_auto", None)
130
+ kwargs.pop("_commit_hash", None)
131
+
132
+ hub_kwargs = {k: kwargs.pop(k) for k in _HUB_DOWNLOAD_KWARGS if k in kwargs}
133
+
134
+ if config is None:
135
+ config_kwargs = dict(hub_kwargs)
136
+ if ablation is not None:
137
+ config_kwargs["ablation"] = ablation
138
+ config = RidgeMultiHorizonConfig.from_pretrained(
139
+ pretrained_model_name_or_path, **config_kwargs
140
+ )
141
+ elif ablation is not None:
142
+ config.ablation = ablation
143
+
144
+ model = cls(config)
145
+ weights_filename = f"model_{config.ablation}.safetensors"
146
+
147
+ if os.path.isdir(str(pretrained_model_name_or_path)):
148
+ weights_path = os.path.join(
149
+ str(pretrained_model_name_or_path), weights_filename)
150
+ if not os.path.isfile(weights_path):
151
+ raise FileNotFoundError(
152
+ f"Expected {weights_filename} in {pretrained_model_name_or_path}"
153
+ )
154
+ else:
155
+ weights_path = hf_hub_download(
156
+ repo_id=str(pretrained_model_name_or_path),
157
+ filename=weights_filename,
158
+ **hub_kwargs,
159
+ )
160
+
161
+ state = load_file(weights_path)
162
+ missing, unexpected = model.load_state_dict(state, strict=False)
163
+ if missing:
164
+ raise RuntimeError(
165
+ f"{weights_filename} is missing buffers required by the model: {missing}"
166
+ )
167
+ if unexpected:
168
+ # Not fatal, but worth surfacing in case a checkpoint has stale keys.
169
+ print(
170
+ f"RidgeMultiHorizonModel: ignoring unexpected keys in "
171
+ f"{weights_filename}: {unexpected}"
172
+ )
173
+
174
+ model.eval()
175
+ return model
176
+
177
+ @torch.no_grad()
178
+ def predict(self, timestamps, cgm, insulin, carbs) -> np.ndarray:
179
+ """Run inference for a benchmark.py-style batch.
180
+
181
+ Args:
182
+ timestamps: int64 ns timestamps, shape ``(B, T_in)``.
183
+ cgm: float CGM values, shape ``(B, T_in)``.
184
+ insulin: float insulin values, shape ``(B, T_in)`` (used only if
185
+ the active ablation requires Insulin features).
186
+ carbs: float carb values, shape ``(B, T_in)`` (used only if the
187
+ active ablation requires Carbs features).
188
+
189
+ Returns:
190
+ ``(B, horizon_length)`` numpy array of predicted CGM values.
191
+ """
192
+ features = _build_tabular_features(
193
+ timestamps=np.asarray(timestamps),
194
+ cgm=np.asarray(cgm, dtype=np.float64),
195
+ insulin=np.asarray(insulin, dtype=np.float64),
196
+ carbs=np.asarray(carbs, dtype=np.float64),
197
+ feature_names=self.config.feature_names,
198
+ history_length=self.config.history_length,
199
+ )
200
+ device = self.coef.device
201
+ x = torch.as_tensor(features, dtype=self.coef.dtype, device=device)
202
+ out = self.forward(x)
203
+ return out.detach().cpu().numpy()
204
+
205
+
206
+ def _build_tabular_features(
207
+ *,
208
+ timestamps: np.ndarray,
209
+ cgm: np.ndarray,
210
+ insulin: np.ndarray,
211
+ carbs: np.ndarray,
212
+ feature_names: list,
213
+ history_length: int,
214
+ ) -> np.ndarray:
215
+ """Assemble a (B, F) feature matrix in the order given by ``feature_names``.
216
+
217
+ Convention: ``CGM_t<i>`` means the i-th *most recent* sample within the
218
+ last ``history_length`` steps, i.e. ``CGM_t0`` = oldest in the window,
219
+ ``CGM_t<history_length-1>`` = newest. Same convention applies to
220
+ ``Insulin_t<i>`` / ``Carbs_t<i>``. ``hour_sin`` / ``hour_cos`` are derived
221
+ from the most recent input timestamp (UTC hour-of-day).
222
+ """
223
+ if cgm.shape[-1] < history_length:
224
+ raise ValueError(
225
+ f"Need at least {history_length} CGM samples, got {cgm.shape[-1]}"
226
+ )
227
+ cgm_h = cgm[..., -history_length:]
228
+ insulin_h = insulin[..., -history_length:]
229
+ carbs_h = carbs[..., -history_length:]
230
+
231
+ # Hour-of-day from the most recent input timestamp (ns since epoch).
232
+ last_ts = np.asarray(timestamps)[..., -1].astype(np.int64)
233
+ hours = (last_ts // 3_600_000_000_000) % 24
234
+ hour_sin = np.sin(2.0 * math.pi * hours / 24.0)
235
+ hour_cos = np.cos(2.0 * math.pi * hours / 24.0)
236
+
237
+ columns = []
238
+ for name in feature_names:
239
+ if name.startswith("CGM_t"):
240
+ i = int(name.split("_t", 1)[1])
241
+ columns.append(cgm_h[..., i])
242
+ elif name.startswith("Insulin_t"):
243
+ i = int(name.split("_t", 1)[1])
244
+ columns.append(insulin_h[..., i])
245
+ elif name.startswith("Carbs_t"):
246
+ i = int(name.split("_t", 1)[1])
247
+ columns.append(carbs_h[..., i])
248
+ elif name == "hour_sin":
249
+ columns.append(hour_sin)
250
+ elif name == "hour_cos":
251
+ columns.append(hour_cos)
252
+ else:
253
+ raise ValueError(f"Unknown feature column: {name!r}")
254
+ return np.stack(columns, axis=-1).astype(np.float32)
model_all.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:eb1cc1ecc7a8d58993966a9e4f6b44e80ec48b6b130a3370865ccd9120af4903
3
+ size 4480
model_carbs.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7f2aa37a10c6548161e19f3cf3ec890f32f302a8144b9255485eacde03c01fb8
3
+ size 3136
model_cgm.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a2a839117a4ad2b23b19d2d3a2cb2b676ac01a2fa42804a72e5ca629c64812f3
3
+ size 1792
model_insulin.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:73669bf02fe503007004f75bcc7ff94c84ebebb6472ec6163e32fa4e51579d52
3
+ size 3136
push.sh ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # Upload hub/ridge to the Hugging Face Hub.
3
+ # Run from anywhere; the script resolves its own location.
4
+ #
5
+ # Override the destination repo via the REPO env var (default:
6
+ # anonymous-4FAD/Ridge). Extra args are forwarded to ``huggingface-cli upload``.
7
+ #
8
+ # Requires:
9
+ # - huggingface-cli installed (it ships with huggingface_hub).
10
+ # - You are logged in: ``huggingface-cli login``.
11
+
12
+ set -euo pipefail
13
+
14
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ REPO="${REPO:-anonymous-4FAD/Ridge}"
16
+
17
+ echo "Uploading ${HERE} -> ${REPO}"
18
+ huggingface-cli upload "$REPO" "$HERE" . --repo-type model "$@"