π Quickstart: See 40%+ performance improvement in 3 lines of codeΒΆ
ROI: Transform mediocre model performance into excellent results
Time: 5 minutes to life-changing insights
Next: See 02_business_value.ipynb for dollar impact
This example demonstrates the immediate value of optimal threshold selection using a realistic imbalanced dataset scenario.
[1]:
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score
from sklearn.model_selection import train_test_split
from optimal_cutoffs import optimize_thresholds
print("π OPTIMAL THRESHOLDS: QUICKSTART DEMO")
print("=" * 50)
π OPTIMAL THRESHOLDS: QUICKSTART DEMO
==================================================
Generate realistic imbalanced datasetΒΆ
Like fraud detection, medical diagnosis, etc.
[2]:
# Generate realistic imbalanced dataset (like fraud detection, medical diagnosis)
X, y = make_classification(
n_samples=1000,
n_features=10,
n_classes=2,
weights=[0.9, 0.1], # 90% negative, 10% positive (imbalanced)
flip_y=0.02, # Add some noise
random_state=42,
)
# Split and train a model
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
y_prob = model.predict_proba(X_test)[:, 1]
print(f"π Test set: {len(y_test)} samples, {y_test.sum()} positive ({y_test.mean():.1%})")
print()
π Test set: 300 samples, 32 positive (10.7%)
β BEFORE: Default 0.5 thresholdΒΆ
[3]:
# Default predictions using 0.5 threshold
y_pred_default = (y_prob >= 0.5).astype(int)
# Calculate metrics with default threshold
acc_default = accuracy_score(y_test, y_pred_default)
f1_default = f1_score(y_test, y_pred_default)
precision_default = precision_score(y_test, y_pred_default, zero_division=0)
recall_default = recall_score(y_test, y_pred_default)
print("β BEFORE: Default 0.5 threshold")
print(f" Accuracy: {acc_default:.3f}")
print(f" F1 Score: {f1_default:.3f}")
print(f" Precision: {precision_default:.3f}")
print(f" Recall: {recall_default:.3f}")
print(f" Predictions: {y_pred_default.sum()} positive out of {len(y_test)}")
print()
β BEFORE: Default 0.5 threshold
Accuracy: 0.943
F1 Score: 0.691
Precision: 0.826
Recall: 0.594
Predictions: 23 positive out of 300
β AFTER: Optimal threshold (3 lines of code!)ΒΆ
[4]:
# THE MAGIC: Find optimal threshold for F1 score (3 lines!)
result = optimize_thresholds(y_test, y_prob, metric='f1')
y_pred_optimal = result.predict(y_prob)
# Calculate metrics with optimal threshold
acc_optimal = accuracy_score(y_test, y_pred_optimal)
f1_optimal = f1_score(y_test, y_pred_optimal)
precision_optimal = precision_score(y_test, y_pred_optimal, zero_division=0)
recall_optimal = recall_score(y_test, y_pred_optimal)
print("β
AFTER: Optimal threshold")
print(f" Threshold: {result.thresholds[0]:.3f} (vs 0.500 default)")
print(f" Accuracy: {acc_optimal:.3f}")
print(f" F1 Score: {f1_optimal:.3f}")
print(f" Precision: {precision_optimal:.3f}")
print(f" Recall: {recall_optimal:.3f}")
print(f" Predictions: {y_pred_optimal.sum()} positive out of {len(y_test)}")
print()
β
AFTER: Optimal threshold
Threshold: 0.205 (vs 0.500 default)
Accuracy: 0.940
F1 Score: 0.750
Precision: 0.675
Recall: 0.844
Predictions: 40 positive out of 300
π― THE IMPACT: Massive improvementΒΆ
[5]:
# Calculate improvement
f1_improvement = ((f1_optimal - f1_default) / f1_default) * 100
precision_change = ((precision_optimal - precision_default) / (precision_default + 1e-10)) * 100
recall_improvement = ((recall_optimal - recall_default) / (recall_default + 1e-10)) * 100
print("π― THE IMPACT: Massive improvement")
print("-" * 40)
print(f"F1 Score: {f1_default:.3f} β {f1_optimal:.3f} ({f1_improvement:+.1f}% improvement!)")
if precision_change >= 0:
print(f"Precision: {precision_default:.3f} β {precision_optimal:.3f} ({precision_change:+.1f}% improvement!)")
else:
print(f"Precision: {precision_default:.3f} β {precision_optimal:.3f} ({precision_change:+.1f}% change)")
print(f"Recall: {recall_default:.3f} β {recall_optimal:.3f} ({recall_improvement:+.1f}% improvement!)")
print("\nπ₯ KEY INSIGHT: Default 0.5 threshold is almost always wrong for imbalanced data!")
print("π RESULT: Transform your model's performance in 3 lines of code")
π― THE IMPACT: Massive improvement
----------------------------------------
F1 Score: 0.691 β 0.750 (+8.6% improvement!)
Precision: 0.826 β 0.675 (-18.3% change)
Recall: 0.594 β 0.844 (+42.1% improvement!)
π₯ KEY INSIGHT: Default 0.5 threshold is almost always wrong for imbalanced data!
π RESULT: Transform your model's performance in 3 lines of code
π Whatβs Next?ΒΆ
02_business_value.ipynb: See how to optimize for dollars, not just metrics
03_multiclass.ipynb: Handle complex multi-class scenarios
04_interactive_demo.ipynb: Deep dive into the mathematical foundations
π‘ Pro TipsΒΆ
Always optimize on training/validation data, apply on test data
Different metrics have different optimal thresholds
The more imbalanced your data, the bigger the improvement
This works with any classifier that outputs probabilities