learn-ml-production-with-phoebe / Session 5 of 6
ML in Production: The Leader Cut · Session 5 of 6

Monitor what you will act on

Most monitoring is built the wrong way round. A team wires up every chart the platform offers, points alerts at a shared channel, and waits. Within a month the channel is muted, and the one alert that mattered arrives in a room nobody is in. Tonight starts from the other end: what could go wrong, what you would actually do about each thing, who does it, and what doing it costs. Then two facts that shape every monitor you build. Most of what you can watch arrives before the truth does, and a model that decides which cases get labelled can quietly teach itself to be wrong. You leave with an alert-to-action table for a system you own, with the rows that have no action already deleted.

🟠 Advanced Leaders who own the pager budget Builders who wire the alerts 45 min
0-3 · Welcome 3-18 · Signals, actions, loops 18-40 · Build-along: the alert-to-action table 40-45 · Q&A
Part 0

Where we start

Session 4 priced a retrain and showed that an alarm is one of the cheapest ways to buy accuracy back. That alarm only works if three things are true: it watches something that moves when the model goes wrong, somebody acts when it fires, and the thing it watches is not being shaped by the model itself. Tonight is those three things in order. None of them is a dashboard question. Each is a decision about attention, which is the scarcest thing an operations team has.

🎫 Clear all three quiz questions to stamp your passport Live = presented in the 45 minutes Self-study = the full depth, after class ★ Build-along = fill it in for your own system

★ What you walk out with tonight. An alert-to-action table for one real ML system: every signal with its threshold, its action, its owner and the cost of acting, the rows with no action struck out, and one guard against the model choosing its own labels. Plus the sentence that ends most monitoring debates: "if nobody would do anything when this fires, we are not going to page anyone about it."

Part 1 · covers what can be watched, and when

Most of what you can watch arrives before the truth does

5 min live

The decision first: which of the things you watch can tell you the model is wrong, and how late. A leader who does not ask gets a wall of green charts that are all measuring the plumbing. The mechanism is the label delay from session 4. Between the moment a prediction is served and the moment its true outcome lands, three layers of the system are already visible. The fourth, the one everyone actually cares about, is not.

WHAT YOU CAN SEE, AND WHEN: THREE LAYERS NOW, ONE AFTER THE LABEL DELAY prediction served label arrives the label delay visible from the first prediction 1 · software 2 · inputs 3 · outputs 4 · performance latency, throughput, memory, server load Monitor 6 distribution of each input x Monitors 2, 3 distribution of the predictions what the model says blind for one label delay: nothing to score yet accuracy vs labels Covariate shift shows in row 2 on day one. Concept drift, a change in P(Y|X), leaves rows 1 to 3 untouched. It waits in row 4, one label delay behind. Monitor numbers are the ML Test Score's monitoring tests.
🔍 Click to zoom - three layers can alarm the day something breaks; the one that measures being wrong waits out the ochre gap
LiveNg's method: start from what could go wrong2 min▶

Andrew Ng's Machine Learning in Production lectures teach monitoring as a brainstorm before it is a dashboard (reported, from compiled lecture notes). Sit down with the team and list everything that could go wrong. Then pick metrics in three families: software metrics such as memory, compute, latency, throughput and server load; input metrics that describe the distribution of what the model is fed; and output metrics that describe what the model returns. Set a threshold on each, and expect to adapt both the metrics and the thresholds over time as you learn which ones move when something real happens.

The last step is the one most teams skip. A threshold set on launch day is a guess. Treating it as permanent is how a channel fills with alerts nobody reads, and Part 2 is about pricing that.

LiveThe seven monitoring tests in the ML Test Score2 min▶

Breck and colleagues give monitoring its own section of seven tests, scored like the other three: half a point by hand and documented, a full point automated. Session 1's constructed readiness sheet scored this section lowest, at 1.0 of 7, and that is the shape to check your own sheet against; the paper itself does not rank the sections by how often teams fail them.

