Machine Learning · lesson 3 of 11
Beginner
4Intermediate
5Advanced
2Also part of Machine Learning
6Introduction to Machine Learning Models
Build, train, and evaluate your first classification model using Scikit-Learn.
By SkillByExample · Updated
Machine learning focuses on algorithms that learn patterns from datasets. In this tutorial, we will build a classification model to predict iris species using scikit-learn.
Environment Setup
Install the required scientific packages:
pip install scikit-learn numpy pandas
Model Training Lifecycle
The machine learning lifecycle consists of:
- Loading and cleaning data.
- Splitting into training and test datasets.
- Defining and training the model estimator.
- Evaluating metrics.
import pandas as pd
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
# 1. Load Dataset
raw_data = load_iris()
X = pd.DataFrame(raw_data.data, columns=raw_data.feature_names)
y = raw_data.target
# 2. Split Data (80% Train, 20% Test)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# 3. Initialize and Train Model
classifier = RandomForestClassifier(n_estimators=100, random_state=42)
classifier.fit(X_train, y_train)
# 4. Predict and Evaluate
predictions = classifier.predict(X_test)
accuracy = accuracy_score(y_test, predictions)
print(f"Model Accuracy: {accuracy:.4f}")
print("\nClassification Report:")
print(classification_report(y_test, predictions, target_names=raw_data.target_names))
$ python ml_lifecycle.py
Model Accuracy: 0.9000
Classification Report:
precision recall f1-score support
setosa 1.00 1.00 1.00 10
versicolor 0.82 0.90 0.86 10
virginica 0.89 0.80 0.84 10
accuracy 0.90 30
macro avg 0.90 0.90 0.90 30
weighted avg 0.90 0.90 0.90 30
Setosa is linearly separable from the other two species, so the forest gets it perfect. The errors are all versicolor/virginica confusion — those two overlap in petal measurements, which is why precision and recall split unevenly between them instead of failing uniformly.
Tracking Parameters
In production environments, avoid running scripts blind. Use MLOps systems like MLflow to track parameters:
import mlflow
with mlflow.start_run():
mlflow.log_param("n_estimators", 100)
mlflow.log_metric("accuracy", accuracy)
mlflow.sklearn.log_model(
classifier, name="model", skops_trusted_types=["sklearn.tree._tree.Tree"]
)
print("Logged run:", mlflow.active_run().info.run_id)
$ python ml_mlflow.py
Logged run: 6606a35aedb64eed890f7bf2f63ee2bc
Your run ID will differ — MLflow generates a fresh one per run. As of MLflow 3.x,
log_model serializes scikit-learn estimators with skops instead of pickle, and
skops refuses to load tree-based models (RandomForest, GradientBoosting, decision
trees) unless you name sklearn.tree._tree.Tree in skops_trusted_types — the flat
node-index arrays those models store aren’t bounds-checked on load, so skops treats
them as untrusted by default. Only pass that argument for models you created yourself.
Practice
-
Change
test_sizefrom0.2to0.4and re-run. Does accuracy go up or down, and why might a smaller training set hurt a forest more than a linear model?Solution
Accuracy typically drops a little (fewer training examples means less data per tree to split on), and the per-class report becomes noisier because each test class now has more than 10 samples, so a single misclassification swings the score less.
-
Swap
RandomForestClassifierforsklearn.linear_model.LogisticRegression(addmax_iter=200) and compareclassification_reportoutput.Solution
from sklearn.linear_model import LogisticRegression classifier = LogisticRegression(max_iter=200, random_state=42)On this dataset logistic regression scores similarly to the forest — iris is small and close to linearly separable, so the extra capacity of a forest isn’t needed.
-
Log a second MLflow run with
n_estimators=10instead of100and compare the loggedaccuracymetric between runs usingmlflow.search_runs().Solution
import mlflow runs = mlflow.search_runs(order_by=["metrics.accuracy DESC"]) print(runs[["run_id", "metrics.accuracy", "params.n_estimators"]])Fewer trees usually means a small accuracy drop, though on a dataset this small the gap can be within noise.
-
Remove
stratify=yfrom thetrain_test_splitcall and re-run several times. Why does the classification report vary more between runs now?Solution
Without stratification, each split’s class proportions are random, so a small test set (30 rows) can end up with, say, 12 setosa and 6 virginica instead of an even 10/10/10 split — that imbalance shows up directly in per-class support and recall.