Project 05 06

GLUP24

Deep-learning models that predict blood glucose levels for people with type 1 diabetes from continuous monitoring data.

Deep learning research
Python · PyTorch · Optuna · MLflow · Time series

The GLUP24 challenge is a forecasting problem with real consequences: predict the blood glucose levels of people with type 1 diabetes over a given time horizon. Better predictions mean earlier warning of a hypo- or hyperglycaemic episode, and a treatment that can be adjusted before it becomes urgent rather than after.

The data

The dataset comes from six people with type 1 diabetes, all on insulin pump therapy with continuous glucose monitors and fitness bands. Each record combines what the person did with what their body was doing: glucose readings, insulin doses, meal times, exercise, sleep, work, stress, and illness on one side; heart rate, galvanic skin response, skin and air temperature, and step count on the other.

That mixture is what makes the problem hard. The signals arrive at different frequencies, some are self-reported and therefore late or missing, and the relationship between an action and its effect on glucose is delayed by anywhere from minutes to hours.

Approach

Four architectures are implemented behind a common interface — CNN, RNN, LSTM, and GRU — so that the same preprocessing, training loop, and evaluation apply to all of them. Training is driven by a JSON parameter file, hyperparameters are searched with Optuna, and every run is logged to a local MLflow server along with its model artefact.

The workflow is deliberately split into separate scripts: train.py to fit and register a model, optimize.py to run the Optuna search, test.py to evaluate a registered run and log its metrics and prediction-versus-truth plots back to MLflow, and evaluate.py to inspect a model without recording anything.

What I learned

Real physiological data is nothing like a benchmark dataset. Sensors disconnect, people forget to log meals, and the gaps are not random — someone is least likely to record what they ate exactly when something interesting is happening. Deciding how to resample, interpolate, and mark missing values shaped the results far more than the choice between an LSTM and a GRU.

That comparison was itself instructive. I expected a clear winner between the four architectures and found something closer to a tie, with the differences between feature sets and window lengths dwarfing the differences between models. It was my first real evidence that effort spent on the inputs usually beats effort spent on the network.

Separating training, optimisation, and evaluation into distinct entry points around an MLflow run ID was a structural decision I have reused in every project since. It meant a model could be trained once and then evaluated repeatedly from a stable identifier instead of being retrained to be inspected.

And working on medical-adjacent data made the stakes of a metric concrete. A mean absolute error that looks respectable in aggregate can still hide exactly the excursions that matter clinically. Learning to ask what a model gets wrong, rather than how often it is right, started here.