Introduction to machine learning

CSI 4106 - Fall 2026

Marcel Turcotte

Version: Sep 15, 2026 11:59

Preamble

Message of the day (1/2)

Message of the day (2/2)

From the Previous Lecture

  • Symbolic and connectionist methods are two major traditions in AI.
  • Defining intelligence remains challenging.
  • Russell and Norvig describe four perspectives on AI: thinking humanly, acting humanly, thinking rationally, and acting rationally.
  • Narrow AI targets particular tasks; artificial general intelligence is a broader and contested goal.
  • Difficult, unresolved questions frequently concern embodiment, agency, sentience, consciousness, emotion, and cognition.

Learning objectives

  • Distinguish supervised, unsupervised, and reinforcement learning by the feedback available
  • Identify examples, features, and targets in a supervised-learning dataset
  • Differentiate classification from regression, and learning from inference
  • Apply the basic scikit-learn workflow: load data, explore it, fit a model, and make predictions
  • Explain why a separate test set is needed to estimate performance on unseen data

Introduction

Rationale

Why should a computer program learn?

Definition

Mitchell (1997), page 2

A computer program is said to learn from experience E with respect to some class of tasks T and performance measure P, if its performance at tasks in T, as measured by P, improves with experience E.

Concepts

See: ml_concepts-00.svg

Types of problems

We will begin with three broad learning settings, distinguished by the feedback available:

  1. Unsupervised learning: The examples have no target labels.
  2. Supervised learning: Each training example is accompanied by a target label.
  3. Reinforcement learning: An agent receives numerical rewards while interacting with an environment.

Supervised learning is the most extensively studied and arguably the most intuitive type of learning. It is typically the first type of learning introduced in educational contexts.

Unsupervised Learning

Given: feature vectors x_1, x_2, \ldots, x_N, but no target labels y_i.

Code
import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(7)
centres = [(-2.0, -0.8), (0.2, 1.8), (2.3, -0.5)]
points = np.vstack([
    rng.normal(loc=centre, scale=0.42, size=(35, 2))
    for centre in centres
])

plt.scatter(points[:, 0], points[:, 1], color="#4472C4", alpha=0.8)
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.gca().set_aspect("equal", adjustable="box")
plt.show()

Reinforcement Learning

An agent takes actions in an environment, observes the consequences, and receives numerical rewards.

Goal: Learn a policy for choosing actions that maximizes cumulative reward.

Supervised Learning: Two Phases

For the supervised-learning workflow studied in this course:

  1. Learning (building a model)
  2. Inference (using the model)

Learning: Building a Model

Inference: Using a Model

Carp-e Diem! (example)

1. Problem: Will They Bite Today?

Objective: Develop a predictive model that classifies a fishing day as Poor, Average, or Excellent.

2. Attributes (features)

Fishing traditions and guides, including The Old Farmer’s Almanac, often use the moon phase when recommending fishing days. We will treat it as a candidate feature; whether it is genuinely predictive is an empirical question.

  • Moon Phase (Categorical): ‘New Moon’, ‘First Quarter’, ‘Full Moon’, and ‘Last Quarter’.
  • Forecast (Categorical): ‘Rainy’, ‘Cloudy’, and ‘Sunny’.
  • Outdoor Temperature (Numerical): The air temperature in degrees Celsius.
  • Water Temperature (Numerical): The water temperature of the lake or river.

3. Training data

Example Moon Phase Forecast Outdoor Temperature (°C) Water Temperature (°C) Fishing Outcome
1 Full Moon Sunny 25 22 Excellent
2 New Moon Cloudy 18 19 Average
3 First Quarter Rainy 15 17 Poor
4 Last Quarter Sunny 30 24 Excellent
5 Full Moon Cloudy 20 20 Average
6 New Moon Rainy 22 21 Poor

3. Training data: data representation

Moon Phase Forecast Outdoor Temperature (°C) Water Temperature (°C)
Full Moon Sunny 25 22
New Moon Cloudy 18 19
First Quarter Rainy 15 17
Last Quarter Sunny 30 24
Full Moon Cloudy 20 20
New Moon Rainy 22 21

