Iris Flower Classifier with Python

Train a Random Forest model to classify iris flowers by species.

Introduction

30 Second Summary

Every time you sort laundry by color or identify a bird by its feathers, you're doing classification. Machine learning does the same thing, but with data and math instead of instinct.

In this project, you will build a Python script that trains a model to classify iris flowers into three species based on their physical measurements. You'll load real data, train a classifier, evaluate its accuracy, and visualize what the model learned.

What You'll Build

A Python classification pipeline that loads the Iris dataset, trains a Random Forest classifier using scikit-learn, evaluates model performance, and visualizes prediction results.

By the end of this project, you'll have:

  • A trained Random Forest model that predicts iris flower species with high accuracy.
  • A complete Python script (iris_classifier.py) implementing the end-to-end ML workflow from data loading to evaluation.
  • Data visualizations showing feature importances and a confusion matrix.
  • Secret Mission: Compare multiple algorithms using cross-validation to find the best classifier.

Are there any prerequisites?

None. This project includes full setup instructions for Python, VS Code, and all required packages. No prior machine learning experience is needed.

Set Up Your Python Environment

To train a machine learning model, you need a programming language and a set of libraries that handle the math and data processing for you.

In this step, you'll install Python, create an isolated project environment, and install the two libraries your classifier needs: scikit-learn for machine learning and matplotlib for visualization.

In this step, get ready to:
  • Install and verify Python 3.13.
  • Create a project folder with a virtual environment.
  • Install scikit-learn and matplotlib.
Install and verify Python

Python is the runtime that executes your machine learning code. This project requires Python 3.11 or higher, and we recommend 3.13 for the best stability.

  • Open your terminal.
  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
  • Check if Python is already installed by running this command:

macOS

python3 --version

Windows

python --version

You should see a version number printed in the terminal.

✔️ I see version 3.11 or higher

Your Python version is compatible with this project. You're all set to move on to the next substep.

ⓧ I see a version lower than 3.11

You have Python installed, but it's an older version that won't work with scikit-learn 1.8.0. You need to install Python 3.13 alongside your existing version.

macOS

  • Download the macOS 64-bit universal2 installer.
  • Run the .pkg file and follow the prompts to install.
  • After installation, verify by running:
python3 --version

You should see Python 3.13.13 or similar. If you still see the old version, close and reopen your terminal, then try again.

Windows

  • Download the Windows installer (64-bit).
  • Run the .exe file.
  • On the first screen, check the box that says Add python.exe to PATH.
  • Click Install Now and wait for it to finish.
  • Close and reopen PowerShell, then verify by running:
python --version

You should see Python 3.13.13 or similar.

ⓧ Command not found

Python is not installed on your machine yet. Let's install Python 3.13 now.

macOS

  • Download the macOS 64-bit universal2 installer.
  • Run the .pkg file and follow the prompts to install.
  • After installation, close and reopen your terminal.
  • Verify by running:
python3 --version

You should see Python 3.13.13 or similar.

Windows

  • Download the Windows installer (64-bit).
  • Run the .exe file.
  • On the first screen, check the box that says Add python.exe to PATH.
  • Click Install Now and wait for it to finish.
  • Close and reopen PowerShell, then verify by running:
python --version

You should see Python 3.13.13 or similar.

Still not seeing a version number?

Make sure you closed and reopened your terminal after installing Python. On Windows, double-check that you ticked Add python.exe to PATH during installation. If you missed it, re-run the installer and select Modify to add it.

help me troubleshoot my Python installation

Create your project folder and virtual environment

A virtual environment is an isolated space where your project's libraries live. This prevents conflicts between packages used by different projects on your machine.

  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir iris-classifier
cd iris-classifier
  • Create a virtual environment by running this command:

macOS

python3 -m venv venv

Windows

python -m venv venv
  • Activate the virtual environment by running:

macOS

source venv/bin/activate

Windows

venv\Scripts\activate

You should see (venv) appear at the beginning of your terminal prompt. This confirms the virtual environment is active.

