Exercise 5: Regression 2

In this notebook, we cover:

Part Topic Time
1 Case understanding and first model 15 min
2 Probabilities and thresholds 10 min
3 Confusion matrix and metrics 10 min
4 ROC and AUC 10 min
5 Comparing customer categories 10 min
Wrap-up Reflection 5 min

Case: Rising defaults at LendWise

You are a business analyst working for LendWise, a fintech company that offers fast digital consumer loans. Over the last six months, LendWise has seen a noticeable spike in credit defaults in two customer categories:

  • Early-career urban borrowers: Typically younger customers, often with lower savings, moderate income, and irregular repayment histories.

  • Self-employed platform workers: Customers with fluctuating income, often higher short-term debt exposure, and less predictable monthly cash flows.

The risk team wants to understand these groups better. They are especially interested in whether default risk follows the same logic in both categories, or whether the predictors and model quality differ substantially.

In this notebook, you first focus on early-career urban borrowers and build a logistic regression model to predict default. Afterward, you compare the results with self-employed platform workers.

LendWise is interested in questions such as:

  • Which factors are associated with a higher probability of default in early-career urban borrowers?
  • How can predicted probabilities be translated into default / non-default classifications?
  • How well does the model perform? How informative are the ROC curve and the AUC?
  • Does a model work equally well across customer categories?

Data description

The dataset contains the following variables:

  • customer_category: customer segment
  • income: monthly income in EUR
  • debt_to_income: debt-to-income ratio
  • missed_payments_12m: number of missed payments in the last 12 months
  • credit_utilization: share of available credit currently used (between 0 and 1)
  • months_with_company: months since first activity with LendWise
  • default: whether the customer defaulted (1 = yes, 0 = no)

Note: The dataset was curated by the company’s Risk Analytics Department. It has already been cleaned, validated, and prepared for modeling.

import pandas as pd

df = pd.read_csv("data/credit_default.csv")
df.head()
customer_category income debt_to_income missed_payments_12m credit_utilization months_with_company default
0 early_career_urban 3283.287284 0.453151 2.0 0.574281 21.0 0
1 platform_worker 1976.088070 0.597144 0.0 0.855863 39.0 1
2 platform_worker 3299.177450 0.664904 4.0 0.969859 27.0 1
3 platform_worker 2539.814969 0.505792 0.0 0.939466 7.0 0
4 early_career_urban 1655.521735 0.342233 2.0 0.461253 30.0 1

Part 1 — Analyze early-career urban borrowers with logistic regression

In this first part, focus only on early-career urban borrowers.

Task 1.1 — Prepare the subset

Create a filtered dataset that contains only customers from early-career urban borrowers.

# Your solution here
# df_ec_urban = ...

Task 1.2 — Estimate the model

Estimate a logistic regression model to predict credit default.

  • Define the target variable (default)
  • Use all remaining numeric variables as predictors
  • Fit the logistic regression model
  • Retrieve the estimated coefficients and intercept
from sklearn.linear_model import LogisticRegression

# Your solution here...

Task 1.3 — Interpret the model

Interpret the coefficients in substantive terms:

  • Which variables increase the likelihood of default?
  • Which variables decrease it?
  • Which variable appears to have the strongest relationship with default?

Task 1.4 — From coefficients to classification

Explain how the model moves from:

  • a linear combination of predictors
  • to a predicted probability
  • to a classification as default / non-default

Part 2 — Probabilities and thresholds

In this part, we move from model coefficients to predicted probabilities and classification decisions.

Logistic regression outputs probabilities, which must be converted into classes using a threshold. The threshold directly affects business outcomes: lowering it increases approvals (but also defaults), while raising it reduces risk (but may reject good customers).

Task 2.1 — Understanding outputs

Run the code and answer the following questions:

y_prob = model.predict_proba(X)[:, 1]
y_pred = model.predict(X)
y_prob[:5], y_pred[:5]
  • What is the difference between y_prob and y_pred?
  • Why does predict_proba return two columns?

Task 2.2 — Manual thresholding