The data is often presented in a tabular (matrix) format, where each row represents an attribute vector (feature vector), typically denoted as x_i, which corresponds to the i-th example in the training set.

3. Training data: label representation

Fishing Outcome
Excellent
Average
Poor
Excellent
Average
Poor

The labels are generally represented as a column vector, with y_i denoting the label for the i-th example.

4. Model Training

Model training uses labelled examples to construct a model that can make predictions. Depending on the algorithm, training may estimate parameters, build a structure, or simply store examples.

4. Model Training (continued)

A simple model that fits all six training examples is:

  • If the forecast is Sunny, predict Excellent.
  • If the forecast is Cloudy, predict Average.
  • If the forecast is Rainy, predict Poor.

5. Prediction

Given new, unseen data, predict today’s fishing category.

  • Moon Phase: New Moon
  • Forecast: Sunny
  • Outdoor Temperature: 24°C
  • Water Temperature: 21°C

Prediction: Excellent

Life cycle

  1. Data collection and preparation
  2. Feature engineering
  3. Training
  4. Model evaluation
  5. Model deployment
  6. Monitoring and maintenance

Formal definitions

Supervised learning (notation)

The dataset (“experience”) is a collection of labelled examples.

  • \{(x_i, y_i)\}_{i=1}^N
    • Each x_i is a feature (attribute) vector with D dimensions.
    • x_i^{(j)} is the value of feature j for example i, where j \in \{1, \ldots, D\} and i \in \{1, \ldots, N\}.
    • The target y_i may be a class from a finite set \{1, 2, \ldots, C\}, a real number, or a structured object such as a sequence, tree, or graph.

Problem: Given the dataset, create a model that can predict the value of y for an unseen x.

Supervised learning (notation, continued)

  • When the target y_i is a class, taken from a finite list of classes, \{1, 2, \ldots, C\}, we call the task a classification task.

  • When the target y_i is a real number, we call the task a regression task.

Example with code

Scikit-learn

scikit-learn is an open-source machine learning library that supports supervised and unsupervised learning. It also provides tools for model fitting, data preprocessing, model selection, model evaluation, and many other tasks.

scikit-learn provides dozens of built-in machine learning algorithms and models, called estimators.

Built on NumPy, SciPy, and matplotlib.

Scikit-learn

Example: Palmer Penguins Dataset

Example: In Case of a Missing Library

try:
    from palmerpenguins import load_penguins
except ModuleNotFoundError:
    %pip install -q palmerpenguins
    from palmerpenguins import load_penguins

Example: Loading the Data

# It is customary to use X and y for the data and labels

X, y = load_penguins(return_X_y = True)

# Remove rows with missing measurements

X = X.dropna()
y = y.loc[X.index]

Example: Using a Decision Tree

from sklearn import tree

clf = tree.DecisionTreeClassifier(criterion="entropy", random_state=42)

Example: Training

# Training

clf = clf.fit(X, y)

Example: Visualizing the tree (1/2)

import matplotlib.pyplot as plt

tree.plot_tree(clf)
plt.show()

Example: Visualizing the tree (2/2)

target_names = clf.classes_

tree.plot_tree(clf, 
               feature_names = X.columns,
               class_names = target_names,
               label = 'none',
               filled = True)
plt.show()

Example: Prediction

import pandas as pd

# Create two new examples

column_names = ['bill_length_mm', 'bill_depth_mm', 'flipper_length_mm', 'body_mass_g']
new_penguins = pd.DataFrame(
    [[34.2, 17.9, 186.8, 2945.0], [51.0, 15.2, 223.7, 5560.0]],
    columns=column_names,
)

# Prediction

predictions = clf.predict(new_penguins)

# Printing the predicted labels for our two examples

print(predictions)
['Adelie' 'Gentoo']

Example: Complete

