DS DevShelfHub Projects · AI tools
Cheatsheets / scikit-learn
Cheatsheet · AI frameworks

scikit-learn: Estimators, Pipelines, Preprocessing and Model Selection Reference Guide

By DevShelfHub

Estimators, fit/predict/transform, pipelines, preprocessing, model selection, metrics — the classical ML surface you actually use.

118 items 9 min Estimator Pipeline CV

Start hereQuick start · 6 you’ll reach for daily

Fitmodel.fit(X_train, y_train)
Predictmodel.predict(X_test)
Probabilitiesmodel.predict_proba(X)[:,1]
Pipelinemake_pipeline(StandardScaler(), LogReg())
Splittrain_test_split(X, y, stratify=y)
CV scorecross_val_score(m, X, y, cv=5)

Target versions · paceVersions

Targets: scikit-learn ≥ 1.5 numpy ≥ 1.26 pandas ≥ 2.0 python ≥ 3.9

scikit-learn moves slowly and predictably — the core fit/predict/transform triad hasn’t changed in years. Recent shifts: set_config(transform_output="pandas") keeps DataFrames flowing through pipelines (1.2+), HistGradientBoosting* is now competitive with XGBoost/LightGBM, and OneHotEncoder(sparse=...) was renamed to sparse_output=.... This sheet pins to 1.5+.

Install · configSetup

bash
# Install — core + the usual companions
pip install "scikit-learn>=1.5" numpy pandas scipy

# Conda (uses MKL by default)
conda install -c conda-forge scikit-learn

# Common extras
pip install joblib                          # parallel I/O for model persistence
pip install xgboost lightgbm catboost       # gradient-boosting drop-ins
pip install imbalanced-learn                # SMOTE + samplers
pip install scikit-learn-intelex            # Intel CPU accelerators

# Use the modern Pandas-aware output (DataFrames in / DataFrames out)
python -c "
from sklearn import set_config
set_config(transform_output='pandas',  # transformers return DataFrames
           display='diagram')           # pretty repr in notebooks
"

Where things liveCommon imports

from sklearn.pipeline import Pipeline, make_pipelineCompose preprocess + model into one estimator.
from sklearn.compose import ColumnTransformer, make_column_selectorPer-column-group preprocessing.
from sklearn.preprocessing import StandardScaler, OneHotEncoder, MinMaxScalerThe everyday transformers.
from sklearn.impute import SimpleImputer, KNNImputerMissing-value handling.
from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCVSplitters + tuners.
from sklearn.linear_model import LogisticRegression, Ridge, Lasso, ElasticNetLinear models.
from sklearn.ensemble import RandomForestClassifier, HistGradientBoostingClassifierTree ensembles — the modern defaults.
from sklearn.metrics import classification_report, roc_auc_score, mean_squared_errorEvaluation.
from sklearn import set_configGlobal config — pandas output, diagram repr.
import joblibPersistence + parallel utilities.

fit · predict · transformThe estimator API

est.fit(X, y) / est.fit(X)Train. Supervised takes y; unsupervised doesn’t.
est.predict(X)Hard predictions (classifiers + regressors).
est.predict_proba(X) / est.decision_function(X)Soft scores. Not every classifier has both.
est.transform(X) / est.fit_transform(X)Transformers only. Returns the transformed features.
est.score(X, y)Default metric for the estimator (R^2 / accuracy).
est.get_params() / est.set_params(**kw)Hyperparameters as a dict.
est.classes_ / est.feature_names_in_ / est.n_features_in_Trailing-underscore attributes are learned at fit time.
est.feature_importances_ / est.coef_ / est.intercept_Model-specific introspection.
clone(est)Make an unfitted copy — useful for cross-val loops.

Datasets · splittersData, splits, CV

from sklearn.datasets import load_iris, fetch_openml, make_classificationBundled / cached / synthetic data.
train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)Stratify on y when classes are imbalanced.
KFold(n_splits=5, shuffle=True, random_state=42)Plain k-fold — regression.
StratifiedKFold(...)Preferred CV for classification. Preserves class balance per fold.
GroupKFold / StratifiedGroupKFoldKeep rows of the same group together (e.g. same user).
TimeSeriesSplit(n_splits=5)Forward-only walk-forward splits. Use for time series.
cross_val_score(est, X, y, cv=5, scoring="roc_auc", n_jobs=-1)Quick CV score.
cross_validate(est, ..., return_estimator=True)Multiple metrics + per-fold fitted estimators.
cross_val_predict(est, X, y, cv=5, method="predict_proba")Out-of-fold predictions.

Scale · encode · imputePreprocessing

