55 · The estimator API: fit, predict, transform
Every scikit-learn object speaks the same three-method language — learn it once and swapping models becomes a one-line change.
Every scikit-learn object implements the same interface: `fit(X, y)` to learn, then either `predict(X)` (estimators) or `transform(X)` (transformers). That consistency is why swapping a `LinearRegression` for a `RandomForest` is a one-line edit — the surrounding code never changes.
Without this:
Without this unified API, every model would have its own bespoke method names and data shapes — you'd rewrite your whole training script each time you tried a different algorithm.
One interface to rule them all
scikit-learn's superpower is consistency. Hundreds of models, scalers, and encoders all obey the same tiny contract:
fit(X, y)— learn from data. Every object implements it. Afterfit, the object holds whatever it learned (coefficients, split thresholds, scaling statistics) in attributes ending with a trailing underscore.predict(X)— produce target predictions. Objects that implement this are estimators (models):LinearRegression,RandomForestClassifier,LogisticRegression.transform(X)— produce a new, transformed feature matrix. Objects that implement this are transformers (preprocessors):StandardScaler,OneHotEncoder,PCA.
Because the contract never changes, your training code stays identical whether you fit a linear model or a gradient-boosted forest. Swapping algorithms is literally a one-line change.
The X / y shape convention
scikit-learn always expects:
- X — a 2-D feature matrix of shape
(n_samples, n_features). One row per example, one column per feature. Even with a single feature you must pass shape(n, 1), not(n,). - y — a 1-D target vector of shape
(n_samples,). One label per example.
Internally sklearn converts pandas DataFrames and Series into NumPy arrays, so you can pass either — but the shapes must respect this 2-D-X / 1-D-y rule.
Python (in browser)
The full supervised loop in five lines: load, split (`random_state=42` for reproducibility), `fit` on train, `predict` on test, score. R² near 0.45 is normal for this dataset — diabetes progression is genuinely hard to predict from ten features.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
`fit` learns once from training data; `predict` is then called repeatedly on any new inputs of the same shape. The test set is never shown to `fit`.
Python (in browser)
`fit_intercept` is a hyperparameter (you choose it). `coef_` and `intercept_` are learned parameters (the data chooses them). The trailing underscore is sklearn's universal signal: 'this attribute only exists after `fit`'.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
In scikit-learn, what distinguishes an estimator from a transformer?
- Every sklearn object implements `fit`. Estimators add `predict` (target predictions); transformers add `transform` (a new feature matrix).
- X is always 2-D `(n_samples, n_features)`; y is always 1-D `(n_samples,)`. A single feature still needs shape `(n, 1)`.
- Hyperparameters are set in the constructor (pre-fit); learned parameters appear after `fit` and carry a trailing underscore (`coef_`, `intercept_`).
Every supervised and unsupervised workflow in scikit-learn — regression, classification, clustering, dimensionality reduction — uses this exact `fit`/`predict`/`transform` contract. It is the API you'll call thousands of times across the rest of the ML track.
If you remove it: Without the unified API, trying a new algorithm would mean learning a new set of method names and data formats every time — turning routine experimentation into a constant rewrite.