Scikit-learn (sklearn) Cheat Sheet
Last updated
Load and split the data
Hold back a test set before anything else, and only look at it at the very end.
| Task | Code |
|---|---|
| Import the splitter | from sklearn.model_selection import train_test_split |
| Features and target from a DataFrame | X = df.drop(columns="target")
y = df["target"] |
| Built-in dataset as pandas | from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True, as_frame=True) |
| Synthetic data to experiment with | from sklearn.datasets import make_classification
X, y = make_classification(n_samples=500, n_features=8, random_state=0) |
| 80/20 train and test split | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) |
| Keep class proportions in both parts | train_test_split(X, y, test_size=0.2, stratify=y, random_state=42) |
| Train, validation and test (60/20/20) | X_tmp, X_test, y_tmp, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
X_train, X_val, y_train, y_val = train_test_split(X_tmp, y_tmp, test_size=0.25, random_state=0) |
Preprocess features
Fit a transformer on the training data only, then transform both sets. Fitting on test data leaks information.
| Task | Code |
|---|---|
| Imports | from sklearn.preprocessing import StandardScaler, MinMaxScaler, OneHotEncoder, OrdinalEncoder |
| Scale to mean 0 and standard deviation 1 | scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train[["age", "income"]])
X_test_s = scaler.transform(X_test[["age", "income"]]) |
| Scale to the range 0 to 1 | MinMaxScaler().fit_transform(X_train[["age", "income"]]) |
| One-hot encode categories | enc = OneHotEncoder(handle_unknown="ignore", sparse_output=False)
enc.fit_transform(X_train[["city"]]) |
| Encode ordered categories as numbers | OrdinalEncoder(categories=[["low", "mid", "high"]]).fit_transform([["mid"], ["high"]]) |
| Fill missing values | from sklearn.impute import SimpleImputer
SimpleImputer(strategy="median").fit_transform(X_train[["age", "income"]]) |
| Polynomial and interaction features | from sklearn.preprocessing import PolynomialFeatures
PolynomialFeatures(degree=2, include_bias=False).fit_transform(X_train[["age", "income"]]) |
| Get DataFrames back instead of arrays | scaler.set_output(transform="pandas") |
| Text labels to integers | from sklearn.preprocessing import LabelEncoder
LabelEncoder().fit_transform(["cat", "dog", "cat"]) |
Choose a model
Start simple and keep the simple model as the score to beat.
| Problem | Start with | Then try |
|---|---|---|
| Predict a number (regression) | LinearRegression(), Ridge(alpha=1.0) | RandomForestRegressor(), HistGradientBoostingRegressor() |
| Predict a class (classification) | LogisticRegression(max_iter=1000) | RandomForestClassifier(), HistGradientBoostingClassifier() |
| Small data, similar points share a label | KNeighborsClassifier(n_neighbors=5) | SVC(kernel="rbf") |
| Rules you can read | DecisionTreeClassifier(max_depth=3) | RandomForestClassifier() |
| Group rows without labels | KMeans(n_clusters=3) | DBSCAN(eps=0.5) |
| Fewer features for plots or speed | PCA(n_components=2) | TSNE(n_components=2) |
| Find unusual rows | IsolationForest(random_state=0) | LocalOutlierFactor() |
Fit a model
Every estimator follows the same pattern: create it with its settings, then call fit.
| Task | Code |
|---|---|
| The pattern for every model | model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train) |
| Linear regression | from sklearn.linear_model import LinearRegression
LinearRegression() |
| Regularized linear regression | from sklearn.linear_model import Ridge, Lasso
Ridge(alpha=1.0), Lasso(alpha=0.1) |
| Logistic regression (classification) | from sklearn.linear_model import LogisticRegression
LogisticRegression(C=1.0, max_iter=1000) |
| k nearest neighbors | from sklearn.neighbors import KNeighborsClassifier
KNeighborsClassifier(n_neighbors=5) |
| Decision tree | from sklearn.tree import DecisionTreeClassifier
DecisionTreeClassifier(max_depth=3, random_state=0) |
| Random forest | from sklearn.ensemble import RandomForestClassifier
RandomForestClassifier(n_estimators=200, random_state=0) |
| Gradient boosting, fast on big data | from sklearn.ensemble import HistGradientBoostingClassifier
HistGradientBoostingClassifier(random_state=0) |
| Support vector machine | from sklearn.svm import SVC
SVC(kernel="rbf", C=1.0) |
| Naive Bayes | from sklearn.naive_bayes import GaussianNB
GaussianNB() |
| Baseline that always guesses the majority | from sklearn.dummy import DummyClassifier
DummyClassifier(strategy="most_frequent") |
Predict and inspect
| Task | Code |
|---|---|
| Predict classes or values | y_pred = model.predict(X_test) |
| Probability of the positive class | model.predict_proba(X_test)[:, 1] |
| Quick score: accuracy or R² | model.score(X_test, y_test) |
| Coefficients of a linear model | model.coef_, model.intercept_ |
| Feature importance of a tree model | pd.Series(forest.feature_importances_, index=X_train.columns).sort_values() |
| Importance by shuffling each feature | from sklearn.inspection import permutation_importance
permutation_importance(model, X_test, y_test, random_state=0).importances_mean |
| Class labels the model knows | model.classes_ |
| Read and change settings | model.get_params(), model.set_params(C=0.5) |
| Draw a decision tree | from sklearn.tree import plot_tree
plot_tree(tree, filled=True, feature_names=list(X_train.columns)) |
Classification metrics
Accuracy alone hides the errors on a rare class. Check precision, recall and the confusion matrix too.
| Task | Code |
|---|---|
| Imports | from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score |
| Accuracy | accuracy_score(y_test, y_pred) |
| Precision, recall and F1 | precision_score(y_test, y_pred), recall_score(y_test, y_pred), f1_score(y_test, y_pred) |
| F1 for several classes | f1_score(y_test, y_pred, average="macro") |
| Every metric per class | from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred)) |
| Confusion matrix | from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, y_pred) |
| Plot the confusion matrix | from sklearn.metrics import ConfusionMatrixDisplay
ConfusionMatrixDisplay.from_estimator(model, X_test, y_test) |
| ROC AUC from probabilities | from sklearn.metrics import roc_auc_score
roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]) |
| Plot the ROC curve | from sklearn.metrics import RocCurveDisplay
RocCurveDisplay.from_estimator(model, X_test, y_test) |
| Accuracy for imbalanced classes | from sklearn.metrics import balanced_accuracy_score
balanced_accuracy_score(y_test, y_pred) |
| Your own decision threshold | y_pred = (model.predict_proba(X_test)[:, 1] >= 0.3).astype(int) |
Regression metrics
Error metrics are in the target's units (lower is better). R² is the share of variance explained (1 is perfect).
| Task | Code |
|---|---|
| Imports | from sklearn.metrics import mean_absolute_error, mean_squared_error, root_mean_squared_error, r2_score |
| Mean absolute error | mean_absolute_error(y_test, y_pred) |
| Mean squared error and its root | mean_squared_error(y_test, y_pred), root_mean_squared_error(y_test, y_pred) |
| R² score | r2_score(y_test, y_pred) |
| Mean absolute percentage error | from sklearn.metrics import mean_absolute_percentage_error
mean_absolute_percentage_error(y_test, y_pred) |
| Plot predicted against actual | from sklearn.metrics import PredictionErrorDisplay
PredictionErrorDisplay.from_predictions(y_test, y_pred, kind="actual_vs_predicted") |
Pipelines
A pipeline chains preprocessing and a model into one estimator, so cross-validation and grid search fit every step on training folds only.
| Task | Code |
|---|---|
| Imports | from sklearn.pipeline import make_pipeline, Pipeline |
| Scale, then fit a model | pipe = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
pipe.fit(X_train, y_train) |
| Steps with your own names | pipe = Pipeline([("scale", StandardScaler()), ("model", LogisticRegression(max_iter=1000))]) |
| Reach a step inside | pipe.named_steps["model"], pipe[-1] |
| Different steps for different columns | from sklearn.compose import ColumnTransformer
pre = ColumnTransformer([
("num", StandardScaler(), ["age", "income"]),
("cat", OneHotEncoder(handle_unknown="ignore"), ["city"]),
]) |
| Preprocessing and model in one object | model = make_pipeline(pre, RandomForestClassifier(random_state=0))
model.fit(X_train, y_train)
model.score(X_test, y_test) |
| Pick columns by type | from sklearn.compose import make_column_selector
make_column_selector(dtype_include="number")(X_train) |
| Impute, then scale | make_pipeline(SimpleImputer(strategy="median"), StandardScaler()) |
| Names of the output features | pre.get_feature_names_out() |
Cross-validation
Cross-validation trains and scores the model on several splits, which gives a steadier estimate than one test set.
| Task | Code |
|---|---|
| Imports | from sklearn.model_selection import cross_val_score, cross_validate, KFold, StratifiedKFold |
| Score on 5 folds | scores = cross_val_score(pipe, X, y, cv=5)
scores.mean(), scores.std() |
| Choose the metric | cross_val_score(pipe, X, y, cv=5, scoring="f1_macro") |
| Shuffled folds | cv = KFold(n_splits=5, shuffle=True, random_state=0) |
| Same class balance in each fold | cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=0) |
| Several metrics and train scores | cross_validate(pipe, X, y, cv=cv, scoring=["accuracy", "f1"], return_train_score=True) |
| A prediction for every row, made out of fold | from sklearn.model_selection import cross_val_predict
cross_val_predict(pipe, X, y, cv=5) |
| Folds by group, folds in time order | from sklearn.model_selection import GroupKFold, TimeSeriesSplit
GroupKFold(n_splits=5), TimeSeriesSplit(n_splits=5) |
| Every valid scoring name | from sklearn.metrics import get_scorer_names
get_scorer_names() |
Grid search and tuning
A search fits the model for each setting with cross-validation, keeps the best one and refits it on all the training data.
| Task | Code |
|---|---|
| Imports | from sklearn.model_selection import GridSearchCV, RandomizedSearchCV |
| Try every combination | grid = GridSearchCV(RandomForestClassifier(random_state=0), {"n_estimators": [50, 100], "max_depth": [None, 5]}, cv=5)
grid.fit(X_train, y_train) |
| Best settings and their score | grid.best_params_, grid.best_score_ |
| Use the best model | grid.best_estimator_.predict(X_test), grid.score(X_test, y_test) |
| Tune a step inside a pipeline | GridSearchCV(pipe, {"logisticregression__C": [0.1, 1, 10]}, cv=5).fit(X_train, y_train) |
| Random settings from distributions | from scipy.stats import randint
search = RandomizedSearchCV(RandomForestClassifier(random_state=0), {"n_estimators": randint(50, 150)}, n_iter=5, cv=3, random_state=0)
search.fit(X_train, y_train) |
| Use every CPU core | GridSearchCV(pipe, {"logisticregression__C": [0.1, 1]}, cv=5, n_jobs=-1) |
| All results as a table | pd.DataFrame(grid.cv_results_).sort_values("rank_test_score") |
Clustering and dimensionality reduction
Unsupervised models learn from X alone. Scale the features first, because both use distances.
| Task | Code |
|---|---|
| k-means clusters | from sklearn.cluster import KMeans
km = KMeans(n_clusters=3, random_state=0)
labels = km.fit_predict(X) |
| Cluster centers and inertia | km.cluster_centers_, km.inertia_ |
| How well separated the clusters are | from sklearn.metrics import silhouette_score
silhouette_score(X, labels) |
| Density-based clusters, noise is -1 | from sklearn.cluster import DBSCAN
DBSCAN(eps=0.5, min_samples=5).fit_predict(X) |
| Project onto 2 components | from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_2d = pca.fit_transform(X) |
| Variance each component explains | pca.explained_variance_ratio_ |
| Keep 95% of the variance | PCA(n_components=0.95).fit_transform(X) |
scikit-learn 1.9: old forms and what to write now
Code copied from older tutorials can fail or warn in scikit-learn 1.9. Write the forms in the scikit-learn 1.9 column instead.
| Task | scikit-learn 1.9 | Old form |
|---|---|---|
| Root mean squared error | root_mean_squared_error(y_test, y_pred) | mean_squared_error(y_test, y_pred, squared=False) |
| Dense one-hot output | OneHotEncoder(sparse_output=False) | OneHotEncoder(sparse=False) |
| L1 (lasso) logistic regression | LogisticRegression(l1_ratio=1, solver="liblinear") | LogisticRegression(penalty="l1", solver="liblinear") |
| Logistic regression without regularization | LogisticRegression(C=np.inf) | LogisticRegression(penalty=None) |
Save, load and reproduce
| Task | Code |
|---|---|
| Save a fitted model or pipeline | import joblib
joblib.dump(model, "model.joblib") |
| Load it back | model = joblib.load("model.joblib") |
| Same result on every run | random_state=0 |
| Which version is installed | import sklearn
sklearn.__version__ |
The scikit-learn code behind a real machine learning workflow, in the order you write it: load and split the data, preprocess it, pick a model, fit and predict, measure the result, chain the steps into a pipeline, cross-validate and tune with grid search. Each row is a short snippet you can paste, plus one line on what it does.
Every model in scikit-learn shares one API: fit learns from training data, predict and transform apply what it learned. Everything here is written for scikit-learn 1.9, the version Coddy runs, with X for the features and y for the target. scikit-learn works on NumPy arrays and pandas DataFrames, and the Matplotlib cheat sheet covers the plots. New to Python itself? Start with the Python cheat sheet.
Scikit-learn cheat sheet FAQ
Is this scikit-learn cheat sheet free?
Yes. This scikit-learn cheat sheet is completely free, with no sign-up required. Bookmark it, or print it to PDF from your browser, and come back whenever you need the exact call for a pipeline, a metric or a grid search.
Is sklearn the same as scikit-learn?
pip install scikit-learn), and sklearn is the name you import in code (from sklearn.linear_model import LinearRegression). An sklearn cheat sheet and a scikit-learn cheat sheet cover the same thing.What is the difference between fit, transform and fit_transform?
fit learns from data: a scaler learns each column's mean, a model learns its weights. transform applies what was learned, and fit_transform does both in one call. Use fit_transform on the training set and only transform on the test set, or the test data leaks into training. A pipeline does this for you.Do I need to scale my features?
For models that use distances or gradients, yes: k nearest neighbors, SVMs, k-means, PCA and regularized linear and logistic regression all work better on scaled data. Tree models such as decision trees, random forests and gradient boosting do not need scaling. Put the scaler in a pipeline so it is fitted on training data only.
Which scikit-learn model should I start with?
LinearRegression to predict numbers, LogisticRegression to predict classes. Then try RandomForestClassifier or HistGradientBoostingClassifier (or their regressor versions), compare them with cross-validation, and tune the best one with GridSearchCV.Which scikit-learn version does this cheat sheet cover?
squared=False in mean_squared_error, sparse=False in OneHotEncoder and the penalty argument of LogisticRegression, are in the old forms table next to what to write instead.