1. Courses
  2. Data
  3. Data Science and Machine Learning
  4. Stop 1

35 minIntermediate

Framing a problem as a model

Leadership asks for "AI to fix out-of-stocks". Before any model exists, someone has to say which decision it will change, what exactly it predicts, how it will be judged and what it has to beat. This lesson turns that request into a one-page framing you can defend, and shows you how to tell when a better rule is the honest answer.

By the end you can

  • Turn a vague request into a decision, a target with its unit and horizon, a metric pair and a baseline
  • Tell regression, classification, ranking and anomaly detection apart, and pick the one the decision needs
  • Spot labels that lie, such as sales on days the shelf was empty, and choose how to handle them
  • Compute a baseline forecast and its error in pandas, and write a one-page framing around it
  • Size the value roughly and decide whether machine learning is worth building at all

The everyday picture

A weather forecast on its own changes nothing. It becomes useful when someone acts on it: you take an umbrella, a farmer brings the harvest in a day early, a fishing crew stays in port. Each of them needs a different prediction. You need the chance of rain this afternoon where you live. The farmer needs the total rain over the next three days. The crew needs the wind at sea tomorrow at dawn. Same sky, three predictions, because there are three decisions.

Forecasters also know a forecast has to earn its place. The simplest forecast there is says "tomorrow will be like today", and weather services measure their skill against simple rules like that one. A forecast that can't beat "like yesterday" isn't worth broadcasting. Two more details carry over to your work. The forecast can only use readings taken before it was made. And the cost of being wrong is lopsided: carrying an umbrella you didn't need costs little, getting soaked on the way to an interview costs a lot, so you carry one at a 30% chance of rain.

Machine learning at work has the same shape. Start from the decision, predict what that decision needs using only what is known at the time, weigh the two kinds of mistake, and prove you beat the simple rule.

Start from the decision

"Use AI for out-of-stocks" describes a worry. A model can't act on a worry. Your first job is to find the decision a prediction could improve, because a prediction is only ever an input to a decision. If no decision changes, the model's accuracy doesn't matter to anyone.

At Mangrove Market, out-of-stocks touch several decisions, each with a different owner and rhythm:

  • The nightly from each of about 320 stores to its distribution centre (DC). Supply chain owns it, a system computes it at 22:00, and it covers every product each store carries: millions of order lines a night.
  • The DCs' weekly purchase orders to suppliers, owned by the buyers.
  • Which substitute the app offers when an item is cut from an order, owned by the app team.
  • How much shelf space each product gets, revised a few times a year.

Pick one. They need different predictions (daily demand per store, weekly demand per DC, an order of substitutes, long-run sales rates), and a project that tries to serve all four serves none. Tomás, the data analyst who is moving into data science, picks the nightly store order for three reasons. It runs every night, so gains add up fast. Its formula already exists, so a better forecast can drop in without changing anyone's job. And the stock-out it causes is the one customers see: about 9% of app orders have an item cut today.

Here is today's rule, written down with one store's numbers:

Output
order tonight = 4 days x average daily sales of the last 28 days - stock on hand

Store 117, milk 1 litre
average daily sales, last 28 days   30 units
cover for 4 days                    4 x 30 = 120 units
stock on hand at close              45 units
order tonight                       120 - 45 = 75 units

Look closely and you can see a forecast hidden inside the rule. "Average daily sales of the last 28 days" is a prediction of each of the next four days' demand. That is the part a model can replace. The rest (four days of cover, minus stock on hand) is a policy that supply chain owns. Keep that split clear. If you change the forecast and the policy at once and stock-outs fall, nobody can tell which change worked.

Before going further, write down five answers. Who acts on the prediction? How often? What exactly can they change? What does a wrong prediction cost in each direction? How long is it between deciding and seeing the result? For the store order: the replenishment system, every night, the order quantity, waste and crowded back rooms when it is too high or empty shelves and cut app orders when it is too low, and about a day of .

History sales and stock Forecast days 1 to 4 Order nightly, 22:00 DC delivery next morning Shelf stock on display Sales tills and app features order formula to DC restock censored when shelf is empty logged
The forecast is one step in a loop. When the shelf runs empty, recorded sales stop at what was on display, the next forecast learns a lower number, the next order is smaller, and the shelf empties again.

