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?
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?
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.