What does (venv) mean?

The (venv) prefix tells you that any packages you install with pip will go into this project's isolated environment, not your global Python installation. When you're done working, you can type deactivate to leave the virtual environment.

Don't see (venv) in your prompt?

On Windows, if you see an error about execution policies, run this command first, then try activating again:

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

On macOS, make sure you typed source before the path. Without it, the activation script won't run in your current session.

help me activate my Python virtual environment

Now let's open this project folder in VS Code.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Visual Studio Code and press Enter to open it.
  • In VS Code, click File in the top menu bar.
  • Click Open Folder.
  • Navigate to your Desktop, select the iris-classifier folder, and click Open.

Don't have VS Code installed?

Download it for free from https://code.visualstudio.com. Run the installer, then come back to this step.

Install the required packages

Your virtual environment is active, so any packages you install now are scoped to this project only.

  • Install scikit-learn and matplotlib by running this command in your terminal:
pip install scikit-learn==1.8.0 matplotlib==3.10.9

What does this command do?

pip is Python's package manager. The == syntax pins each library to an exact version so your results are reproducible.

scikit-learn provides the machine learning algorithms (like Random Forest) you'll use to classify flowers. matplotlib is the charting library you'll use to visualize your model's results.

The installation may take a minute. You'll see progress bars for each package and its dependencies.

  • Verify the packages installed correctly by running:
pip list

You should see scikit-learn and matplotlib in the list along with their dependencies (like numpy and scipy).

Seeing an error during installation?

Make sure (venv) is showing in your terminal prompt. If it's not, you need to activate your virtual environment again before running pip install.

If you see a permissions error, do not use sudo. Instead, deactivate and recreate your virtual environment.

help me fix my pip install error

Your Python environment is ready with all the tools you need. Next up, you'll load a real flower dataset and start exploring the data your model will learn from.

Load and Explore the Iris Dataset

Your Python environment is set up and ready to go. Now it's time to write your first machine learning code.

Every machine learning project starts with data. In this step, you'll load the Iris dataset, explore its structure, and split it into training and testing portions so your model can learn from one set and be evaluated on another.

In this step, get ready to:
  • Load the Iris dataset into Python.
  • Explore the dataset's shape, features, and target classes.
  • Split the data into training and testing sets.
Create the classifier script and load the Iris dataset

The Iris dataset is a classic collection of 150 flower measurements built directly into scikit-learn. No downloading or file management needed.

  • In VS Code, create a new file by pressing Cmd+N (macOS) or Ctrl+N (Windows).
  • Save the file by pressing Cmd+S (macOS) or Ctrl+S (Windows) and name it iris_classifier.py.
  • Add the following code to set up the imports, print a header, and load the dataset:
# Iris Flower Classifier - Machine Learning with scikit-learn
# Classifies iris flowers into 3 species based on petal/sepal measurements

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, ConfusionMatrixDisplay
import matplotlib.pyplot as plt
import numpy as np

# Step 2: Load and explore the Iris dataset
print("=" * 50)
print("IRIS FLOWER CLASSIFIER")
print("=" * 50)

iris = load_iris()
X = iris.data
y = iris.target

What does this code do?

The imports bring in all the tools you'll need across the project. load_iris fetches the built-in Iris flower dataset from scikit-learn.

The variable X holds the feature measurements (sepal length, sepal width, petal length, petal width) for all 150 flowers. The variable y holds the species label (0, 1, or 2) for each flower.

  • Save iris_classifier.py.
  • Run the script in your terminal by running:
python iris_classifier.py
  • You should see the header banner printed in your terminal:
==================================================
IRIS FLOWER CLASSIFIER
==================================================

Seeing a ModuleNotFoundError?

Make sure your virtual environment is activated. You should see (venv) at the start of your terminal prompt. If not, activate it with venv\Scripts\activate (Windows) or source venv/bin/activate (macOS/Linux), then run the script again.