Quick check

Which part of today's ordering rule should a model replace first?

Target, unit and horizon

Once the decision is fixed, three choices define the prediction. The unit is one row: here one store, one product, one day, because that is the grain at which the order is placed. The target is the number the model outputs for that row: units customers wanted to buy. The horizon is how far ahead you predict. The order goes at 22:00, the truck arrives the next morning, and the order has to cover tomorrow to day 4, so the forecast must cover days 1 to 4 after the order night.

The horizon fixes what you may use. At 22:00 you know sales up to today's close, tonight's stock on hand, promotions planned for next week and the festival calendar. You don't know tomorrow's sales, tomorrow's weather or tomorrow's closing stock. A forecast for day 4 rests on older information than one for day 1, so it is usually worse; in Forecasting demand you will report error per horizon.

tonight 22:00 Known tonight sales up to today stock at close promos, festivals Target window D+1 D+2 D+3 D+4 units per day, tomorrow to day 4 28 days back today time features: left label: right not allowed as input data logged after 22:00
Every prediction has a moment it is made. Features come from the left of the 22:00 line, the label from the right. The truck arrives overnight, so the target window is tomorrow to day 4.

This is : you collect past examples where you know both the inputs and the outcome, and the model learns the link between them. Each training row is one store-product-day from history. The are what was known at 22:00 the night before: sales over the last 28 days, the same weekday last week, day of the week, whether a promotion was planned, days to the next festival. The is what happened: units sold that day. In Mangrove's tables a store or DC is a site and a product is an article, so the history lives in daily_sales(store_id, article_id, sale_date, units_sold).

The shape of the target decides the kind of task. Most business machine learning falls into four kinds:

TaskIt outputsMangrove exampleIn this course
A numberUnits of milk store 117 sells tomorrowds-03, ds-04
A probability for a categoryWill this app customer stop ordering next month?ds-05
RankingAn order for a listWhich substitutes to show first when an item is cutnot covered
A flag on what looks unusualA partner order with an extra zerods-06

Forecasting is regression where the rows are ordered in time. The past predicts the future, and the future must never leak back into the features; Features and leakage is about exactly that.

The same worry can be framed several ways. "Will milk run out at store 117 tomorrow?" is classification. It sounds closer to the problem, but its answer depends on tonight's order, which is the thing you are trying to set, and a yes or no can't tell the formula how many units to order. Demand per day is regression, and it plugs straight into the order. Frame the prediction as the input the decision needs.

Quick check

A colleague proposes a model that predicts "will this product be out of stock at this store tomorrow, yes or no" to improve the nightly order. What is the main problem?

Labels that lie: censored demand

The label is supposed to be what customers wanted. What the data records is what they bought. On most days the two match. On a day the shelf goes empty at 3 pm, they don't: the till records 12 units sold, but customers who came after 3 pm wanted more and left without it. That is : the true number is at least what you saw, and you don't know by how much. For Mangrove's fast movers, about 1 in 9 store-product-days has some out-of-stock time (approximate).

Censored labels do quiet damage. A model trained on raw sales learns that demand is lower than it really is, most of all for the products that run out most often. A low forecast produces a small order, the small order empties the shelf again, and the empty shelf produces another low sale to learn from. That is the dashed arrow in the first diagram. Today's 28-day average has the same flaw, and it is part of why it under-forecasts by about 9%.

You have three options, from cheap to careful:

  • Drop censored days from training and from scoring. It is easy and it removes the worst lies. The catch: stock-outs cluster on the busiest days (festival eves, promotions), so dropping them can remove exactly the peaks the model most needs to learn.
  • Keep them with a lower weight in training, and leave them out when you score the model. The model still sees the busy days, but trusts them less. Don't add "was out of stock that day" as a feature for the day you predict: at 22:00 the night before, nobody knows it yet.
  • Estimate the lost demand. The app gives a direct signal: when an item is cut from an app order, a customer asked for it and didn't get it, so cut app lines are a floor for lost demand. For store sales, scale up from the sales before the shelf emptied. If 12 units sold by 3 pm on a day that usually sells 60% of its units by 3 pm, the full-day demand was about 12 ÷ 0.6 = 20.