X, y = load_penguins(return_X_y = True)
X = X.dropna()
y = y.loc[X.index]
clf = tree.DecisionTreeClassifier(criterion="entropy", random_state=42)
clf = clf.fit(X, y)
tree.plot_tree(clf)
new_penguins = pd.DataFrame(
    [[34.2, 17.9, 186.8, 2945.0], [51.0, 15.2, 223.7, 5560.0]],
    columns=column_names,
)
print(clf.predict(new_penguins))
['Adelie' 'Gentoo']

Example: Apparent Performance

from sklearn.metrics import classification_report, accuracy_score

# Make predictions

y_pred = clf.predict(X)

# Evaluate the model

accuracy = accuracy_score(y, y_pred)
report = classification_report(y, y_pred, labels=clf.classes_, target_names=clf.classes_)

print(f'Accuracy: {accuracy:.2f}')
print('Classification Report:')
print(report)

Example: Apparent Performance

Accuracy: 1.00
Classification Report:
              precision    recall  f1-score   support

      Adelie       1.00      1.00      1.00       151
   Chinstrap       1.00      1.00      1.00        68
      Gentoo       1.00      1.00      1.00       123

    accuracy                           1.00       342
   macro avg       1.00      1.00      1.00       342
weighted avg       1.00      1.00      1.00       342

Example: Discussion

We have demonstrated a complete example:

  • Loading the data
  • Selecting a classifier
  • Training the model
  • Visualizing the model
  • Making a prediction

Example: Wait a Minute!

from sklearn.metrics import classification_report, accuracy_score

# Make predictions

y_pred = clf.predict(X)

# Evaluate the model

accuracy = accuracy_score(y, y_pred)
report = classification_report(y, y_pred, labels=clf.classes_, target_names=clf.classes_)

print(f'Accuracy: {accuracy:.2f}')
print('Classification Report:')
print(report)

Important

This example is misleading, or even flawed!

Example: Exploration

penguins = load_penguins()
type(penguins)
pandas.DataFrame
penguins.head()

Example: Exploration

species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex year
0 Adelie Torgersen 39.1 18.7 181.0 3750.0 male 2007
1 Adelie Torgersen 39.5 17.4 186.0 3800.0 female 2007
2 Adelie Torgersen 40.3 18.0 195.0 3250.0 female 2007
3 Adelie Torgersen NaN NaN NaN NaN NaN 2007
4 Adelie Torgersen 36.7 19.3 193.0 3450.0 female 2007

Example: Exploration

penguins.describe()

Example: Exploration

bill_length_mm bill_depth_mm flipper_length_mm body_mass_g year
count 342.000000 342.000000 342.000000 342.000000 344.000000
mean 43.921930 17.151170 200.915205 4201.754386 2008.029070
std 5.459584 1.974793 14.061714 801.954536 0.818356
min 32.100000 13.100000 172.000000 2700.000000 2007.000000
25% 39.225000 15.600000 190.000000 3550.000000 2007.000000
50% 44.450000 17.300000 197.000000 4050.000000 2008.000000
75% 48.500000 18.700000 213.000000 4750.000000 2009.000000
max 59.600000 21.500000 231.000000 6300.000000 2009.000000

Example: Using Seaborn

import seaborn as sns

# Pairplot using seaborn

sns.pairplot(penguins, hue='species', markers=["o", "s", "D"])
plt.suptitle("Pairwise Scatter Plots of Penguins Features")
plt.show()

Example: Using Seaborn

Example: Training and Test Set

from sklearn.model_selection import train_test_split

# Split the dataset into training and testing sets

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.2,
    random_state=7,
    stratify=y,
)

Example: Creating a New Classifier

clf = tree.DecisionTreeClassifier(criterion="entropy", random_state=42)

Example: Training the New Classifier

clf.fit(X_train, y_train)

Example: Visualizing the Tree

tree.plot_tree(clf, 
               feature_names = X.columns,
               class_names = target_names,
               label = 'none',
               filled = True)
plt.show()

Example: Making Predictions

# Make predictions
y_pred = clf.predict(X_test)

Example: Measuring the Performance

