Monday, August 24, 2026
HomeData ScienceHandling Imbalanced Datasets in Machine Learning – Python Guide

Handling Imbalanced Datasets in Machine Learning – Python Guide

Table of Content

Class imbalance is one of the most common real-world challenges in machine learning. Fraud detection, disease diagnosis, churn prediction — in all of these, the rare class (fraud, disease, churn) is what you care about most, but it makes up only 1-5% of the data. A naive classifier that predicts the majority class every time achieves 99% accuracy but is completely useless. This guide shows you how to actually solve the problem.

Understanding the Problem

Scattered puzzle pieces on a wooden surface
Photo by Hans Tilstra on Unsplash

Most ML algorithms optimise for overall accuracy, which is misleading with imbalanced data. If 1% of transactions are fraudulent, predicting “not fraud” for every transaction gives 99% accuracy but catches zero fraud cases. The real metrics you need are precision, recall, F1, and AUC-ROC — all of which measure how well the model handles the minority class.

from sklearn.metrics import classification_report, roc_auc_score

print(classification_report(y_test, y_pred))
print(f"AUC-ROC: {roc_auc_score(y_test, y_prob):.4f}")

Strategy 1 – Adjust Class Weights

The simplest and most effective first step: tell the model to penalise mistakes on the minority class more heavily. Most sklearn estimators support class_weight='balanced':

from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression

# Automatically compute weights inversely proportional to class frequency
rf = RandomForestClassifier(class_weight='balanced', n_estimators=100, random_state=42)
rf.fit(X_train, y_train)

# Manual weights
lr = LogisticRegression(class_weight={0: 1, 1: 10}, max_iter=1000)
lr.fit(X_train, y_train)

This is often enough to solve mild imbalance (10:1 ratio). Try this before any resampling.

Strategy 2 – Oversampling the Minority Class

man writing on white board
Photo by Campaign Creators on Unsplash

SMOTE (Synthetic Minority Over-sampling Technique) creates synthetic minority class samples by interpolating between existing minority samples. This is better than simple duplication because it adds diversity.

pip install imbalanced-learn
from imblearn.over_sampling import SMOTE
from collections import Counter

print("Before:", Counter(y_train))  # {0: 9500, 1: 500}

smote = SMOTE(random_state=42, k_neighbors=5)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)

print("After:", Counter(y_resampled))  # {0: 9500, 1: 9500}

Critical: Only apply SMOTE to training data, never to test data. Apply it after the train/test split.

Strategy 3 – Undersampling the Majority Class

from imblearn.under_sampling import RandomUnderSampler, TomekLinks

# Random undersampling
rus = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = rus.fit_resample(X_train, y_train)

# Tomek Links — removes majority class samples near the decision boundary
tl = TomekLinks()
X_clean, y_clean = tl.fit_resample(X_train, y_train)

Undersampling discards majority class data. Fine if you have lots of it; risky with smaller datasets.

Strategy 4 – Combine Over and Undersampling

from imblearn.combine import SMOTETomek, SMOTEENN

# SMOTE + Tomek Links (best general-purpose combination)
smt = SMOTETomek(random_state=42)
X_resampled, y_resampled = smt.fit_resample(X_train, y_train)

SMOTETomek first oversamples with SMOTE then cleans the boundary with Tomek Links. It’s one of the best general-purpose strategies for binary classification with imbalance.

Strategy 5 – Algorithm-Level Solutions

Some algorithms handle imbalance natively. Balanced Random Forest samples balanced bootstrap sets for each tree:

from imblearn.ensemble import BalancedRandomForestClassifier, EasyEnsembleClassifier

brf = BalancedRandomForestClassifier(n_estimators=100, random_state=42)
brf.fit(X_train, y_train)

# EasyEnsemble combines multiple undersampled classifiers
ee = EasyEnsembleClassifier(n_estimators=10, random_state=42)
ee.fit(X_train, y_train)

Strategy 6 – Adjust Classification Threshold

By default, classifiers use 0.5 as the decision threshold. For imbalanced data, lowering this to 0.2-0.3 increases recall at the cost of precision:

y_prob = model.predict_proba(X_test)[:, 1]

# Threshold sweep
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_test, y_prob)

# Find threshold that maximises F1
f1_scores = 2 * (precisions * recalls) / (precisions + recalls + 1e-9)
optimal_threshold = thresholds[f1_scores.argmax()]
print(f"Optimal threshold: {optimal_threshold:.3f}")

y_pred_adjusted = (y_prob >= optimal_threshold).astype(int)
print(classification_report(y_test, y_pred_adjusted))

Which Strategy Should You Use?

Start with class_weight='balanced' — it’s zero cost and often solves the problem. If your imbalance ratio is extreme (>100:1), add SMOTE. For ensemble models, try BalancedRandomForest. Always tune the decision threshold at the end — it’s the highest-leverage, lowest-risk lever. And always evaluate with AUC-ROC and the PR curve, never just accuracy.

Conclusion

Imbalanced datasets are the rule, not the exception, in real-world machine learning. The solution is not a single silver bullet but a combination of strategies: appropriate metrics, class weights, SMOTE, and threshold tuning. Master these techniques and you’ll be able to build models that actually perform on the minority class — which is almost always the class that matters most.

Leave feedback about this

  • Rating

Durgesh Kekare
Durgesh Kekarehttps://www.dataexpertise.in
Durgesh Kekare is a data science educator and founder of DataExpertise.in. With expertise in Python, machine learning, and analytics, he helps 10,000+ learners break into data careers.

Latest Posts

List of Categories