How do you know a day was censored? The cleanest signal is on_hand_close in stock_snapshot. If the store closed with stock left, the shelf probably never emptied. It is a proxy, and an imperfect one: with stock accuracy around 82%, some "in stock" days had stock the system believed in that wasn't on the shelf. Write down the rule you used and how many rows it removed, because every later number depends on it. You will build this flag in SQL in the practice task.

Quick check

A store sold 12 loaves of bread by 2 pm, then the shelf was empty for the rest of the day. On normal days it sells about 40% of its bread by 2 pm. What is a fair estimate of that day's demand?

Two metrics: one for the model, one for the business

A model metric tells you how close the forecast is. A business metric tells you whether anything got better. You need both, and you need to agree them before you see any results, so nobody picks the metric that flatters the model afterwards.

For demand forecasts the main model metric in this course is . It adds up every miss, ignoring direction, and divides by the total actual units, so a product that sells 300 units a day counts more than one that sells 2. Pair it with , which keeps the sign and tells you whether you are too high or too low overall. A forecast can have a decent WAPE and still under-order every single day.

Output
day    actual   forecast   |actual - forecast|
Mon      10        12               2
Tue      20        15               5
Wed      30        30               0
sum      60        57               7

WAPE = 7 / 60          = 11.7%
bias = (57 - 60) / 60  = -5.0%   (too low overall)

Why not the familiar MAPE, the average of each row's percentage error? It divides by each row's actual, so a slow mover with 0 units sold makes it divide by zero, and small sellers dominate it. Forecasting demand compares the error measures properly.

The business metric is what the decision owner cares about. For the store order there are three: the out-of-stock rate (the share of store-product-days with an empty shelf at some point), waste (perishables thrown away) and stock on hand (money tied up and back-room space). They pull against each other. You could drive stock-outs to zero by ordering three times as much, and the waste bill would show why that is a bad idea. So report them as a set and agree limits up front, for example "fewer out-of-stock days, with stock on hand up by no more than about 8% and no rise in milk and bread waste".

The two kinds of metric are measured in different places. Model metrics come from : a on history, where you stand at 22:00 on each past night, forecast with only what was known then, and compare with what happened. Features and leakage shows how to split by time without leaking the future. Business metrics need online evaluation: real orders in real stores. At Mangrove that means a store pilot, where 20 stores order from the new forecast and 20 similar stores keep the old rule for several weeks (Experiments: A/B tests, holdouts and store pilots). Offline gains often shrink online. A better forecast doesn't help if the DC can't pick the extra units, the shelf has no room, or the stock waits in the back room.

The baseline, and whether it is worth building

A is the simplest honest prediction, and every model must beat it on the same rows, the same period and the same metric. Use two:

  • Today's rule as a forecast: average daily sales over the last 28 days. The business already runs on it, so it is the bar that matters.
  • : the same weekday last week. It knows nothing but the weekly pattern, which makes it a good test of whether a fancier model learned anything more.

On Tomás's backtest (50 fast-moving products in 20 stores, trained on data up to 30 June 2026 and validated on the eight weeks from 1 July to 25 August), the baselines score like this:

ForecastWAPE, all weeksWAPE, festival weekBias
Same day last week (seasonal naive)39%61%−3%
28-day average (today's rule)34%58%−9% (−41% in the festival week)

The table already shapes the project. The 28-day average beats the seasonal naive overall, because averaging four weeks smooths out noise. Its festival-week bias of −41% shows where the money is: it is slow to notice a jump in demand, so it under-orders exactly when demand peaks. A model has to win there. Later lessons build models to beat these rows, and the best reaches about 24% (Training and comparing models). The rule is plain: a model that doesn't beat the baseline doesn't ship, and a model that beats it by a hair isn't worth a new system to run and watch.

Google's Rules of Machine Learning starts with this rule: "Don't be afraid to launch a product without machine learning." A good rule often gets you most of the value, and it gives you the baseline and the data you will need later. So before building, size the value roughly:

Output
App orders a day                          60,000
with an item cut (about 9%)               about 5,400
share caused by the top fast movers       about 50%   (assumption to check)
share a better forecast removes           about 1/3   (assumption to check)
orders saved from a cut item              about 900 a day

Cost: 2 people for about 6 months at about $5,000 a month each = about $60,000

Every number after the first two is an assumption, so label it and check it. Each saved cut keeps a sale and spares a customer the frustration that makes people stop ordering (ds-05). The store shelves add more value on top, since they serve about 400,000 checkout transactions a day. If the sizing comes out small, or the decision can't change (say the DC can't deliver any more often or any more units), stop here. Picking the right problems for AI covers that choice in general.