help me fix a ModuleNotFoundError for scikit-learn in my Python script

Explore the dataset structure

Before training a model, you need to understand what your data looks like. Printing key properties reveals the shape, feature names, and sample values.

  • In iris_classifier.py, add the following code below the y = iris.target line to explore the dataset:
print(f"\nDataset shape: {X.shape}")
print(f"Number of samples: {X.shape[0]}")
print(f"Number of features: {X.shape[1]}")
print(f"Feature names: {iris.feature_names}")
print(f"Target names: {list(iris.target_names)}")
print(f"\nFirst 5 samples:")
print(X[:5])
print(f"Their labels: {y[:5]} -> {iris.target_names[y[:5]]}")

What does this code do?

These print statements reveal the dataset's structure. X.shape tells you there are 150 samples with 4 features each.

The feature names show the four measurements taken from each flower: sepal length, sepal width, petal length, and petal width. The target names reveal the three species you're classifying: setosa, versicolor, and virginica.

  • Save iris_classifier.py and run it again:
python iris_classifier.py
  • You should see the dataset details printed below the header, including Dataset shape: (150, 4) and the first 5 sample rows with their species labels.

Output looks garbled or missing?

Check that you pasted the code directly after the y = iris.target line with no blank lines missing in between. Make sure the f-string curly braces {X.shape} are intact and not accidentally deleted.

help me fix print output issues in my iris_classifier.py script

Split the data into training and testing sets

A model needs separate data for learning and for evaluation. If you test on the same data you trained on, you can't tell whether the model truly learned or just memorized.

What is a train/test split?

Splitting data means setting aside a portion (25% in this project) that the model never sees during training. After training, you evaluate accuracy on this unseen test set to measure real-world performance.

  • Add the following code at the bottom of iris_classifier.py to split the data:
# Split data into training and testing sets (75% train, 25% test)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42
)
print(f"\nTraining set size: {X_train.shape[0]}")
print(f"Testing set size: {X_test.shape[0]}")

What does this code do?

The train_test_split function randomly divides your 150 samples into two groups: 112 for training and 38 for testing.

Setting random_state=42 ensures the split is the same every time you run the script. This makes your results reproducible.

  • Save iris_classifier.py and run it again:
python iris_classifier.py
  • At the bottom of the output, you should see Training set size: 112 and Testing set size: 38.

Seeing different numbers?

If your training set size is not 112, check that you have test_size=0.25 and random_state=42 in your train_test_split call. Different values will produce different splits.

help me fix my train_test_split output showing unexpected numbers

✔️ Awesome, I've got everything!

Great. Double check you've saved iris_classifier.py before moving on.

ⓧ I'd like to double check the full code

Here is the complete iris_classifier.py file at this point:

# Iris Flower Classifier - Machine Learning with scikit-learn
# Classifies iris flowers into 3 species based on petal/sepal measurements

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, ConfusionMatrixDisplay
import matplotlib.pyplot as plt
import numpy as np

# Step 2: Load and explore the Iris dataset
print("=" * 50)
print("IRIS FLOWER CLASSIFIER")
print("=" * 50)

iris = load_iris()
X = iris.data
y = iris.target

print(f"\nDataset shape: {X.shape}")
print(f"Number of samples: {X.shape[0]}")
print(f"Number of features: {X.shape[1]}")
print(f"Feature names: {iris.feature_names}")
print(f"Target names: {list(iris.target_names)}")
print(f"\nFirst 5 samples:")
print(X[:5])
print(f"Their labels: {y[:5]} -> {iris.target_names[y[:5]]}")

# Split data into training and testing sets (75% train, 25% test)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42
)
print(f"\nTraining set size: {X_train.shape[0]}")
print(f"Testing set size: {X_test.shape[0]}")

Your data is loaded, explored, and split into training and testing sets. Next up, you'll train a Random Forest classifier on this data and see how accurately it can predict flower species.

Train and Evaluate a Random Forest Classifier