StandardScaler()Zero mean, unit variance. Preferred for linear / SVM / NN inputs.
MinMaxScaler(feature_range=(0,1)) / MaxAbsScaler()Bounded scaling.
RobustScaler()Median + IQR scaling — resists outliers.
PowerTransformer(method="yeo-johnson")Make distributions more Gaussian. Works on negative values.
QuantileTransformer(output_distribution="normal")Non-linear rank-based transform.
OneHotEncoder(handle_unknown="ignore", sparse_output=False)Categorical → dummies. ignore survives unseen categories.
OrdinalEncoder(handle_unknown="use_encoded_value", unknown_value=-1)Label-encode, robust to new categories.
TargetEncoder(smooth="auto")Target-mean encoding with leak-safe CV (1.4+).
SimpleImputer(strategy="median" | "mean" | "most_frequent" | "constant")Fill missing.
KNNImputer(n_neighbors=5)Distance-based imputation.
FunctionTransformer(np.log1p, validate=False)Wrap a function into a transformer for pipelines.

Compose preprocess + modelPipelines & ColumnTransformer

Pipeline([("scale", StandardScaler()), ("clf", LogisticRegression())])Named steps. Last step does predict.
make_pipeline(StandardScaler(), LogisticRegression())Auto-name steps from class names (snake_case).
ColumnTransformer([("num", scaler, num_cols), ("cat", ohe, cat_cols)], remainder="drop")Per-column-group transformers.
make_column_selector(dtype_include="number")Auto-pick columns by dtype.
remainder="passthrough"Keep unmatched columns untransformed. Default is "drop".
FeatureUnion([("pca", PCA()), ("kbest", SelectKBest())])Run transformers in parallel, concat outputs.
pipe[-1] / pipe.named_steps["clf"]Reach into a step.
pipe.set_params(clf__C=0.5)Tune a nested param — step__param.
pipe.get_feature_names_out()Names after preprocessing — vital for inspection.
set_config(transform_output="pandas")Transformers return DataFrames, not arrays. Keeps column names alive.
python
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.linear_model import LogisticRegression

num_cols = ["age", "income"]
cat_cols = ["country", "plan"]

# Per-column-group preprocessing
preprocess = ColumnTransformer(transformers=[
    ("num", Pipeline([
        ("impute", SimpleImputer(strategy="median")),
        ("scale",  StandardScaler()),
    ]), num_cols),
    ("cat", Pipeline([
        ("impute", SimpleImputer(strategy="most_frequent")),
        ("ohe",    OneHotEncoder(handle_unknown="ignore", sparse_output=False)),
    ]), cat_cols),
], remainder="drop", verbose_feature_names_out=False)

# Full estimator — preprocess + model
clf = Pipeline([
    ("pre",   preprocess),
    ("model", LogisticRegression(C=1.0, max_iter=1000, class_weight="balanced")),
])

clf.fit(X_train, y_train)
clf.predict_proba(X_test)[:, 1]

# Inspect the final feature names (set_config(transform_output='pandas') helps too)
preprocess.fit(X_train)
preprocess.get_feature_names_out()

Linear · trees · SVM · ...Models

Linear & kernel

LinearRegression() / Ridge(alpha=1.0) / Lasso(alpha=0.1) / ElasticNetRegression. Ridge = L2, Lasso = L1, ElasticNet = both.
LogisticRegression(C=1.0, penalty="l2", class_weight="balanced", max_iter=1000)Workhorse classifier. Scale features first.
SGDClassifier(loss="log_loss") / SGDRegressorStochastic gradient — for very large datasets / streaming.
SVC(kernel="rbf", C=1.0, gamma="scale") / SVRKernel SVM. Scale features. Slow past ~50k rows.
LinearSVC(C=1.0, dual="auto")Linear-kernel SVM — much faster than SVC(kernel="linear").
KNeighborsClassifier(n_neighbors=5, weights="distance")k-NN. Scale features.
GaussianNB() / MultinomialNB() / BernoulliNB()Naive Bayes — baselines for text.

Trees & ensembles

DecisionTreeClassifier(max_depth=None, min_samples_leaf=1)Single tree.
RandomForestClassifier(n_estimators=300, n_jobs=-1)Bagged trees — solid default for tabular.
ExtraTreesClassifier(...)More randomized splits than RF.
HistGradientBoostingClassifier(learning_rate=0.1, max_depth=None)Native sklearn boosting. Handles NaN. Preferred over deprecated GradientBoostingClassifier.
VotingClassifier(estimators=[...], voting="soft")Average or vote across models.
StackingClassifier(estimators=[...], final_estimator=...)Meta-learner on top of base models. CV-aware.

Unsupervised

KMeans(n_clusters=8, n_init="auto")Clustering. Scale features; tune n_clusters.
DBSCAN(eps=0.5, min_samples=5)Density-based. Finds noise points + variable cluster sizes.
AgglomerativeClustering(n_clusters=None, distance_threshold=1.0)Hierarchical.
PCA(n_components=0.95)Keep 95% of variance. Linear dim-reduction.
TruncatedSVD(n_components=100)PCA-like for sparse matrices (TF-IDF).
IsolationForest(contamination="auto")Anomaly detection by tree isolation.