Last, write down what would make you stop: a backtest that doesn't beat 34% WAPE by at least a few points, or a pilot that cuts stock-outs only by piling up stock. A project without a stop rule keeps going on hope.

Build it

Write the one-page framing for the store order and compute the two baselines' error in pandas, so the page carries real numbers.

  1. Copy the framing template

    Fill it in with the decision owner, not alone. Leave the numbers blank until step 3.

    Markdown
    # Framing: <project name>
    Decision owner:                 Reviewed with:                 Date:
    
    ## 1. Decision
    What decision changes, who makes it, how often:
    What they can change, and what they cannot:
    Cost of a prediction that is too high / too low:
    
    ## 2. Prediction
    Unit (one row is):
    Target (the number or class we predict):
    Horizon (predicted when, for which period):
    Known at prediction time:
    Task type (regression / classification / ranking / anomaly):
    
    ## 3. Labels
    Where the label comes from:
    When the label lies (censored, late, missing) and what we do about it:
    
    ## 4. Metrics (agreed before any results)
    Model metrics:                  Business metrics and limits:
    Offline test (backtest period): Online test (pilot design):
    
    ## 5. Baselines
    Today's rule as a prediction:   score:
    Simple second baseline:         score:
    
    ## 6. Is it worth it?
    Value if it works (rough, assumptions labelled):
    Cost to build and run:
    
    ## 7. Stop rule
    We stop, or keep the rule, if:
  2. Build both baselines in pandas

    The table must have one row per store, product and day, with 0 on days nothing sold; if yours skips zero days, fill them first, or a window of 28 rows won't be 28 days. shift(1) makes the window end yesterday, so the day being predicted never sits inside its own forecast.

    Python
    import pandas as pd
    
    # daily_sales: store_id, article_id, sale_date, units_sold (zero days included)
    sales = pd.read_parquet("daily_sales.parquet")
    sales["sale_date"] = pd.to_datetime(sales["sale_date"])
    sales = sales.sort_values(["store_id", "article_id", "sale_date"])
    
    units = sales.groupby(["store_id", "article_id"])["units_sold"]
    
    # Today's rule as a forecast: mean of the 28 days BEFORE the day predicted
    sales["baseline_28d"] = units.transform(
        lambda s: s.shift(1).rolling(28, min_periods=28).mean()
    )
    
    # Seasonal naive: the same weekday last week
    sales["naive_7d"] = units.shift(7)

    This is the forecast for the day after the order night. For day 4 the window ends four days earlier, so the same code with shift(4) gives the day-4 forecast.

  3. Flag usable labels and score on the same rows

    Join the closing stock, keep in-stock days in the validation weeks, and score both baselines on exactly the same rows.

    Python
    stock = pd.read_parquet("stock_snapshot.parquet")
    stock["sale_date"] = pd.to_datetime(stock["snapshot_date"])
    
    df = sales.merge(
        stock[["store_id", "article_id", "sale_date", "on_hand_close"]],
        on=["store_id", "article_id", "sale_date"], how="left",
    )
    df["usable"] = df["on_hand_close"] > 0   # no snapshot: NaN > 0 is False
    
    def wape(actual, forecast):
        return (actual - forecast).abs().sum() / actual.sum()
    
    def bias(actual, forecast):
        return (forecast.sum() - actual.sum()) / actual.sum()
    
    in_valid = df["sale_date"].between(pd.Timestamp("2026-07-01"), pd.Timestamp("2026-08-25"))
    valid = df[in_valid & df["usable"]].dropna(subset=["baseline_28d", "naive_7d"])
    
    for col in ["baseline_28d", "naive_7d"]:
        print(f"{col:13} WAPE {wape(valid.units_sold, valid[col]):.1%}"
              f"  bias {bias(valid.units_sold, valid[col]):+.1%}")

    On Tomás's 50 products in 20 stores the output is close to the course's backtest table:

    Output
    baseline_28d  WAPE 34.2%  bias -8.9%
    naive_7d      WAPE 38.8%  bias -3.1%
  4. Finish the page and review it

    Put the baseline scores in section 5, write the value sizing with every assumption labelled, and agree the stop rule with the decision owner. Then ask one question out loud: "If the model hits this number, will you change the order?" If the answer is no, find out why before you write another line of code.

