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
| Topic | What it covers | |
|---|---|---|
| Estimators and fit/predict | The uniform API behind every scikit-learn model: fit, predict, transform, and the data shapes the library silently | lesson |
| Pipelines and preprocessing | Because the pipeline is a single estimator, a final fit on all training data is all you need before deployment. Persist | lesson |
| Model selection and metrics | Nested cross-validation, grid and randomised search, and picking a metric that reflects the cost of being wrong rather | lesson |
| Splitting data and cross-validation strategies | train_test_split only partitions rows. It cannot know that twenty rows belong to the same customer or that row 5,000 is | lesson |
| Linear models | Logistic regression fits a linear model to the log-odds and predicts a class; the probabilities are a monotone | lesson |
| Tree-based models | oob_score_ gives a cheap validation estimate for a forest because each tree was trained without roughly a third of the | lesson |
| Support vector machines and kernels | An SVM finds the boundary with the widest margin between classes. Distance is central to that objective, so a feature | lesson |
| Clustering and manifold learning | KMeans and MiniBatchKMeans, DBSCAN and AgglomerativeClustering, silhouette scores, PCA for compression and t-SNE for | lesson |
| Feature engineering and text features | Counts answer 'how often does this word appear'; TF-IDF down-weights terms that appear in almost every document and | lesson |
| Missing data and outliers | Before choosing an imputation strategy, check whether the missingness itself predicts the label. If rows with a missing | lesson |
| Imbalanced classification | class_weight and threshold tuning, resampling with imbalanced-learn inside a pipeline, and measuring success with | lesson |
| Persistence, inspection and reproducibility | A pickle is code, not data: loading one executes what it references. Only load artefacts you produced yourself, and | lesson |
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 featureFull 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)
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 viewsFull 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 smallFull 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 transformersFull lesson: Persistence, inspection and reproducibility →
FAQ
Is this scikit-learn cheat sheet free to use?
Where do the examples come from?
How do I go deeper than a cheat sheet?
Related cheat sheets
AI Basics AI Agents Math for AI Machine Learning TensorFlow PyTorch
Last refreshed 2026-09-27.