Clean data, no levels given
1.169
Latent ODE median fold error. popPK with covariates 1.171, true model 1.172.
Clean data, 16 levels given
1.081
Latent ODE. popPK MAP gets 1.004, the true model 1.000.
ADA onset before level 24
1.247
Latent ODE, 45 patients. Constant-CL popPK 1.384, time-varying CL 1.161.
Structural checks passed
16 of 17
Failed: clean network, dose proportionality.
Full pipeline
165 s
Laptop CPU. Networks stopped early after 135 to 151 epochs.
The network
A latent neural ODE with a GRU encoder for the levels seen so far.
- The covariates (weight, albumin, INF, PLT) go through a small MLP to a context vector c (8 numbers).
- Each patient has a latent vector u (4 numbers), a learned stand-in for the random effects. Its prior depends on c.
A GRU reads the first k measured levels and gives the posterior of u. That is the network's version of Bayesian updating;
with no levels the posterior is the prior.
- A state x (6 numbers) starts at x0(c, u) and follows dx/dt = f(x, u, c), solved with a fixed-step RK4 written in PyTorch.
- Each dose is a learned jump in x at the dose time.
- A small head maps (x, u) to log concentration, so predictions are always positive.
Trained with Adam (learning rate 0.003, batches of 50), a KL warm-up over 25 epochs,
early stopping after 30 epochs without improvement, and dose-rescaling augmentation, which is valid because Drug X has linear PK.
The simulated data
Patient counts per dataset, from the run log.
| Dataset | Train | Validation | Test | Levels below LLOQ | Turned ADA positive |
|---|
| Clean | 300 | 60 | 120 | 0.0% | none |
| Dose levels + assay error | 300 | 60 | 120 | 0.9% | none |
| ADA | 300 | 60 | 120 | 2.6% | 40% |
Clean: one dose level, no assay error, no IOV. Dose levels: several mg/kg dose levels with IOV, assay error and censoring below the LLOQ. ADA: the same, plus anti-drug antibodies that switch on partway through and raise clearance. popPK comparators are two-compartment models fitted by iterative two-stage estimation and forecast by MAP.