# Evaluate the model
accuracy = accuracy_score(y_test, y_pred)
report = classification_report(
    y_test,
    y_pred,
    labels=clf.classes_,
    target_names=clf.classes_,
)

print(f'Accuracy: {accuracy:.2f}')
print('Classification Report:')
print(report)

Example: Measuring the Performance

Accuracy: 0.91
Classification Report:
              precision    recall  f1-score   support

      Adelie       0.96      0.90      0.93        30
   Chinstrap       0.72      0.93      0.81        14
      Gentoo       1.00      0.92      0.96        25

    accuracy                           0.91        69
   macro avg       0.90      0.92      0.90        69
weighted avg       0.93      0.91      0.92        69

Summary

  • We distinguished supervised, unsupervised, and reinforcement learning by the feedback available.
  • We identified examples, features, and targets in a supervised-learning problem.
  • We applied the scikit-learn workflow to the Palmer Penguins dataset.
  • We explored the data, trained a classifier, and made predictions.
  • We used a separate test set to estimate performance on unseen data.

Prologue

Further readings (1/3)

  • The Hundred-Page Machine Learning Book (Burkov 2019) is a succinct and focused textbook that can feasibly be read in one week, making it an excellent introductory resource.
  • Available under a “read first, buy later” model, allowing readers to evaluate its content before purchasing.
  • Its author, Andriy Burkov, received his Ph.D. in AI from Université Laval.

Further readings (2/3)

Further readings (3/3)

  • Mathematics for Machine Learning (Deisenroth et al. 2020) aims to provide the necessary mathematical skills to read machine learning books.
  • PDF of the book
  • “This book provides great coverage of all the basic mathematical concepts for machine learning. I’m looking forward to sharing it with students, colleagues, and anyone interested in building a solid understanding of the fundamentals.” Joelle Pineau, McGill University and Facebook

References

Burkov, Andriy. 2019. The Hundred-Page Machine Learning Book. Andriy Burkov.
Deisenroth, Marc Peter, A. Aldo Faisal, and Cheng Soon Ong. 2020. Mathematics for Machine Learning. Cambridge University Press. https://doi.org/10.1017/9781108679930.
Géron, Aurélien. 2022. Hands-on Machine Learning with Scikit-Learn, Keras, and TensorFlow. 3rd ed. O’Reilly Media, Inc.
Kingsford, C, and Steven L Salzberg. 2008. “What Are Decision Trees?” Nature Biotechnology 26 (9): 1011–13. https://doi.org/10.1038/nbt0908-1011.
Mitchell, Tom M. 1997. Machine Learning. McGraw-Hill.
Russell, Stuart, and Peter Norvig. 2020. Artificial Intelligence: A Modern Approach. 4th ed. Pearson. http://aima.cs.berkeley.edu/.

Next lecture

  • Decision trees and entropy
  • Decision boundaries and logistic regression
  • K-nearest neighbours

Appendix: Iris Dataset

Example: Iris Dataset

Example: Loading the Data

from sklearn.datasets import load_iris

# Load the Iris dataset

iris = load_iris()

Example: Using a Decision Tree

from sklearn import tree

clf = tree.DecisionTreeClassifier(criterion="entropy", random_state=42)

Example: Training

# It is customary to use X and y for the data and labels

X, y = iris.data, iris.target

# Training

clf = clf.fit(X, y)

Example: Visualizing the tree (1/2)

import matplotlib.pyplot as plt

tree.plot_tree(clf)
plt.show()

Example: Visualizing the tree (2/2)

tree.plot_tree(clf, 
               feature_names=iris.feature_names, 
               class_names=iris.target_names,
               label='none',
               filled=True)
plt.show()

Example: Prediction

# Create two new examples
# 'sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)'

new_irises = [[5.1, 3.5, 1.4, 0.2], [6.7, 3.0, 5.2, 2.3]]

# Prediction

predictions = clf.predict(new_irises)

# Printing the predicted labels for our two examples

print(iris.target_names[predictions])
['setosa' 'virginica']