CV · grid · halvingModel selection & tuning

GridSearchCV(est, param_grid={...}, cv=cv, scoring="roc_auc", n_jobs=-1)Exhaustive grid. Refits the best on full train by default.
RandomizedSearchCV(est, param_distributions={...}, n_iter=50)Sample the space. Preferred over Grid past 4 hyperparams.
HalvingGridSearchCV / HalvingRandomSearchCVSuccessive-halving — many configs on small data, few on full.
param_grid={"clf__C": [0.1, 1, 10]}Pipeline params use step__param syntax.
scoring=["roc_auc", "f1"] / scoring={"auc": "roc_auc"}Multi-metric. Need refit="auc" when using a dict.
gs.best_estimator_ / best_params_ / cv_results_Outputs after fit.
learning_curve(est, X, y, train_sizes=...)Diagnose underfit vs overfit.
validation_curve(est, X, y, "C", [0.01, 0.1, 1, 10])Score vs single hyperparam.
permutation_importance(est, X, y, n_repeats=10)Model-agnostic feature importance.
python
from sklearn.model_selection import (
    train_test_split, StratifiedKFold, GridSearchCV, cross_val_score
)
from sklearn.metrics import classification_report

# 1. Train/test split — stratify keeps class balance
X_tr, X_te, y_tr, y_te = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42,
)

# 2. K-fold with stratification — the right default for classification
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

# 3. Cheap baseline: cross-val score of a single model
scores = cross_val_score(clf, X_tr, y_tr, cv=cv, scoring="f1", n_jobs=-1)
print(f"CV f1 = {scores.mean():.3f} ± {scores.std():.3f}")

# 4. Tune hyperparameters — search over the whole Pipeline namespace
grid = {
    "pre__num__scale__with_mean": [True, False],          # double underscore = step__param
    "model__C":            [0.1, 1.0, 10.0],
    "model__class_weight": [None, "balanced"],
}
gs = GridSearchCV(
    clf, param_grid=grid, cv=cv, scoring="roc_auc",
    n_jobs=-1, refit=True, verbose=1,
)
gs.fit(X_tr, y_tr)
print("best:", gs.best_params_, gs.best_score_)

# 5. Held-out evaluation
print(classification_report(y_te, gs.predict(X_te)))

Classification · regressionMetrics

accuracy_score(y, y_hat)Fraction correct. Misleading on imbalanced data.
precision_score / recall_score / f1_score(..., average="macro")Multi-class: macro averages classes, weighted weights by support.
roc_auc_score(y, proba) / average_precision_score(y, proba)ROC AUC + PR AUC. Preferred for imbalanced classification.
classification_report(y, y_hat, digits=3)Per-class precision / recall / f1 / support.
confusion_matrix(y, y_hat) / ConfusionMatrixDisplay.from_predictions(...)Matrix + matplotlib display.
log_loss(y, proba) / brier_score_loss(y, proba)Probabilistic loss / calibration.
mean_squared_error(y, y_hat, squared=False)RMSE. squared=False returns root.
mean_absolute_error / mean_absolute_percentage_error / r2_scoreMAE / MAPE / R².
make_scorer(my_fn, greater_is_better=True)Wrap a custom metric for scoring=.

Calibration · PDP · importanceCalibration & inspection

CalibratedClassifierCV(clf, method="isotonic", cv=5)Recalibrate probabilities post-fit.
CalibrationDisplay.from_estimator(clf, X, y)Reliability diagram.
PartialDependenceDisplay.from_estimator(clf, X, features=[...])PDP / ICE plots.
permutation_importance(...).importances_meanDrop in score when a feature is shuffled.
RocCurveDisplay.from_estimator(clf, X, y) / PrecisionRecallDisplayOne-liner ROC / PR plots.
LearningCurveDisplay.from_estimator(...)Train vs val score vs train size.

joblib · ONNX · skopsPersistence & deployment

joblib.dump(est, "model.joblib", compress=3)Standard serialization. Version-sensitive — pin the sklearn version.
joblib.load("model.joblib")Load. Trust the source — pickle executes code.
skops.io.dump(est, "model.skops") / skops.io.load(..., trusted=[...])Safer alternative — signed, no arbitrary code execution.
from skl2onnx import to_onnx; to_onnx(est, X[:1])Export to ONNX for cross-language inference.
pickle protocol matches the training Python versionAlways serialize + load with the same Python + sklearn versions.

Preprocess · tune · persistEnd-to-end · Adult-income classifier

