57 · Pipelines: compose preprocessing + model
Chain transformers and a final estimator into one object with a single `fit`/`predict` — the only honest way to preprocess inside cross-validation.
A `Pipeline` chains transformers and a final estimator into ONE object that behaves like a single estimator: one `fit`, one `predict`. It applies the exact same preprocessing to train, test, and production automatically — and it's the only way to keep cross-validation honest.
Without this:
Without a pipeline you must manually re-apply every transform — in the right order, with the right fitted statistics — to test and production data. Miss a step and predictions silently break; scale before splitting and your cross-validation scores are quietly leaked and inflated.
The problem pipelines solve
In the last lesson you scaled, encoded, and fit a model as separate steps. That works in a notebook — but it's fragile. To predict on new data you must remember to re-run every transform, in the same order, using the same fitted statistics. Forget one and your model receives data it has never seen the shape of.
Worse, the manual approach makes cross-validation dishonest. If you scale the whole dataset and then run CV, every fold's scaler already absorbed statistics from the other folds — the test fold leaks into preprocessing. Your CV score comes out optimistic, and you ship a model that underperforms.
A Pipeline fixes both problems. It chains a sequence of transformers and a final estimator into one composite object that itself obeys the estimator API:
pipe.fit(X_train, y_train)— fits each transformer and the final model in sequence.pipe.predict(X_test)— applies every fitted transform, then predicts.
From the outside, the whole pipeline is a single estimator. You can pass it to cross_val_score, GridSearchCV, or joblib.dump exactly like a bare model — and the preprocessing travels with it.
Python (in browser)
The `Pipeline` of `StandardScaler` + `LogisticRegression` is fit and scored with single calls. Scaling and prediction are handled internally — the test set is scaled with train statistics automatically, so leakage is impossible by construction.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
`make_pipeline` is the shorthand: it auto-names each step after its class (`standardscaler`, `logisticregression`). Inspect or reach into any fitted step via `pipe.named_steps['<name>']`.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
A `Pipeline` whose first step is a `ColumnTransformer` (scaler for numeric, one-hot for categorical) and whose final step is a classifier. The entire mixed-type preprocessing-plus-model workflow is now a single fit-and-score object.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
During `fit`, every step except the last runs `fit_transform`; the final estimator only runs `fit`. During `predict`, every transformer runs `transform` only (reusing fitted stats), then the estimator predicts.
How does a Pipeline prevent data leakage during cross-validation?
- A `Pipeline` chains transformers + a final estimator into one object with a single `fit`/`predict`; from the outside it behaves like a bare estimator.
- `make_pipeline` auto-names steps; inspect fitted steps via `pipe.named_steps`. A `Pipeline` can wrap a `ColumnTransformer` for mixed-type data.
- Pipelines keep cross-validation honest: each fold re-fits all preprocessing on its own training split, so test-fold statistics never leak.
Production ML code is almost always a pipeline: it bundles preprocessing with the model so the exact same transforms apply at train, validation, and serving time. `GridSearchCV` and `cross_val_score` rely on pipelines to tune and evaluate without leakage.
If you remove it: Without pipelines you'd re-implement preprocessing by hand for every dataset split and deployment, inevitably introducing order-of-operations bugs and silent cross-validation leakage that inflate your reported metrics.