You have training data and testing data ready to go. Now it is time to build the actual machine learning model that learns patterns from the training data and uses them to predict flower species.

In this step, you will train a Random Forest classifier on your training set and then evaluate how well it performs on data it has never seen before.

In this step, get ready to:
  • Train a Random Forest model on 112 training samples.
  • Generate predictions on the 38 test samples and measure accuracy.
  • Print a detailed classification report showing per-species performance.
Create and train the Random Forest model

A Random Forest works by creating many decision trees, each trained on a slightly different random subset of the data. When it is time to make a prediction, every tree votes and the majority wins.

  • In iris_classifier.py, scroll to the bottom of the file (below the line that prints the testing set size).
  • Add the following code at the bottom to create and train your model:
# Step 3: Train and evaluate a Random Forest Classifier
print("\n" + "=" * 50)
print("TRAINING THE MODEL")
print("=" * 50)

clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_train, y_train)

What does this code do?

RandomForestClassifier(n_estimators=100, random_state=42) creates a forest of 100 decision trees. The random_state=42 parameter ensures you get reproducible results every time you run the script.

clf.fit(X_train, y_train) is where the actual learning happens. The model examines the 112 training samples and learns which combinations of petal and sepal measurements correspond to each species.

Why Random Forest instead of a single decision tree?

A single decision tree can memorize quirks in the training data and perform poorly on new data. By combining 100 trees that each see slightly different slices of the data, Random Forest smooths out those quirks and produces more reliable predictions.

Random Forest also provides feature importances natively, which you will use in the next step to understand which measurements matter most.

Make predictions and evaluate the model

Training is complete, but you need to know how well the model actually performs. You will test it on the 38 samples it has never seen and measure its accuracy.

  • Add this code directly below the clf.fit(X_train, y_train) line:
y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"\nModel Accuracy: {accuracy:.2%}")

print("\nClassification Report:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))

What does this code do?

clf.predict(X_test) feeds the 38 test samples into the trained model and returns a predicted species for each one. These predictions are stored in y_pred.

accuracy_score(y_test, y_pred) compares the predicted labels against the actual labels and calculates what percentage are correct.

classification_report goes deeper than a single accuracy number. It shows precision, recall, and F1-score for each of the three species, so you can see if the model struggles with any particular flower.

  • Save iris_classifier.py.
  • Run the script in your terminal by running:
python iris_classifier.py

You should see a "TRAINING THE MODEL" section in the output with an accuracy of 95% or higher, followed by a classification report table.

Not seeing 95%+ accuracy?

Make sure you used random_state=42 in both the train_test_split call (from the previous step) and the RandomForestClassifier call. Different random states produce different splits and forests, which changes accuracy.

If you see a NameError, check that the new code is placed after the train_test_split block. The variables X_train, y_train, X_test, and y_test must be defined before you use them.

help me debug my iris classifier accuracy issue

✔️ Awesome, I've got everything!

Great. Double check you have saved your file before moving on.

ⓧ I'd like to double check the full code

# Iris Flower Classifier - Machine Learning with scikit-learn
# Classifies iris flowers into 3 species based on petal/sepal measurements

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, ConfusionMatrixDisplay
import matplotlib.pyplot as plt
import numpy as np

# Step 2: Load and explore the Iris dataset
print("=" * 50)
print("IRIS FLOWER CLASSIFIER")
print("=" * 50)

iris = load_iris()
X = iris.data
y = iris.target

print(f"\nDataset shape: {X.shape}")
print(f"Number of samples: {X.shape[0]}")
print(f"Number of features: {X.shape[1]}")
print(f"Feature names: {iris.feature_names}")
print(f"Target names: {list(iris.target_names)}")
print(f"\nFirst 5 samples:")
print(X[:5])
print(f"Their labels: {y[:5]} -> {iris.target_names[y[:5]]}")

# Split data into training and testing sets (75% train, 25% test)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42
)
print(f"\nTraining set size: {X_train.shape[0]}")
print(f"Testing set size: {X_test.shape[0]}")

