Skip to content

Supervised learning

  • Lesson 2
  • 55 min
  • Module 1: Understand machine learning

What you will be able to do

Understand how a program learns from examples that have the right answer, and why this is called supervised learning. Then you can say, for any prediction, what the model looks at (the features) and what it learns to give (the label). You can also say if the answer is a class or a number.

NotebookDo this lesson in a notebookColab · Kaggle · GitHub

The notebook teaches colour names to a model with 15 coloured swatches, and predicts the price of a flat from its size. Then it splits Larkfield’s tickets into features and a label. Its setup cells install pandas and scikit-learn and download the practice data, so it needs no local setup. About 25 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 readyAbout 55 minutes

What you need to know

What you need on your computer (only for the local route; the notebook needs none of it)

The notebook was tested in Jupyter on macOS. It used Python 3.14.6, pandas 3.0.6, scikit-learn 1.9.1 and matplotlib 3.11.2.

Think about how a small child learns the names of colours. You show her a red ball and say “red”. Later you show her a red car and say “red” again, and then a blue cup: “blue”. One day she points at an orange and says “red”. You say: “No, that is orange.” After many examples and many small corrections, something changes. She sees a toy that she has never seen before, and says “green”. She is right.

Look at what she learned, and what nobody told her. You never explained that the shape does not matter, or that a car and a ball can have the same colour. She found out from the examples that only the colour decides the word. You also never gave her a rule such as “green is between yellow and blue”. She learned the rule from examples with the right answer, and she can now use it on things that she has never seen.

A computer can learn in the same way. This lesson shows how, and gives each part of the story its technical name.

Each part of the colour story has a name in machine learning:

  • Each object that you show the child is an example. In data, one example is one row.
  • What the child looks at, the colour, is a feature. A feature is a fact about an example that the model uses as input. An example usually has many features.
  • The word that you say, “red”, is the label: the right answer for that example.
  • Your corrections (“no, that is orange”) are the supervision. During learning, someone gives the right answer for every example, so the learner can correct its mistakes.
  • When the child names a new toy, that is a prediction.
  • When she names new toys correctly, she generalises. Generalisation means that a model does well on new examples, not only on the examples that it learned from. It is the only thing that matters in practice.

This is why this kind of learning is called supervised learning: a supervisor gives the right answer for every example during learning. In machine learning, the supervisor is rarely a person who sits next to the computer. It is the label column in the data: someone or something wrote the right answers earlier, and the program learns from them.

The picture shows the colour story as data. Each swatch is one example. Its colour is the feature, and its name card is the label.

Fifteen coloured squares, each with a name card under it: three red, three orange, three yellow, three green and three blue, in a mixed order. An arrow leads to a new orange square with a card that shows a question mark. A second arrow leads to the same square with a dashed card that says orange.
Supervised learning: 15 examples, each with its label (the name card). The model learns from them, then predicts the label of a new swatch that it never saw.
Text description of the diagram

On the left are 15 colour swatches in a mixed order, as a child meets them. Each one has a name card under it: red, green, blue, orange or yellow. There are three swatches of each name, in different shades, for example a dark red and a light red.

An arrow leads to a new swatch, an orange one, with a card that shows a question mark: nobody has given its name. A second arrow leads to the same swatch with a dashed card that says “orange”. This is the prediction: the name that the model gives after it learned from the 15 labelled examples.

A computer sees a colour as three numbers: the amount of red, green and blue light, each from 0 to 255. Pure red is (255, 0, 0), and white is (255, 255, 255). So in data, one swatch is a row with three features and one label. The notebook makes the 15 swatches of the picture as a DataFrame:

swatches = pd.DataFrame(
[("red", 220, 40, 40), ("red", 190, 25, 35), ("red", 235, 70, 60),
("orange", 245, 135, 35), ("orange", 235, 115, 25), ("orange", 250, 155, 60),
("yellow", 250, 220, 50), ("yellow", 240, 205, 40), ("yellow", 255, 235, 100),
("green", 50, 165, 70), ("green", 90, 190, 80), ("green", 30, 130, 55),
("blue", 40, 100, 200), ("blue", 80, 140, 225), ("blue", 30, 70, 170)],
columns=["name", "red", "green", "blue"],
)
X = swatches[["red", "green", "blue"]] # the features
y = swatches["name"] # the label
print(X.shape, y.shape)
swatches.head(4)

The output:

(15, 3) (15,)
name red green blue
0 red 220 40 40
1 red 190 25 35
2 red 235 70 60
3 orange 245 135 35