Bring it to your team

Ask these when someone proposes a model, before any work starts.

  • Which decision will this change, who owns it and how often is it made?
  • What exactly do we predict: one row is what, the target is what, and for which days ahead?
  • What do we know at the moment of prediction, and what do we only learn later?
  • How do we treat days when the shelf was empty?
  • What are the baseline's WAPE and bias on the same backtest, and by how much must we beat them?
  • Which business metrics and limits have we agreed, and what result would make us stop?

Red flags

  • "Let's see what the data tells us", with no decision named.
  • A model accuracy number with no baseline next to it.
  • Labels taken straight from sales, with no word about stock-outs.
  • Only a model metric, or only a business metric.
  • A plan to switch all 320 stores at once, with no pilot.

Practice

Find the usable labels and measure the censoring

Two tables: daily_sales(store_id, article_id, sale_date, units_sold) and stock_snapshot(store_id, article_id, snapshot_date, on_hand_open, on_hand_close). A day is a usable label when the snapshot for that same store, product and date exists and its on_hand_close is above 0. Days with no snapshot are not usable. Return one row per store and product with store_id, article_id, days (all sales days), usable_days, avg_all (average units sold over all days) and avg_usable (average over usable days only), both averages rounded to one decimal. FILTER on an aggregate helps; it is covered in SQL you'll actually use.

SQL exerciseRuns in a real PostgreSQL inside your browser
-- One row per store and product: all days, usable days, and both averages
SELECT store_id, article_id,
       count(*) AS days,
       round(avg(units_sold)::numeric, 1) AS avg_all
FROM daily_sales
GROUP BY store_id, article_id;
Ctrl + Enter runs
Show a solution
SQL
SELECT s.store_id, s.article_id,
       count(*) AS days,
       count(*) FILTER (WHERE k.on_hand_close > 0) AS usable_days,
       round(avg(s.units_sold)::numeric, 1) AS avg_all,
       round(avg(s.units_sold) FILTER (WHERE k.on_hand_close > 0)::numeric, 1) AS avg_usable
FROM daily_sales s
LEFT JOIN stock_snapshot k                -- LEFT keeps days with no snapshot
  ON  k.store_id = s.store_id             -- join on all three keys, or store 2's
  AND k.article_id = s.article_id         -- milk rows double up store 1's
  AND k.snapshot_date = s.sale_date
GROUP BY s.store_id, s.article_id;

A missing snapshot leaves on_hand_close NULL, and NULL > 0 is not true, so store 2's 4 July drops out of the usable count without any extra code. Look at store 1's milk: 25.3 units a day over all days, 30.5 over usable days. The two empty-shelf days pull the plain average down by about 17%, which is the censoring a model would learn. Even 30.5 may be low if the empty days were the busiest ones. Bread at store 1 never ran out, so both averages agree.

Pass the exercise to finish this task.

Frame "flag unusual partner orders"

The sales team asks for "AI to catch wrong partner orders". About 1,800 partner shops place about 4,000 orders a week. Some lines are mistakes: an extra zero, or cases typed as units. Today a rule flags a line when the quantity is more than 3 times the shop's 8-week median for that product. It flags about 40 lines a week, and when sales reps call the shops, about half turn out to be real mistakes. Write a short framing using the template sections: decision, prediction (unit, target, timing, task type), labels, metric pair, baseline, value and stop rule.

  • You name the decision (a rep calls the shop before the DC picks the order) and who acts on the flag
  • You define the unit (one order line) and the target (was it a mistake), and say whether it is classification with labels or anomaly detection without
  • You say where labels come from (rep calls, corrections after delivery) and that unflagged lines are never checked, so their labels are missing
  • You pair a model metric (precision of flags, mistakes found) with a business metric (lines corrected after delivery, rep time)
  • You use the 3× median rule (about 40 flags a week, about half real) as the baseline, and say what a model must show to replace it
