Logistic Regression & Classification Metrics
2155 words
11 min read
Visual companion
Python
Type and operator map
Python Week 1: the first filter for runtime behavior
View
Revision summary
What this note is really saying
Short form
# Logistic Regression & Classification Metrics ## 🎯 Learning Objectives - Explain why linear regression fails for classification and how logistic regression fixes it - Understand the sigmoid function and how it produces probabilities - Derive the logistic regression cost function and gradient - Evaluate classificat...

Logistic Regression & Classification Metrics
🎯 Learning Objectives
- Explain why linear regression fails for classification and how logistic regression fixes it
- Understand the sigmoid function and how it produces probabilities
- Derive the logistic regression cost function and gradient
- Evaluate classification models with accuracy, precision, recall, F1, and AUC-ROC
- Implement logistic regression using sklearn
📋 Prerequisites
- Linear Regression — logistic regression is structurally similar but for classification
- Probability basics — odds, log-odds, probability
- Gradient descent — same optimization algorithm
📖 Core Content
4.1 Intuition: Why Not Just Use Linear Regression for Classification?
Imagine predicting "will a student pass an exam?" (y=1 = pass, y=0 = fail) from hours studied. If we use linear regression, two things break:
- Predictions outside [0,1]: For very few hours, the line might predict -0.2 (meaningless as a probability). For many hours, it might predict 1.3.
- Sensitive to outliers: Adding more data points far to the right would tilt the regression line, changing all predictions. Logistic regression fixes this by wrapping the linear model in the sigmoid function, which squashes outputs to the range [0,1] — interpretable as probabilities. (Diagram)
4.2 The Sigmoid Function
σ(z)=1+e−z1Properties:
- Range: (0, 1) — never exactly 0 or 1
- σ(0)=0.5 — the decision threshold
- As z→+∞, σ(z)→1
- As z→−∞, σ(z)→0
python# runnable import numpy as np import matplotlib.pyplot as plt z = np.linspace(-10, 10, 100) sigmoid = 1 / (1 + np.exp(-z)) plt.plot(z, sigmoid, 'b-', linewidth=2) plt.axhline(y=0.5, color='r', linestyle='--', label='Decision boundary (0.5)') plt.axvline(x=0, color='gray', linestyle=':', alpha=0.5) plt.xlabel('z = θᵀx') plt.ylabel('σ(z) = P(y=1|x)') plt.title('Sigmoid Function') plt.grid(True, alpha=0.3) plt.legend() plt.show()
4.3 Formal Definition
The Hypothesis (probability of class 1):
Decision Rule:
The decision boundary is where θTx=0 (since σ(0)=0.5).
4.4 The Cost Function
We can't use MSE for logistic regression because it creates a non-convex cost function (many local minima). Instead, we use log loss (binary cross-entropy):
Why this works:
- If y=1: cost = −log(hθ(x)). If hθ(x)≈1, cost ≈ 0. If hθ(x)≈0, cost → ∞.
- If y=0: cost = −log(1−hθ(x)). If hθ(x)≈0, cost ≈ 0. If hθ(x)≈1, cost → ∞. The gradient (same form as linear regression!):
4.5 Worked Example 1: Hand Calculation
Let's classify students as pass (y=1) or fail (y=0) based on hours studied.
| Hours ( x ) | Pass ( y ) |
|---|---|
| 1 | 0 |
| 2 | 0 |
| 3 | 1 |
| 4 | 1 |
Step 1: Initialize θ0=0,θ1=0.
Step 2: Compute predictions (all 0.5 since z=0).
Step 3: Compute log loss:
Wait, let me be more careful.
For y=0: cost = −log(1−0.5)=−log(0.5)=0.693 For y=1: cost = −log(0.5)=0.693
For our dataset: J=41(0.693+0.693+0.693+0.693)=0.693
Step 4: Gradient descent (one iteration with α=0.1):
Update: θ0=0−0.1(0)=0, θ1=0−0.1(−0.5)=0.05
After many iterations (using sklearn), we get approximately θ=[−4,1.6].
Decision boundary: z=−4+1.6x=0⟹x=2.5 hours.
So the model predicts "pass" if hours > 2.5, "fail" otherwise. This matches our intuition — 1-2 hours tends to fail, 3-4 hours tends to pass.
4.6 Multiclass Classification: Softmax
For problems with K > 2 classes (e.g., handwritten digit recognition 0-9), we use softmax regression:
This gives a probability distribution over K classes (all values between 0 and 1, summing to 1).
python# runnable from sklearn.linear_model import LogisticRegression from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score iris = load_iris() X, y = iris.data, iris.target # 3 classes of iris flowers X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # One-vs-Rest (default) or multinomial model = LogisticRegression(multi_class='multinomial', max_iter=200) model.fit(X_train, y_train) y_pred = model.predict(X_test) probabilities = model.predict_proba(X_test) print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}") print(f"Sample probabilities: {probabilities[0]}") print(f"Predicted class: {y_pred[0]}")
4.7 Classification Evaluation Metrics
Confusion Matrix:
| Predicted Positive | Predicted Negative | |
|---|---|---|
| Actual Positive | True Positive (TP) | False Negative (FN) |
| Actual Negative | False Positive (FP) | True Negative (TN) |
Key Metrics:
| Metric | Formula | Best For | When to Use |
|---|---|---|---|
| Accuracy | TP+TN+FP+FNTP+TN | Balanced classes | General performance |
| Precision | TP+FPTP | Minimizing false positives | Spam detection (don't flag good email) |
| Recall (Sensitivity) | TP+FNTP | Minimizing false negatives | Disease detection (don't miss sick patients) |
| Specificity | TN+FPTN | Correctly rejecting negatives | Legitimate email identification |
| F1 Score | 2⋅Precision+RecallPrecision⋅Recall | Imbalanced classes | Harmonic mean of P and R |
AUC-ROC: Measures the model's ability to distinguish between classes across all thresholds. AUC = 1: perfect. AUC = 0.5: random. AUC < 0.5: worse than random (flip predictions).
python# runnable from sklearn.metrics import confusion_matrix, classification_report, roc_auc_score, roc_curve import numpy as np y_true = np.array([0, 0, 1, 1, 0, 1, 0, 1, 1, 0]) y_pred = np.array([0, 1, 1, 1, 0, 1, 0, 0, 1, 0]) print("Confusion Matrix:") print(confusion_matrix(y_true, y_pred)) print("\nClassification Report:") print(classification_report(y_true, y_pred))
4.8 Worked Example 2: Computing Metrics
For a spam classifier with: TP=80, FP=10, FN=20, TN=90
Step 1: Total = 200 emails.
Step 2:
- Accuracy = (80+90)/200 = 170/200 = 0.85
- Precision = 80/(80+10) = 80/90 = 0.889
- Recall = 80/(80+20) = 80/100 = 0.80
- F1 = 2(0.889×0.80)/(0.889+0.80) = 2(0.711)/1.689 = 0.842 Interpretation:
- "85% of all emails were correctly classified"
- "When the model says spam, it's 88.9% correct"
- "The model catches 80% of actual spam"
- "F1 of 0.842 balances precision and recall"
4.9 When to Use / Not Use
| ✅ When to Use | ❌ When NOT to Use |
|---|---|
| Binary/multiclass classification | Non-linear decision boundaries (use SVM/kernel) |
| Need calibrated probabilities | Complex feature interactions (use random forest) |
| Baseline classifier | Very large feature spaces (p >> n, use regularized) |
| Interpretability needed | If data is not linearly separable at the feature level |
📐 Key Formulas / Concepts
| Concept | Formula | Notes |
|---|---|---|
| Sigmoid | σ(z)=1+e−z1 | Maps ℝ→(0,1) |
| Hypothesis | hθ(x)=σ(θTx) | Probability of class 1 |
| Log Loss | −m1∑[ylog(h)+(1−y)log(1−h)] | Convex, no local minima |
| Decision Boundary | hθ(x)=0.5 | θTx=0 |
| Gradient | m1∑(hθ(x(i))−y(i))x(i) | Same form as linear regression! |
| Softmax | ∑jeθjTxeθkTx | Multiclass probabilities |
| F1 Score | 2×P+RP×R | Harmonic mean |
⚠️ Common Pitfalls
Pitfall 1: Using Accuracy on Imbalanced Data
The mistake: Evaluating a fraud detector (99.9% legitimate, 0.1% fraud) on accuracy.
Why: Always predicting "not fraud" gives 99.9% accuracy — but misses all fraud! The model is useless.
Fix: Use precision, recall, F1, or AUC-ROC. For fraud detection, recall (catching fraud) matters more.
Pitfall 2: Not Setting the Decision Threshold
The mistake: Assuming 0.5 is the optimal threshold.
Why: The business needs may demand different tradeoffs. Cancer screening needs high recall (threshold < 0.5). Spam detection needs high precision (threshold > 0.5).
Fix: Plot precision-recall curve and pick the threshold that optimizes your business metric.
Pitfall 3: Multicollinearity in Logistic Regression
The mistake: Including highly correlated features without care.
Why: Like linear regression, logistic regression coefficients become unstable with correlated features. Standard errors inflate significantly.
Fix: Use VIF (Variance Inflation Factor) to detect multicollinearity; remove or combine correlated features.
📝 Practice Questions
Q1: Calculate σ(2) manually.σ(2)=1+e−21=1+0.1351=1.1351=0.881The probability of class 1 is 88.1% when z=2. Q2: With θ = [-1, 0.5], what's the decision boundary equation?Answer: The decision boundary is where θTx=0: −1+0.5x=0⟹x=2So if the feature value > 2, predict class 1 (< 2, predict class 0). Q3: For a cancer test: TP=90, FP=10, FN=10, TN=890 out of 1000 patients. Compute accuracy, precision, recall, and F1.
- Accuracy = (90+890)/1000 = 0.98 (98%)
- Precision = 90/(90+10) = 0.90 (90%)
- Recall = 90/(90+10) = 0.90 (90%)
- F1 = 2(0.9×0.9)/(0.9+0.9) = 0.90 (90%)
Note: Even with 98% accuracy, 10 out of 100 cancer patients are missed (FN=10). Is that acceptable? Q4: Why can't we use MSE for logistic regression?Answer: MSE creates a non-convex cost function for logistic regression with many local minima. Gradient descent might get stuck in a suboptimal local minimum. Log loss (binary cross-entropy) is convex — it has a single global minimum that gradient descent reliably finds. Q5: In a spam filter, which matters more: precision or recall?Answer: Precision typically matters more. A false positive (marking legitimate email as spam) is worse than a false negative (letting spam through). The user will be more annoyed by missing important emails than by seeing occasional spam. But this depends on the use case — in an exam pass/fail model, both matter equally. Q6: Convert odds of 4:1 to probability and log-odds.Odds = P(y=1) / P(y=0) = 4/1 = 4Probability: P = odds/(1+odds) = 4/5 = 0.80Log-odds = ln(4) = 1.386In logistic regression, θTx gives the log-odds. So θTx=1.386 corresponds to 80% probability. Q7: AUC = 0.5 means what about the model?Answer: AUC = 0.5 means the model is no better than random guessing. The ROC curve follows the diagonal line — for every threshold, the true positive rate equals the false positive rate. The model has zero discriminatory power. Q8: Implement logistic regression for 2D Iris data using sklearnpythonfrom sklearn.linear_model import LogisticRegression from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split import numpy as np iris = load_iris() # Use only first 2 features for binary classification (setosa vs others) X = iris.data[:100, :2] # Only setosa (0) and versicolor (1) y = iris.target[:100] # Binary: 0 or 1 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) model = LogisticRegression() model.fit(X_train, y_train) print(f"Accuracy: {model.score(X_test, y_test):.3f}") print(f"Coefficients: {model.coef_}") print(f"Intercept: {model.intercept_}")Q9: What is the difference between one-vs-rest and multinomial (softmax) for multiclass?Answer:
- One-vs-Rest (OvR): Trains K separate binary classifiers (one per class vs. all others). Each gets its own set of parameters. Simple but probabilities may not sum to 1.
- Softmax/Multinomial: A single model with K sets of parameters. Produces a proper probability distribution (all classes sum to 1). Preferred when classes are mutually exclusive. Q10: Your model has high precision but low recall. What does this mean?
Answer:
- High precision: When the model predicts positive, it's usually right (few false positives).
- Low recall: The model misses many actual positives (many false negatives).
The model is very "cautious" — it only predicts positive when it's very confident, so it misses borderline cases. To improve recall, lower the decision threshold below 0.5. Q11: When would F1 be more appropriate than accuracy?Answer: F1 is better when classes are imbalanced. Example: 95% legitimate, 5% fraudulent transactions. A model predicting "legitimate" always gets 95% accuracy. F1 captures the model's ability to detect the minority (fraud) class. Always use F1 (or precision/recall) when the positive class < 20% of the data. Q12: Explain the confusion matrix for a COVID test with 1% prevalence, test sensitivity 95%, specificity 99%. Compute PPV.Out of 10,000 people: 100 sick (TP=95, FN=5), 9900 healthy (TN=9801, FP=99).PPV (Precision): TP/(TP+FP) = 95/(95+99) = 95/194 = 0.49Interpretation: Even with 95% sensitivity and 99% specificity, only 49% of positive tests are actually sick! This is because the disease is rare (1% prevalence). This counterintuitive result is the "base rate fallacy."
🔗 Cross-References
- Next Topic: k-Nearest Neighbors — instance-based learning
- Related: Classification Metrics — deeper dive on ROC, PR curves
- Related: Gradient Descent — optimization details
- External: IITM BSCS2004 Week 4, Hands-On ML Ch. 4, ISLR Ch. 4 Join Discord PreviousMultiple & Polynomial RegressionNextk-Nearest Neighbors