By custom, the features are in a table called X, with one row per example. The labels are in a column called y, with one value per example. X has 15 rows and 3 columns; y has 15 values.

Priya trains a nearest-neighbour classifier. Its idea is simple: for a new swatch, it looks for the 3 examples that are most similar, and gives their most common name. “Most similar” means that the three numbers are closest. Training is one line, and it gets both X and y: the features and the right answers. The last line uses show_swatches(), a small helper in the notebook that draws swatches with a name under each one.

from sklearn.neighbors import KNeighborsClassifier
model = KNeighborsClassifier(n_neighbors=3)
model.fit(X, y) # training: learn from examples with labels
new = pd.DataFrame([(200, 60, 50), (110, 170, 220), (240, 125, 40)], columns=["red", "green", "blue"])
predictions = model.predict(new) # prediction: no labels here
print(list(predictions))
show_swatches(new, predictions, "Three new swatches and the predicted names")

The output (the notebook also draws the three swatches with their names):

['red', 'blue', 'orange']

The model never saw these three swatches, and it named all three as a person would. Why “orange” for the third one? Priya asks the model for the 3 examples that it used, and how far each one is:

distances, rows = model.kneighbors(new.iloc[[2]])
nearest = swatches.iloc[rows[0]].assign(distance=distances[0].round(0))
nearest

The output:

name red green blue distance
3 orange 245 135 35 12.0
4 orange 235 115 25 19.0
5 orange 250 155 60 37.0

The distance measures how different two colours are: 0 means the same three numbers. All three nearest examples are orange, so the prediction is “orange”. The model did what the child did: it compared the new colour with the colours it knew, and used their names.

Two kinds of answer: classification and regression

Section titled “Two kinds of answer: classification and regression”

The colour name is a class: one of a few fixed answers. When the label is a class, the task is classification. Many everyday systems classify. A spam filter gives “spam” or “not spam”. A screening system marks a scan as “needs a doctor’s review” or not. An online shop puts each new product into one of its categories, such as “garden” or “kitchen”. When there are only two classes, as for spam, the task is binary classification.

Other questions need a number as the answer. Examples are the price of a house, the minutes until a delivery arrives, or tomorrow’s temperature. When the label is a number, the task is regression. The name is historical: it comes from a 19th-century study of the heights of parents and children. Today it means predicting a number.

The idea of learning is the same for both. Here is a tiny regression example with the same nearest-neighbour idea. Eight flats have a size in square metres (the feature) and a price in thousands of dollars (the label). For a new flat of 70 square metres, the model finds the 3 flats with the most similar size. It gives the mean of their prices:

from sklearn.neighbors import KNeighborsRegressor
flats = pd.DataFrame({
"size_m2": [35, 42, 50, 58, 65, 80, 95, 110],
"price_k": [150, 175, 200, 230, 255, 300, 345, 390],
})
price_model = KNeighborsRegressor(n_neighbors=3)
price_model.fit(flats[["size_m2"]], flats["price_k"])
new_flat = pd.DataFrame({"size_m2": [70]})
print(round(price_model.predict(new_flat)[0], 2))

The output:

261.67

The 3 most similar flats are 65, 80 and 58 square metres, with prices 255, 300 and 230. Their mean is 785 ÷ 3 = 261.67, so the model predicts about $262,000.

  • Flats with a known price (examples)
  • Predicted price, 70 m²
Eight flats with their size and price (the examples), and the predicted price of a new flat of 70 square metres.
Text description of the chart

A scatter chart of eight flats. The horizontal axis is the size, from 30 to 115 square metres. The vertical axis is the price, from 0 to 400 thousand dollars. The points rise from left to right. The eight flats are: 35 square metres for 150, 42 for 175, 50 for 200, 58 for 230, 65 for 255, 80 for 300, 95 for 345 and 110 for 390. A ninth point, in another colour, is the prediction for a new flat of 70 square metres. It is at 261.67, between the flats of 65 and 80 square metres.

There is a practical difference between the two kinds of answer. For a price, a prediction of 262 when the truth is 265 is nearly right, and you can measure how far off it is. For a colour, “orange” when the truth is “red” is wrong. You cannot say that it is “nearly red”. This difference decides how you measure a model, and Module 3 is about exactly that.