#Monitoring testVisible before labels?
1Dependency changes result in notificationYes
2Data invariants hold for inputsYes
3Training and serving are not skewedYes
4Models are not too staleYes, as model age
5Models are numerically stableYes
6Computing performance has not regressedYes
7Prediction quality has not regressedNo: it needs labels

Six of seven can alarm on the day something breaks. Only the seventh measures the thing the business pays for, and it is the one that runs a label delay behind.

LiveThree kinds of shift, and which one an input monitor can see1 min▶

Chip Huyen's blog post on data distribution shifts gives the cleanest definitions (read, blog). Covariate shift: P(X) changes while P(Y|X) stays the same; the inputs move, the rule linking them to the outcome does not. Label shift: P(Y) changes while P(X|Y) stays the same; the mix of outcomes moves. Concept drift: P(Y|X) changes while P(X) stays the same; the same inputs now mean a different outcome.

Ng's lectures use a simpler pair (reported): data drift when the distribution of x changes, concept drift when the mapping from x to y changes. He uses the two words loosely at times, so when a team says "drift", ask which one they mean.

The practical consequence is in the figure. An input monitor sees covariate shift, because it is by definition a change in the inputs. It cannot see concept drift, because the inputs have not moved: the only place concept drift shows up is performance against labels, after the labels land. Label shift sits between them; the output distribution may hint at it, but confirming it takes labels too.

Self-studyWhere the statistics and the pipeline monitors live2 min▶

This session decides what to watch and why. How to measure a distribution change, which statistic, which test, which window, is taught in Model Evaluation b9, drift and continuous evaluation ↗. Monitors on the pipeline feeding the model, freshness, volume and schema, are taught in Data Observability a2, the five signals ↗. Both plug into the input row of the figure; neither changes the rule that performance waits for labels.

Real world

Thirty-six Google teams, and the test they skipped. When Breck and colleagues met 36 teams across Google, none of the 28 tests was implemented by more than 80 percent of them. The one they single out as "perhaps the most important and least implemented" is a monitoring test: training and serving are not skewed. It needs no labels at all; it compares the features the model sees live with the features it was trained on. The decision a leader signs here: before any accuracy dashboard is funded, the three rows that need no labels are live, and the team can say out loud how long row four is blind.

Part 2 · covers alert-to-action

An alert without an action is noise

6 min live

The decision first: for every alert, what happens when it fires, and who does it. If the honest answer is "someone looks at it", the alert is a chart with a sound attached. The mechanism is a chain of four links: a signal, a threshold on it, an action the threshold triggers, and a person who owns the action. Break any link and the alert still fires; it just stops meaning anything.

EVERY ALERT IS A CHAIN OF FOUR LINKS (CONSTRUCTED THRESHOLDS) SIGNAL THRESHOLD ACTION OWNER Serving latency over budget for 15 min Page on-call, roll back session 3's rollback On-call Share of a feature missing jumps vs last month Block retrain, ticket upstream the fix is not in the model Data owner Prediction distribution shifts vs launch week Review, shadow a refit session 3's shadow mode Model owner Accuracy, labelled rows falls 10 pts over 4 wks Refit on all history session 4's alarm policy Model owner A chart someone liked none written none: an alert with no action delete it Thresholds are constructed for the figure. The ochre column is the one that makes an alert worth its page.
🔍 Click to zoom - read each row right to left: if the action or the owner is blank, the signal on the left is noise
LiveSculley: what to monitor, and three places to look2 min▶

