Define a baseline
- Lesson 6
- 70 min
- Module 2: Frame the prediction problem
Lesson 6 of 27 · Machine Learning: From Problem to Reliable ModelDefine a baseline
1. Understand machine learning
2. Frame the prediction problem
3. Evaluate supervised models
4. Build the first models
5. Try other model families
6. Tune and finish the model
7. Understand and choose the model
8. Prepare the model for handoff
What you will be able to do
Measure the simplest predictions before you train any model, and write down the result that a model must reach. Without a baseline, a score of 84.5% sounds good, even when the model catches nothing.
NotebookDo this lesson in a notebook
The notebook computes every baseline on this page, first on ten tickets and then on the 1,179 May tickets. You also test one more rule and fill in the modelling brief. Its setup cells install pandas and scikit-learn and download the practice data, so it needs no local setup. About 30 minutes.
Colab and Kaggle open your own copy. They need a free Google or Kaggle account. Stuck? See the solution notebook.
Before you startWhat to know and to have ready
What you need to know
- The decision, the capacity of 20% and the two kinds of error. Recall and precision in words. Both from Translate a need: From the decision to the metric.
- Classification, and the answers that need no model (a rule), from Choose the learning task.
- Virtual environments and
requirements.txt, from Isolate dependencies in Python for Practical AI Engineering. Notebooks and their kernel, from Notebook discipline in the Python course. You need them only for the local project.
What you need on your computer (only for the local route; the notebook needs none of it)
- Python 3.12 or later, from Install and verify Python in the Python course.
- VS Code, from Install and verify Python: Step 3: get a code editor.
- An internet connection, and about 500 MB of free disk space: the environment uses about 450 MB on macOS, and the data 2.5 MB. No account.
- This lesson makes the project folder
~/projects/ticket-model, in Set up your project. Every later lesson of the course can use it.
Tested on macOS. The setup used Python 3.14.6, pandas 3.0.6, scikit-learn 1.9.1, matplotlib 3.11.2 and ipykernel 7.4.0. The Windows and Linux commands are not tested. The notebook was tested in Jupyter.
Before you buy a weather app
Section titled “Before you buy a weather app”Imagine a weather app that costs money and promises: “Our forecast for tomorrow is right 70% of the time.” Is that good? You cannot tell yet. Try the simplest forecast that anyone can make for free: “tomorrow will be like today”. In many places, that free forecast is right on most days, because the weather changes slowly. If it is right 65% of the time, the expensive app adds only a little. If it is right 80% of the time, the app is worse than doing nothing clever at all.
The same question comes before every model. A number such as 70%, or 84.5%, means nothing alone. It means something only next to what you get with no model at all. So before you train anything, you measure the simplest predictions on the same data and with the same measures. These simple predictions are the baselines, and every model in this course is compared with them.
What a baseline is
Section titled “What a baseline is”A baseline is the simplest prediction that anyone can make without a model. It needs no learning, or only one number learned from the train set. You measure it first, on the same data and with the same measures as the model. Then every model result has a reference: a model is useful only if it does clearly better than its baselines. A baseline that is hard to beat is also useful news, because then a simple rule may be the right answer.
For Larkfield’s yes/no question, two baselines make a flag for each ticket:
- Majority class: always predict the most common answer. Most tickets do not escalate, so this baseline never flags. It is the “tomorrow will be like today” of classification: it costs nothing and is often right.
- A rule: flag the tickets with priority 1. It uses one fact that the support team already trusts.
Ten tickets, counted by hand
Section titled “Ten tickets, counted by hand”Here are ten made-up tickets. Two of them escalated: T-1 and T-5.
| Ticket | Priority | Team | Escalated |
|---|---|---|---|
| T-1 | 1 | payment | 1 |
| T-2 | 3 | delivery | 0 |
| T-3 | 2 | returns | 0 |
| T-4 | 1 | delivery | 0 |
| T-5 | 2 | warranty | 1 |
| T-6 | 3 | account | 0 |
| T-7 | 2 | delivery | 0 |
| T-8 | 3 | returns | 0 |
| T-9 | 1 | account | 0 |
| T-10 | 2 | payment | 0 |
The majority class never flags, so it lets both escalations through. It is right on the 8 tickets that did not escalate, so it is right 8 times out of 10. The rule flags T-1, T-4 and T-9. T-1 escalated, so the rule caught it. T-4 and T-9 did not escalate, so they are two false alarms: unnecessary reviews. T-5 escalated without a flag, so the rule missed it. The other 6 tickets were correctly left alone. So the rule is right 7 times out of 10.
From these four counts come three shares, which you met in words in the last lesson:
- Recall: how many of the escalations did we catch? The rule caught 1 of the 2, so its recall is 0.5. The majority class caught none: 0.
- Precision: how many of the flagged tickets really escalated? 1 of the rule’s 3 flags did: 0.333. The majority class flags nothing, so it has no precision.
- Accuracy: on how many tickets was the flag (or the absence of a flag) right? 8 of 10 for the majority class, 7 of 10 for the rule.
The table puts the counts side by side:
| Majority: never flag | Rule: priority 1 | |
|---|---|---|
| Caught (flagged, escalated) | 0 | 1 (T-1) |
| False alarms (flagged, did not escalate) | 0 | 2 (T-4, T-9) |
| Missed (not flagged, escalated) | 2 (T-1, T-5) | 1 (T-5) |
| Correctly left (not flagged, did not escalate) | 8 | 6 |
| Recall: caught ÷ escalations | 0 ÷ 2 = 0 | 1 ÷ 2 = 0.5 |
| Precision: caught ÷ flagged | none flagged | 1 ÷ 3 = 0.333 |
| Accuracy: right ÷ all tickets | 8 ÷ 10 = 0.8 | 7 ÷ 10 = 0.7 |
Look at the last row. The majority class never helps Grace, and it has the higher accuracy. The rule catches one of the two escalations, and it has the lower accuracy. Keep this in mind for the real data. Classification metrics gives these four counts their standard names and explains why accuracy behaves like this.
A constant score
Section titled “A constant score”The models of this course do not give a plain yes or no. They give each ticket a score from 0 to 1, where a higher score means “more likely to escalate”. The senior team then reviews the tickets with the highest scores. So a score needs its own baseline: the constant score, which gives every ticket the same score. A natural choice is the escalation rate of the train set.
Two measures judge a score before any cut into yes and no. The precision–recall trade-off explains both. For now, one sentence each is enough:
- ROC AUC: the chance that a random escalated ticket gets a higher score than a random other ticket. 0.5 is guessing, and 1.0 is a perfect ranking.
- Average precision (AP): how good the precision is as you go down the list of tickets, from the highest score. For a score that cannot rank the tickets at all, it equals the escalation rate.
On the ten tickets, the constant score gives every ticket 0.2, their escalation rate. With the same score for every ticket, no escalated ticket can be above another ticket. So ROC AUC is 0.5, and AP is 0.2, the rate. That is the floor for every model: ROC AUC above 0.5, and AP above the escalation rate.
Worked example: Priya’s baselines for May
Section titled “Worked example: Priya’s baselines for May”Priya computes the baselines on the validation set, the 1,179 May tickets. (Train, validation and test sets explains why a result is measured on tickets that played no part in learning.) Each baseline learns only from train: the most common class and the escalation rate come from the train tickets, and the rule needs no data. Each code block is a cell of the lesson notebook, where the setup cells have already loaded pandas as pd and numpy as np.
First, she writes a function that counts the four kinds of result and computes the shares. It is the hand count above, in code:
def flag_report(y, flags): """Compare 0/1 flags with the real 0/1 answers: four counts and four shares.""" y = np.asarray(y, dtype=bool) flags = np.asarray(flags, dtype=bool) caught, false_alarms = int((flags & y).sum()), int((flags & ~y).sum()) missed, correctly_left = int((~flags & y).sum()), int((~flags & ~y).sum()) return {"flagged": caught + false_alarms, "share flagged": round((caught + false_alarms) / len(y), 3), "caught": caught, "false alarms": false_alarms, "missed": missed, "correctly left": correctly_left, "precision": round(caught / (caught + false_alarms), 3) if caught + false_alarms else None, "recall": round(caught / (caught + missed), 3), "accuracy": round((caught + correctly_left) / len(y), 3)}On the ten tickets, it gives the numbers of the table above. Then she loads the data. read() is the same function as in Translate a need:
TARGET = "escalated_72h"train = read("data/train.csv")valid = read("data/valid.csv")majority_class = train[TARGET].mode()[0]train_rate = round(train[TARGET].mean(), 3)print("Most common class in train:", majority_class, " train escalation rate:", train_rate)The output:
Most common class in train: 0 train escalation rate: 0.117Before she runs the next cell, Priya asks Omar to predict which baseline has the higher accuracy. He says: “The rule, of course. It finds escalations.”
y = valid[TARGET]baselines = pd.DataFrame([flag_report(y, [majority_class] * len(valid)), flag_report(y, valid["priority"] == 1)], index=["majority: never escalate", "rule: flag priority 1"])baselinesThe output:
flagged share flagged caught false alarms missed correctly left precision recall accuracymajority: never escalate 0 0.000 0 0 183 996 NaN 0.000 0.845rule: flag priority 1 163 0.138 61 102 122 894 0.374 0.333 0.810Read it row by row:
- Never escalate is right on 996 of the 1,179 tickets: an accuracy of 84.5%. It catches none of the 183 escalations. Its precision is
NaN(not a number), because it flags nothing, and 0 ÷ 0 has no value. - Flag priority 1 flags 163 tickets, 13.8%, which is inside the capacity of 20%. Of its flags, 61 escalated, so its precision is 0.374. It catches 61 of the 183 escalations, so its recall is 0.333: one in three. Its accuracy, 81.0%, is lower than the useless baseline’s.
Omar was wrong, as most people are the first time. The failure case below shows the trap, and Classification metrics explains it in full. Last, Priya tries the constant score, with the train rate 0.117 for every May ticket. The two metric functions come from sklearn.metrics; the notebook imports them in section 2:
constant_scores = [train_rate] * len(valid)print("ROC AUC:", roc_auc_score(y, constant_scores))print("Average precision:", round(average_precision_score(y, constant_scores), 3))print("Escalation rate in valid:", round(y.mean(), 3))The output:
ROC AUC: 0.5Average precision: 0.155Escalation rate in valid: 0.155So a model’s ROC AUC must be above 0.5, and its AP above 0.155, on May. The three baselines, together:
| Baseline (on valid, May 2026) | Flagged | Precision | Recall | Accuracy |
|---|---|---|---|---|
| Majority class: never escalate | 0 (0%) | — | 0.000 | 0.845 |
| Rule: flag priority 1 | 163 (13.8%) | 0.374 | 0.333 | 0.810 |
| Constant score 0.117 (the train rate) | — | ROC AUC 0.5; AP 0.155 (the rate) |
The improvement target
Section titled “The improvement target”A baseline says where you start. An improvement target says what result makes a model worth using. Write it in the terms of the decision, and write it before you see any model’s score. If you write it afterwards, it is too easy to move the target until it fits the result.
Grace’s decision gives two conditions. The senior team can review at most 20% of new tickets. Inside that limit, the rule already catches 33% of the escalations. A model must catch clearly more, or the rule is enough. Grace and Priya agree on this target:
Flag at most 20% of new tickets (the capacity), and catch at least 40% of escalations (the rule catches 33%).
In the words of the last lesson: the share flagged must be at most 20%, and the recall must be at least 40%. Neither baseline meets the target:
| Share flagged (at most 20%) | Recall (at least 40%) | Meets the target | |
|---|---|---|---|
| Never escalate | 0% | 0.000 | No |
| Flag priority 1 | 13.8% | 0.333 | No: it catches too few |
Every model in this course must meet this target. You check it on the validation set while you work, and on the test set once, at the end. In the notebook, the function meets_target() checks it:
def meets_target(report): """True if the flags fit the capacity (at most 20%) and catch at least 40%.""" return report["share flagged"] <= 0.20 and report["recall"] >= 0.40
rule = flag_report(y, valid["priority"] == 1)print("Rule meets the target:", meets_target(rule))The output:
Rule meets the target: FalseSet up your project
Section titled “Set up your project”You can do the whole course in the lesson notebooks, in Colab or Kaggle, with no installation. In Module 8, you also need files and commands on your computer, because a model handoff is files and commands. This section makes that local project now, so that it is ready. It takes about 15 minutes. If you use only the notebooks for now, go on to Guided practice, and come back before Module 8.
At the end, you have this folder:
ticket-model/ .venv/ the virtual environment requirements.txt the packages and their versions get_data.py downloads and checks the data data/ train.csv valid.csv test.csv and five more filesCheck Python
Section titled “Check Python”Open a terminal, and check the Python version. You need 3.12 or later.
python3 --versionpython --versionpython3 --versionYou should see Python 3.12 or a higher number, for example Python 3.14.6. If you see Python 3.11 or lower, or “command not found”, install Python as in Install and verify Python.
Make the project folder
Section titled “Make the project folder”-
Make the folder
~/projects/ticket-model, and go into it:Terminal window mkdir -p ~/projects/ticket-modelcd ~/projects/ticket-modelTerminal window mkdir ~\projects\ticket-modelcd ~\projects\ticket-modelIf the folder already exists,
mkdirshows an error. You can ignore it.Terminal window mkdir -p ~/projects/ticket-modelcd ~/projects/ticket-model -
Check where you are. Run
pwd. The path ends withprojects/ticket-model(on Windows,projects\ticket-model).
Run every command in the rest of the course in this folder.
Make the environment
Section titled “Make the environment”A virtual environment keeps this project’s packages apart from every other project, as in Isolate dependencies in the Python course.
-
Make the environment:
Terminal window python3 -m venv .venvTerminal window python -m venv .venvTerminal window python3 -m venv .venv -
Activate it:
Terminal window source .venv/bin/activateTerminal window .venv\Scripts\Activate.ps1If PowerShell says that running scripts is disabled, run
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUseronce. Then activate again. Isolate dependencies in the Python course explains this error.Terminal window source .venv/bin/activateIf the output says that
ensurepipis not available, runsudo apt install python3-venvfirst. Then make the environment again. -
Check that the prompt starts with
(.venv). From now on, typepythonon every system.
Install the packages
Section titled “Install the packages”-
In VS Code, open the folder
ticket-model(File › Open Folder). -
Make a new file
requirements.txtin it, with these four lines:requirements.txt pandas==3.0.6scikit-learn==1.9.1matplotlib==3.11.2ipykernel -
Save the file.
-
In the terminal, install the packages:
Terminal window python -m pip install -r requirements.txtIt takes one or two minutes. The last line starts with
Successfully installed, and the list includespandas-3.0.6andscikit-learn-1.9.1. If pip also says that a new version of pip is available, you can ignore it. -
Check the versions:
Terminal window python -c "import pandas, sklearn; print(pandas.__version__, sklearn.__version__)"You should see
3.0.6 1.9.1.
Why each line: pandas reads and changes tables, and scikit-learn has the models and the metrics. matplotlib draws the charts in the notebooks. ipykernel lets VS Code run a notebook with this environment’s Python. The first three have an exact version (==), so your numbers match the lessons. In Module 8, you add two more exact versions, because a saved model needs them.
Download the data
Section titled “Download the data”Mei’s script get_data.py downloads the eight data files and checks each file’s checksum. It uses only Python’s standard library.
-
Download the script into the project folder:
Terminal window curl -fsSL -O https://raw.githubusercontent.com/Nextia-Intelligence/nextia-learning-labs/main/C05/get_data.pyTerminal window curl.exe -fsSL -O https://raw.githubusercontent.com/Nextia-Intelligence/nextia-learning-labs/main/C05/get_data.pyType
curl.exe, notcurl. In Windows PowerShell,curlis a different command.Terminal window curl -fsSL -O https://raw.githubusercontent.com/Nextia-Intelligence/nextia-learning-labs/main/C05/get_data.pyIf the output is
curl: command not found, runsudo apt install curl(orsudo dnf install curl) first. -
Run it:
Terminal window python get_data.pyThe output:
Downloaded train.csvDownloaded valid.csvDownloaded test.csvDownloaded split_manifest.jsonDownloaded extra_features.csvDownloaded daily_tickets.csvDownloaded july_tickets.csvDownloaded july_labels.csvReady: train 16939 rows (1983 escalated), valid 1179 (183), test 1002 (157). -
Run it a second time. Now it prints only the
Ready:line, because every file is there and correct.
The last line is the check. Train has 16,939 tickets with 1,983 escalations. May has 1,179 with 183, and June has 1,002 with 157. If a file is broken or different, get_data.py downloads that file again.
Open a notebook in VS Code
Section titled “Open a notebook in VS Code”The lesson notebooks also run on your computer, with the environment that you just made.
- In VS Code, install the Python and Jupyter extensions from Microsoft (View › Extensions, then search for each name).
- Make a folder
notebooksin the project. - Download a lesson notebook into it. Use View on GitHub in the notebook box of a lesson, then the download button.
- Open the notebook in VS Code.
- Select Select Kernel › Python Environments, then the entry with
.venv. - Run the cells from the top, as in Colab.
The setup cells of a lesson notebook work in their own folder ticket-model, next to the notebook, and download their own copy of the data there. This keeps each notebook self-contained, and it never changes your project’s data/.
To check the environment in a notebook, make a new notebook with File › New File, then Jupyter Notebook. Save it in the project folder, select the .venv kernel, and run this cell:
import pandas as pd, sklearnprint("pandas", pd.__version__, " scikit-learn", sklearn.__version__)train = pd.read_csv("data/train.csv")print(len(train), "train tickets,", train["escalated_72h"].sum(), "escalated")The output:
pandas 3.0.6 scikit-learn 1.9.116939 train tickets, 1983 escalatedIf you see ModuleNotFoundError: No module named 'sklearn', the notebook uses another Python. Select the .venv kernel again (step 5). If you see FileNotFoundError for data/train.csv, the notebook is not in the project folder: save it in ticket-model, next to data/.
Or use Colab or Kaggle
Section titled “Or use Colab or Kaggle”You do not need any of the above for the lesson notebooks. In the notebook box of a lesson, select Open in Colab (a free Google account) or Open in Kaggle (a free Kaggle account). The notebook’s first cells install the same versions of pandas and scikit-learn and download the data. In Kaggle, turn on Internet in the notebook settings first; Kaggle asks for a verified phone number for this.
Reset the project
Section titled “Reset the project”To get back to a known state:
- Data: run
python get_data.py --reset. It deletesdata/and downloads every file again. The last line is theReady:line above. - Environment: close the terminal, delete the folder
.venv, and do Make the environment and Install the packages again.requirements.txtstays. - A project file from a later lesson: copy the course’s finished file from C05/project. Its README says which lesson writes each file.
Guided practice: the baselines in the notebook
Section titled “Guided practice: the baselines in the notebook”- Open the notebook from the box Do this lesson in a notebook at the top of this page. Or open it in VS Code with the
.venvkernel, as in Open a notebook in VS Code. - Run the setup cells. The data cell ends with the
Ready:line. - In section 1, work out the accuracy of both baselines on the ten tickets by hand. Then run the cell. You see
0.8for the majority and0.7for the rule. - In section 2, run the constant score on the ten tickets. You see
ROC AUC: 0.5andAverage precision: 0.2. - In section 3, write your prediction, then run the real baselines. You see accuracy
0.845and recall0.000for the majority, and163flagged with recall0.333for the rule. - Run the constant score on May. You see
Average precision: 0.155. - In section 4, run
meets_target(). You seeRule meets the target: False.
Your turn: Grace’s rule
Section titled “Your turn: Grace’s rule”Change one thing: the rule. Grace says: “Since the new warranty policy of 1 May, warranty tickets escalate more. Flag priority 1 or warranty tickets.” Before you run it, predict: will it catch more escalations than the priority-1 rule? Will it fit the capacity? In the notebook, section 5, make grace_flags, compute its flag_report, and run the check cell.
Show the answer
grace_flags = (valid["priority"] == 1) | (valid["team"] == "warranty")grace = flag_report(y, grace_flags)print(grace)print("Meets the target:", meets_target(grace)){'flagged': 312, 'share flagged': 0.265, 'caught': 98, 'false alarms': 214, 'missed': 85, 'correctly left': 782, 'precision': 0.314, 'recall': 0.536, 'accuracy': 0.746}Meets the target: FalseGrace’s rule catches 98 of 183 escalations: a recall of 0.536, more than the target of 40%. But it flags 312 tickets, 26.5%, more than the senior team can review. So it does not meet the target. A rule flags what it flags, and you cannot make it flag exactly 20%. A model gives a score, and you can cut a score at any level. The precision–recall trade-off shows how, and Thresholds and calibration chooses the cut that fits the 20%.
The notebook has an optional cell for your own rule. Try one or two at most. Each rule that you test on the May tickets, and keep because it scored well, makes the May numbers a little too good. Train, validation and test sets explains why.
Common mistake
Accuracy picks the useless baseline
Symptom: Tomás compares the three rules by accuracy, “the standard measure”, and recommends the first one:
flagged recall accuracynever escalate 0 0.000 0.845priority 1 163 0.333 0.810priority 1 or warranty 312 0.536 0.746Text description of the chart
A column chart with three columns on an axis from 0 to 100%. Never escalate: 84.5%. Flag priority 1: 81.0%. Flag priority 1 or warranty: 74.6%. The rule that flags nothing has the highest accuracy.
Text description of the chart
A column chart of the escalations that each rule flags, out of 183 in May. Never escalate catches 0. Flag priority 1 catches 61. Flag priority 1 or warranty catches 98. The order is the opposite of the order by accuracy.
Cause: 84.5% of the May tickets did not escalate. A rule that always says “no” is right on all of them. Accuracy counts every correct “no”, but Grace’s decision is about the “yes”. When one answer is rare, accuracy mostly measures the common answer. Classification metrics explains this trap in full.
Fix: choose the measures from the decision, as in Translate a need. For Larkfield: the share flagged against the capacity, and the recall and precision of the flags; for scores, AP and ROC AUC. Always show the baselines next to a result.
Consequence in AI work: a team that optimises accuracy here ends with a model that flags almost nothing. It reports a high number, nobody sees an error, and the escalations wait in the normal queue as before. This is the mistake of “optimising a metric that does not match the decision”. It comes back in Module 3.
Knowledge check
Section titled “Knowledge check”Check your understanding
A colleague reports: our escalation model has 84% accuracy on May. What do you ask before you believe that it is useful?
Show the answer
Ask for the baselines and for the measures of the decision. On May, a rule that never flags has 84.5% accuracy and catches nothing, so 84% may be worse than doing nothing. Ask what share of tickets the model flags (at most 20%). Ask how many of the escalations it catches (its recall, at least 40%) and how many of its flags are right (its precision). Compare them with the rule “flag priority 1”: 13.8% flagged, recall 0.333, precision 0.374.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Check your understanding
Grace's rule catches 53.6% of the May escalations. Why does it not meet the improvement target? Why can a model with a score meet it?
Show the answer
It flags 26.5% of the tickets, more than the 20% that the senior team can review. The target has two conditions, and the rule breaks the capacity condition. A rule is fixed: it flags what matches. A model gives each ticket a score, so you can choose the cut that flags exactly the capacity. Then the question is how many escalations are in that top 20%.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Module practice
Section titled “Module practice”The module practice asks you to write a one-page modelling brief for ticket escalation, before any model exists. A brief puts every decision of this module on one page: the decision, the target, the data, the costs, the baselines and the improvement target. Grace, Omar and Tomás can then read it, and disagree, before anyone spends time on a model. A disagreement on one page costs minutes; the same disagreement after two weeks of modelling costs the two weeks.
Worked example: the template
Section titled “Worked example: the template”Copy the template into a file reports/modelling-brief.md in your project, or into the last Markdown cell of the notebook. Each part needs one or two sentences, with the numbers of this module.
# Modelling brief: ticket escalation
| Part | Answer ||---|---|| Decision and owner | Who acts on the prediction, and what do they do? || Prediction unit | One prediction is about one … || Prediction time | When must the prediction exist? || Target | The exact definition, with its time window. || Features | The columns known at the prediction time. || Never features | The columns written after the prediction time. || Data and split | Which rows, which split, how many in each part. || Cost of a missed escalation | What happens to the customer? || Cost of an unnecessary review | What does it cost the team? || Capacity | How many flags can the team handle? || Baselines (on valid) | The numbers of the simple predictions. || Measures | Which measures, and why not accuracy. || Improvement target | The result that makes a model worth using. || Why not only a rule | What the best rule cannot do. || Risks | What can make the model worse in real use. |Your task: the brief for ticket escalation
Section titled “Your task: the brief for ticket escalation”Fill in every part for Larkfield’s escalation model. Use the numbers from Translate a need and from this lesson. Then compare your brief with Priya’s. Yours can use other words; check that it has the same decisions and the same numbers.
Show Priya’s brief
| Part | Answer |
|---|---|
| Decision and owner | Grace (support lead) owns it. Her team sends a flagged ticket straight to the senior team, instead of the normal queue. |
| Prediction unit | One ticket. |
| Prediction time | When the ticket is created. |
| Target | escalated_72h: 1 if a senior agent took the ticket within 72 hours after created_at, otherwise 0. |
| Features | The 10 columns from the SQL course: channel, team, priority, segment, region, order_value, word_count, customer_tenure_days, prior_tickets_90d, created_hour. To test in Module 6: prior_escalations_90d (known at creation). |
| Never features | priority_now (the escalation sets it), customer_escalation_rate (uses later targets), and every value written after creation: the first reply, the closing time, outcome events. |
| Data and split | The full export, split by time as in the SQL course. Train: 16,939 tickets, July 2024 to April 2026, 11.7% escalated. Valid: 1,179, May 2026, 15.5%. Test: 1,002, 1 to 27 June 2026, 15.7%. The test set is used once, at the end. |
| Cost of a missed escalation | The customer waits in the normal queue, often a day more. Some customers leave Larkfield. |
| Cost of an unnecessary review | About 10 minutes of a senior agent, and one review place that a real escalation could have had. |
| Capacity | At most 20% of new tickets: about 7.6 tickets a day in May. |
| Baselines (on valid) | Never escalate: accuracy 0.845, recall 0. Constant score 0.117: ROC AUC 0.5, AP 0.155. Flag priority 1: 13.8% flagged, precision 0.374, recall 0.333. |
| Measures | The share flagged (against the capacity), and recall and precision at that share. For scores: AP and ROC AUC. Not accuracy: never escalating has the highest accuracy. |
| Improvement target | Flag at most 20% of new tickets and catch at least 40% of escalations. Check on valid; confirm once on test. |
| Why not only a rule | Priority 1 catches 33%. Priority 1 or warranty catches 53.6%, but flags 26.5%, above the capacity. A rule cannot be cut at exactly 20%; a score can. |
| Risks | The escalation rate rose after the warranty policy of 1 May 2026 (11.7% in train, 15.5% in May). A model from older tickets may give scores that are too low. Guests have no history. Some customers tend to escalate, and no column shows it. |
A complete brief has three things that are easy to miss. The target has its time window (72 hours). The capacity is a number. The baselines are numbers, not only names.
Module check
Section titled “Module check”Check your understanding
Retrieval: name the three baselines of this module and give one number for each on the May tickets.
Show the answer
- Majority class, never escalate: accuracy 0.845, recall 0. It catches none of the 183 escalations.
- Constant score, the train rate 0.117 for every ticket: ROC AUC 0.5, average precision 0.155 (the May escalation rate).
- Rule, flag priority 1: 163 tickets flagged (13.8%), precision 0.374, recall 0.333.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Check your understanding
Predict and explain: a first model flags 19% of the May tickets with a recall of 0.38 and a precision of 0.37. Does it meet the improvement target? Is it better than the rule flag priority 1?
Show the answer
It does not meet the target. It fits the capacity (19% is at most 20%), but its recall, 0.38, is below 0.40. It is a little better than the rule on recall (0.38 against 0.333). But it also flags more tickets (19% against 13.8%), with about the same precision. So the gain is small, and part of it comes only from flagging more. Priya would not use it yet. She would look for a model that catches at least 40% within the 20%.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Check your understanding
Completion check: explain to Omar what action a prediction enables at Larkfield and what it costs to be wrong in each direction. Use the capacity and the numbers of this module.
Show the answer
The action: when a ticket is created, a flag sends it straight to the senior team. A customer with a serious problem then gets a senior agent on the first day, instead of waiting in the normal queue.
The cost of a wrong “no” (a missed escalation): the customer waits, often a day more, and some customers leave Larkfield. The rule “flag priority 1” misses 122 of the 183 May escalations.
The cost of a wrong “yes” (an unnecessary review): about 10 minutes of a senior agent. It also uses a review place that a real escalation could have had. The senior team can review at most 20% of new tickets, about 7.6 a day in May. So unnecessary reviews push real escalations out.
What it means for the model: a miss costs more than a review, but the capacity is fixed. So the model must catch as many escalations as possible within 20% flagged: at least 40%, against 33% for the rule. Accuracy does not show this, because never escalating has the best accuracy (84.5%).
A complete answer names the action, both errors with their costs, and the capacity, and links them to the measures.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Recap
In this module, you turned Grace’s need into a prediction problem that a model can be measured against:
- The problem: a flagged ticket goes to the senior team, at most 20% of new tickets. One ticket, at creation, target
escalated_72h, with the 10 features from the SQL course. Neverpriority_noworcustomer_escalation_rate. - The baselines on May: never escalating is 84.5% accurate and catches nothing. A constant score has ROC AUC 0.5 and AP 0.155. The rule “flag priority 1” flags 13.8%, with precision 0.374 and recall 0.333.
- The improvement target: flag at most 20% and catch at least 40% of escalations.
- The project:
~/projects/ticket-modelwith.venv,requirements.txt,get_data.pyanddata/. To reset it, runpython get_data.py --reset, or make.venvagain, as in Reset the project.
Next, in Module 3, you learn how a model is judged before you build one. The first question: why must a model be tested on data that it did not learn from?