Pipelines
Preparing data is part of fitting a model. If a scaler learns from our test examples, the test has already influenced the result. A pipeline helps us keep those fitting steps together and inside the training procedure.
14 sections · 10 questions · 4 coding challenges
The arrow keys move between sections too.
How Do We Repeat the Whole Procedure Without Changing It?
BOTIE
Pipelines grew out of this broader software and experimental problem rather than a single new statistical formula. Scikit-learn's 2011 paper describes a library built around consistent interfaces for learning procedures. Its pipeline tools make a sequence of transformations and a predictor behave as one fitted object.
Each learned preparation step fits only on the training data, then passes its result onward. Later observations travel through the stored steps in the same order. During cross-validation, the whole sequence must be fitted again inside each training fold. Packaging the procedure helps us enforce that boundary instead of relying on memory.
The Test Answers Can Leak in Before the Fit
A model trained on standardized measurements needs the same transformation when new observations arrive. If training and prediction follow different preparation steps, even a correctly fitted model can receive the wrong kind of input.
A pipeline keeps the ordered preparation steps and final model together.
Include preparation in the prediction process
Raw input is not necessarily what the model was trained to read. The transformation before it is part of the route from measurements to predictions.
Raw measurement
- Original units
Preparation
- Transform using stored settings
Model
- Predict from prepared input
The order and fitted state belong to one chain
The full examples trace inputs through each step and compare correct fold-local fitting with leaked preparation.
A pipeline makes the intended process easier to repeat. It still needs sensible split boundaries and properly implemented steps.
Explore the full example
Follow the data through each transformation and into the model. Check which rows supply the fitted statistics and which rows only use them.
A standardizer over height, age and daily walk, which never reads the weight
A column chosen by its correlation with the target
Amber is the transformer fitted on every person before the folds were dealt, indigo is the same transformer refitted inside each fold, and the figure over each pair is amber less indigo, averaged over thirty seeds of five-fold k-nearest neighbours.
Part 1. Preprocessing Is Part of the Model
1. A held-out person arrives alone
Take the grid search page’s twelve people, measured by height in centimetres and weight in kilograms, and hold three of them out, the people at 153, 165 and 177 cm. A model that predicts weight from standardized height is fitted on the other nine, and now the first held-out person arrives to be scored. Their height has to be standardized before the model can read it, and the question is what centre and what spread to subtract and divide by.
Their own are no use. One height has no spread at all, so asking to standardize a single person is refused, because the column is constant.
| held-out person | height | standardized by the training nine | predicted weight | true weight |
|---|
The numbers in the boxes come from the nine training people. Their heights centre at 167.11 cm with a spread of 10.38 cm, and the held-out person at 153 cm becomes −1.360 under those two numbers, at 165 cm −0.203, and at 177 cm 0.953. Press the second button and hold out the three tallest instead.
The centre falls to 162.11 and the spread to 7.67, and the three held-out heights standardize to 1.942, 2.334 and 2.725, more than two spreads above anyone the fit saw, which is the truth about them and is what the scaled numbers should say.
Keep in mind
2. The centre and spread belong to the fit
So the centre and spread are learned from the training people and reused on everyone who comes later, which makes them a fitted parameter of the model in every sense that matters. They were read off the training rows, they change when the training rows change, and a prediction cannot be made without them. The middle three and the tallest three give two different standardizers from the same twelve people, because the nine left to train on differ, and each standardizer is the right one for the model fitted beside it.
z = (height − 167.11) / 10.38 the middle three held out
z = (height − 162.11) / 7.67 the three tallest held outThe held-out person at 153 cm, by hand
The nine training heights add to 1504 centimetres. Their fitted standard deviation is about 10.38 centimetres. Use those training statistics for both held-out people.
training mean = 1504 / 9 ≈ 167.11 cm
score at 153 cm ≈ (153 − 167.11) / 10.38 ≈ −1.360
score at 177 cm ≈ (177 − 167.11) / 10.38 ≈ 0.953Neither held-out person contributed to that mean or spread. The values shown are rounded from the fitted training statistics.
What the two fits predict
With the middle three held out the chain predicts 52.75, 63.66 and 74.98 kg for people who weigh 52, 63 and 76, a held-out R² of 0.9930 against a training R² of 0.9917. With the tallest three held out it predicts 74.71, 77.61 and 80.53 kg for people who weigh 76, 78 and 82, every one an underestimate, since the chain is reaching past its data, and the held-out R² falls to 0.7871 while the training R² stays at 0.9872.
The standardizer did not cause that gap; the three tallest people are simply outside what nine shorter ones can teach.
Keep in mind
3. Two objects that must stay in step
Written by hand, that is two objects to keep in step, a standardizer and a model, with a rule that the standardizer is fitted exactly where the model is fitted and applied exactly where the model predicts. Every place the model is used is a place the rule can be broken. A fold loop written by hand has to refit the standardizer on each fold’s training rows; a search over settings has to do it for every candidate at every fold; a serving endpoint has to apply the one standardizer that the deployed model was fitted with and never another.
None of that is hard, and each is the kind of rule that is right when the loop is first written and wrong after the third change to it.
The alternative is to make the two objects one. A chain holds its steps and its model together and exposes the same fit and predict as any single model on this site, so wherever a model is fitted the steps are fitted, and wherever a model predicts the fitted steps are applied, because there is nowhere else the fitting or the applying could happen.
Keep in mind
Part 2. One Chain, One Fit, One Predict
4. Steps in order, then the model
The chain on this page has two steps and a model. The first step expands height to height and its square, the second standardizes both columns, and the model is a ridge regression at a penalty of one. Fit runs the steps in that order on the training rows and then fits the model on what the last step produced. Each step is named, the names are unique, and the order the steps are given in is the order they run in.
fit expanded = expansion fitted on the training rows, applied to them
scaled = standardizer fitted on expanded, applied to expanded
model fitted on (scaled, training weights)
predict expanded = the fitted expansion, applied to the new rows
scaled = the fitted standardizer, applied to expanded
model.predict(scaled)A chain with no steps at all is allowed, and it is then the model and nothing more, which is measured rather than assumed. On the nine training people a chain with an empty step list and a bare ridge at the same penalty predict the three held-out weights to a largest difference of exactly zero. Allowing the empty chain is what lets it be the default wrapper rather than a special case a caller has to decide about.
Keep in mind
5. Each step learns from what the step before produced
The standardizer in this chain does not learn the centre and spread of height. It learns the centre and spread of whatever the expansion handed it, which is two columns, height and height squared, and the boxes in section 1 show both. On the nine training people the square centres at 28033.78 with a spread of 3467.39, numbers the standardizer could not have known from the raw height, because the column did not exist until the expansion made it.
standardizer, fitted after the expansion, learned
height centre 167.11 spread 10.38
height² centre 28033.78 spread 3467.39That is the rule, and at predict time nothing else would work, since the standardizer will be handed the expansion’s output and so has to have been fitted on the expansion’s output; a standardizer fitted on the raw height would meet a column called height squared that it had never learned a scaling for, and refuse it.
Keep in mind
6. Predict applies and learns nothing
Predict is the shorter half. It hands the new rows to the fitted expansion, hands what comes back to the fitted standardizer, and hands what comes back from that to the fitted model. Nothing is fitted anywhere along the way. Measured on the chain in section 1, the standardizer’s centre for height is 167.1111 before a predict on the three held-out people and 167.1111 after it, the same number to the last digit, because predict has no code path that could change it.
That sentence is the whole of the leak protection at serving time. There is no second call site where a transformer could be fitted on the rows being scored, since the only place a transformer is ever fitted is inside fit, and fit is called on the training rows.
Keep in mind
7. Inside cross-validation nothing special happens
The held-out evaluation page’s fold loop calls fit on a fold’s training rows and evaluate on its held-out rows, once per fold, on whatever model it is handed. Hand it the chain and it does exactly that, and since the chain’s fit fits the steps, the standardizer is refitted on each fold’s training rows for no reason other than that fit was called. The loop knows nothing about what the chain contains and needs to know nothing.
Four folds over the twelve people
Dealt into four folds with the page’s seed, the chain scores 0.9986, 0.9916, 0.9234 and 0.9894 on the four held-out threes, a mean of 0.9758, and at every fold the standardizer was fitted on that fold’s nine training people. Part 4 checks the claim in the previous sentence rather than trusting it.
Keep in mind
Part 3. The Leak, Measured
8. Where the leak comes from
Now the mistake the object exists to prevent, written down and then measured. Standardize the columns once over all the people, and only then deal the folds. Every training fold has now been scaled by a centre that its held-out rows helped to compute. With five folds each training fold holds four fifths of the rows, so the centre over everyone is a weighted average of the centre the fold should have used and the centre of the rows it is about to be judged on.
centre over all rows = (4/5) · centre of the training fold + (1/5) · centre of the held-out foldWhether that matters, and how much, cannot be settled by looking at the formula, so the playground at the top of the page measures it. Twelve hand-typed people are too few to fold thirty times over, so the measurement draws people by seed, thirty, sixty or two hundred of them, measured by height in centimetres, age in years and how far they walk in a day in kilometres, with a weight that is a plain line through the three plus a little noise.
The three columns are on three different scales, so a k-nearest neighbours regressor that skipped the standardizer would let age decide who is near, and the standardizer genuinely has work to do.
Keep in mind
9. A standardizer leaks little, and in no particular direction
Press the button for the first thirty seeds and read the thirty-people column. Fitted on every person and then folded, the standardizer arrangement scores a mean held-out R² of 0.4813; refitted inside each fold it scores 0.4830. The shortcut did not flatter the score at all here, it cost 0.0017, and fourteen of the thirty seeds went the other way. At sixty people the gap is +0.0004 with fifteen of thirty flattered, and at two hundred it is +0.0001 with eighteen of thirty, a coin toss that shrinks as the people multiply.
| people | fitted before the folds | fitted inside each fold | gap | seeds flattered | largest single-seed gap |
|---|---|---|---|---|---|
| 30 | 0.4813 | 0.4830 | −0.0017 | 14 of 30 | 0.1019 |
| 60 | 0.7668 | 0.7664 | +0.0004 | 15 of 30 | 0.0256 |
| 200 | 0.8635 | 0.8634 | +0.0001 | 18 of 30 | 0.0037 |
Mean held-out R² of five-fold k-nearest neighbours at five neighbours, seeds 0 to 29. The gap is the first score less the second.
Each dot is one seed’s gap at 30 people, fitted outside the folds less fitted inside them, seeds 0 to 29. Right of zero the shortcut flattered the score.
The strip is the number that matters. A step that leaked something worth having would flatter most seeds, and this one flatters fourteen of thirty and costs the other sixteen, with the dots straddling zero and the largest single-seed gap at thirty people, 0.1019, larger than the mean gap by a factor of sixty. Press the button for seeds 30 to 59 and the mean is −0.0104 with fourteen of thirty flattered again. I have not found a family of seeds on which the standardizer flatters more than about half of them.
Keep in mind
10. Why it is small, and why doubling the people shrinks it
Two reasons, and the model is the first. Nearest neighbours reads only distances, and a distance between two standardized people subtracts the same centre from both, so the centre cancels entirely and only the spread survives.
d(a, b)² = Σⱼ ((aⱼ − bⱼ) / sⱼ)² the centre mⱼ appears in neither termWhat leaks, then, is the ratio of each column’s spread over everyone to its spread over the training fold, a number close to one that reweights the three columns by a fraction shrinking like one over the number of people. That is the second reason. Nothing about that ratio knows the weight, so it cannot lean the fit toward the held-out answers any more than away from them, and a leak that is blind to the target can move the score in either direction, which is why fourteen of thirty seeds were flattered and sixteen were not.
›Why the held-out evaluation page's line felt even less
That page measured the same leak on a ridge fit at a small penalty and found gaps of a few ten-thousandths, and the reason is one step further along the same argument. A least-squares line is unchanged by any rescaling of its columns, since the slope simply rescales to match, so for it neither the centre nor the spread leaks anything at all; only the penalty, which charges for the size of a coefficient and so notices what scale the coefficient is in, lets any of the standardizer’s numbers through.
Part 6 measures that same sensitivity from the other side.
Keep in mind
11. A step that reads the target leaks the target
The lower panel of the playground fits something deliberately not built here, a step that keeps whichever of twenty noise columns correlates best with a target that is itself noise. No column deserves any score above zero, and a neighbours fit on any one of them should do worse than answering the mean weight every time.
Both arrangements do exactly that. Choosing the column inside each fold scores −0.8867 at thirty people, and choosing it on every person first scores −0.5979, which looks less bad by a margin that has survived every family of seeds I have run.
| people | chosen before the folds | chosen inside each fold | gap | seeds flattered | largest single-seed gap |
|---|---|---|---|---|---|
| 30 | −0.5979 | −0.8867 | +0.2888 | 27 of 30 | 0.7329 |
| 60 | −0.2696 | −0.4252 | +0.1556 | 27 of 30 | 0.4518 |
| 200 | −0.1985 | −0.2392 | +0.0407 | 18 of 30 | 0.1972 |
The same folds and the same neighbours regressor as the standardizer's table, on twenty columns of noise beside a target of noise.
Feature selection used the target values from the very rows later presented as held out. Among twenty noise features, the strongest chance correlation can look substantial on a small sample.
The resulting score inflation is positive in twenty-seven of thirty seeds in this experiment. It shrinks as the sample grows, but remains visible. A seemingly useful score can therefore arise from leaking answers into feature selection even when the input features contain no predictive information.
Keep in mind
12. The size of the leak is not the argument
It would be easy to read Part 3 as saying the chain matters only for a step that reads the target, and that reading is half right. No step on this page reads the target, and for the steps that are here the leak is within noise of zero. The argument for the object was never the size of the penalty for getting the fold wrong.
It is that the question stops being the caller’s to remember, at every fold, every candidate and every serving call, and that once the steps and the model are one object a setting inside a step becomes something a search can vary. Parts 4 and 5 are about those two things.
Keep in mind
Check yourself
Questions on Parts 1 to 3
Question 1 of 5
A held-out person could be standardized against their own centre and spread rather than the training rows’.
Part 4. The Configuration Is Never Fitted
13. A template and its fitted copy
Section 7 handed one chain object to four folds in turn and claimed each fold got its own fit. For that to be true the steps and the model a caller builds the chain from must never themselves be fitted, or the second fold would start from whatever the first fold learned. So fit copies them. The copies are fitted and stored, and the originals, which are the configuration, stay exactly as they were built. The ledger reads that claim off a chain fitted on the nine training people.
…
The configured model and both configured steps report themselves unfitted after the fit; the fitted copies report themselves fitted; and the copies are different objects from the configuration, so a change to one cannot reach the other. Refitting the same object on a different nine and comparing it with a chain built fresh for those nine gives predictions that agree to a largest difference of exactly zero, which is what starting from scratch means.
Keep in mind
14. Four folds, four independent fits
The same check, run inside the fold loop. At each of the four folds the shared object is refitted on that fold’s nine and scored on its three, and a chain built fresh for the fold is fitted and scored beside it. If anything from an earlier fold survived on the shared object the two would differ somewhere; the figure over each bar is the largest difference between their predictions on that fold.
Zero at every fold. Afterwards the shared object is fitted, to the fourth fold it saw, and its configuration is still unfitted, which is the same pair of facts the playground reports about the chain it handed to a hundred and fifty fits per column. Five folds would give five independent fits, and thirty seeds of five folds give a hundred and fifty, for the same reason.
Keep in mind
15. Nothing is committed until everything succeeded
A fit can fail halfway. The expansion may succeed and the standardizer refuse, or both steps may succeed and the model refuse, and a chain that had already stored its new fitted steps by then would be left holding fitted steps from one fit beside a fitted model from another. So the chain computes every part into a result first and stores nothing until the model has fitted too.
The ledger’s seventh and eighth rows break a refit on purpose, handing the fitted chain a constant height column, which the standardizer refuses because a constant column has no spread.
refit on a constant column refused, the column has zero variance
still fitted afterwards yes
predictions moved by 0.0The refusal comes back by name, the chain is still fitted to the nine people it had before, and its predictions on the three held-out people have moved by exactly nothing. A refit that fails leaves the previous fit whole rather than half replaced.
Keep in mind
Part 5. Searching a Setting Inside a Step
16. Degree is not the model's to choose
The grid search page varied a neighbour count, which is a field of the neighbours model, and a ridge penalty, which is a field of the ridge model. The degree of the expansion in this chain is neither. It is a field of the expansion step, and a search over the ridge model alone has no way to reach it.
Asked to vary a degree on the ridge model, the search refuses at construction and names the two fields the model does have, its intercept switch and its penalty, and that refusal is quoted under the lattice below.
Wrapped in a chain, the whole configuration is one model whose two fields are its steps and its model, and both can be varied. That is the capability the object buys, and it is stronger than the leak argument, since without it the question of which degree to use could not be put to a search at all.
Keep in mind
17. A candidate is a whole object
Each search candidate combines a complete preprocessing sequence with a model configuration. This example crosses four polynomial degrees with four ridge penalties, then evaluates each combination on four shared folds.
candidates = 4 degrees × 4 penalties = 16
cross-validation fits = 16 × 4 folds = 64Every candidate uses the same seeded folds, so their scores compare configurations on the same partitions.
steps ∈ { expand to 1 then standardize, expand to 2 then standardize, expand to 3 ..., expand to 4 ... }
model ∈ { ridge at 0.01, ridge at 0.1, ridge at 1, ridge at 10 }
candidates = 4 × 4 = 16 fits = 16 × 4 folds = 64Keep in mind
18. What the lattice says on the twelve people
On the twelve people the search keeps degree 1 at a penalty of 0.1, with a mean held-out R² of 0.9796, and degree 1 at 0.01 finishes within a few millionths of it. Degree 2 at 0.1 scores 0.9790, degree 2 at 1 scores 0.9758, and every candidate at a penalty of 10 is far behind, degree 1 at 0.6157 and degree 4 at 0.9081.
The spread across the sixteen is 0.3639, which says the settings mattered, though what mattered was the penalty; the degrees at any one small penalty finish within 0.015 of one another, and the expansion earns nothing on twelve people who lie very nearly on a line.
The Ideal Case
On fifteen people lying almost exactly on one line the winner is again degree 1 at 0.1, at 0.9976, and the spread of 0.2828 is once more the penalty of 10 ruining every degree. The search reports both numbers because a winner without its spread is a number that cannot be read, and here the spread says the search chose a penalty and had no opinion about the degree.
Keep in mind
19. A misspelt name is refused, never ignored
Some pipeline APIs address nested settings with a string combining the step name and parameter name. Such an API can validate those names; silently ignoring a misspelling is an implementation error, not an inherent property of strings.
This SDK builds candidates from configured objects. Its constructors reject unknown fields before the search starts, so an invalid candidate cannot quietly become another copy of the default model.
a range over the chain's field "stepz" refused at construction, the chain has "model" and "steps"
a range over the ridge model's "degree" refused at construction, the model has "fit_intercept" and "penalty"Keep in mind
Part 6. The Order of the Steps
20. Expand then standardize, or standardize then expand
Two steps can run in two orders, and the chain treats the order as part of the model rather than as a detail, so it is worth asking whether the model can tell. Expand height and then standardize both columns, and the ridge is handed two columns each with centre zero and spread one. Standardize height and then square it, and the ridge is handed the standardized height beside its square, whose centre is one and whose spread is something else. The chart runs both orders at six penalties on the same four folds.
Indigo expands height and then standardizes both columns; amber standardizes height and then squares it. Both are mean held-out R² across the same four seeded folds.
At a penalty of zero the two orders score 0.9579 and 0.9579 and predict the three held-out weights to a largest difference of 1.2e−13, which is rounding. At every positive penalty they part, and the chain’s own order scores higher at each one, 0.9764 against 0.9581 at 0.01, 0.9790 against 0.9597 at 0.1, 0.9758 against 0.9523 at 1, and 0.8105 against 0.5539 at 10, with the held-out predictions differing by 0.735 kg at a penalty of one and 2.334 kg at ten.
Keep in mind
21. Why a penalised model feels the order and least squares does not
The two column sets span the same curves. Height and its square, or standardized height and its square, either pair together with an intercept can draw any parabola in height, so a fit that only asks which parabola is closest to the nine training people finds the same one either way. That is what the penalty of zero shows, and a plain least-squares model in place of the ridge gives the same 1.2e−13.
A ridge penalty is a charge on the squared coefficients of whatever columns it was handed, and handing it different columns changes what it is charging for.
expand then standardize, penalty 1 height 4.821 height² 4.853 both columns centre 0, spread 1
standardize then expand, penalty 1 height 9.191 height² 0.241 the square has centre 1, spread 0.932On heights between 150 and 183 cm the standardized height and the standardized square are very nearly the same column, and the ridge splits the slope between them, 4.821 and 4.853, which is the grouping the ridge and lasso page describes. Standardized first and then squared, the square is centred at one and carries little that the height does not, and the ridge puts 9.191 on the height and 0.241 on the square. Both orders fit the same nine people with the same family of curves, and the one that hands the penalty every column at the same spread scored higher at every penalty tried.
Keep in mind
Part 7. Implementation and Failure Contracts
22. What a complete implementation specifies
A complete implementation states what a step is and how steps are named and ordered, that each step is fitted on the output of the step before it, that predict applies the fitted steps and fits nothing, that the configured steps and model are copied before every fit and never fitted themselves, that a fit commits nothing until every part has succeeded, how a search varies a setting inside a step and what a wrong name does, whether an empty step list is allowed, which kind of model a chain of each task will accept, and what it does when a row arrives with a column missing, a column it never saw, or its columns in another order.
Keep in mind
23. What the chain refuses, accepts, and lets through
Every row below was put to the chain, on the twelve people where a row needs people, and the widget under the table asks the same list again on each load so the two cannot drift apart.
| the edge | the behaviour |
|---|---|
| no steps at all | accepted; the chain is the bare model, to a largest prediction gap of exactly zero. |
| no features at all | refused at the first step, since there is nothing to expand. |
| one training person, or a constant height column | refused by the standardizer, because a column with no spread cannot be scaled. |
| a height that is not a number | refused at the boundary, by the same guard every column here passes through. |
| a target shorter than the features | refused by name, with both lengths in the message. |
| a degree the training people cannot support | refused by the ridge, which needs at least as many rows as parameters; degree 9 on 8 people is ten parameters on eight rows. |
| predict before fit, or read the fitted steps before fit | refused; there is no fitted copy to read. |
| predict with a feature missing | refused, though not by the first step; a standardizer transforms the subset it is given, and the model behind it refuses the exact set it was fitted on being incomplete. |
| predict with a feature the fit never saw | depends on which step meets it. A standardizer refuses a column it never learned a scaling for; an expansion computes the terms it needs and ignores the rest. |
| predict with the features reordered | accepted; every step and the model match columns by name. |
| a step already fitted on other people, handed in | accepted and refitted from scratch on the training people; the handed-in object keeps its own fit, which the chain never reads. |
| a transformer as the model, or a classifier as a regression chain's model | refused at construction, by the declared type of the model field. |
| a binary-only classifier as a classification chain's model | refused at construction; the classification chain wraps a multi-class classifier so it can score every class. |
| a model handed in as a step | accepted at construction and fails inside fit with a bare attribute error, not a named refusal. Documented below. |
| two steps with one name, a blank name, or a name the chain does not run | refused by name, because the names are what a fitted chain is read and a step replaced by. |
| an unknown constructor keyword, or a search over a misspelt field | refused at construction, naming the fields that exist. |
| four people dealt into five folds | refused by the folds, before any chain is fitted. |
| a classification chain with one class in the target | refused by the classifier, since there is nothing to discriminate between. |
…
Keep in mind
24. Documented rather than defended
Two rows in the table are honest gaps rather than contracts. A step is accepted by name and object at construction and nothing checks that the object can transform, so a ridge model handed in as a step is accepted and fails inside fit with a bare attribute error about a missing method, which is not one of the named refusals.
And an expansion met by a column it never saw ignores the column rather than refusing it, so a chain whose first step is an expansion will quietly predict for a row carrying an extra measurement, where a chain whose first step is a standardizer will refuse the same row by name. Neither is defended here.
The first would be a type check at construction; the second is a difference between two steps’ own rules that the chain inherits rather than makes.
Keep in mind
Check yourself
Questions on Parts 4 to 6
Question 1 of 5
After a chain has been fitted, the configured steps and the configured model report themselves fitted.
Try it with Botie
Build with Botie
Write and run Python