Flower Species Predictor in Python
Train ML models to classify iris flowers by petal and sepal measurements.
Introduction
30 Second Summary
Every time a plant identification app tells you which flower you're looking at, there's a machine learning model behind the scenes comparing measurements and making a prediction. The same technique powers spam filters, medical diagnoses, and fraud detection.
In this project, you will build a machine learning model that predicts iris flower species from physical measurements. You'll train two different models, compare their accuracy, and visualize how they make decisions.
What You'll Build
A Python script that takes iris flower measurements (petal length, petal width, sepal length, sepal width) and predicts which of three species the flower belongs to using trained classification models.
By the end of this project, you'll have:
- A working classification pipeline that loads data, splits it for training and testing, trains models, and evaluates predictions.
- Two trained machine learning models (Decision Tree and Logistic Regression) with accuracy comparison to understand model selection.
- Data visualizations including scatter plots and confusion matrices that show how your models separate species and where they make mistakes.
- Secret Mission: Apply your ML workflow to a completely new dataset and prove the pattern is transferable.
Are there any prerequisites?
You'll need basic Python knowledge (variables, functions, loops). No prior machine learning experience is required.
Set Up Your Python Environment
Before you can train a machine learning model, you need the right tools on your machine. Python is the programming language that powers most ML workflows, and a few key libraries handle the heavy lifting.
In this step, you'll install Python, set up an isolated project environment, and install the three libraries your classifier needs.
In this step, get ready to:
- Install Python 3.12 or newer.
- Create a project folder with a virtual environment.
- Install scikit-learn, pandas, and matplotlib.
Install Python
Python is the language you'll write your classifier in. The ML libraries this project uses require Python 3.12 or newer.
- Open your browser and go to python.org/downloads.
- Download the latest Python installer for your operating system.
What about the PATH checkbox?
On Windows, the installer shows an option labelled Add Python to PATH on the very first screen. Check this box before clicking Install Now. Without it, your terminal will not find the python command.
On macOS, the python.org installer adds Python to your shell path automatically.
- Run the installer and follow the prompts to completion.
- Once the installer finishes, open a terminal to verify the installation.
- 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 your Python version by running this command:
macOS
python3 --version
Windows
python --version
✔️ I see version 3.12 or higher
You're all set. Your terminal shows something like Python 3.12.x or Python 3.13.x or higher. Move on to the next substep.
ⓧ I see an older version
Your system has an older Python installed. The ML libraries in this project require Python 3.12 or newer.
- Go back to python.org/downloads and download the latest Python 3.12+ installer.
- On Windows, make sure Add Python to PATH is checked, then click Install Now.
- On macOS, double-click the .pkg file and follow the installer prompts. The new version installs alongside the old one.
- After installation, close and reopen your terminal, then re-run the version check command above.
macOS users with an older system Python
After installing from python.org, the new version is available as python3 in your terminal. If python3 --version still shows the old version, open a fresh terminal window and try again.
ⓧ Command not found
Your system does not have Python installed yet.
- Go to python.org/downloads and download the latest Python 3.12+ installer for your operating system.
- On Windows, check Add Python to PATH on the first screen, then click Install Now.
- On macOS, double-click the downloaded .pkg file and follow the installer prompts.
- Close and reopen your terminal after installation, then re-run the version check command above.
Create a project folder and virtual environment
A virtual environment is an isolated space where Python installs packages just for this project. It keeps your system clean and prevents version conflicts between projects.
You'll also need Visual Studio Code as your code editor. If you don't already have it, download it from code.visualstudio.com and run the installer for your operating system.
- 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, open the integrated terminal by pressing Ctrl+` (Windows) or Cmd+` (macOS).
- 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
- Now open this folder in VS Code by clicking File in the top menu bar.
- Click Open Folder.
- Navigate to your Desktop, select the iris-classifier folder, and click Open.
- If VS Code asks whether you trust the authors of the files in this folder, click Yes, I trust the authors.
- Open a new integrated terminal by pressing Ctrl+` (Windows) or Cmd+` (macOS).
Your terminal prompt should now show you're inside the iris-classifier folder.
- Create and activate a virtual environment by running these commands:
macOS
python3 -m venv venv
source venv/bin/activate
Windows
python -m venv venv
venv\Scripts\activate
What do these commands do?
python -m venv venv creates a new virtual environment inside a folder called venv. This folder holds its own copy of Python and a place to install packages.
The activate command switches your terminal session to use this isolated environment. You'll know it worked when you see (venv) at the start of your terminal prompt.
You should see (venv) appear at the beginning of your terminal prompt.
Don't see (venv) in your prompt?
Make sure you ran the activate command (not just the python -m venv venv command). On Windows, if you get a script execution error, run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned in PowerShell first, then try the activate command again.
help me activate my Python virtual environment
Install the ML libraries
With your virtual environment active, you can install the three libraries your classifier needs. scikit-learn provides the ML algorithms. pandas makes data exploration easy. matplotlib handles visualization.
- Install all three libraries by running this command:
pip install scikit-learn pandas matplotlib
What is pip installing?
This single command installs scikit-learn (the ML toolkit), pandas (data manipulation), and matplotlib (plotting). It also installs their dependencies like NumPy and SciPy automatically.
The installation may take a minute or two. You'll see progress bars as each package downloads.
- Verify that scikit-learn installed correctly by running:
python -c "import sklearn; print(sklearn.__version__)"
You should see a version number like 1.8.0 printed in your terminal.
Seeing a ModuleNotFoundError?
Make sure your virtual environment is still active. You should see (venv) at the start of your prompt. If not, re-run the activate command from the previous substep.
If you're on macOS and used python3 to create the venv, use python3 in this command too: python3 -c "import sklearn; print(sklearn.__version__)".
help me fix my scikit-learn installation
Your environment is ready to go. Next up, you'll load your first dataset and start exploring the data your model will learn from.
Load and Explore the Iris Dataset
Your Python environment is ready with all the libraries installed. Now it's time to bring in some real data and see what machine learning actually works with.
In this step, you'll load a classic dataset, explore its structure, and create a visualization that reveals patterns hiding in the numbers.
In this step, get ready to:
- Create your Python script and load the Iris dataset into a DataFrame.
- Explore the dataset structure with shape, features, and statistics.
- Visualize the data with a scatter plot that reveals class separation.
Create your script and load the data
The Iris dataset is the "Hello World" of machine learning. It contains 150 flower measurements across three species, with no missing values and clear patterns.
It's built directly into scikit-learn, so there's nothing to download. You'll load it into a pandas DataFrame for easy exploration.
- In the VS Code Explorer sidebar, right-click inside the iris-classifier folder and select New File.
- Name the file iris_classifier.py and press Enter.
- Add the following imports and data loading code to your new file:
# Step 2: Load and Explore the Iris Dataset
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, ConfusionMatrixDisplay
# Load the Iris dataset
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df["species"] = iris.target
What does this code do?
The imports bring in all the tools you'll need for this project. You won't use all of them in this step, but importing them upfront keeps your file organized.
- pandas gives you DataFrames for exploring tabular data.
- matplotlib creates charts and visualizations.
- load_iris() loads the dataset directly from scikit-learn. No file downloads needed.
- df["species"] = iris.target adds the species label (0, 1, or 2) as a new column in the DataFrame.
- Save iris_classifier.py with Ctrl+S.
- Run the script in your terminal by running:
python iris_classifier.py
You should see no output and no errors. The data is loaded silently into memory.
Seeing a ModuleNotFoundError?
- Make sure your virtual environment is activated. You should see (venv) at the start of your terminal prompt.
- If you don't see (venv), reactivate it with venv\Scripts\activate and then rerun the install command from Step 1.
Why is my script throwing a ModuleNotFoundError?
Explore the dataset structure
Before training any model, you need to understand your data. How many samples are there? What features do you have? What are you trying to predict?
- In iris_classifier.py, add the following code below the line df["species"] = iris.target:
# Explore the dataset
print("Dataset shape:", df.shape)
print("\nFeature names:", iris.feature_names)
print("\nTarget names:", iris.target_names)
print("\nFirst 5 rows:")
print(df.head())
print("\nBasic statistics:")
print(df.describe())
What does this code do?
- df.shape tells you the dataset has 150 rows (samples) and 5 columns (4 features + species).
- iris.feature_names shows the four measurements: sepal length, sepal width, petal length, and petal width.
- iris.target_names reveals the three species you're predicting: setosa, versicolor, and virginica.
- df.describe() gives summary statistics like mean, min, max, and standard deviation for each feature.
- Save iris_classifier.py and run it again:
python iris_classifier.py
You should see the dataset shape (150, 5), a table of the first 5 rows, and statistics for each column printed in your terminal.
What do these numbers mean?
150 samples means you have 150 individual flower measurements. 4 features means each flower was measured in 4 ways. 3 target classes means there are 3 species to predict.
Your model's job is to learn which combinations of measurements correspond to which species.
Seeing a SyntaxError?
- Check that you have matching quotes on every print() statement. Each string needs opening and closing quotes.
- Make sure there's no extra indentation on the print lines. They should all start at column 1 (no spaces before them).
Help me fix a SyntaxError in my iris_classifier.py script.
Visualize the data with a scatter plot
Numbers are useful, but a picture reveals patterns instantly. A scatter plot of petal measurements shows you why machine learning can work on this data.
If the species form distinct clusters in the plot, a model can learn to draw boundaries between them.
- Add the following visualization code at the bottom of iris_classifier.py:
# Visualize: scatter plot of petal length vs petal width
plt.figure(figsize=(8, 6))
for species_id, species_name in enumerate(iris.target_names):
subset = df[df["species"] == species_id]
plt.scatter(
subset["petal length (cm)"],
subset["petal width (cm)"],
label=species_name
)
plt.xlabel("Petal Length (cm)")
plt.ylabel("Petal Width (cm)")
plt.title("Iris Species by Petal Measurements")
plt.legend()
plt.savefig("iris_scatter.png")
plt.show()
What does this code do?
- The for loop plots each species in a different color, so you can see how they cluster.
- plt.savefig("iris_scatter.png") saves the chart as an image file in your project folder.
- plt.show() opens the chart in a pop-up window so you can see it immediately.
- Save iris_classifier.py and run it again:
python iris_classifier.py
A window pops up with a scatter plot showing three distinct clusters of dots. Close the plot window to continue.
- Confirm the image was saved by running:
ls
You should see iris_scatter.png listed alongside iris_classifier.py in the output.
What should the scatter plot look like?
You should see three groups of dots. Setosa (one color) sits in the bottom-left corner, clearly separated from the other two species.
Versicolor and virginica overlap slightly in the middle-right area. This overlap is what makes the classification challenge interesting. A model needs to learn the boundary between these two.
Plot window not appearing?
- On some systems, the plot window opens behind VS Code. Check your taskbar for a Python or matplotlib window.
- Even if the window doesn't appear, the image still saves to your folder. Check for iris_scatter.png in the VS Code Explorer sidebar.
Why isn't my matplotlib plot window showing up?
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
Here's the complete iris_classifier.py so far:
# Step 2: Load and Explore the Iris Dataset
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, ConfusionMatrixDisplay
# Load the Iris dataset
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df["species"] = iris.target
# Explore the dataset
print("Dataset shape:", df.shape)
print("\nFeature names:", iris.feature_names)
print("\nTarget names:", iris.target_names)
print("\nFirst 5 rows:")
print(df.head())
print("\nBasic statistics:")
print(df.describe())
# Visualize: scatter plot of petal length vs petal width
plt.figure(figsize=(8, 6))
for species_id, species_name in enumerate(iris.target_names):
subset = df[df["species"] == species_id]
plt.scatter(
subset["petal length (cm)"],
subset["petal width (cm)"],
label=species_name
)
plt.xlabel("Petal Length (cm)")
plt.ylabel("Petal Width (cm)")
plt.title("Iris Species by Petal Measurements")
plt.legend()
plt.savefig("iris_scatter.png")
plt.show()
You've loaded real data, explored its structure, and created a visualization that shows clear patterns. Next up, you'll split this data and train your first machine learning model.
Split Data and Train Your First Model
In the previous step, you loaded the Iris dataset and explored its structure. Your scatter plot showed clear clusters of species based on petal measurements.
Now you'll train a machine learning model to automatically classify those species from measurements. To do this properly, you first need to split your data into two groups: one for training and one for testing.
In this step, get ready to:
- Split the dataset into training and test sets.
- Train a Decision Tree classifier on the training data.
- Make predictions and measure accuracy on unseen test data.
Split into training and test sets
A machine learning model needs to prove it works on data it has never seen before. If you test it on the same data you trained it with, you have no way to know if it actually learned patterns or just memorized the answers.
What is a train/test split?
You divide your dataset into two groups. The training set (80%) is what the model learns from. The test set (20%) is held back to evaluate performance on unseen data.
This prevents overfitting, where a model scores perfectly on training data but fails on new data. The test set acts as a reality check.
- In iris_classifier.py, scroll to the bottom of your file (after the plt.show() line) and add the following code:
# Step 3: Split Data and Train Your First Model
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42
)
print(f"\nTraining set size: {X_train.shape[0]}")
print(f"Test set size: {X_test.shape[0]}")
What does this code do?
- X = iris.data stores the 4 feature measurements (petal length, petal width, sepal length, sepal width) as the input data.
- y = iris.target stores the species labels (0, 1, or 2) as the answers the model needs to learn.
- test_size=0.2 reserves 20% of the data (30 samples) for testing.
- stratify=y ensures each species is represented proportionally in both sets, so you don't accidentally put all of one species in the test set.
- random_state=42 makes the split reproducible. Everyone running this code gets the same split.
- Save iris_classifier.py.
- Run the script in your terminal by running:
python iris_classifier.py
- Close the scatter plot window when it appears. After it closes, you should see Training set size: 120 and Test set size: 30 printed in the terminal.
Don't see the training/test sizes?
- Make sure you close the matplotlib plot window that pops up. The script pauses at plt.show() until you close it.
- Check that your new code is below the plt.show() line, not above it.
- Verify your virtual environment is active. You should see (venv) at the start of your terminal prompt.
Why isn't my train/test split printing output?
Train a Decision Tree classifier
Your data is split and ready. Now you'll feed the training set to a Decision Tree algorithm, which learns rules like "if petal length > 2.5 cm and petal width < 1.7 cm, then it's versicolor."
- Add this code below the print statements you just wrote:
# Train a Decision Tree classifier
dt_model = DecisionTreeClassifier(random_state=42)
dt_model.fit(X_train, y_train)
What does this code do?
- DecisionTreeClassifier(random_state=42) creates a new, untrained Decision Tree model.
- .fit(X_train, y_train) is where the learning happens. The model examines the 120 training samples and builds a tree of decision rules to classify species.
You won't see new output from this code yet. The next section uses this trained model to make predictions.
Make predictions and check accuracy
Your model is trained. Time for the moment of truth: give it the 30 test samples it has never seen and check how many species it classifies correctly.
- Add this code below the .fit() line:
# Make predictions and check accuracy
dt_predictions = dt_model.predict(X_test)
dt_accuracy = accuracy_score(y_test, dt_predictions)
print(f"\nDecision Tree Accuracy: {dt_accuracy:.4f}")
What does this code do?
- .predict(X_test) feeds the 30 test measurements to the model and gets back 30 predicted species labels.
- accuracy_score(y_test, dt_predictions) compares the predictions against the actual answers and returns the percentage that matched.
- :.4f formats the accuracy to 4 decimal places for readability.
- Save iris_classifier.py and run the script again:
python iris_classifier.py
- Close the scatter plot window. You should see Decision Tree Accuracy: followed by a number above 0.90 printed in your terminal.
What does this accuracy mean?
An accuracy of 0.96 means the model correctly classified 96% of the test flowers. Out of 30 test samples, it might only get 1 wrong. Not bad for a few lines of code.
Seeing a NameError or accuracy of 0.0?
- If you see NameError: name 'X_train' is not defined, make sure the train_test_split code comes before the Decision Tree training code.
- Check that you're passing X_test to .predict(), not X_train. Testing on training data defeats the purpose of the split.
Help me debug my Decision Tree accuracy score.
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
Here's what your full iris_classifier.py should look like at this point:
# Step 2: Load and Explore the Iris Dataset
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, ConfusionMatrixDisplay
# Load the Iris dataset
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df["species"] = iris.target
# Explore the dataset
print("Dataset shape:", df.shape)
print("\nFeature names:", iris.feature_names)
print("\nTarget names:", iris.target_names)
print("\nFirst 5 rows:")
print(df.head())
print("\nBasic statistics:")
print(df.describe())
# Visualize: scatter plot of petal length vs petal width
plt.figure(figsize=(8, 6))
for species_id, species_name in enumerate(iris.target_names):
subset = df[df["species"] == species_id]
plt.scatter(
subset["petal length (cm)"],
subset["petal width (cm)"],
label=species_name
)
plt.xlabel("Petal Length (cm)")
plt.ylabel("Petal Width (cm)")
plt.title("Iris Species by Petal Measurements")
plt.legend()
plt.savefig("iris_scatter.png")
plt.show()
# Step 3: Split Data and Train Your First Model
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42
)
print(f"\nTraining set size: {X_train.shape[0]}")
print(f"Test set size: {X_test.shape[0]}")
# Train a Decision Tree classifier
dt_model = DecisionTreeClassifier(random_state=42)
dt_model.fit(X_train, y_train)
# Make predictions and check accuracy
dt_predictions = dt_model.predict(X_test)
dt_accuracy = accuracy_score(y_test, dt_predictions)
print(f"\nDecision Tree Accuracy: {dt_accuracy:.4f}")
Your first ML model is trained and delivering strong accuracy. Next up, you'll dig deeper into how the model performs per species and compare it against a second algorithm to see which one does better.
Evaluate and Compare Models
Your Decision Tree is trained and making predictions. But a single accuracy number only tells part of the story. Which species does the model struggle with? Are there patterns in the mistakes?
In this step, you'll dig deeper into model performance with classification reports and confusion matrices. You'll also train a second model to compare. Professional data scientists never ship the first model they try.
In this step, get ready to:
- Generate a classification report and confusion matrix for your Decision Tree.
- Train a Logistic Regression model and compare its accuracy.
- Visualize confusion matrices side by side for both models.
Generate a classification report and confusion matrix
Accuracy tells you what percentage of predictions were correct overall. A classification report breaks this down per species, showing precision, recall, and F1-score. A confusion matrix shows exactly which species get confused with each other.
- In iris_classifier.py, add the following code at the bottom of your file to generate detailed evaluation metrics:
# Step 4: Evaluate and Compare Models
print("\nDecision Tree Classification Report:")
print(classification_report(y_test, dt_predictions, target_names=iris.target_names))
print("Decision Tree Confusion Matrix:")
dt_cm = confusion_matrix(y_test, dt_predictions)
print(dt_cm)
What does this code do?
classification_report prints precision (of all flowers predicted as species X, how many were correct), recall (of all actual species X flowers, how many were found), and F1-score (the balance of both) for each species.
confusion_matrix returns a grid where each row is the true species and each column is the predicted species. Diagonal values are correct predictions. Off-diagonal values are mistakes.
- Save iris_classifier.py and run it in your terminal:
python iris_classifier.py
- You should see a formatted table with precision, recall, and F1-score for each species (setosa, versicolor, virginica), followed by a 3x3 grid of numbers representing the confusion matrix.
Seeing a NameError?
Make sure you added this code below the existing Decision Tree code from Step 3. The variables y_test, dt_predictions, and iris.target_names must already be defined earlier in the script.
help me debug my classification report code
Train a second model for comparison
A single model's accuracy is meaningless without a baseline. Logistic Regression is one of the simplest and most reliable classifiers. Training a second model lets you see if the Decision Tree's performance is genuinely good or just average for this dataset.
- Add the following code below your confusion matrix output to train and evaluate a Logistic Regression model:
# Train a Logistic Regression model for comparison
lr_model = LogisticRegression(max_iter=200, random_state=42)
lr_model.fit(X_train, y_train)
lr_predictions = lr_model.predict(X_test)
lr_accuracy = accuracy_score(y_test, lr_predictions)
print(f"\nLogistic Regression Accuracy: {lr_accuracy:.4f}")
print("\nLogistic Regression Classification Report:")
print(classification_report(y_test, lr_predictions, target_names=iris.target_names))
What does this code do?
LogisticRegression(max_iter=200, random_state=42) creates a Logistic Regression classifier. The max_iter=200 parameter gives the model enough iterations to converge on a solution. The default of 100 sometimes is not enough and triggers a warning.
The rest follows the same pattern as your Decision Tree: fit on training data, predict on test data, measure accuracy. This consistent API is one of the reasons scikit-learn is so popular.
- Save iris_classifier.py and run the script again:
python iris_classifier.py
- You should see the Logistic Regression accuracy printed, followed by its classification report. Compare the accuracy numbers for both models.
Why compare two models?
Different algorithms learn patterns in different ways. A Decision Tree splits data along feature thresholds (like "if petal length > 2.5 cm"). Logistic Regression draws linear boundaries between classes.
One model might perform better depending on how the data is shaped. Comparing models is a habit that separates professional ML practitioners from beginners.
Seeing a convergence warning?
If you see a warning about convergence, make sure you set max_iter=200 in the LogisticRegression() call. This gives the algorithm more iterations to find a solution.
help me fix a convergence warning
Visualize the confusion matrix
Numbers in a raw matrix are hard to interpret at a glance. A heatmap makes it instantly clear where the model succeeds and where it struggles.
- Add this code at the bottom of iris_classifier.py to create a side-by-side confusion matrix visualization for both models:
# Visualize the confusion matrix
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
ConfusionMatrixDisplay.from_predictions(
y_test, dt_predictions,
display_labels=iris.target_names,
ax=axes[0]
)
axes[0].set_title("Decision Tree")
ConfusionMatrixDisplay.from_predictions(
y_test, lr_predictions,
display_labels=iris.target_names,
ax=axes[1]
)
axes[1].set_title("Logistic Regression")
plt.tight_layout()
plt.savefig("confusion_matrices.png")
plt.show()
print("\n--- Model Comparison ---")
print(f"Decision Tree Accuracy: {dt_accuracy:.4f}")
print(f"Logistic Regression Accuracy: {lr_accuracy:.4f}")
best = "Decision Tree" if dt_accuracy >= lr_accuracy else "Logistic Regression"
print(f"Best model: {best}")
What does this code do?
plt.subplots(1, 2) creates a figure with two side-by-side plots. ConfusionMatrixDisplay.from_predictions() generates a color-coded heatmap where darker cells mean more predictions fell in that bucket.
The final comparison block prints both accuracies together and determines which model performed best. The image is saved as confusion_matrices.png so you have a visual record of your results.
- Save iris_classifier.py and run the script one final time:
python iris_classifier.py
- A window should pop up showing two confusion matrix heatmaps side by side. Close the plot window to let the script finish printing the model comparison summary.
- You should also see confusion_matrices.png appear in your iris-classifier folder.
Plot window not appearing?
Some environments suppress plot display. Check that confusion_matrices.png was saved in your project folder. You can open the image file directly to verify the visualization.
If the file was not created, check that plt.savefig("confusion_matrices.png") appears before plt.show() in your code. Calling show first clears the figure.
help me fix my confusion matrix visualization
✔️ Awesome, I've got everything!
Great. Double check you've saved your file and your iris-classifier folder now contains both iris_scatter.png and confusion_matrices.png.
ⓧ I'd like to double check the full code
Here is the complete iris_classifier.py file up to this point. Compare yours against it:
# Step 2: Load and Explore the Iris Dataset
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, ConfusionMatrixDisplay
# Load the Iris dataset
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df["species"] = iris.target
# Explore the dataset
print("Dataset shape:", df.shape)
print("\nFeature names:", iris.feature_names)
print("\nTarget names:", iris.target_names)
print("\nFirst 5 rows:")
print(df.head())
print("\nBasic statistics:")
print(df.describe())
# Visualize: scatter plot of petal length vs petal width
plt.figure(figsize=(8, 6))
for species_id, species_name in enumerate(iris.target_names):
subset = df[df["species"] == species_id]
plt.scatter(
subset["petal length (cm)"],
subset["petal width (cm)"],
label=species_name
)
plt.xlabel("Petal Length (cm)")
plt.ylabel("Petal Width (cm)")
plt.title("Iris Species by Petal Measurements")
plt.legend()
plt.savefig("iris_scatter.png")
plt.show()
# Step 3: Split Data and Train Your First Model
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42
)
print(f"\nTraining set size: {X_train.shape[0]}")
print(f"Test set size: {X_test.shape[0]}")
# Train a Decision Tree classifier
dt_model = DecisionTreeClassifier(random_state=42)
dt_model.fit(X_train, y_train)
# Make predictions and check accuracy
dt_predictions = dt_model.predict(X_test)
dt_accuracy = accuracy_score(y_test, dt_predictions)
print(f"\nDecision Tree Accuracy: {dt_accuracy:.4f}")
# Step 4: Evaluate and Compare Models
print("\nDecision Tree Classification Report:")
print(classification_report(y_test, dt_predictions, target_names=iris.target_names))
print("Decision Tree Confusion Matrix:")
dt_cm = confusion_matrix(y_test, dt_predictions)
print(dt_cm)
# Train a Logistic Regression model for comparison
lr_model = LogisticRegression(max_iter=200, random_state=42)
lr_model.fit(X_train, y_train)
lr_predictions = lr_model.predict(X_test)
lr_accuracy = accuracy_score(y_test, lr_predictions)
print(f"\nLogistic Regression Accuracy: {lr_accuracy:.4f}")
print("\nLogistic Regression Classification Report:")
print(classification_report(y_test, lr_predictions, target_names=iris.target_names))
# Visualize the confusion matrix
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
ConfusionMatrixDisplay.from_predictions(
y_test, dt_predictions,
display_labels=iris.target_names,
ax=axes[0]
)
axes[0].set_title("Decision Tree")
ConfusionMatrixDisplay.from_predictions(
y_test, lr_predictions,
display_labels=iris.target_names,
ax=axes[1]
)
axes[1].set_title("Logistic Regression")
plt.tight_layout()
plt.savefig("confusion_matrices.png")
plt.show()
print("\n--- Model Comparison ---")
print(f"Decision Tree Accuracy: {dt_accuracy:.4f}")
print(f"Logistic Regression Accuracy: {lr_accuracy:.4f}")
best = "Decision Tree" if dt_accuracy >= lr_accuracy else "Logistic Regression"
print(f"Best model: {best}")
You now have a complete ML classification pipeline. You loaded data, explored it visually, split it properly, trained two models, and evaluated them with multiple metrics. This is the exact workflow data scientists use every day, regardless of the dataset or problem.
Secret mission
Apply Your Workflow to a New Dataset
The real test of any skill is whether you can apply it to something new. Take everything you just learned and use it on a completely different dataset. If the workflow transfers, you've truly learned it.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing costs. Decide whether to keep your project files for future reference, or delete them to free up disk space.
Resources you used:
- iris-classifier project folder on your Desktop (includes Python scripts, virtual environment, and generated images).
Keep everything running
No action needed. Choose this if you plan to keep experimenting with the scripts or want to reference your code later.
- Your iris-classifier folder stays on your Desktop with all scripts and generated images intact.
- The virtual environment venv stays inside the project folder. Reactivate it anytime to run your scripts again.
Pause - I'll come back to this later
Since this project is entirely local with no running processes, there is nothing to pause. Your files sit on disk without consuming any active resources.
- Deactivate your virtual environment by running:
deactivate
- When you return, reactivate the virtual environment and run your scripts as before.
Delete - I don't want to use this again
Remove all project files and start fresh. This deletes your scripts, the virtual environment, and all generated images.
- Deactivate your virtual environment first by running:
deactivate
- Navigate to your Desktop and delete the project folder.
macOS
cd ~/Desktop
rm -rf iris-classifier
Windows
cd ~\Desktop
rmdir /s /q iris-classifier
- Confirm the folder is gone by running:
ls
You should no longer see iris-classifier in the output.
Nice Work!
Nice Work!
Congratulations! You just built your first machine learning models from scratch. You took raw flower measurements, trained two different classifiers, and evaluated their performance with real metrics.
You've learned how to:
- Loaded and explored a dataset using pandas and matplotlib, then split it into training and test sets to prevent data leakage.
- Trained a Decision Tree classifier and a Logistic Regression model, then compared their accuracy to build the habit of never shipping the first model you try.
- Evaluated models with accuracy scores, classification reports, and confusion matrix visualizations to understand exactly where your models succeed and fail.
- Applied the same ML workflow to a completely new dataset (the Wine dataset), proving the pattern is transferable to any classification problem.
Ready to quiz yourself?