Example: Complete

iris = load_iris()
clf = tree.DecisionTreeClassifier(criterion="entropy", random_state=42)
X, y = iris.data, iris.target
clf = clf.fit(X, y)
tree.plot_tree(clf)
new_irises = [[5.1, 3.5, 1.4, 0.2], [6.7, 3.0, 5.2, 2.3]]
predictions = clf.predict(new_irises)
print(iris.target_names[predictions])
['setosa' 'virginica']

Example: Performance

from sklearn.metrics import classification_report, accuracy_score

# Make predictions

y_pred = clf.predict(X)

# Evaluate the model

accuracy = accuracy_score(y, y_pred)
report = classification_report(y, y_pred, target_names=iris.target_names)

print(f'Accuracy: {accuracy:.2f}')
print('Classification Report:')
print(report)

Example: Performance

Accuracy: 1.00
Classification Report:
              precision    recall  f1-score   support

      setosa       1.00      1.00      1.00        50
  versicolor       1.00      1.00      1.00        50
   virginica       1.00      1.00      1.00        50

    accuracy                           1.00       150
   macro avg       1.00      1.00      1.00       150
weighted avg       1.00      1.00      1.00       150

Example: Discussion

We have demonstrated a complete example:

  • Loading the data
  • Selecting a classifier
  • Training the model
  • Visualizing the model
  • Making a prediction

Example: Take 2

from sklearn.metrics import classification_report, accuracy_score

# Make predictions

y_pred = clf.predict(X)

# Evaluate the model

accuracy = accuracy_score(y, y_pred)
report = classification_report(y, y_pred, target_names=iris.target_names)

print(f'Accuracy: {accuracy:.2f}')
print('Classification Report:')
print(report)

Important

This example is misleading, or even flawed!

Example: Exploration

print(f'Dataset Description:\n{iris["DESCR"]}\n')
Dataset Description:
.. _iris_dataset:

Iris plants dataset
--------------------

**Data Set Characteristics:**

:Number of Instances: 150 (50 in each of three classes)
:Number of Attributes: 4 numeric, predictive attributes and the class
:Attribute Information:
    - sepal length in cm
    - sepal width in cm
    - petal length in cm
    - petal width in cm
    - class:
            - Iris-Setosa
            - Iris-Versicolour
            - Iris-Virginica

:Summary Statistics:

============== ==== ==== ======= ===== ====================
                Min  Max   Mean    SD   Class Correlation
============== ==== ==== ======= ===== ====================
sepal length:   4.3  7.9   5.84   0.83    0.7826
sepal width:    2.0  4.4   3.05   0.43   -0.4194
petal length:   1.0  6.9   3.76   1.76    0.9490  (high!)
petal width:    0.1  2.5   1.20   0.76    0.9565  (high!)
============== ==== ==== ======= ===== ====================

:Missing Attribute Values: None
:Class Distribution: 33.3% for each of 3 classes.
:Creator: R.A. Fisher
:Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov)
:Date: July, 1988

The famous Iris database, first used by Sir R.A. Fisher. The dataset is taken
from Fisher's paper. Note that it's the same as in R, but not as in the UCI
Machine Learning Repository, which has two wrong data points.

This is perhaps the best known database to be found in the
pattern recognition literature.  Fisher's paper is a classic in the field and
is referenced frequently to this day.  (See Duda & Hart, for example.)  The
data set contains 3 classes of 50 instances each, where each class refers to a
type of iris plant.  One class is linearly separable from the other 2; the
latter are NOT linearly separable from each other.