In the section of the hidden-technical-debt paper on changes in the external world, Sculley and colleagues write: "Comprehensive live monitoring of system behavior in real time combined with automated response is critical for long-term system reliability." Then: "The key question is: what to monitor?" They name three starting points (read).

  • Prediction bias. In a system working as intended, the distribution of predicted labels should match the distribution of observed labels. A change there is a cheap, early sign that the world has moved. It is not a sufficient test: a null model that predicts the average label for everything passes it perfectly. Slice it by segment and it becomes much sharper.
  • Action limits. Where the system takes actions in the world, bidding, approving, blocking, set limits on those actions as a sanity check, and alert when one is hit. The limit is a floor under a model going wrong fast.
  • Up-stream producers. Data flowing in from other teams' systems should be monitored against its own expectations, and those producers' alerts should reach the team that consumes the data. Session 1's unstable data dependencies, made operational.

Note the word "automated response". The paper pairs monitoring with action from its first sentence on the subject.

LiveAn alert threshold is a spending decision: the bench shows it2 min▶

Session 4's bench already priced this, on real Elec2 rows at a one-day label delay. The alarm policy that refits when four-week accuracy on labelled rows falls 10 points below where it started retrains 6 times and scores 72.78 percent. Now make it a hair trigger: fire on any dip at all, watching only the last day. It retrains 209 times and scores 72.79 percent.

AlarmRetrainsAccuracyCorrect rows
10 points, 4-week window672.7810,666
Any dip at all, 1-day window20972.7910,668

The extra 203 retrains buy 2 correct rows out of 14,656. Every one of those retrains is an alert somebody acted on. A threshold decides how often the team is interrupted and how much compute is spent, long before it decides accuracy.

Reproduce it. Open session 4's bench, keep labels at 1 day and refits on all labelled history, then set Retrain to "on an alarm", Alarm when accuracy falls to "any dip at all", and Alarm watches to "1 day". Compare it with the same alarm at "10 points" and "4 weeks".

LiveZinkevich Rule 10: watch for silent failures2 min▶

Martin Zinkevich's Rules of Machine Learning give this failure its own rule, "Watch for silent failures." (read). His examples are the kind no latency chart will ever catch. A feature column that was populated in 90 percent of examples drops to 60 percent, and the model keeps serving, slightly worse, with nothing crashing. A table behind Google Play went stale for 6 months; refreshing it gave "a boost of 2% in install rate".

Both are row 2 of Part 1's figure: an input-side signal, visible without a single label, that nobody was watching. And both have an obvious action: find the upstream owner and fix the feed, which is exactly the second row of the alert chain above.

Self-studyAlert hygiene for the pipeline itself1 min▶

The same discipline, applied to data pipelines rather than models, is taught in Data Observability a4, alert or noise ↗: how to count alerts per week, how to tell a noisy check from a broken one, and when to retire a check. The rule carries over unchanged: a check that never leads to an action is costing attention and buying nothing.

Real world

Elec2's constant columns (self-study). The electricity file used on session 4's bench looks clean. Its ARFF header records a ReplaceMissingValues filter, and three inputs, Victoria's price, Victoria's demand and the transfer between states, are constant for the first 17,424 rows, 363 days: their values were missing and filled in before the file was published (measured). A monitor on "share of constant values per input" would have flagged three of the five market inputs the bench uses from day one, with a clear action attached: ask the producer what happened before the model learns a year of nothing. The decision a leader signs here: every alert on the list names its action and its owner, and any that cannot is removed before launch, not after the channel is muted.

Part 3 · covers feedback loops

When the model grades its own homework

4 min live

The decision first: how much of your traffic is decided without the model, so you can still learn what the model gets wrong. Without that slice, a model that chooses which cases get acted on also chooses which cases get labelled, and every retrain learns only from the cases it already liked. The monitor looks healthy because it is measured on the same selected cases. Here is the mechanism, drawn for a lending model.

A DIRECT FEEDBACK LOOP, AND THE SLICE THAT BREAKS IT (CONSTRUCTED LENDING EXAMPLE) Model scores applicants Action in the world approve or decline declined: outcome never seen Labels arrive only for approved cases Next training set built from those labels only Held-out slice a small random share decided without the model the model picks its own next labels labels it did not pick The slice's size is a business choice, constructed here: it costs some decisions made without the model.
🔍 Click to zoom - the hachured box learns only from cases the model chose; the ochre slice is the only view of the cases it turned away
LiveSculley: direct and hidden feedback loops2 min▶

