+1 (484) 312-5566

After Deploy: Drift Monitoring and Retraining Triggers for Keras Models

Accuracy on your held-out test set is the last honest number you get for free. Everything after deployment costs instrumentation. Most teams we review have a well-tested export path, a versioned artifact, and no idea whether the model served last Tuesday was still good — because nothing downstream of the endpoint was logged.

This post covers what to record at serving time, which drift signals are worth an alert, and how to decide that a retrain is justified rather than reflexive.

Why before how: three different failures

"Drift" gets used for three failures with different detection costs and different fixes.

  1. Input (covariate) drift — the feature distribution moves. A new camera, a firmware update that changes JPEG compression, a sensor recalibration, a new customer segment. Detectable immediately, with no labels.
  2. Prediction drift — the output distribution moves. Positive rate climbs from 4% to 11%. Also label-free, and often the earliest usable proxy for trouble.
  3. Concept drift — the relationship between inputs and target changes. Inputs look normal, predictions look normal, and the model is simply wrong more often. Only labels reveal it.

Only the third one directly means "the model got worse." The first two are early warnings that may or may not matter. Treat them that way: input drift raises a question, degraded task metrics close the case.

Log the right things at inference

The monitoring you can do is bounded entirely by what you wrote down. Minimum viable serving log, one row per request:

  • Request ID, timestamp, and the model version that served it. Without the version you cannot attribute a regression to a release.
  • A compact summary of the input — for tabular, the raw features; for images or audio, not the payload but the embedding or a handful of cheap statistics (mean, std, resolution, brightness, decode failures).
  • The full output vector, not just the argmax. Predicted class plus max softmax probability lets you track confidence distributions, which shift before accuracy does.
  • Preprocessing outcome flags: clipped values, out-of-range inputs, missing fields, fallbacks taken.
  • Latency, and whether the request hit a fallback path.

For image and text models, penultimate-layer embeddings are the practical monitoring feature. Serve them alongside predictions:

import keras

served = keras.Model(
    inputs=model.inputs,
    outputs=[model.output, model.get_layer("penultimate").output],
)
served.export("export/7")

One export, two signals. Storing a 1280-dim float16 embedding per request costs about 2.5 KB — negligible against the cost of not knowing.

Measuring drift without drowning in alerts

Pick a reference window — usually the training distribution, or a known-good production period — and compare rolling production windows against it.

For one-dimensional numeric features, Population Stability Index is the workhorse: bin the reference into deciles, compute sum((p_prod - p_ref) * log(p_prod / p_ref)). Conventional reading: below 0.1 is stable, 0.1–0.25 is worth investigating, above 0.25 is a material shift. For categorical features, compare category frequencies and watch for unseen categories, which are usually a pipeline bug rather than drift.

For embeddings, per-dimension tests are noise. Compare distributions as a whole: maximum mean discrepancy between reference and production batches, or the simpler operational proxy — mean cosine distance to the reference centroid, plus the fraction of requests beyond the 99th-percentile distance seen in training.

Two practical rules that cut false alarms more than any statistic choice:

  • Kolmogorov–Smirnov on large samples flags everything. With 100k requests a day, statistically significant differences are guaranteed and meaningless. Alert on effect size (PSI, distance), not p-values.
  • Window and de-bounce. Compare daily or weekly windows of comparable size, require a threshold breach on two consecutive windows, and segment by known cycles. Monday is not Saturday; that is seasonality, not drift.

Getting labels, because the rest is inference

The only measurement that settles the argument is task performance on fresh labeled data. Three ways to get it, cheapest first:

  1. Delayed ground truth. Many problems produce labels naturally after a lag: the part failed or it didn't, the claim was approved, the forecast horizon closed. Join them back to the prediction log by request ID and compute a rolling metric. This is the best signal available and it needs only plumbing.
  2. Sampled human review. Label a small random sample — a few hundred per period — and stratify by confidence so uncertain cases are represented. Random beats "review the flagged ones": a sample biased toward low confidence cannot estimate overall accuracy.
  3. Proxy metrics. Override rates, downstream rework, user corrections. Noisy, but cheap and continuous.

Track the metric you deployed against — per-class recall at the operating threshold, not overall accuracy — and store it per model version, so a rollback comparison is a query and not an archaeology project.

Deciding to retrain

Retraining on a schedule is fine when data arrives steadily and labels are cheap. It is also the reflex that quietly ships regressions, because a retrained model gets promoted on the assumption that newer is better.

Retraining is justified when at least one holds:

  • Measured task metrics dropped past a threshold you set in advance, on two consecutive evaluation windows.
  • A known population change happened — new site, new hardware, new product line — and input drift confirms it.
  • Enough new labeled data has accumulated that it materially changes the training set, particularly for classes previously thin.

Retraining is not justified because a PSI crossed 0.1 on one feature for one day, or because a quarter ended. And when drift is really a data bug — a preprocessing change, an upstream schema edit, a unit switch — retraining bakes the bug into the weights. Check the pipeline before you check the architecture.

Whichever trigger fires, the promotion gate stays the same: retrain reproducibly, evaluate the candidate and the incumbent on the same fresh holdout, require the candidate to win on the metric that matters and not regress on any protected slice, run the export parity tests, and ship behind a shadow or canary deployment before full traffic. Keep the previous artifact and its metrics ready for rollback.

A reasonable first week of instrumentation

You do not need a monitoring platform to start. In order:

  1. Log predictions with model version, timestamp, input summary, and confidence.
  2. Add a daily job computing PSI on the top five features (or embedding distance) against the training reference, writing results to a table.
  3. Wire whatever delayed labels already exist back to the prediction log and chart the rolling task metric by version.
  4. Set two alerts only: task metric below threshold, and unseen-category or decode-failure rate above baseline.
  5. Write down, before anything fires, what each alert obliges someone to do.

That is a few days of engineering and it converts "the model seems fine" into a number with a date on it. Everything more sophisticated — automated retraining pipelines, per-segment dashboards, statistical test suites — is worth building only after those four signals exist and someone reads them.