# Step 3: Train and evaluate a Random Forest Classifier
print("\n" + "=" * 50)
print("TRAINING THE MODEL")
print("=" * 50)

clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_train, y_train)

y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"\nModel Accuracy: {accuracy:.2%}")

print("\nClassification Report:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))

Your model is trained and evaluated. Next up, you will visualize which flower features the model considers most important for making its predictions.

Visualize Feature Importances

In the last step, you trained a Random Forest model and measured its accuracy. Knowing the model is accurate is useful, but understanding why it makes correct predictions is even more valuable.

Feature importances tell you which measurements the model relies on most when classifying flowers. In this step, you will extract those importance scores and turn them into a bar chart so you can see at a glance which features drive the predictions.

In this step, get ready to:
  • Extract feature importance scores from the trained Random Forest model.
  • Create a horizontal bar chart showing which iris features matter most.
  • Save the visualization to a file and display it.
Extract feature importances from the trained model

Random Forest models track how much each input feature contributes to correct predictions. This information is stored in the feature_importances_ attribute after the model is trained.

  • In iris_classifier.py, scroll to the bottom of your file (after the classification report line) and add the following code:
# Step 4: Visualize feature importances
print("=" * 50)
print("FEATURE IMPORTANCES")
print("=" * 50)

importances = clf.feature_importances_
feature_names = iris.feature_names

What does this code do?

clf.feature_importances_ returns an array of scores (one per feature) that sum to 1.0. A higher score means that feature played a bigger role in the model's decisions.

iris.feature_names gives us the human-readable labels (sepal length, sepal width, petal length, petal width) so we can label the chart clearly.

What is feature importance?

Feature importance measures how much each input variable helps the model make correct predictions. A Random Forest calculates this by looking at how much each feature reduces prediction errors across all its decision trees.

Features with higher importance scores are more useful for distinguishing between the three iris species.

  • Save iris_classifier.py.
Create and save the feature importance bar chart

Now that you have the raw importance scores, you will turn them into a horizontal bar chart using matplotlib. Sorting the bars from smallest to largest makes the most important feature stand out at the top.

  • Add the following code directly below the lines you just added in iris_classifier.py:
sorted_idx = np.argsort(importances)
plt.figure(figsize=(10, 6))
plt.barh(range(len(sorted_idx)), importances[sorted_idx], align="center")
plt.yticks(range(len(sorted_idx)), [feature_names[i] for i in sorted_idx])
plt.xlabel("Feature Importance")
plt.title("Random Forest - Feature Importances")
plt.tight_layout()
plt.savefig("feature_importances.png", dpi=150)
plt.show()

for i in sorted_idx:
    print(f"  {feature_names[i]}: {importances[i]:.4f}")

What does this code do?

  • np.argsort(importances) returns the indices that would sort the importances from lowest to highest. This lets the chart display features in rank order.
  • plt.barh() creates a horizontal bar chart. Horizontal bars are easier to read when labels are text (like feature names).
  • plt.savefig("feature_importances.png", dpi=150) saves the chart as an image file in your project folder at 150 dots per inch.
  • The for loop prints the exact numeric importance of each feature to the terminal so you have precise values alongside the visual.
  • Save iris_classifier.py.
  • Run the script by entering this command in your terminal:
python iris_classifier.py
  • A chart window will pop up showing the horizontal bar chart. Close the chart window to let the script continue.
  • You should see a "FEATURE IMPORTANCES" section printed in the terminal with numeric scores for each feature. Petal length and petal width should have the highest values.
  • Confirm that feature_importances.png was saved in your project folder by running:
ls

You should see feature_importances.png listed alongside iris_classifier.py.

Chart window not appearing?

Make sure your virtual environment is still activated (you should see (venv) in your terminal prompt). If matplotlib cannot find a display backend, the script may hang. Close any frozen terminal and rerun the script.

If the chart still does not appear, check that you saved the file after adding the new code. The feature_importances.png file should still be saved even if the window does not display.

Help me troubleshoot why my matplotlib chart is not showing up.

✔️ Awesome, I've got everything!

Great. Double check you have saved iris_classifier.py and that feature_importances.png exists in your project folder.

ⓧ I'd like to double check the full code

Here is the full iris_classifier.py file as it should look at the end of this step:

# Iris Flower Classifier - Machine Learning with scikit-learn
# Classifies iris flowers into 3 species based on petal/sepal measurements

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, ConfusionMatrixDisplay
import matplotlib.pyplot as plt
import numpy as np

# Step 2: Load and explore the Iris dataset
print("=" * 50)
print("IRIS FLOWER CLASSIFIER")
print("=" * 50)

iris = load_iris()
X = iris.data
y = iris.target

print(f"\nDataset shape: {X.shape}")
print(f"Number of samples: {X.shape[0]}")
print(f"Number of features: {X.shape[1]}")
print(f"Feature names: {iris.feature_names}")
print(f"Target names: {list(iris.target_names)}")
print(f"\nFirst 5 samples:")
print(X[:5])
print(f"Their labels: {y[:5]} -> {iris.target_names[y[:5]]}")

# Split data into training and testing sets (75% train, 25% test)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42
)
print(f"\nTraining set size: {X_train.shape[0]}")
print(f"Testing set size: {X_test.shape[0]}")