The hidden-technical-debt paper separates two kinds (read). A direct feedback loop: "A model may directly influence the selection of its own future training data." That is the figure: the approvals decide the labels. A hidden feedback loop is harder to find, because it runs between systems: "two systems influence each other indirectly through the world." Two models owned by two teams, each changing the behaviour the other learns from, with neither team's monitor built to see the other.

Neither loop crashes anything. Both can make every monitor in Part 1 look better while the model gets worse on the cases it no longer sees.

LiveHuyen: degenerate loops and feedback loop length1 min▶

Chip Huyen names the failure a degenerate feedback loop: "a system's outputs are used to create or process the same system's inputs" (read, blog). Recommenders are the familiar case; lending, fraud and hiring screens are the expensive ones.

She also names the dial that sets how fast any loop can be caught: feedback loop length, the time from serving a prediction to getting feedback on it. It is session 4's label delay under another name. For fraud she gives a dispute window of "a month to three months" (read, blog). Her book, Designing Machine Learning Systems, covers the same ground at more depth; its text was not read for this session, so nothing here is quoted from it.

Self-studyThree guards against a model picking its own labels2 min▶
  • A held-out slice. A small random share of cases is decided without the model, by the old rule or at random within safe limits, and its outcomes are labelled like any other. It costs some worse decisions; it buys the only unbiased view of what the model turns away. Its size is a business choice, and the table in the build-along gives it a row.
  • Log what the model did not choose. Store the score and the decision for every case, including the declined ones. You cannot learn their outcomes, but you can see when the share being declined moves, which is an output-row signal from Part 1.
  • Measure the label delay, as session 4's homework asked. The loop length tells you how far behind the performance row is, and therefore how long a loop can run before any accuracy alarm could notice.
Real world

The fraud model's alarm is always looking at last quarter. Huyen's fraud dispute window, a month to three months, is a label delay. A fraud model's accuracy alarm can only score transactions whose disputes have had time to arrive, so on any given morning it is grading the model that was running up to three months ago. Every row of the alert table that depends on labels inherits that lag. The decision a leader signs here: the size of the held-out slice, and who owns it, written down before the model's first retrain, because the loop starts closing on day one and the labels that would reveal it are months behind.

Build-along

The alert-to-action table

★ 22 min · everyone builds

Pick one ML system you own or are about to approve. If you have none, use the Elec2 price-direction model from session 4; the figure fills its table as a constructed worked example. Six steps, each a block you copy into a document and fill in. The table is finished when every surviving row has an action, an owner and a price, and one row guards against the model choosing its own labels.

THE TABLE, FILLED FOR THE ELEC2 PRICE MODEL (CONSTRUCTED WORKED EXAMPLE) Signal Threshold Action Owner Cost of acting Serving latency over budget 15 min roll back on-call minutes of traffic Victoria inputs constant any input flat 1 day block retrain, ticket upstream owner one ticket, no refit Accuracy, labelled rows falls 10 pts, 4 wks refit on all history model owner $500 a refit (s4) Daily UP share none none nobody deleted The last row had no action, so it was struck before launch. The $500 is session 4's constructed default. Every row here is constructed for teaching: your numbers will differ.
🔍 Click to zoom - a row earns its place by the ochre column; the struck row is the most useful edit on the page

Brainstorm what could go wrong, before any metric. Ng's order: the failures first, grouped by where they would show. Ten minutes, with the people who run the system. Write failures, not charts.

★ Block 1 · what could go wrongSystem: ____________________________ Software (it is slow, down, or out of memory): - ________________________________ - ________________________________ Inputs (what it is fed has changed or broken): - ________________________________ (e.g. "a feed goes flat for a day") - ________________________________ Outputs (what it says has changed): - ________________________________ (e.g. "share approved jumps") Performance (it is wrong more often): - ________________________________

