Tutorial

Applied ML Cheatsheet in Python: Iris Dataset From EDA to Cross-Validation

End-to-end ML in Python on the Iris dataset — EDA, train-test split, scaling, logistic regression, decision trees, and metrics.

Anuj SainiAug 23, 20264 min read

This notebook is the shortest path from "I know Python" to "I shipped a model" — Iris end-to-end with every line you will repeat on the next dataset.

What does the minimal honest pipeline contain?

Load -> EDA -> Train/Test split -> Scale (fit on train only) -> Fit -> Predict -> Report -> Cross-validate. Skip any step and the accuracy you quote leaks. Cross-reference EDA playbook for the inspection twin and NumPy foundations for array mechanics.

Ingredients: Iris (150 rows, 4 numeric features, 3 species), the classic clean dataset for a first pipeline.

How do you load and inspect Iris?

Setup:

python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix
python
iris = load_iris()
X_raw, y_raw = iris.data, iris.target
feature_names, target_names = iris.feature_names, iris.target_names
 
df = pd.DataFrame(X_raw, columns=feature_names)
df['species'] = y_raw
df['species_name'] = df['species'].map({0:'setosa',1:'versicolor',2:'virginica'})
print(df.head(3))
print(df['species_name'].value_counts())

Rendered output: three rows with sepal length (cm) ~5.1 etc. and species_name counts 50/50/50 — perfectly balanced, so accuracy is honest here (unlike imbalanced churn later).

How do you do EDA before any model?

One pairplot plus a correlation heatmap answers "are features separable?"

python
sns.pairplot(df, hue='species_name', vars=feature_names, diag_kind='kde')
plt.show()
print(df[feature_names].corr().round(2))
 
sns.heatmap(df[feature_names].corr(), annot=True, cmap='coolwarm', center=0)
plt.title('Feature Correlation — Iris')
plt.show()

Rendered output: setosa clusters linearly separable on petal dimensions; petal length with petal width r~0.96 signals redundancy — feature selection territory.

How do you split, scale, and fit without leakage?

Fit the scaler on train only, then transform both.

python
X_train, X_test, y_train, y_test = train_test_split(X_raw, y_raw, test_size=0.2, random_state=42, stratify=y_raw)
 
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)   # fit + transform train
X_test_scaled = scaler.transform(X_test)         # transform only!
 
clf = LogisticRegression(max_iter=200)
clf.fit(X_train_scaled, y_train)
pred = clf.predict(X_test_scaled)
print(classification_report(y_test, pred, target_names=target_names))
print(confusion_matrix(y_test, pred))

Rendered output: classification_report shows precision/recall 1.00/1.00 for setosa, ~0.95 for versicolor/virginica; confusion matrix has 30 correct out of 30 on this split — Iris is easy, which is why we add harder models.

python
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
 
for name, model in [
    ('DecisionTree', DecisionTreeClassifier(random_state=42)),
    ('RandomForest', RandomForestClassifier(n_estimators=100, random_state=42)),
]:
    scores = cross_val_score(model, X_raw, y_raw, cv=5)
    print(f"{name}: {scores.mean():.3f} +/- {scores.std():.3f}")
Feature / Criteria

Gotcha: Fitting StandardScaler on the Full Dataset

Calling scaler.fit_transform(X_raw) before the split leaks test statistics into training and inflates reported accuracy by 1-3 pp. Always fit on X_train then transform test — the notebook shows both paths diverging on the same seed.

How do you report and extend?

Ship the per-class precision/recall, not just accuracy, plus the 5-fold cross_val_score mean/std. Extend by swapping Iris for your CSV per Pandas master workbook grouping patterns before modelling.


Download the Notebook and Practise

This article is a walkthrough of a runnable Jupyter notebook. Download the original .ipynb and run it locally or on Colab — every code block above appears in order.

Download the Applied Ml Cheatsheet Notebook

Get the complete .ipynb with outputs — runs on any Python 3.10+ environment with pandas, numpy, and the libraries listed in setup.

Download .ipynb

Continue your track: Data Analyst Roadmap · Python and Pandas Guide · SQL NULL Handbook · SQL JOIN Fan-Out · Topfolio Practice · Data Analyst vs Engineer

Dataset generators where applicable are in courses/workbooks/generators/ — see citations atop for the exact *.py source for this notebook.


Frequently Asked Questions

What is the minimal ML pipeline this cheatsheet follows?

Load Iris -> EDA (pairplot, correlation) -> train_test_split -> StandardScaler (fit on train only) -> fit LogisticRegression/DecisionTree/RandomForest -> predict -> classification_report + confusion_matrix -> cross_val_score.

Why scale features before logistic regression?

StandardScaler (zero mean, unit variance) stabilises gradient descent and prevents features on larger scales from dominating the loss.

When is accuracy misleading?

On imbalanced data. Report precision, recall, and f1-score via classification_report alongside the confusion matrix.

What does cross-validation prove?

cross_val_score with cv=5 estimates out-of-sample performance so a single lucky split does not inflate reported accuracy.

Frequently Asked Questions

What is the minimal ML pipeline this cheatsheet follows?

Load Iris -> EDA (pairplot, correlation) -> train_test_split -> StandardScaler (fit on train only) -> fit LogisticRegression/DecisionTree/RandomForest -> predict -> classification_report + confusion_matrix -> cross_val_score.

Why scale features before logistic regression?

StandardScaler (zero mean, unit variance) stabilises gradient descent and prevents features on larger scales from dominating the loss.

When is accuracy misleading?

On imbalanced data. Report precision, recall, and f1-score via classification_report alongside the confusion matrix.

What does cross-validation prove?

cross_val_score with cv=5 estimates out-of-sample performance so a single lucky split does not inflate reported accuracy.

Anuj Saini

Written by

Anuj SainiFounder & Lead Instructor

Founder at Topfolio with 6+ years in data & analytics across JPMC, Ultrahuman, and high-growth startups. Sat on hiring panels, reviewed 500+ resumes, and writes practical SQL & data guides.