scikit-learn cheat sheet

A scannable scikit-learn reference: 20 short snippets across 12 topics, each linking back to the lesson it came from.

At a glance

TopicWhat it covers
Estimators and fit/predictThe uniform API behind every scikit-learn model: fit, predict, transform, and the data shapes the library silentlylesson
Pipelines and preprocessingBecause the pipeline is a single estimator, a final fit on all training data is all you need before deployment. Persistlesson
Model selection and metricsNested cross-validation, grid and randomised search, and picking a metric that reflects the cost of being wrong ratherlesson
Splitting data and cross-validation strategiestrain_test_split only partitions rows. It cannot know that twenty rows belong to the same customer or that row 5,000 islesson
Linear modelsLogistic regression fits a linear model to the log-odds and predicts a class; the probabilities are a monotonelesson
Tree-based modelsoob_score_ gives a cheap validation estimate for a forest because each tree was trained without roughly a third of thelesson
Support vector machines and kernelsAn SVM finds the boundary with the widest margin between classes. Distance is central to that objective, so a featurelesson
Clustering and manifold learningKMeans and MiniBatchKMeans, DBSCAN and AgglomerativeClustering, silhouette scores, PCA for compression and t-SNE forlesson
Feature engineering and text featuresCounts answer 'how often does this word appear'; TF-IDF down-weights terms that appear in almost every document andlesson
Missing data and outliersBefore choosing an imputation strategy, check whether the missingness itself predicts the label. If rows with a missinglesson
Imbalanced classificationclass_weight and threshold tuning, resampling with imbalanced-learn inside a pipeline, and measuring success withlesson
Persistence, inspection and reproducibilityA pickle is code, not data: loading one executes what it references. Only load artefacts you produced yourself, andlesson

Quick snippets

Estimators and fit/predict

Choosing a first model

from sklearn.dummy import DummyClassifier

# always beat a trivial baseline first
dummy = DummyClassifier(strategy="most_frequent").fit(X_train, y_train)
print("baseline", dummy.score(X_test, y_test))

# and check the data before tuning anything
print(np.bincount(y))            # class balance
print(np.isnan(X).sum())         # missing values per feature

Full lesson: Estimators and fit/predict →

Pipelines and preprocessing

Leakage in practice

from sklearn.model_selection import cross_val_score

# WRONG: the scaler saw every row, including the validation folds
X_all_scaled = StandardScaler().fit_transform(X_all)
scores = cross_val_score(LogisticRegression(), X_all_scaled, y, cv=5)
print("too optimistic", scores.mean())

# RIGHT: scaling happens inside each fold
pipe = Pipeline([("scale", StandardScaler()), ("clf", LogisticRegression())])
scores = cross_val_score(pipe, X_all, y, cv=5, scoring="roc_auc")
print("honest", scores.mean())

Custom transformers and feature logic

from sklearn import set_config
set_config(display="diagram")      # renders the pipeline in a notebook

# inspect what the pipeline produced
feature_names = model.named_steps["prep"].get_feature_names_out()
print(len(feature_names))

Full lesson: Pipelines and preprocessing →

Model selection and metrics

Metrics that match the problem

from sklearn.metrics import (classification_report, confusion_matrix,
                             f1_score, precision_recall_curve, roc_auc_score)

y_pred = best.predict(X_test)
y_prob = best.predict_proba(X_test)[:, 1]

print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred, digits=3))
print("roc auc", round(roc_auc_score(y_test, y_prob), 3))

precision, recall, thresholds = precision_recall_curve(y_test, y_prob)
# choose the threshold from the business cost, not the default 0.5

Getting an honest number

from sklearn.model_selection import cross_val_score, train_test_split

# hold out a final test set that the search never sees
X_dev, X_test, y_dev, y_test = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=7)

grid.fit(X_dev, y_dev)
grid.best_estimator_.score(X_test, y_test)      # report this number

# is the gap between folds large? then the model is unstable, not tuned
scores = cross_val_score(grid.best_estimator_, X_dev, y_dev, cv=cv)
print(scores.mean(), scores.std(), scores)