Show a model answer
Markdown
Decision: a sales rep calls the shop to confirm a flagged line before the DC
  picks the order. Owner: the sales team lead. Every order, every day.
Unit: one order line (shop, product, order). Target: was the line a mistake?
Timing: scored when the order arrives, before picking. Known then: the shop's
  past orders, the product's pack sizes, the shop's 8-week median.
Task: classification if we keep the outcome of rep calls as labels; anomaly
  detection while we have almost none.
Labels: rep call outcomes and corrections after delivery. Lines nobody flagged
  are never called, so we only learn about mistakes the rule already catches.
Model metric: precision (share of flags that are real mistakes) and mistakes
  found per week. Business metric: lines corrected after delivery, rep minutes.
Baseline: the 3x median rule, about 40 flags a week, about 20 real (50%).
Value: each mistake caught saves a return trip and a credit note.
Stop rule: if a model can't find clearly more mistakes for about 40 calls a week,
  or keep the same catches with fewer calls, we keep the rule.

The label problem is the one most people miss: only flagged lines get checked, so a model trained on today's labels mostly learns the rule back. A small random sample of unflagged lines checked each week fixes that. You will see in Explaining and choosing models how this case ends.

Check yourself

Marketing asks for "a churn model" for the app. What should you ask first?

On the same 8-week backtest, Tomás's first model scores WAPE 33% against the 28-day average's 34%. Its bias is −8% and its festival-week WAPE is 57%. What is the best reading?

In a store pilot, the new forecasts for the products that run out most often keep coming in below what the stores could have sold. Which cause is most likely?

Flashcards

Open my review

Key takeaways

  • A prediction is an input to a decision. Name the decision, its owner and its rhythm before choosing any data or model.
  • Define the unit, the target and the horizon, and use only what is known at the moment of prediction.
  • Sales are censored demand on empty-shelf days. Drop, down-weight or rebuild those labels, and write down which.
  • Agree a model metric (WAPE and bias) and business metrics (stock-outs, waste, stock held) before seeing results; test offline, then in a pilot.
  • Every model must beat today's rule on the same backtest by a margin worth the cost. Size the value roughly and write a stop rule.

Sources and further reading