# Step 3: Train and evaluate a Random Forest Classifier
print("\n" + "=" * 50)
print("TRAINING THE MODEL")
print("=" * 50)

clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_train, y_train)

y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"\nModel Accuracy: {accuracy:.2%}")

print("\nClassification Report:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))

# Step 4: Visualize feature importances
print("=" * 50)
print("FEATURE IMPORTANCES")
print("=" * 50)

importances = clf.feature_importances_
feature_names = iris.feature_names

sorted_idx = np.argsort(importances)
plt.figure(figsize=(10, 6))
plt.barh(range(len(sorted_idx)), importances[sorted_idx], align="center")
plt.yticks(range(len(sorted_idx)), [feature_names[i] for i in sorted_idx])
plt.xlabel("Feature Importance")
plt.title("Random Forest - Feature Importances")
plt.tight_layout()
plt.savefig("feature_importances.png", dpi=150)
plt.show()

for i in sorted_idx:
    print(f"  {feature_names[i]}: {importances[i]:.4f}")

Your model can now show you exactly which measurements matter most. Next up, you will build a confusion matrix to see which specific species the model gets right and where it makes mistakes.

Create a Confusion Matrix Visualization

Your feature importance chart reveals which measurements the model relies on most. But it doesn't tell you where the model makes mistakes.

A confusion matrix solves this by comparing every prediction against the actual label. In this step, you'll generate one to see exactly which species your model confuses with each other.

In this step, get ready to:
  • Confirm the ConfusionMatrixDisplay import is already in place.
  • Generate and plot a confusion matrix showing prediction results per species.
  • Run the complete script end-to-end and verify both visualizations are saved.
Confirm the ConfusionMatrixDisplay import

A confusion matrix is a table that compares your model's predictions against the actual correct labels. Each cell shows how many samples of one species were predicted as another species.

scikit-learn provides ConfusionMatrixDisplay to generate this visualization. You already imported it at the top of your file back in Step 2.

  • In iris_classifier.py, scroll to the top and confirm this import line already exists:
from sklearn.metrics import accuracy_score, classification_report, ConfusionMatrixDisplay

What is a confusion matrix?

Accuracy tells you the overall percentage of correct predictions. A confusion matrix goes deeper by showing the breakdown per class.

For example, if your model misclassifies versicolor as virginica, the confusion matrix shows exactly how many times that happened. This helps you understand where the model struggles and where it excels.

Add the confusion matrix visualization code
  • In iris_classifier.py, scroll to the very bottom of the file.
  • Find the last line, which prints the feature importances:
for i in sorted_idx:
    print(f"  {feature_names[i]}: {importances[i]:.4f}")
  • Add the following code below that line to create and save the confusion matrix visualization:
# Step 5: Create a confusion matrix visualization
print("\n" + "=" * 50)
print("CONFUSION MATRIX")
print("=" * 50)

fig, ax = plt.subplots(figsize=(8, 6))
ConfusionMatrixDisplay.from_predictions(
    y_test, y_pred, display_labels=iris.target_names, ax=ax, cmap="Blues"
)
plt.title("Confusion Matrix - Iris Classifier")
plt.tight_layout()
plt.savefig("confusion_matrix.png", dpi=150)
plt.show()

print("\nDone! Check 'feature_importances.png' and 'confusion_matrix.png'")

What does this code do?

  • plt.subplots(figsize=(8, 6)) creates a figure and axes object. The axes object lets ConfusionMatrixDisplay draw directly onto the figure.
  • ConfusionMatrixDisplay.from_predictions() compares y_test (actual labels) against y_pred (predicted labels) and draws a colored grid.
  • display_labels=iris.target_names labels the axes with species names (setosa, versicolor, virginica) instead of numbers.
  • cmap="Blues" sets the color scheme. Darker blue cells indicate higher counts.
  • plt.savefig("confusion_matrix.png", dpi=150) saves the plot as a high-resolution PNG file in your project folder.
  • Save iris_classifier.py.

You won't see the confusion matrix yet. The next substep runs the complete script to generate it.

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before running it.

ⓧ I'd like to double check the full code

Here is the complete iris_classifier.py file at this point:

# Iris Flower Classifier - Machine Learning with scikit-learn
# Classifies iris flowers into 3 species based on petal/sepal measurements

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, ConfusionMatrixDisplay
import matplotlib.pyplot as plt
import numpy as np

# Step 2: Load and explore the Iris dataset
print("=" * 50)
print("IRIS FLOWER CLASSIFIER")
print("=" * 50)

iris = load_iris()
X = iris.data
y = iris.target

print(f"\nDataset shape: {X.shape}")
print(f"Number of samples: {X.shape[0]}")
print(f"Number of features: {X.shape[1]}")
print(f"Feature names: {iris.feature_names}")
print(f"Target names: {list(iris.target_names)}")
print(f"\nFirst 5 samples:")
print(X[:5])
print(f"Their labels: {y[:5]} -> {iris.target_names[y[:5]]}")

# Split data into training and testing sets (75% train, 25% test)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42
)
print(f"\nTraining set size: {X_train.shape[0]}")
print(f"Testing set size: {X_test.shape[0]}")