Full pipeline — ColumnTransformer, HistGradientBoosting, RandomizedSearchCV, joblib save. Drop-in template for tabular classification.

python
# End-to-end: load → split → preprocess + model in a Pipeline → tune → persist.
import joblib
import pandas as pd
from sklearn.datasets import fetch_openml
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.model_selection import StratifiedKFold, RandomizedSearchCV
from sklearn.metrics import classification_report

df = fetch_openml("adult", version=2, as_frame=True).frame
y  = (df.pop("class") == ">50K").astype(int)
X  = df

num = X.select_dtypes("number").columns.tolist()
cat = X.select_dtypes(exclude="number").columns.tolist()

pre = ColumnTransformer([
    ("num", Pipeline([("imp", SimpleImputer("median")),
                      ("sc",  StandardScaler())]),                num),
    ("cat", Pipeline([("imp", SimpleImputer("most_frequent")),
                      ("ohe", OneHotEncoder(handle_unknown="ignore"))]), cat),
])

pipe = Pipeline([("pre", pre),
                 ("clf", HistGradientBoostingClassifier(random_state=0))])

search = RandomizedSearchCV(
    pipe,
    {"clf__learning_rate": [0.05, 0.1, 0.2],
     "clf__max_depth":     [None, 4, 6, 8],
     "clf__l2_regularization": [0, 0.1, 1.0]},
    n_iter=12, scoring="roc_auc", n_jobs=-1, random_state=0,
    cv=StratifiedKFold(5, shuffle=True, random_state=0),
)
search.fit(X, y)
print(classification_report(y, search.predict(X)))

joblib.dump(search.best_estimator_, "model.joblib")

Best practiceGood to know

Wrap preprocessing + model in a Pipeline from day one. Without it you'll fit the scaler on train + test combined and leak data. Pipelines fit on train only and reuse those parameters at predict time — the only correct way.
Default to HistGradientBoosting for tabular data. Handles NaN natively, no scaling needed, competitive with XGBoost/LightGBM, and ships with sklearn. The classic GradientBoostingClassifier is deprecated for new code.
Stratify your splits and your CV folds. train_test_split(..., stratify=y) + StratifiedKFold keep class proportions stable — the difference between a useful CV signal and noise on imbalanced data.

Common trapsWatch out for

Leakage: fitting a scaler on the full dataset. scaler.fit(X) outside a pipeline contaminates test data with training stats. Always pipe.fit(X_train, y_train); let the pipeline do it.
predict_proba doesn’t mean "well-calibrated". Tree / SVM probabilities can be very off — useful for ranking, not for thresholds at face value. Use CalibratedClassifierCV + a reliability diagram.
Tree-based feature_importances_ can be misleading. Biased toward high-cardinality features and unrelated to causal effect. Pair with permutation_importance for sanity checking.

Go deeperSee also

scikit-learn FAQ

What is scikit-learn used for?

scikit-learn is the go-to Python library for classical machine learning. It covers supervised learning (regression, classification), unsupervised learning (clustering, dimensionality reduction), model selection (cross-validation, grid search), and preprocessing (scaling, encoding). It is not used for deep learning — use PyTorch or TensorFlow for neural networks.

What is the scikit-learn estimator API?

Every scikit-learn object follows a consistent interface: fit(X, y) trains the model, predict(X) returns predictions, transform(X) applies a transformation (for preprocessors), and score(X, y) returns a default metric. This uniformity makes it easy to swap models and chain them in pipelines.

What is a scikit-learn Pipeline?

A Pipeline chains preprocessing steps and a final estimator into a single object. Call Pipeline(steps=[(name, transformer), ..., (name, model)]) or the shorthand make_pipeline(). The pipeline applies transformers sequentially then calls fit/predict on the model. It prevents data leakage and makes cross-validation clean.

How do I tune hyperparameters in scikit-learn?

Use GridSearchCV to exhaustively search a parameter grid or RandomizedSearchCV to sample randomly — both use cross-validation internally. Pass a dict of parameter names (step__param format for Pipeline params) and the scoring metric. Access the best estimator with gs.best_estimator_ and best score with gs.best_score_.

How do I evaluate a model in scikit-learn?

Use cross_val_score(model, X, y, cv=5, scoring="f1") for a quick k-fold evaluation. For detailed classification metrics call classification_report(y_true, y_pred). For regression use mean_squared_error, r2_score, or mean_absolute_error from sklearn.metrics. Always evaluate on a held-out test set, not the training data.

How do I handle categorical features in scikit-learn?

Use OneHotEncoder for nominal categories (no order) and OrdinalEncoder for ordinal ones. Wrap them in a ColumnTransformer to apply different transformations to different columns: ColumnTransformer([("cat", OneHotEncoder(), cat_cols), ("num", StandardScaler(), num_cols)]). Include the ColumnTransformer as the first step in a Pipeline.