Give each failure a signal and say when it becomes visible. "Now" means on the first affected prediction. "After the label delay" means performance: write the delay in hours or days, measured, not guessed.

★ Block 2 · signal and when you can see itFailure Signal Visible __________________________ _____________________________ now / after ____ delay __________________________ _____________________________ now / after ____ delay __________________________ _____________________________ now / after ____ delay __________________________ _____________________________ now / after ____ delay Our label delay (median / 90th percentile): ______ / ______

Set a threshold, and decide now how you will know it is too tight. The honest test is a count: alerts per month, and how many led to an action. Session 4's hair-trigger alarm acted 209 times to buy what 6 actions bought.

★ Block 3 · threshold and its own checkSignal: ______________________ Threshold: ___________________ over window: ________ Expected alerts per month: ____ Too tight if: more than ____ alerts a month, or fewer than ____ % lead to an action Review this threshold on: ________ (Ng: thresholds adapt over time)

Write the action, the owner and the cost of acting. An owner is a person who gets woken up, not a team channel. The cost can be minutes of traffic, an engineer's afternoon, or a retrain priced as in session 4.

★ Block 4 · action, owner, costSignal Action when it fires Owner Cost of acting _____________ ______________________________ ___________ ______________ _____________ ______________________________ ___________ ______________ _____________ ______________________________ ___________ ______________ _____________ ______________________________ ___________ ______________ Retrain cost we use: $______ per retrain (session 4 default: $500, constructed)

Delete every row with no action. Strike it through, keep it on the page for one review so the team sees what was cut, then remove it from the alerting system. A chart can stay on a dashboard; it does not get to page anyone.

★ Block 5 · the deletionsRows struck (no action, or no owner): - ____________________ reason: ____________________ - ____________________ reason: ____________________ Rows left: ____ Alerts per month expected from them: ____

Write the feedback-loop guard. Does the model decide which cases get labelled? If yes, name the held-out slice: its share, how cases enter it, what it costs, and who owns it. If no, write why, in one sentence.

★ Block 6 · the feedback-loop guardDoes the model choose which cases get a label? yes / no If yes, held-out slice: Share of cases decided without the model: ____ % How a case enters the slice: _________________ (random, not chosen) What the slice costs per month: ______________ Owner: ______________ We log score and decision for every case, including declined: yes / no Other systems our outputs feed (hidden loops): ______________
What you would build

Keep the table as data next to the model's code, so it is reviewed like code and no alert exists that is not in it. And compute accuracy only on rows whose labels have actually arrived, or the performance row will quietly score predictions against labels that were not there yet.

