Q&A library Python

How do I handle imbalanced classes in scikit-learn?

Python Advanced class-weightimbalancedscikit-learn

Short answer

Stop using accuracy, which rewards always predicting the majority class, and use a metric like F1 or ROC AUC. Set class_weight to balanced, stratify your splits, and consider resampling inside a pipeline.

The short version

With imbalanced classes, first stop trusting accuracy, because always predicting the majority class scores high while being useless. Use a metric like F1, recall or ROC AUC. Then help the model with class_weight="balanced", keep splits stratified, and if needed resample the training data, doing the resampling inside a pipeline so it never touches the test fold.

Why accuracy misleads

Suppose 95 per cent of rows are class A. A model that always says A is 95 per cent accurate and completely worthless, because it never finds a single B. Accuracy hides this failure. Metrics that look at the rare class expose it.

from sklearn.metrics import classification_report
print(classification_report(y_test, predictions))

classification_report shows precision, recall and F1 per class, so the poor recall on the minority class is visible instead of buried in an accuracy figure.

Weighting the classes

Many estimators accept class_weight="balanced", which makes mistakes on the rare class cost more, nudging the model to pay attention to it.

from sklearn.linear_model import LogisticRegression
model = LogisticRegression(class_weight="balanced")

This is the simplest first step and often helps a lot, because it addresses the imbalance without changing the data.

Keeping splits representative

Always split and cross-validate in a stratified way, so each fold keeps the same class proportions as the whole set. With a rare class, an unstratified split can land almost all the minority examples in one side.

from sklearn.model_selection import train_test_split
train_test_split(X, y, stratify=y, random_state=0)

Resampling, done safely

You can oversample the minority class or undersample the majority, but this must happen on training data only, inside the cross-validation loop, or it leaks. The imbalanced-learn library provides a pipeline that resamples per fold correctly.

# using imbalanced-learn's pipeline so resampling stays inside each fold
from imblearn.pipeline import Pipeline as ImbPipeline
from imblearn.over_sampling import SMOTE
from sklearn.linear_model import LogisticRegression

model = ImbPipeline([("smote", SMOTE()), ("clf", LogisticRegression())])

The common mistake is resampling the whole dataset before splitting, which copies minority rows into both train and test and inflates your scores. Keeping resampling inside the pipeline prevents that.

Choosing the right target metric

Decide what matters for your problem. If missing a rare positive is costly, optimise recall; if false alarms are costly, weigh precision; F1 balances the two, and ROC AUC or precision-recall AUC summarise performance across thresholds. Pick the metric first, then tune towards it, so you are not optimising accuracy by accident.

The honest summary

There is no single switch for imbalance. Measure with a suitable metric, weight or resample thoughtfully, keep everything stratified and leak-free, and judge success on the minority class you actually care about, not on overall accuracy.

Need this solved on your own data?

The library is free and always will be. When the problem is bigger than an answer, we take on the work.

Start a project