Full lesson: Model selection and metrics →

Splitting data and cross-validation strategies

train_test_split in detail

import numpy as np
from sklearn.model_selection import train_test_split

X_dev, X_test, y_dev, y_test = train_test_split(
    X, y,
    test_size=0.2,          # or train_size=0.8, never both
    random_state=42,        # makes the split reproducible
    stratify=y,             # preserves the class ratio in both parts
    shuffle=True)           # must be False for ordered data

print(np.bincount(y_test))         # check the class balance survived
print(X_dev.shape, X_test.shape)

Choosing a cross-validation splitter

# a pipeline is what makes the score honest: preprocessing refits in every fold
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

pipe = Pipeline([("scale", StandardScaler()),
                 ("clf", LogisticRegression(max_iter=1000, class_weight="balanced"))])

Reporting the result

from sklearn.model_selection import RepeatedStratifiedKFold, cross_validate

cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=42)

res = cross_validate(pipe, X_dev, y_dev, cv=cv,
                     scoring=["roc_auc", "average_precision", "recall"],
                     return_train_score=True, n_jobs=-1)

for key in ["test_roc_auc", "test_average_precision", "test_recall"]:
    s = res[key]
    print(key, round(s.mean(), 4), "+/-", round(s.std(), 4))
print("train-test gap", round(res["train_roc_auc"].mean() - res["test_roc_auc"].mean(), 4))

Full lesson: Splitting data and cross-validation strategies →

Linear models

Regularisation

from sklearn.linear_model import ElasticNet, Lasso, Ridge

# alpha is the strength: bigger alpha = more shrinkage
for alpha in [0.001, 0.1, 1.0, 10.0]:
    m = Ridge(alpha=alpha).fit(X_train_scaled, y_train)
    print(alpha, round(m.score(X_test_scaled, y_test), 4))

lasso = Lasso(alpha=0.01, max_iter=5000).fit(X_train_scaled, y_train)
print("features kept", (lasso.coef_ != 0).sum(), "of", len(lasso.coef_))

enet = ElasticNet(alpha=0.01, l1_ratio=0.5, max_iter=5000)

Reading coefficients

import numpy as np
import pandas as pd

model = clf.named_steps["model"]
pd.DataFrame({
    "feature": feature_names,
    "coef": model.coef_[0],
    "odds_ratio": np.exp(model.coef_[0]),
}).sort_values("coef", key=np.abs, ascending=False).head(10)

Full lesson: Linear models →

Tree-based models

A single tree

from sklearn.tree import DecisionTreeClassifier, export_text

tree = DecisionTreeClassifier(
    max_depth=4,             # the main brake on overfitting
    min_samples_leaf=20,     # each leaf must cover real rows
    min_samples_split=40,
    ccp_alpha=0.0,           # cost-complexity pruning, tuned separately
    random_state=42).fit(X_train, y_train)

print(tree.get_depth(), tree.get_n_leaves())
print(export_text(tree, feature_names=list(feature_names), max_depth=3))

Feature importances and their pitfalls

import numpy as np
from sklearn.inspection import permutation_importance

# impurity importance: fast, but biased toward high-cardinality features
print(sorted(zip(feature_names, forest.feature_importances_),
             key=lambda p: -p[1])[:5])

perm = permutation_importance(boost, X_val, y_val,
                              scoring="roc_auc", n_repeats=10,
                              random_state=42, n_jobs=-1)
print(sorted(zip(feature_names, perm.importances_mean),
             key=lambda p: -p[1])[:5])

Full lesson: Tree-based models →

Support vector machines and kernels

Kernels, C and gamma

search = GridSearchCV(
    pipe,
    {"svc__C": [0.1, 1, 10, 100],
     "svc__gamma": ["scale", 0.01, 0.1, 1.0]},
    scoring="roc_auc", cv=5, n_jobs=-1, refit=True).fit(X_train, y_train)