Question The label Kind of answer Task
Is this email spam? spam or not A class (two) Classification
What is written in this handwritten digit? 0 to 9 A class (ten) Classification
Which category is this new product in? garden, kitchen, … A class Classification
Will this new ticket escalate within 72 hours? 1 or 0 A class (two) Classification
What will this house sell for? a price A number Regression
How many minutes until this delivery arrives? minutes A number Regression
What will the temperature be tomorrow? degrees A number Regression
How many tickets will arrive tomorrow? a count A number Regression

Larkfield’s history has the same shape as the colour swatches, only larger. One row is one ticket. Ten columns describe the ticket at the moment when it arrives. They include the channel, the team, the priority, the order value and the customer’s history. These are the features. The column escalated_72h says what happened later: 1 if a senior agent took over the ticket within 72 hours, otherwise 0. This is the label. In this course, the label is also called the target: the column that the model learns to predict. The two words mean the same thing here.

Larkfield’s history comes in three files. The largest, train.csv, holds the tickets up to April 2026, and models learn from it. Train, validation and test sets explains why there are three files. Priya reads the train tickets and looks at three of them:

train = pd.read_csv("data/train.csv", dtype={"customer_id": "string"},
keep_default_na=False, na_values=[""])
FEATURES = ["channel", "team", "segment", "region", "priority", "order_value", "word_count",
"customer_tenure_days", "prior_tickets_90d", "created_hour"]
TARGET = "escalated_72h"
train[FEATURES + [TARGET]].head(3)

The output, as a table:

channel team segment region priority order_value word_count customer_tenure_days prior_tickets_90d created_hour escalated_72h
chat delivery home south 3 53.76 48 738.0 0 6 0
phone warranty home north 1 24.30 85 1496.0 0 7 0
chat returns business east 3 699.55 111 1243.0 0 7 0

The first ten columns are the features: what the model looks at, as the child looks at the colour. The last column is the label: the right answer, as the name card. Then Priya splits the table into X and y, exactly as for the swatches:

X = train[FEATURES]
y = train[TARGET]
print("X:", X.shape, " y:", y.shape)
print(y.value_counts())

The output:

X: (16939, 10) y: (16939,)
escalated_72h
0 14956
1 1983
Name: count, dtype: int64

X has 16,939 rows and 10 features. y has one label per ticket, and only two values: 0 for 14,956 tickets and 1 for 1,983. The label is a class, so Larkfield’s task is binary classification.

One rule matters from the start. The model must know every feature at the moment when it makes the prediction. Grace wants the prediction when a ticket arrives. So a feature cannot be something that happens later, such as the time of the first reply. The label is the exception: nobody knows it until later, and that is why the model must predict it. Translate a need works out exactly which facts are known at that moment.

The child had a parent who said “red”. A model needs the same: a right answer for every example. There are three common sources.

  1. A later event in the history. Larkfield’s label comes from what happened next: a senior agent took the ticket, or did not, within 72 hours. Nobody had to label the tickets by hand. A bank’s label “the loan was repaid” also comes from the history, but only years later.
  2. People who label. Email users click “report spam”. Doctors mark scans. Some companies pay people to label thousands of photos or texts.
  3. Time itself. Tomorrow’s real temperature is known tomorrow. Today’s forecast becomes a labelled example the next day.

Omar asks: “If labels are so useful, why not label everything?” Because labels have costs. They take time and money: a doctor’s hour is expensive. They can be late: Larkfield waits 72 hours for each label, and a bank waits years. And they can be wrong: two people may name the same colour differently, or a tired labeller may click the wrong button. A model learns whatever the labels say, as the failure case below shows.

  1. Open the notebook from the box Do this lesson in a notebook at the top of this page.
  2. Run the setup cells. The data cell ends with Ready: train 16939 rows (1983 escalated), valid 1179 (183), test 1002 (157).
  3. Run sections 1 and 2. Compare each output with the tiny example above.
  4. In section 3, put the swatches (60, 140, 90) and (245, 215, 90) in a DataFrame practice.
  5. Before you run the cell, write down the names that you expect.
  6. Put the model’s names in practice_names, then run the check cell.
  7. In section 4, run the flats example. You should see 261.67.
  8. Put the predicted price of a flat of 100 square metres, rounded to 2 decimals, in price_100. Run the check cell.
Show an example answer
practice = pd.DataFrame([(60, 140, 90), (245, 215, 90)], columns=["red", "green", "blue"])
practice_names = list(model.predict(practice))
print(practice_names)
['green', 'yellow']
price_100 = round(price_model.predict(pd.DataFrame({"size_m2": [100]}))[0], 2)
print(price_100)
345.0

