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.
Step 1 of 4
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.
- 1
Raw measurement
Original units - 2
Preparation
Transform using stored settings - 3
Model
Predict from prepared input
Step 2 of 4
Learn each preparation step on training data
A scaler needs training statistics. A feature selector may need training labels. Fit each step using only the observations permitted for that training run.
- 1
Training rows
Fit preparation - 2
Prepared training rows
Fit model
Step 3 of 4
Reuse fitted steps for new observations
Prediction applies the stored transformations in the same order. It does not relearn them from the arriving batch. This preserves the meaning of the inputs the model expects.
- 1
New rows
Apply stored preparation - 2
Prepared new rows
Apply fitted model
Step 4 of 4
Repeat the whole fit inside each fold
During cross-validation, each training fold needs its own fitted preparation. Preparing the complete dataset before splitting can let validation information influence the model's inputs.
| Training subset | Preparation fitted here | Model fitted here |
|---|---|---|
| Fold A training rows | Scaler A | Model A |
| Fold B training rows | Scaler B | Model B |
Fold A training rows
- Preparation fitted here
- Scaler A
- Model fitted here
- Model A
Fold B training rows
- Preparation fitted here
- Scaler B
- Model fitted here
- Model B
The order and fitted state belong to one chain
Trace which rows fitted each transformation. A validation row should receive the stored transformation; it should not have helped choose that transformation in the first place.
A pipeline makes the intended process easier to repeat. It still needs sensible split boundaries and properly implemented steps.
Keep preprocessing and prediction on the same path
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.
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.
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.
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.
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.39The standardizer will receive expanded features when we predict, so it must learn its reference values from expanded training features too. If we fitted it on raw height alone, it would have no learned centre or scale for the new height-squared column. The pipeline keeps this order consistent between fitting and prediction.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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 = 6418. 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.
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"Part 6. The Order of the Steps
20. Expand then standardize, or standardize then expand
Does preprocessing order change the model? Expand height first and standardize afterwards, and ridge receives two centred, unit-spread columns. Standardize height first and square it afterwards, and the square column has mean one under the population-variance convention used here, with a different spread. The chart compares 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.
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.
Part 7. Preserving the Order and Fitted State of Every Step
22. What is fitted, what is copied and what prediction reuses
The order of a pipeline is part of the model. Each named step fits the output of the preceding step. Prediction reuses that fitted sequence and fits nothing, so the later rows cannot change their own reference.
Here every fit works on copies of the configured steps and model. The original configuration remains unfitted, and no new fit is committed unless every stage succeeds. That prevents a failed fit from leaving half a new pipeline in use.
Nested search settings must identify the correct step and parameter. Also check the treatment of a wrong name, an empty step list, an incompatible final model and incoming columns that are missing, extra or reordered.
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.
| Pipeline stage or input | Where fitting or prediction can fail |
|---|---|
| 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. |
…
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.
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