Episode transcriptOne email, one decision, one page · about 12 minutes · tap any line to play from there
  1. NadiaImran, I heard leadership gave you a new project this week.
  2. ImranThey did. One line in an email. Use AI to fix out-of-stocks. After the festival week we had, I can't blame them.
  3. NadiaAnd what did you do with that line?
  4. ImranMy first thought was to ask Tomás which algorithm he'd use. I'm guessing that's the wrong first question.
  5. NadiaIt's the most common one. Today we'll turn that email into something a model can work on, and see when the honest answer is a better rule.
  6. NadiaStart with a weather forecast. On its own it changes nothing. It matters because someone acts on it. You take an umbrella. A farmer brings the harvest in early. A fishing crew stays in port.
  7. ImranAnd each of them needs something different from the forecast.
  8. NadiaExactly. You need the chance of rain this afternoon. The farmer needs the total rain over three days. The crew needs the wind at sea at dawn. Same sky, three predictions, because there are three decisions.
  9. ImranAnd forecasters get judged against something?
  10. NadiaAgainst simple rules, like tomorrow will be like today. If you can't beat that, you don't broadcast. And the costs are lopsided. A spare umbrella costs little. Getting soaked on the way to an interview costs a lot.
  11. ImranSo start from the decision, predict what the decision needs, and prove you beat the simple rule.
  12. NadiaThat's the lesson in one sentence. Let's take the first part properly. Which decisions does out-of-stocks touch at Mangrove?
  13. ImranSeveral. The nightly order each store sends to its distribution centre. The weekly purchase orders to suppliers. Which substitute the app offers when an item is cut. And shelf space.
  14. NadiaFour decisions, four owners, four rhythms. Pick one. Tomás picked the nightly store order. It runs every night, the formula already exists, and its stock-outs are the ones customers see. About nine percent of app orders have an item cut today.
  15. ImranRemind me what the formula is.
  16. NadiaFour days of cover at the average daily sales of the last twenty-eight days, minus stock on hand. For milk at store one seventeen, that's four times thirty, so a hundred and twenty, minus forty-five on hand. Order seventy-five.
  17. ImranAnd where's the forecast in that?
  18. NadiaThe twenty-eight day average. It's a prediction of each of the next four days. That's the part a model replaces. The four days of cover is a policy, and supply chain owns it.
  19. ImranSo I shouldn't change both at once.
  20. NadiaRight. If you change the forecast and the policy together and stock-outs fall, nobody knows which change worked.
  21. NadiaIf you can see the screen, the first diagram is a loop of six boxes. History feeds a forecast, the forecast sets the order, the order goes to the DC, the truck refills the shelf, the shelf makes sales, and sales become history again.
  22. ImranOne arrow is dashed, between the shelf and the sales. It says censored when the shelf is empty.
  23. NadiaThat's the label problem. The data records what people bought. What you want to predict is what they wanted. Shelf empty at three in the afternoon, the till says twelve sold, and people who came at five left with nothing.
  24. ImranSo the true demand was at least twelve, and we don't know how much more.
  25. NadiaThat's censored demand. For fast movers, roughly one store product day in nine has some out-of-stock time. And it feeds itself. Low sales teach a low forecast, the order gets smaller, and the shelf empties again.
  26. ImranWhat do you do about it?
  27. NadiaThree options. Drop those days from training and scoring. Keep them with a lower weight. Or estimate the lost demand. The app helps there. Every cut item is a customer who asked for something and didn't get it.
  28. ImranDropping them sounds easiest. What's the catch?
  29. NadiaStock-outs bunch up on the busiest days. Festival eves, promotions. Drop them and you can drop the exact peaks you most need the model to learn.
  30. ImranHow do you even know the shelf was empty?
  31. NadiaThe stock snapshot. If the store closed with stock left, the shelf probably never emptied. It's a proxy. Stock accuracy is about eighty-two percent, so some of those in-stock days weren't. Write down the rule you used and how many rows it removed.
  32. ImranOkay. So what exactly is the model predicting?
  33. NadiaThree choices. The unit is one row, so one store, one product, one day. The target is units customers wanted. The horizon is how far ahead. The order goes at ten at night, the truck comes in the morning, and the order has to cover tomorrow to day four.
  34. NadiaThe second diagram is a timeline. A dashed line marks tonight at ten. To its left, what you know: sales up to today, stock at close, planned promotions and festivals. To its right, four boxes, day one to day four. That's the target.
  35. ImranAnd anything logged after ten o'clock can't be an input.
  36. NadiaRight. Features come from the left of the line, the label from the right. The next lesson is all about what happens when something sneaks across.
  37. ImranWhy not predict will it run out, yes or no? That sounds closer to the problem.
  38. NadiaGood instinct, wrong fit. Whether it runs out depends on tonight's order, which is the thing you're trying to set. And a yes or no can't tell the formula how many units to order. Forecast demand, a number. That's regression.
  39. ImranAnd classification is for questions like will this customer stop ordering.
  40. NadiaYes, that comes later in the course. Ranking puts a list in order, like which substitutes to show first. Anomaly detection flags the odd one out, like a partner order with an extra zero.
  41. ImranMetrics, then. How will we know it's better?
  42. NadiaTwo kinds, agreed before you see any results. A model metric and a business metric. The model metric here is WAPE, weighted absolute percentage error. Add up every miss, ignoring direction, and divide by the total actual units.
  43. ImranSo a product selling three hundred a day counts more than one selling two.
  44. NadiaYes. And pair it with bias, which keeps the sign. Total forecast minus total actual, divided by total actual. A forecast can have a decent WAPE and still under-order every single day.
  45. ImranAnd the business side is stock-outs.
  46. NadiaStock-outs, waste and stock on hand, as a set. You could get stock-outs to zero by ordering three times as much. The waste bill would tell you why that's a bad idea. So agree the limits up front.
  47. ImranAnd where does each one get measured?
  48. NadiaThe model metric offline, in a backtest. You stand at ten o'clock on each past night, forecast with only what was known, and compare. The business metrics need a pilot. Twenty stores on the new forecast, twenty similar stores on the old rule.
  49. ImranWhich brings us to the bar we have to clear.
  50. NadiaThe baseline. Two of them. Today's rule as a forecast, the twenty-eight day average. And seasonal naive, which is the same weekday last week.
  51. ImranTomás ran both. Fifty fast movers in twenty stores, eight weeks of validation. Same day last week scored thirty-nine percent WAPE. The twenty-eight day average scored thirty-four, with a bias of minus nine percent.
  52. NadiaAnd in the festival week?
  53. ImranA bias of minus forty-one percent. It under-ordered badly, right when demand jumped.
  54. NadiaThat's where the money is. A model that doesn't beat thirty-four percent doesn't ship. And one that beats it by a hair isn't worth a new system to run and watch.
  55. ImranGoogle's Rules of Machine Learning say something like that, don't they?
  56. NadiaRule one. Don't be afraid to launch a product without machine learning. A good rule gets you a long way, and it becomes your baseline.
  57. ImranSo here's what Tomás and I sent back to leadership. One page. The decision is the nightly store order, owned by supply chain. The target is demand per store, product and day, for days one to four, with stock-out days flagged.
  58. NadiaAnd the metric pair?
  59. ImranWAPE and bias on the backtest, then stock-outs, perishable waste and stock on hand in a twenty-store pilot. Baselines at thirty-four and thirty-nine percent.
  60. NadiaAnd the value?
  61. ImranAbout five thousand four hundred app orders a day have a cut item. If the top fast movers cause half, and a better forecast removes a third, that's roughly nine hundred fewer orders a day with a cut item. Both of those are assumptions we have to check.
  62. NadiaAnd the line that made the supply chain lead say yes?
  63. ImranThe stop rule. If the backtest doesn't beat thirty-four percent by at least four points, or the pilot only cuts stock-outs by piling up stock, we stop.
  64. NadiaA project without a stop rule keeps going on hope.
  65. NadiaThe Build it section turns all this into practice. You copy a one-page template with seven parts, from the decision to the stop rule, and fill it in with the decision owner.
  66. ImranThen the pandas part.
  67. NadiaYou sort daily sales by store, product and date. For each store and product, you shift by one day and take a rolling twenty-eight day mean, so the window ends yesterday. A shift of seven days gives the same weekday last week.
  68. ImranAnd then you score them.
  69. NadiaJoin the closing stock, keep only in-stock days in the validation weeks, and score both baselines on exactly the same rows. Every later model in the course gets scored that way.
  70. ImranAnd the practice has a SQL version of the censoring check.
  71. NadiaIt does. Per store and product, you compute the average sales over all days and over in-stock days only. For one milk product the plain average is about twenty-five, and the in-stock average is about thirty and a half.
  72. ImranSo the empty-shelf days drag the average down by about seventeen percent.
  73. NadiaHere's one to think about. Marketing asks you for a churn model. What's your first question? Take a second.
  74. ImranWhich decision will the prediction change, who acts on it, and how often. Coupons, phone calls, or nothing at all.
  75. NadiaExactly. Until you know that, you can't pick the time window, the metric or the threshold.
  76. ImranMy takeaways. One, a prediction is an input to a decision, so name the decision and its owner first. Two, sales lie on empty-shelf days, so handle those labels on purpose. Three, beat today's rule on the same backtest, by enough to be worth it, or keep the rule.
  77. NadiaGood. I'd add the stop rule. Write down what would end the project before you start, while everyone is still calm.
  78. ImranAnd next time?
  79. NadiaFeatures and leakage. Why a first model that scores six percent WAPE is a reason to worry.
Finished reading?Mark it complete to fill in its stop on your course line.

Use it at work

Simple forecast

A trend plus weekly pattern fitted to daily sales, the next 4 weeks forecast and a check against the last weeks.

Open in the Data Lab
Next stopFeatures and leakage
Was this lesson helpful?
Questions and discussion

Loading the discussion…