Transformers and Estimators in Machine Learning
A pipeline stores its steps as a list of (name, estimator) tuples, and the estimator for step i sits at index 1 of that tuple.
Predicting What the Last Step Receives
A pipeline is easiest to understand by watching data move through it. This article starts with a small, runnable pipeline with two steps. The first step is a transformer that adds one to every number. The last step labels each number as low or high by comparing it with a cutoff. Before you read the trace, make a prediction: when you call predict on the raw numbers 3, 5, and 8, which values reach the labeling step?
What do you think happens?
When pipeline.predict([3, 5, 8]) runs, does the labeling step receive 3, 5, and 8, or something else?
Reveal answer
4, 6, and 9, the values after the first step has transformed them
The pipeline does not hand the raw numbers to the labeling step. It runs the first step's transform before the last step's predict, so the labeling step sees the transformed values. Each one of the three inputs has gone through the add-one step, so 3 becomes 4, 5 becomes 6, and 8 becomes 9.
The surprise in that answer is useful. If your guess was 3, 5, and 8, your mental model of the pipeline is missing the hand-off between steps. The rest of this article builds that missing piece, one step at a time, so that you can predict the path of data through any pipeline and find the exact point where a result goes wrong.
How a Pipeline Stores Its Steps
A pipeline stores its steps as a list of (name, estimator) tuples. The estimator for step i sits at index 1 of that tuple, so pipeline.steps[0][1] is the first estimator, pipeline.steps[1][1] is the second estimator, and so on. The name at index 0 is a label you choose. When you trace a pipeline, the index is what tells you which step you are looking at.
Read the diagram as a lookup. To reach the estimator for the first step, go to position 0 of the steps list, then take index 1 of the tuple you find there. The name tells you which step it is; the estimator is what actually does the work of fitting, transforming, or predicting.
A Small Pipeline to Trace
The code below is a toy pipeline written for this article. The AddOne class is a transformer: it has a transform method that adds one to every number. The LowHighLabeler class is the final step: it has a fit method and a predict method that compares each value with a cutoff. Read the code first and notice how the steps are stored and which method calls are made. Note that this is a sketch that uses plain Python lists so that the data flow is easy to follow, not a production pattern.
['low', 'high', 'high']- AddOne is the transformer: it has fit and transform, and no predict.
- LowHighLabeler is the final estimator: it has fit and predict.
- The steps list holds two (name, estimator) tuples, in order.
- pipeline.fit passes the data through the first step before fitting the last one.
- pipeline.predict transforms the new data with the first step, then calls predict on the labeler.
The printed output is low, high, high. The label for 3 is low because its transformed value 4 is below the cutoff of 6. The labels for 5 and 8 are high because their transformed values, 6 and 9, are at or above the cutoff. The labeling step never sees the raw input 3, 5, 8; it sees 4, 6, 9. That is the hand-off the trace makes visible.
Tracing a Pipeline Through Its Steps
Fitting and prediction use the same steps but call different methods on them. The two paths are described separately below, because the difference between them is the key to reading any pipeline trace.
Why Only the Last Step Needs fit
Every step except the last one is called with fit_transform during fitting and with transform during prediction. That means every intermediate step must be able to transform data. The last step is different: during fitting it is only fitted on the data it receives, and during prediction the pipeline calls its predict method. The source notes that the last step only needs a fit method. It does not have to provide predict.
| Position in the pipeline | Methods it must provide | Called during fitting | Called during prediction |
|---|---|---|---|
| Every step except the last | fit and transform (fit_transform is used during fitting) | fit_transform | transform |
| The last step | fit (predict is only needed if you call pipeline.predict) | fit | predict (or transform, if the last step is a transformer and you call pipeline.transform) |
Which method each step is called with, depending on its position
This is why a pipeline does not have to end in a classifier. The source describes a pipeline built from a scaler and PCA. PCA has no classifier at all, but it does have a transform method. Because the earlier step only needs transform, and the last step only needs fit, you can call transform on the whole pipeline and get the output of PCA applied to the data that the earlier step has already processed. Pipelines are therefore not limited to classifiers, and they can be built from transformers alone.
Finding Where the Output Diverges
When the final output of a pipeline is wrong, do not guess at the cause. Trace the data backward through the intermediate outputs and find the first step where the values stopped matching your expectation. The flowchart below shows that search.
In the toy pipeline, suppose you expected the labeling step to receive 3, 5, and 8. You would check its input and find 4, 6, and 9 instead. The first step's transform is the place where the values changed, and that is expected behaviour, so the mismatch points to your mental model rather than a bug. The point of the trace is to find the exact step where the data first differs from what you assumed, so you know which step to reason about.
Mistakes Learners Make With Pipeline Steps
Common mistake Assuming the final step receives the raw input
What it looks likeExpecting the labeler in the toy pipeline to see 3, 5, and 8 during predict.
Why it failsEvery step before the last one transforms the data first, so the last step receives the transformed output.
Do this insteadFollow the data through each step in order and use the transformed values as the input to the next step.
Common mistake Calling fit_transform on every step during prediction
What it looks likeRefitting AddOne on new data when calling predict.
Why it failsPrediction only transforms the data in the earlier steps. Refitting would change the steps the pipeline was trained with.
Do this insteadDuring prediction, earlier steps use transform, and only the last step uses predict.
Common mistake Expecting every pipeline to end in a classifier
What it looks likeTrying to call predict on a scaler plus PCA pipeline.
Why it failsThe last step only needs a fit method, and PCA has a transform method but no classifier behaviour.
Do this insteadCall transform on the whole pipeline when the last step is a transformer.
Common mistake Mixing up the name and the estimator in steps, so that steps[0][0] is used where steps[0][1] is needed
Common mistake Looking only at the final output and not at the intermediate values when a result is wrong
Practice Tracing a New Pipeline
Suppose a pipeline has a first step that doubles every number and a last step that labels a value as big if it is at least 10. Predict the label for the input values 2, 5, and 6 when you call pipeline.predict on them. Write down the values the labeling step receives before you give the labels.
Hints
- First write the value the doubling step produces for each input.
- The labeling step compares the doubled values with 10, not the original inputs.
- Check your answer by writing the input and output of each step in order.
Key Takeaways
- A pipeline stores its steps as a list of (name, estimator) tuples, and the estimator for step i is at index 1 of that tuple.
- During fitting, every step except the last is fitted and used to transform the data, and the last step is fitted on the data it finally receives.
- During prediction, every step except the last only transforms the data, and the last step then calls predict on the result.
- The last step only needs a fit method, so a pipeline can end in a transformer such as PCA and be used through transform.
- When an output is wrong, trace the intermediate values backward to find the first step where the data differs from what you expected.