The flat of 100 square metres uses the flats of 95, 110 and 80 square metres: (345 + 390 + 300) ÷ 3 = 345.

Change one thing: the label. The file data/daily_tickets.csv has one row per day, from July 2024 to June 2026. Its features are weekday, is_weekend and month, and its label is tickets, the number of tickets created that day.

In section 6 of the notebook, read the file into daily, and make X_daily and y_daily. Then answer: is predicting y_daily classification or regression?

Show an example answer
daily = pd.read_csv("data/daily_tickets.csv")
X_daily = daily[["weekday", "is_weekend", "month"]]
y_daily = daily["tickets"]
print(X_daily.shape, y_daily.shape)
(730, 3) (730,)

The label is a number of tickets per day, so predicting it is regression. The data is from the same help desk. But the example is now a day, not a ticket, and the label is a count, not a class. You train this model in Module 4.

Common mistake

Wrong labels

Symptom: a helper labelled the swatches, and called two of the three orange swatches “red”. Priya trains the same model on these labels:

wrong_y = swatches["name"].copy()
wrong_y.iloc[[3, 4]] = "red" # two orange swatches with the wrong label
wrong_model = KNeighborsClassifier(n_neighbors=3).fit(swatches[["red", "green", "blue"]], wrong_y)
print("New orange swatch:", wrong_model.predict(new.iloc[[2]])[0])
agree = (wrong_model.predict(swatches[["red", "green", "blue"]]) == wrong_y).sum()
print("The model agrees with", agree, "of its 15 labels")

The output:

New orange swatch: red
The model agrees with 15 of its 15 labels

The model now calls a clearly orange swatch “red”. And when Priya checks it against its own labels, it agrees with all 15, so nothing looks wrong.

Cause: in supervised learning, the labels are the supervisor. The model learns what they say, right or wrong. A check against the same wrong labels cannot find the problem.

Fix: before you train, look at a sample of the examples and their labels by hand, and ask how each label was made. If two people label the same examples, count how often they disagree. Fix or remove labels that are wrong, then train again.

Consequence in AI work: wrong labels are common and quiet. A spam filter trained on careless “report spam” clicks learns to hide real newsletters. A medical model trained on labels from one tired reviewer repeats that reviewer’s mistakes. No error message appears: the model only becomes a faithful copy of a wrong supervisor.

Check your understanding

Why is supervised learning called supervised? In Larkfield's ticket model, what plays the part of the supervisor?

Show the answer

During learning, a supervisor gives the right answer for every example, as a parent says “red” or “no, that is orange” to a child. The model learns from these answers, and they correct its mistakes. In Larkfield’s model, the supervisor is the label column escalated_72h: the history of each past ticket says whether it escalated within 72 hours.

Check your understanding

Classification or regression? (a) the minutes until a parcel arrives; (b) whether a card payment is fraud; (c) the number of tickets tomorrow; (d) which of Larkfield's five teams should take a new ticket.

Show the answer

(a) Regression: the answer is a number of minutes. (b) Classification: two classes, fraud or not. (c) Regression: the answer is a count. (d) Classification: the answer is one of five classes, the teams. A team name has no size: “payment” is not “nearly warranty”.

Check your understanding

A model agrees with every label it was trained on, but it calls new orange swatches red. What is the most likely cause, and how do you find it?

Show the answer

Some training labels are wrong: the helper labelled orange swatches “red”. The model learned what its supervisor said, so it agrees with its own labels and the check looks perfect. To find the problem, look at a sample of examples and their labels by hand. Or let a second person label them, and count the disagreements. Then fix the labels and train again.

Recap

  • Supervised learning learns from examples that have the right answer, as a child learns colour names from a parent. The label column is the supervisor.
  • A feature is a fact about an example that the model uses as input (X). The label, also called the target, is the right answer (y). Generalisation means doing well on new examples.
  • When the label is a class, the task is classification (colour names; spam or not; escalated or not). When it is a number, the task is regression (the price of a flat: 261.67 thousand for 70 square metres).
  • Larkfield’s tickets: X has 16,939 rows and 10 features; y is escalated_72h, 1 for 1,983 tickets. The task is binary classification.
  • Labels come from the history, from people, or from time. They cost time, can come late and can be wrong, and a model learns wrong labels without any warning.

Next, you see what a program can learn when there is no label at all: how to put similar things into groups.

Next: Unsupervised learning