Pipelines, scaling, and clustering
Scale and encode inside a Pipeline, cross-validate, then cluster with K-means.
Why it matters: Pipelines stop leakage and ship as one object. K-means handles unlabelled groups.
Basics
Preprocessing
StandardScaler gives mean 0 and std 1. Needed for KNN, SVM, and K-means.
OneHotEncoder is for unordered categories. OrdinalEncoder only when order is real.
SimpleImputer fills missing values (median is safer for skewed data).
Tiny example
Standardize a tiny feature column by hand.
import numpy as np
x = np.array([10.0, 20.0, 30.0])
z = (x - x.mean()) / x.std()
print(np.round(z, 3))Basics
Pipelines
A Pipeline chains prep and a model into one fit / predict object.
Inside cross-validation, each fold refits the scaler on train only. That prevents leakage.
Ship the whole pipeline so production uses the same transforms as training.
Tiny example
Show a step list: scale then model.
steps = [("scale", "StandardScaler"), ("model", "LogisticRegression")]
print(" -> ".join(name for name, _ in steps))Basics
Cross-validation and K-means
K-fold CV trains k times and reports mean and spread.
GridSearchCV tries hyperparameter combos with CV.
K-means groups unlabelled points. Choose k with the elbow method. Scale first.
Clusters are groupings you still have to name.
Tiny example
Average a score across k tiny folds.
scores = [0.81, 0.79, 0.84]
print("cv mean", sum(scores) / len(scores))Then AI / ML
AI / ML examples
Same idea, used in real AI work. Press Try in lab to run it.
AI / ML example
AI / ML: pipeline stops scaling leak
Scaling inside the pipeline is the honest score.
In AI / ML: Production ML wrappers pickle one Pipeline, not a scaler plus a model.
example.py
Python
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
rng = np.random.default_rng(0)
X = rng.normal(0, 1, (300, 20))
y = rng.integers(0, 2, 300)
leaky = StandardScaler().fit_transform(X)
print("leaky", round(float(cross_val_score(LogisticRegression(max_iter=500), leaky, y, cv=5).mean()), 3))
honest = make_pipeline(StandardScaler(), LogisticRegression(max_iter=500))
print("honest", round(float(cross_val_score(honest, X, y, cv=5).mean()), 3))AI / ML example 2
AI / ML: K-means cluster sizes
Scale, fit k=3, print cluster counts.
In AI / ML: Topic and behaviour clusters are named after inspecting each group.
example.py
Python
import numpy as np
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
rng = np.random.default_rng(42)
X = np.vstack([
rng.normal([0, 0], 0.6, (80, 2)),
rng.normal([4, 4], 0.6, (80, 2)),
rng.normal([0, 5], 0.6, (80, 2)),
])
Xs = StandardScaler().fit_transform(X)
labels = KMeans(n_clusters=3, n_init=10, random_state=0).fit_predict(Xs)
uniq, counts = np.unique(labels, return_counts=True)
print(dict(zip(uniq.tolist(), counts.tolist())))Takeaways
- 1Put transforms inside a Pipeline to prevent leakage and ship one artifact.
- 2One-hot unordered categories; ordinal encoding implies real order.
- 3Cross-validate for an honest score; scale before K-means.