Instead of relying on the default threshold of 0.5, we can manually adjust the cutoff to reflect different business objectives. In practice, thresholds are used to identify specific customer groups, for example:

  • customers with high default risk (for intervention or stricter approval)
  • customers with low risk (for fast-track approval or better conditions)

In general, predictions can be obtained for any threshold t as:

t = 0.3
y_pred_t = (y_prob >= t).astype(int)
y_pred_t

First, explore different thresholds by modifying t (e.g., 0.2, 0.4, 0.6, 0.7):

  • How does the number of predicted defaults change?
  • What pattern do you observe as the threshold increases?

Now consider a concrete business task: LendWise wants to identify the 20% most risky customers to prioritize early intervention.

  • How can you choose a threshold so that approximately 20% of customers are classified as default?
  • Which customers would be selected?
# Your solution here ...
# Hint: use the `np.quantile()` function on the predicted probabilities

Similarly, LendWise may want to identify the 20% safest customers:

  • How would you define a threshold for this group?
# Your solution here ...

Part 3 — Confusion matrix and metrics

For simplicity, model performance is evaluated on the same data used for estimation. In practice, a train/test split or cross-validation should be used.

Use the confusion_matrix function of sklearn.metrics to generate the confusion matrix:

from sklearn.metrics import confusion_matrix

cm = confusion_matrix(y, y_pred)
cm

Task 3.1 — Interpret the matrix

The confusion_matrix function returns an unlabeled ndarray. Consult with the documentation to identify:

  • true positives (TP)
  • true negatives (TN)
  • false positives (FP)
  • false negatives (FN)

Task 3.2 — Compute key metrics

Compute and interpret:

  • Accuracy
  • Precision
  • Recall

Task 3.3 — Reflection

LendWise is currently trying to grow its customer base aggressively.

Discuss:

  • Why might the company temporarily accept a higher false-negative risk?
  • Why might the same company later tighten the threshold when macroeconomic conditions worsen?

Part 4 — ROC curve and AUC

Run the following code to compute and visualize the ROC curve:

from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt

fpr, tpr, thresholds = roc_curve(y, y_prob)
roc_auc = auc(fpr, tpr)

# Plot ROC curve
plt.figure()
plt.plot(fpr, tpr, label=f"AUC = {roc_auc:.2f}")
plt.plot([0, 1], [0, 1], linestyle="--")  # random baseline
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.title("ROC Curve")
plt.legend()
plt.show()

Task 4.1 — Understanding ROC

  • What does the ROC curve represent?
  • What are TPR and FPR?

Task 4.2 — Interpreting AUC

  • What does the AUC value tell us?
  • What would values near 0.5, 0.7, and 1.0 suggest?

Task 4.3 — Threshold perspective

  • Why is ROC/AUC useful when the company has not yet fixed one single decision threshold?

Part 5 — Compare early-career urban borrowers and platform workers

Now repeat the same modeling steps for the segment of platform workers.

You do not need to interpret every single line of code again. Focus on comparing the results.

# Your code here ...

Task 5.1 — Fit the second model

Fit a logistic regression model for platform workers.

# Your code here ...

Task 5.2 — Compare coefficients

Compare the coefficients across both categories.

  • Are the same predictors important in both groups?
  • Does any variable appear to matter more strongly in one group than the other?
# Your code here ...

Task 5.3 — Compare ROC and AUC

Compare the ROC curves and AUC values of the two models.

  • Which category seems easier to classify?
  • What might explain the difference?
# Your code here ...

🧩 Wrap-up

🎉🎈 You have completed the notebook – good work! 🎈🎉

In this notebook, we have learned to:

  • Fit and interpret logistic regression models using scikit-learn
  • Distinguish between predicted probabilities and class labels
  • Apply and reflect on different classification thresholds
  • Compute and interpret confusion-matrix-based metrics
  • Understand ROC curves and AUC as threshold-independent evaluation tools
  • Compare model performance across different customer categories
  • Reflect on how model use depends on business context and risk strategy
TipSession 5 survey

Before you wrap up, please complete the Session 5 survey here: ?meta:surveys.session_05.url. Thank you 🙏