# Step 3: Train and evaluate a Random Forest Classifier
print("\n" + "=" * 50)
print("TRAINING THE MODEL")
print("=" * 50)

clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_train, y_train)

y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"\nModel Accuracy: {accuracy:.2%}")

print("\nClassification Report:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))

# Step 4: Visualize feature importances
print("=" * 50)
print("FEATURE IMPORTANCES")
print("=" * 50)

importances = clf.feature_importances_
feature_names = iris.feature_names

sorted_idx = np.argsort(importances)
plt.figure(figsize=(10, 6))
plt.barh(range(len(sorted_idx)), importances[sorted_idx], align="center")
plt.yticks(range(len(sorted_idx)), [feature_names[i] for i in sorted_idx])
plt.xlabel("Feature Importance")
plt.title("Random Forest - Feature Importances")
plt.tight_layout()
plt.savefig("feature_importances.png", dpi=150)
plt.show()

for i in sorted_idx:
    print(f"  {feature_names[i]}: {importances[i]:.4f}")

# Step 5: Create a confusion matrix visualization
print("\n" + "=" * 50)
print("CONFUSION MATRIX")
print("=" * 50)

fig, ax = plt.subplots(figsize=(8, 6))
ConfusionMatrixDisplay.from_predictions(
    y_test, y_pred, display_labels=iris.target_names, ax=ax, cmap="Blues"
)
plt.title("Confusion Matrix - Iris Classifier")
plt.tight_layout()
plt.savefig("confusion_matrix.png", dpi=150)
plt.show()

print("\nDone! Check 'feature_importances.png' and 'confusion_matrix.png'")
Run the complete script end-to-end

Your script is now complete. It loads data, trains a model, evaluates accuracy, and produces two visualizations. Time to run everything from start to finish.

  • Run the complete script by entering this command in your terminal:
python iris_classifier.py

Two matplotlib windows will open one after the other. Close each plot window to continue the script.

  • After the script finishes, confirm both image files were saved by running:
ls

You should see feature_importances.png and confusion_matrix.png listed alongside iris_classifier.py. The terminal output should end with:

Done! Check 'feature_importances.png' and 'confusion_matrix.png'

What should I see in the confusion matrix?

The confusion matrix is a grid with species names on both axes. The diagonal cells (top-left to bottom-right) show correct predictions. Off-diagonal cells show misclassifications.

For the Iris dataset, setosa is almost always predicted perfectly (it's the most distinct species). You may see one or two misclassifications between versicolor and virginica, since those two species overlap in their measurements.

Script not running or plots not appearing?

  • If you see a SyntaxError, check that your parentheses and quotes match exactly in the ConfusionMatrixDisplay.from_predictions() call. The arguments span multiple lines.
  • If the plot window appears blank, close it and check that you included plt.tight_layout() before plt.show().
  • If you see NameError: name 'y_test' is not defined, make sure you added the new code at the bottom of the file (after all the existing code), not in a separate file.

Help me debug my iris classifier script

Secret mission

Compare Multiple Classifiers with Cross-Validation

Your Random Forest model works well, but how do you know it's the best algorithm for this dataset? In this secret mission, you'll pit three different classifiers against each other using cross-validation to find the ultimate iris classifier.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely on your local machine, so there are no ongoing cloud costs or subscriptions to worry about. Decide whether to keep your project files for future experimentation, pause your environment, or delete everything.

Resources you used:

  • Project folder containing iris_classifier.py and generated images.
  • Python virtual environment (venv folder inside your project).
  • Generated visualizations: feature_importances.png, confusion_matrix.png, algorithm_comparison.png.

Keep everything running

No action needed. Choose this if you want to keep experimenting with your classifier, adding new models, or tweaking parameters.

  • Your project folder, virtual environment, and generated images all stay on your Desktop.
  • Python 3.13 and VS Code remain installed for future projects.

Pause - I'll come back to this later

Shut down the virtual environment to free up terminal state. Your files stay on disk so you can pick up where you left off.

  • Deactivate your virtual environment by running this command in your terminal:
deactivate
  • Close VS Code and your terminal window.
  • When you return, reactivate the environment with venv\Scripts\activate (Windows) or source venv/bin/activate (macOS/Linux).

Delete - I don't want to use this again

Remove all project files and start fresh. This deletes your script, virtual environment, and generated images.

  • Deactivate your virtual environment first by running:
deactivate
  • Navigate to your Desktop and delete the project folder.

On macOS/Linux:

cd ~/Desktop
rm -rf iris-classifier

On Windows:

cd $HOME\Desktop
rmdir /s /q iris-classifier
  • Python 3.13 and VS Code are general-purpose tools useful for future projects. Keep them installed unless you are certain you will not use them again.

Nice Work!

Nice Work!

Congratulations! You just trained your first machine learning model. You built a complete Python pipeline that loads real data, trains a Random Forest classifier, evaluates its accuracy, and visualizes the results.

You've learned how to:

  • Loaded and split the Iris dataset into training and testing sets to evaluate model performance fairly.
  • Trained a Random Forest classifier that achieves 95%+ accuracy and generated a classification report showing precision, recall, and F1-score for each species.
  • Visualized feature importances and a confusion matrix to understand what drives predictions and where the model succeeds.
  • Compared multiple algorithms using cross-validation to find the best classifier for the dataset.

Ready to quiz yourself?