.. dropdown:: References

  - Fisher, R.A. "The use of multiple measurements in taxonomic problems"
    Annual Eugenics, 7, Part II, 179-188 (1936); also in "Contributions to
    Mathematical Statistics" (John Wiley, NY, 1950).
  - Duda, R.O., & Hart, P.E. (1973) Pattern Classification and Scene Analysis.
    (Q327.D83) John Wiley & Sons.  ISBN 0-471-22361-1.  See page 218.
  - Dasarathy, B.V. (1980) "Nosing Around the Neighborhood: A New System
    Structure and Classification Rule for Recognition in Partially Exposed
    Environments".  IEEE Transactions on Pattern Analysis and Machine
    Intelligence, Vol. PAMI-2, No. 1, 67-71.
  - Gates, G.W. (1972) "The Reduced Nearest Neighbor Rule".  IEEE Transactions
    on Information Theory, May 1972, 431-433.
  - See also: 1988 MLC Proceedings, 54-64.  Cheeseman et al"s AUTOCLASS II
    conceptual clustering system finds 3 classes in the data.
  - Many, many more ...

Example: Exploration

print(f'Feature Names: {iris.feature_names}')
Feature Names: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
print(f'Target Names: {iris.target_names}')
Target Names: ['setosa' 'versicolor' 'virginica']
print(f'Data Shape: {iris.data.shape}')
Data Shape: (150, 4)
print(f'Target Shape: {iris.target.shape}')
Target Shape: (150,)

Example: Using Pandas (continued)

import pandas as pd

# Create a DataFrame

df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['species'] = iris.target_names[iris.target]

Example: Using Pandas (continued)

# Display the first few rows of the DataFrame

print(df.head())
   sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)  \
0                5.1               3.5                1.4               0.2   
1                4.9               3.0                1.4               0.2   
2                4.7               3.2                1.3               0.2   
3                4.6               3.1                1.5               0.2   
4                5.0               3.6                1.4               0.2   

  species  
0  setosa  
1  setosa  
2  setosa  
3  setosa  
4  setosa  

Example: Using Pandas (continued)

# Summary statistics

print(df.describe())
       sepal length (cm)  sepal width (cm)  petal length (cm)  \
count         150.000000        150.000000         150.000000   
mean            5.843333          3.057333           3.758000   
std             0.828066          0.435866           1.765298   
min             4.300000          2.000000           1.000000   
25%             5.100000          2.800000           1.600000   
50%             5.800000          3.000000           4.350000   
75%             6.400000          3.300000           5.100000   
max             7.900000          4.400000           6.900000   

       petal width (cm)  
count        150.000000  
mean           1.199333  
std            0.762238  
min            0.100000  
25%            0.300000  
50%            1.300000  
75%            1.800000  
max            2.500000  

Example: Using Seaborn

import seaborn as sns

# Pairplot using seaborn

sns.pairplot(df, hue='species', markers=["o", "s", "D"])
plt.suptitle("Pairwise Scatter Plots of Iris Features", y=1.02)
plt.show()

Example: Using Seaborn

Example: Training and Test Set

from sklearn.model_selection import train_test_split

# Split the dataset into training and testing sets

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.2,
    random_state=7,
    stratify=y,
)

Example: Creating a New Classifier

clf = tree.DecisionTreeClassifier(criterion="entropy", random_state=42)

Example: Training the New Classifier

# Train the model
clf.fit(X_train, y_train)

Example: Making Predictions

# Make predictions
y_pred = clf.predict(X_test)

Example: Measuring the Performance

from sklearn.metrics import classification_report, accuracy_score
# Make predictions

# Evaluate the model
accuracy = accuracy_score(y_test, y_pred)
report = classification_report(
    y_test,
    y_pred,
    labels=clf.classes_,
    target_names=iris.target_names[clf.classes_],
)

print(f'Accuracy: {accuracy:.2f}')
print('Classification Report:')
print(report)

Example: Measuring the Performance

Accuracy: 0.93
Classification Report:
              precision    recall  f1-score   support

      setosa       1.00      1.00      1.00        10
  versicolor       0.90      0.90      0.90        10
   virginica       0.90      0.90      0.90        10

    accuracy                           0.93        30
   macro avg       0.93      0.93      0.93        30
weighted avg       0.93      0.93      0.93        30

Marcel Turcotte

Marcel.Turcotte@uOttawa.ca

School of Electrical Engineering and Computer Science (EECS)

University of Ottawa