print(search.best_params_, round(search.best_score_, 4))

Full lesson: Support vector machines and kernels →

Clustering and manifold learning

Density-based and hierarchical clustering

from sklearn.cluster import AgglomerativeClustering, DBSCAN
from sklearn.metrics import adjusted_rand_score

db = DBSCAN(eps=0.7, min_samples=10).fit(X_scaled)
print(np.unique(db.labels_, return_counts=True))   # -1 marks noise points

agg = AgglomerativeClustering(n_clusters=5, linkage="ward")
agg.fit(X_scaled)
print(adjusted_rand_score(db.labels_, agg.labels_))  # agreement between two views

Full lesson: Clustering and manifold learning →

Feature engineering and text features

Encoding categories and numbers

from sklearn.preprocessing import (FunctionTransformer, KBinsDiscretizer,
                                   OneHotEncoder, OrdinalEncoder, PolynomialFeatures)

ohe = OneHotEncoder(handle_unknown="ignore", min_frequency=5,
                    sparse_output=False)
ordinal = OrdinalEncoder(handle_unknown="use_encoded_value", unknown_value=-1)
bins = KBinsDiscretizer(n_bins=8, encode="onehot-dense", strategy="quantile")

# a log transform as a pipeline step, no custom class needed
log1p = FunctionTransformer(np.log1p, inverse_func=np.expm1, validate=True)

Interactions and the cost of width

poly = PolynomialFeatures(degree=2, interaction_only=True,
                         include_bias=False)
X_poly = poly.fit_transform(X[["age", "income"]])
print(X.shape[1], "->", X_poly.shape[1])

# bound the blow-up: only interact a chosen subset
interactions = ColumnTransformer([
    ("poly", PolynomialFeatures(degree=2, interaction_only=True,
                                include_bias=False), ["age", "income"]),
    ("rest", "passthrough", ["sessions"]),
])

Full lesson: Feature engineering and text features →

Missing data and outliers

Outliers and robust preprocessing

from sklearn.preprocessing import QuantileTransformer, RobustScaler

# median and IQR instead of mean and standard deviation
robust = RobustScaler(quantile_range=(10.0, 90.0))
X_robust = robust.fit_transform(X_train)

# map any distribution onto a normal or uniform one
quant = QuantileTransformer(output_distribution="normal",
                            n_quantiles=1000, random_state=42)
X_quant = quant.fit_transform(X_train)

Deciding whether the gap matters

gap = df["income"].isna()
print(df.groupby(gap)["churned"].mean())      # does the gap predict the label?

print(df.isna().mean().sort_values(ascending=False).head())   # how much is missing
print(df[gap].shape[0] / len(df))             # dropping it is only an option when small

Full lesson: Missing data and outliers →

Imbalanced classification

Measuring honestly

from sklearn.metrics import (average_precision_score, balanced_accuracy_score,
                             precision_score, recall_score)

threshold = 0.35        # chosen from the cost of each error, not from habit
y_pred = (prob > threshold).astype(int)

print("average precision", round(average_precision_score(y_test, prob), 4))
print("balanced accuracy", round(balanced_accuracy_score(y_test, y_pred), 4))
print("precision", round(precision_score(y_test, y_pred, zero_division=0), 4))
print("recall", round(recall_score(y_test, y_pred, zero_division=0), 4))

Full lesson: Imbalanced classification →

Persistence, inspection and reproducibility

Pinning and reproducibility

from sklearn import get_config, set_config

set_config(display="diagram")              # notebook rendering of pipelines
print(get_config()["assume_finite"])       # current global settings

# seed every randomised step you own
SEED = 42
set_config(transform_output="pandas")      # keep column names through transformers

Full lesson: Persistence, inspection and reproducibility →

FAQ

Is this scikit-learn cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 12 lessons of the scikit-learn course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full scikit-learn course — it carries the worked explanations, the edge cases and the exercises behind every line here.

AI Basics AI Agents Math for AI Machine Learning TensorFlow PyTorch

Last refreshed 2026-09-27.