Capstone: A scikit-learn Tour & Building a Real Predictive Model

Machine Learning Fundamentals

Chapter 11 · Capstone: A scikit-learn Tour & Building a Real Predictive Model

Every chapter since ml1-3 has quietly used the same shape: fit() to train, predict() to apply, some scoring function to evaluate. This capstone makes that consistency explicit, and closes the loop this entire course opened — bringing both of its own resolved hypotheses together into one final pipeline.

The Consistent scikit-learn API — A Genuine Design Strength

ChapterAlgorithmSame interface
ml1-3LinearRegression.fit(X, y) / .predict(X) / .coef_
ml1-5LogisticRegression.fit(X, y) / .predict(X) / .coef_
ml1-7DecisionTreeClassifier / RandomForestClassifier.fit(X, y) / .predict(X)
ml1-9KMeans.fit(X) / .predict(X) / .fit_predict(X)

Four genuinely different algorithm families — a smooth linear fit, a sigmoid-squashed linear fit, a greedy entropy-splitting tree, an iterative centroid-refinement process with no target at all — and switching between them required almost no change to the surrounding code. That consistency isn't an accident; it's a deliberate design choice this whole course has been quietly relying on since ml1-3.

Pipeline 1 — Closing ml1-3's Own Regression Story

Used-car price prediction, start to finish
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np

X = df_cars[["mileage", "year"]]
y = df_cars["price"]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)  # ml1-2

scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)

model = Ridge(alpha=1.0)   # ml1-3's own LinearRegression, ml1-8's own L2 regularization applied
model.fit(X_train_s, y_train)

preds = model.predict(X_test_s)
mae = mean_absolute_error(y_test, preds)              # ml1-4
rmse = np.sqrt(mean_squared_error(y_test, preds))      # ml1-4
r2 = r2_score(y_test, preds)                           # ml1-4

cv_scores = cross_val_score(model, X_train_s, y_train, cv=5)   # ml1-8

This is ml1-3's own coefficients and ml1-4's own metrics, now wrapped in ml1-8's own regularization and cross-validation — the full arc this course built one deliberate piece at a time.

Pipeline 2 — Closing ml1-5's Own Classification Story

Employee attrition prediction, start to finish — two models, compared
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score

X = pd.get_dummies(df_emp[["department", "age", "years_at_company", "salary"]])
y = df_emp["left_company"].map({"Yes": 1, "No": 0})

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)  # ml1-2
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)

logit = LogisticRegression()          # ml1-5
logit.fit(X_train_s, y_train)

forest = RandomForestClassifier(n_estimators=200, random_state=42)   # ml1-7
forest.fit(X_train, y_train)          # trees don't require scaling — a real, honest asymmetry worth noting

for name, preds in [("Logistic", logit.predict(X_test_s)), ("Forest", forest.predict(X_test))]:
    print(name, precision_score(y_test, preds), recall_score(y_test, preds), f1_score(y_test, preds))  # ml1-6

forest.feature_importances_   # does the forest agree with ml1-5's own salary finding?
Illustrative result — a second, independent confirmation
The random forest's own feature_importances_ plausibly ranks salary highest, echoing ml1-5's own coefficient and ml1-7's own worked split — the third independent method now agreeing on the same answer. Both models' own precision/recall/F1 (ml1-6) come back broadly comparable, with the forest typically edging out logistic regression slightly on recall — consistent with ml1-8's own reasoning: an ensemble reduces variance relative to any single model.

A Final Coda — Revisiting ml1-9 and ml1-10

Rerunning ml1-9's own unsupervised clustering on both datasets one last time is worth doing here specifically because it asks a genuinely different question than either pipeline above — not "does this predict the target," but "what structure exists regardless of any target at all." And if either dataset had employees sitting persistently near a cluster boundary, unable to be assigned crisply with real confidence, ml1-10's own fuzzy membership approach — not implemented here, but conceptually available — is exactly where that specific problem would be addressed, rather than by forcing ml1-9's own crisp k-means to make an arbitrary, boundary-splitting call.

Chapter Attribution

Capstone elementDrawn from
Learned rules vs. hand-coded rules framingml1-1
Train/test split, cross-validation setupml1-2 / ml1-8
Linear regression, standardized coefficientsml1-3
MAE / RMSE / R²ml1-4
Logistic regression, one-hot encodingml1-5
Precision / recall / F1ml1-6
Random forest, feature_importances_ml1-7
Ridge regularization, cross_val_scoreml1-8
The unsupervised clustering codaml1-9
The fuzzy-boundary closing thoughtml1-10

Honest Scope Note

What this capstone — and this course — deliberately doesn't attempt
  • No neural networks. Every model in this course fits a relatively simple, interpretable structure — a line, a sigmoid, a tree, a centroid. Genuinely deep, layered models are nn1's own entire job.
  • No NLP-specific techniques. Every feature used across this whole course was already numeric or a small set of categories. Turning raw text into usable features is nlp1's own job.
  • No production deployment or MLOps. This capstone stops at a working, evaluated model in a notebook. Serving it reliably at scale, monitoring for real-world performance drift over time, versioning models, and automated retraining are a real, substantial engineering layer this course never attempts.

Hands-On Exercises

Exercise 1

Explain why this chapter treats the consistent fit/predict interface across four structurally different algorithms as "a genuine design strength," using this chapter's own comparison table to justify the claim.

📄 View solution
Exercise 2

Explain why the random forest's own feature_importances_ result is described as "a second, independent confirmation," identifying all three methods across this course that now agree on salary's own importance.

📄 View solution
Exercise 3

Using this chapter's own scope note, explain why "no production deployment or MLOps" is a genuinely different kind of gap from "no neural networks" or "no NLP techniques" — what distinguishes it from the other two?

📄 View solution

Chapter 11 Quick Reference — Course Summary

  • Learned rules (ml1-1) vs. hand-coded expert systems, closing the loop opened at ml1-1 and revisited by ml1-7's trees and ml1-10's fuzzy inference systems
  • Train/test/validation discipline (ml1-2) and cross-validation (ml1-8) underlie every model fit in this course
  • Regression (ml1-3/ml1-4) and classification (ml1-5/ml1-6) each closed a real hypothesis ds1 deliberately left open
  • Trees/forests (ml1-7) offered independent confirmation; overfitting/regularization (ml1-8) explained why forests generalize better than single trees
  • Clustering (ml1-9) surfaced a pattern supervised learning was never asked to find; fuzzy logic (ml1-10) addressed crisp logic's own boundary brittleness
  • Next up in the Data Science & ML subject: nn1 (Neural Networks & Deep Learning) — delivering the technical mechanism behind historyai3-3's own perceptron/backpropagation story