Een speler in versvoeding kwam met een simpele vraag bij ons: kunnen jullie de vraag van morgen voorspellen per gerecht, per locatie, nauwkeurig genoeg om geen marge meer weg te gooien en 's middags niet meer uitverkocht te zijn? Achttien maanden later voorspelt het platform met 98% nauwkeurigheid in productie. Men neemt aan dat machine learning het moeilijkste deel was. Dat was het niet.
Het model dat de voorspelling maakt, is een gradient-boosted regressor met daarop een paar geënte seizoensvariabelen. Een bekwame data scientist kan in een namiddag iets uit deze familie opzetten. Wij hadden binnen drie weken een respectabele eerste versie — op de backtest nauwkeurig genoeg om iedereen in de ruimte te laten knikken.
Vervolgens besteedden we vijf maanden aan het bouwen van alles wat « een nauwkeurige backtest » verandert in « een cijfer waarop een operationeel manager zijn dag durft te zetten ». Dat gat is het hele vak, en bijna niemand spreekt erover omdat het niet glamoureus is. Hier is het dus.
01Het model in drie weken
De vraag voorspellen voor een stabiele, goed geregistreerde activiteit is, eerlijk gezegd, een opgelost probleem. Je hebt een doel (verkochte eenheden), een kalender en een stapel historische rijen. Je ontwerpt enkele tientallen variabelen — dag van de week, lag-vensters, voortschrijdende gemiddelden, feestdagen, een weer-join — en je laat een boosting-bibliotheek de interacties vinden. Het is niet in de wiskunde dat de projecten sterven.
Wat de drie weken ons werkelijk opleverden, was de zekerheid dat het signaal simpelweg bestond. De backtest vertelde ons dat de vraag voorspelbaar was tot op een of twee procentpunten, op voorwaarde van schone invoer. Dat is het groene licht. Het is niet het product.
Een goed backtest-cijfer is het gevaarlijkste artefact in machine learning. Het lijkt op de finishlijn terwijl het nauwelijks meer is dan het startschot. Backtests draaien op data die zijn opgeschoond, gejoind en in de tijd uitgelijnd door een mens die het antwoord al kent. De productie heeft geen van die luxes.
02Waar de vijf maanden naartoe gingen
Hier is de eerlijke afrekening van de volgende vijf maanden. Niets daarvan is modelleren. Dit alles is wat het model bruikbaar heeft gemaakt.
- Ingestie die de realiteit overleeft. Verkoopfeeds komen te laat, dubbel of helemaal niet binnen. Een POS herstart en speelt de vorige dag opnieuw af. We bouwden een idempotente ingestie die veilig opnieuw kan worden uitgevoerd en rijen die ze niet vertrouwt in quarantaine plaatst, in plaats van de trainingsset te vergiftigen.
- Een feature store met geheugen. De variabelen waarop het model traint, moeten berekenbaar zijn op het moment van de voorspelling, met uitsluitend de data waarover je op dat ogenblik daadwerkelijk zou beschikken — zonder een blik in de toekomst te werpen. Die point-in-time-correctheid afdwingen kostte weken werk en ving twee lekken op die de oorspronkelijke backtest hadden opgeblazen.
- Backfill en replay. Wanneer de historie van een locatie fout was, moesten we alle stroomafwaartse voorspellingen voor die locatie opnieuw opbouwen zonder het live systeem stil te leggen. Replay is leidingwerk dat niemand demonstreert en dat iedereen nodig heeft.
- Monitoring vóór functies. We leverden de drift- en versheidsalarmen op voordat we de helft van de interface opleverden. Een stilletjes foute voorspelling is erger dan een zichtbaar ontbrekende.
- De menselijke override. Een nieuwe locatie opent, een festival komt eraan, een weg gaat dicht. Het model kan dat niet weten. Planners hadden een gesanctioneerde manier nodig om het cijfer bij te sturen en het systeem van die bijsturing te laten leren.
Het model beantwoordt één vraag. Het platform beslist welke vraag, met welke data, voor wie, en wat er gebeurt wanneer het antwoord fout is.
— Over waarom de verpakking het echte werk is03Het datacontract
Het meest hefboomwerkende dat we bouwden, was geen modelverbetering. Het was een datacontract: een expliciet, gevalideerd schemacontract tussen elke bovenstroomse bron en onze pipeline. Kolomtypes, toegestane bereiken, versheidsvensters, null-policy's — alles gedeclareerd, alles aan de poort gecontroleerd.
Vóór het contract kon een voorspelling stilletjes degraderen omdat een POS-leverancier een valutaveld van centen naar dollars veranderde zonder ons te waarschuwen. Na het contract wordt die verandering bij de ingestie afgewezen met een benoemde, geëscaleerde fout — en blijft de laatste goede voorspelling op het scherm staan in plaats van een nieuwe, zelfverzekerde en foute.
# elke bron wordt aan de poort gevalideerd, niet nadat ze de training heeft vergiftigd sales_daily: units: int >= 0 # wijs negatieven af — terugbetalingen gaan elders heen revenue: decimal(10,2) # centen → gesignaleerd in v3, nu afgedwongen site_id: fk(sites) # onbekende locatie → quarantaine, escaleer naar on-call recorded_at: freshness <= 6h # verouderde feed → behoud de laatste goede voorspelling on_violation: quarantine + alert # nooit: er stilletjes op trainen
Dit is het weinig sexy hart van elk productie-ML-systeem dat we hebben opgeleverd. Het model is een functie; het contract is wat garandeert dat de functie de invoer krijgt die ze is getraind te verwachten. Sla het over en je hebt geen voorspellingsplatform — je hebt een zeer dure generator van willekeurige getallen die meestal gelijk heeft.
04Drift is een functie, geen falen
Elk model degradeert. Smaken verschuiven, een nieuw menu komt eraan, een concurrent opent aan de overkant. De vraag is nooit of de wereld onder je model zal wegglijden — het is of je het uit een dashboard verneemt of via een woedend telefoontje.
We behandelen driftdetectie als een eersteklas productfunctie. Het platform vergelijkt voortdurend de verdelingen van de live invoer en de live fout met de trainingsreferenties. Wanneer een van beide een drempel overschrijdt, doet het drie dingen, in deze volgorde:
- Het waarschuwt iemand — een specifieke mens, met de locatie, de metriek en hoeveel ze is bewogen.
- Het beschermt de uitvoer — door de betrouwbaarheidsintervallen te verbreden of terug te vallen op een eenvoudigere, robuustere referentie, in plaats van te vertrouwen op een model dat nu extrapoleert.
- Het plant een hertraining — met de nieuwe data, voorwaardelijk aan dezelfde backtest-drempel die het origineel moest halen.
Volgehouden in productie, niet alleen op de backtest.
De lege koelkasten 's middags, met meer dan de helft teruggebracht.
Marge die vroeger aan het einde van de dag werd weggegooid.
Merk op dat het uithangbordcijfer — 98% — niet het interessantste is. De interessante cijfers zijn de twee die het omringen, want dat zijn de cijfers die het bedrijf voelt. Nauwkeurigheid is de invoer; minder verspilling en minder tekorten zijn de uitvoer. Een platform dat het eerste optimaliseert en het tweede negeert, is een labproject.
05Het dashboard dat iemand om 8 uur 's ochtends raadpleegt
De voorspelling wordt geconsumeerd door een keukenchef bij het begin van een dienst, op een tablet, met koffie in de hand, in negentig seconden. Die beperking heeft meer beslissingen gevormd dan de architectuur van het model.
Ze vereiste dat het antwoord een hoeveelheid was, geen kansverdeling. Ze vereiste dat « ik ben het er niet mee eens, en dit is waarom » in één tik paste. Ze vereiste dat het scherm de voorspelling van gisteren toonde tegenover wat er werkelijk gebeurde, want vertrouwen verdien je door zichtbaar verantwoordelijk te zijn, niet door zelfverzekerd te zijn. Een model dat zijn historie niet kan tonen aan de persoon die erop steunt, wordt binnen een week stilletjes genegeerd.
Niet de F1-score. Niet de RMSE. De acceptatietest was een keukenchef, in week twee, die zegt « ja, nu doe ik gewoon wat het zegt ». Die zin is meer waard dan welke offline metriek ook, en je verdient hem alleen door de laatste negentig seconden met evenveel zorg te ontwerpen als het model.
06Notities aan onze vroegere zelf
Als je op het punt staat iets van deze vorm te beginnen, is dit wat we zouden zeggen tegen het team dat achttien maanden geleden begon:
- Begroot de verpakking, niet het model. Ga ervan uit dat het model 15% van de inspanning is en plan de overige 85% bewust. De teams die hun deadlines missen, zijn die welke het omgekeerde hebben begroot.
- Schrijf het datacontract eerst. Vóór ook maar één variabele. Het zal een lek in je backtest aan het licht brengen en je behoeden voor het opleveren van een cijfer dat je niet kunt verdedigen.
- Lever monitoring vóór de interface op. Je kunt niet exploiteren wat je niet kunt zien, en een foute voorspelling die niemand heeft opgemerkt, is de faalmodus die contracten doet verliezen.
- Ontwerp de override. Mensen zullen altijd dingen weten die het model niet kent. Geef hun een gesanctioneerde hefboom en leer ervan, anders omzeilen ze het hele systeem in een spreadsheet.
- Maak het model verantwoordelijk op het scherm. Toon zijn historie naast zijn voorspelling. Vertrouwen is evenzeer een interfacebeslissing als een kwestie van wiskunde.
Machine learning was het makkelijke deel. We zeggen dat niet om het model te kleineren — het is werkelijk goed — maar om aan te wijzen waar de moeilijkheid werkelijk ligt. De hype verkoopt de drie weken. De vijf maanden zijn waarvoor je een engineeringteam werkelijk betaalt.