★ monitor_spec.pyfrom datetime import datetime, timedelta MONITORS = [ # constructed example; every row must have an action and an owner {"signal": "p99_latency_ms", "window": "15min", "threshold": "> budget", "action": "roll back", "owner": "on-call"}, {"signal": "share_constant_input", "window": "1d", "threshold": "> 0", "action": "block retrain, ticket", "owner": "upstream owner"}, {"signal": "accuracy_labelled", "window": "28d", "threshold": "drop >= 10 pts", "action": "refit on all history", "owner": "model owner"}, ] assert all(m["action"] and m["owner"] for m in MONITORS), "no action, no alert" def rolling_accuracy(preds, labels, label_arrival_time, now, window: timedelta): """Accuracy over the window, counting only rows whose label has arrived by now.""" hits = total = 0 for p, y, t in zip(preds, labels, label_arrival_time): if t is None or t > now or t < now - window: continue # label not in yet, or outside the window total += 1 hits += int(p == y) return hits / total if total else None # None: nothing to score yet # your numbers will differ

The dashboards that display these, the routing that pages the owner, and the scheduled jobs that run them are built in DataOps b6, deploy and monitor ↗. The statistics for the input and output rows are in Model Evaluation b9 ↗. Governance of ongoing monitoring, who reviews the table and how often, is in Model Risk p8, ongoing monitoring ↗.

Count before you tune. Before arguing about any threshold, pull last month's alerts and mark each one "acted on" or "not". The ratio is the fastest honest review of a monitoring system there is, and it usually settles the argument on its own.

Homework

Before session 6

30 min
  1. Write the brainstorm for one live model with the people who run it, grouped into software, inputs, outputs and performance. Mark each item "now" or "after the label delay".
  2. Fill the table and delete the rows with no action. Keep the struck rows visible for one review so the team sees what was cut and why.
  3. Count last month's alerts and how many of them led to an action. Write both numbers at the top of the table. If the second is much smaller than the first, you have found your first thresholds to change.
  4. Find one feedback loop and write its guard. A place where the model's decisions choose which outcomes you ever see. Name the held-out slice, its size, and its owner, or write why none is needed.
Check yourself

Three questions

Clear all three and session 5 gets stamped in your passport.

1 · Which kind of shift can an input monitor NOT see before the labels arrive?

Covariate shift and a feature going missing are changes in the inputs, visible on day one. Concept drift leaves the inputs alone and changes what they mean, so it waits in the performance row, one label delay behind.

2 · On session 4's bench at a one-day label delay, what did the hair-trigger alarm (any dip at all, watching 1 day) buy over the 10-point, 4-week alarm?

10,668 correct rows against 10,666. An alert threshold decides how often somebody acts, and each action has a price. That is why a threshold is a spending decision before it is an accuracy decision.

3 · A lending model decides which applications are approved, and only approved loans ever produce a repaid-or-defaulted label. Why does it need a held-out slice?

This is Sculley's direct feedback loop and Huyen's degenerate loop. The slice is the only source of labels the model did not choose; its size is a business decision, not a fixed rule.

Sources covered

What this session teaches, and where it came from

✓Ng, Machine Learning in Production, week 1: monitoringCourse page read; lecture content reported from compiled lecture notes: brainstorm what could go wrong, software, input and output metrics, thresholds that adapt, data drift and concept drift. Videos and certificate stay official
✓Breck et al. 2017, The ML Test Score: the monitoring sectionRead at source: the seven monitoring tests, the scoring rule, the 36 teams, the 80 percent finding and the training/serving skew test
✓Sculley et al. 2015, Section 7 and feedback loopsRead at source: the monitoring passage, prediction bias (a null model can pass it), action limits, up-stream producers, direct and hidden feedback loops
✓Zinkevich, Rules of Machine Learning, Rule 10Read at source: "Watch for silent failures", the 90 to 60 percent column, the Play table stale for 6 months and the 2% install-rate boost
✓Huyen, blog posts on distribution shifts and real-time MLRead: covariate shift, label shift, concept drift, degenerate feedback loops, feedback loop length, the fraud dispute window. Her book was not read; nothing here is quoted from it
✓Elec2 and session 4's benchMeasured: the constant Victoria inputs for 17,424 rows, and the two alarm runs quoted from the bench canon
◐Drift statisticsNamed only; taught in Model Evaluation b9 ↗
◐Pipeline monitors and alert hygieneNamed only; taught in Data Observability a2 ↗ and a4 ↗
◐The alert tables and thresholdsConstructed for the figures and the worked example, and labelled so

Every fact on this page, and its verification tier, is recorded in the course's source map.

Session 5 cheat sheet · pin this

Three layers nowSoftware, inputs and outputs are visible from the first prediction.
Performance waitsAccuracy against labels is blind for one label delay. Measure the delay.
Action and owner, or delete itEvery alert names what happens when it fires and the person who does it.
A threshold is a spending decisionOn the bench, 203 extra retrains bought 2 correct rows: 72.79 vs 72.78.
Concept drift hidesP(Y|X) changes while the inputs look the same. Only labels reveal it.
Hold out a sliceIf the model decides who gets labelled, a random share decided without it keeps it honest.