Scikit-Learn Classification
Train, compare, and tune classification algorithms — Logistic Regression, Random Forest, SVM, and Gradient Boosting — on real datasets.
Real-World Scenario
A bank’s fraud detection team needs to classify 2 million daily transactions as legitimate or fraudulent. They need to compare multiple algorithms, understand the precision-recall tradeoff, and deploy the model that maximizes fraud detection while keeping the false-positive rate below 1% (to avoid blocking legitimate customers). This is the full classification workflow.
Logistic Regression — The Baseline
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import classification_report, roc_auc_score
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)
lr = LogisticRegression(C=1.0, max_iter=1000, random_state=42)
lr.fit(X_train_s, y_train)
print("Logistic Regression:")
print(classification_report(y_test, lr.predict(X_test_s)))
print(f"AUC-ROC: {roc_auc_score(y_test, lr.predict_proba(X_test_s)[:, 1]):.4f}")
Random Forest Classifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, classification_report
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
rf = RandomForestClassifier(
n_estimators=200, # number of trees
max_depth=None, # grow until leaves are pure
min_samples_split=5, # min samples to split a node
min_samples_leaf=2, # min samples in a leaf
class_weight="balanced", # handle imbalance
n_jobs=-1, # use all CPU cores
random_state=42,
)
rf.fit(X_train, y_train)
print("Random Forest:")
print(classification_report(y_test, rf.predict(X_test)))
print(f"AUC-ROC: {roc_auc_score(y_test, rf.predict_proba(X_test)[:, 1]):.4f}")
# Feature importances — how much each feature reduces impurity
feature_names = load_breast_cancer().feature_names
importances = rf.feature_importances_
top_idx = np.argsort(importances)[::-1][:10]
print("\nTop 10 features:")
for i in top_idx:
print(f" {feature_names[i]:40s}: {importances[i]:.4f}")
Gradient Boosting Classifier
from sklearn.ensemble import GradientBoostingClassifier, HistGradientBoostingClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# HistGradientBoostingClassifier — faster, supports missing values natively
model = HistGradientBoostingClassifier(
max_iter=300,
learning_rate=0.05,
max_depth=4,
min_samples_leaf=20,
l2_regularization=0.1,
random_state=42,
)
model.fit(X_train, y_train)
print(f"GBM AUC-ROC: {roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]):.4f}")
Support Vector Machine
from sklearn.svm import SVC
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import roc_auc_score
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)
# probability=True needed for predict_proba — slightly slower
svm = SVC(C=10, kernel="rbf", gamma="scale", probability=True, random_state=42)
svm.fit(X_train_s, y_train)
print(f"SVM AUC-ROC: {roc_auc_score(y_test, svm.predict_proba(X_test_s)[:, 1]):.4f}")
Comparing Multiple Classifiers
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_validate, StratifiedKFold
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.svm import SVC
import pandas as pd
import numpy as np
X, y = make_classification(n_samples=2000, n_features=20, n_informative=10,
weights=[0.7, 0.3], random_state=42)
classifiers = {
"Logistic Regression": Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(class_weight="balanced", max_iter=1000)),
]),
"Random Forest": RandomForestClassifier(
n_estimators=200, class_weight="balanced", n_jobs=-1, random_state=42
),
"Gradient Boosting": GradientBoostingClassifier(n_estimators=200, random_state=42),
"SVM": Pipeline([
("scaler", StandardScaler()),
("clf", SVC(class_weight="balanced", probability=True)),
]),
}
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
results = []
for name, clf in classifiers.items():
scores = cross_validate(clf, X, y, cv=cv, scoring=["roc_auc", "f1", "accuracy"])
results.append({
"Model": name,
"AUC-ROC": f"{scores['test_roc_auc'].mean():.4f} ± {scores['test_roc_auc'].std():.4f}",
"F1": f"{scores['test_f1'].mean():.4f} ± {scores['test_f1'].std():.4f}",
"Accuracy": f"{scores['test_accuracy'].mean():.4f} ± {scores['test_accuracy'].std():.4f}",
})
print(pd.DataFrame(results).to_string(index=False))
Adjusting the Decision Threshold
from sklearn.datasets import make_classification
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import precision_recall_curve, f1_score
import numpy as np
X, y = make_classification(n_samples=5000, weights=[0.95, 0.05], random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)
model = GradientBoostingClassifier(random_state=42)
model.fit(X_train, y_train)
y_prob = model.predict_proba(X_test)[:, 1]
# Find threshold that maximizes F1 score
precision, recall, thresholds = precision_recall_curve(y_test, y_prob)
f1_scores = 2 * precision * recall / (precision + recall + 1e-8)
best_threshold = thresholds[np.argmax(f1_scores[:-1])]
print(f"Default threshold (0.5): F1 = {f1_score(y_test, y_prob >= 0.5):.4f}")
print(f"Optimal threshold ({best_threshold:.2f}): F1 = {f1_score(y_test, y_prob >= best_threshold):.4f}") Frequently Asked Questions
How do I choose between Logistic Regression, Random Forest, and Gradient Boosting?
Start with Logistic Regression as a fast, interpretable baseline. Move to Random Forest when the relationship is non-linear and you want robustness without tuning. Use Gradient Boosting (XGBoost, LightGBM) when you want maximum accuracy on tabular data. SVMs work well on small, high-dimensional datasets like text.
What is the difference between predict and predict_proba?
predict() returns the final class label (0 or 1). predict_proba() returns the probability of each class — a float between 0 and 1. Use predict_proba() when you need a calibrated confidence score, or when you want to tune the decision threshold beyond the default 0.5.