CadetX
CX Learn | Complete Machine Learning Guide
Scikit-Learn · Python
CadetX logo CadetX CX Learn
ML-101 · Module 4 Beginner about 35 minutes 11 Lessons Prereq: Modules 1 to 3

Logistic Regression

Logistic regression answers yes-or-no questions. Will this customer leave? Is this payment fraud? Will this student pass? Despite its name, it's a classification algorithm, and one of the most used in business today.

  • Level: Beginner
  • Time: about 35 minutes
  • Needs: Modules 1 to 3

By the end of this module you will be able to

  • Explain what logistic regression does and why it's called "regression"
  • Explain why linear regression doesn't work for yes/no questions
  • Describe how the sigmoid (S-curve) turns a score into a probability
  • Use a threshold to turn a probability into a decision, and explain the trade-off
  • Explain how log loss teaches the model
  • Read coefficients and understand a decision boundary
  • Train and test a logistic regression model in scikit-learn

4.1What is logistic regression?

In Module 3, linear regression predicted a number, such as a house price. But many business questions have only two possible answers:

QuestionPossible answers
Will this customer cancel their contract?Yes / No
Is this card payment fraud?Fraud / Genuine
Is this email spam?Spam / Not spam
Will this loan be repaid?Repaid / Default
Will this job applicant accept our offer?Accept / Decline

This is called binary classification (binary means "two"). Logistic regression is the classic algorithm for it. Instead of saying just "yes" or "no", it gives a probability: "there's a 78% chance this customer will leave".

Logistic regression in one sentence

Logistic regression predicts the probability that something belongs to a category, then uses that probability to answer a yes/no question.

Wait, why is it called "regression" if it does classification?

Because under the hood, it first predicts a number (a probability between 0 and 1), just like regression does. Only at the very end does it turn that number into a yes/no decision. The name is a bit confusing, but it's stuck for over 60 years, so everyone still uses it.

We'll continue with the broadband company from Module 2. They want to predict which customers will leave. One strong clue is how many times a customer has called customer support in the last three months. Unhappy customers call more.

4.2Why not just use linear regression?

We can write "left" as 1 and "stayed" as 0. So why not draw a straight line through the data, like in Module 3? Let's try it with 26 customers.

Customers who stayed sit at 0 and customers who left sit at 1. A straight line through them goes below 0 and above 1, which makes no sense as a probability.-0.400.511.4012345678910Support calls in the last 3 monthsPredictionAbove 1: a "120% chance"?Below 0: a "−13% chance"?Valid range: 0 to 1
Figure 1. Blue dots are customers who stayed (0); amber dots are customers who left (1). A straight line (red) keeps going forever in both directions, so it predicts impossible values.

There are two problems:

  1. Impossible answers. A probability must be between 0% and 100%. The straight line happily predicts 120% for a customer with 10 calls, and −13% for one with none.
  2. Wrong shape. In real life, the chance of leaving doesn't rise steadily forever. It rises quickly in the middle, then levels off near 100%, because you can't be "more certain than certain".

We need a line that bends into an S-shape and stays between 0 and 1. That's exactly what logistic regression does.

4.3The sigmoid: the S-curve

Logistic regression works in two steps.

Step 1: calculate a score, exactly like linear regression. We'll call it z.

z = m × Support calls + c

Step 2: squash the score into a probability using a special function called the sigmoid (or logistic function).

Probability = 1 ÷ (1 + e−z)

Don't worry about the maths. e is just a special number (about 2.718). All you need to know is what the sigmoid does: it takes any number, however big or small, and turns it into a value between 0 and 1.

The sigmoid S-curve. Very negative scores give probabilities near 0, a score of 0 gives 0.5, and very positive scores give probabilities near 1.00.250.50.751-6-4-20246Score (z)Probabilityz = 0 → 0.5Very negative → almost 0Very positive → almost 1
Figure 2. The sigmoid curve. Big negative scores become probabilities close to 0, big positive scores become close to 1, and a score of exactly 0 becomes 0.5 (a 50/50 chance).
Score (z)−4−2024
Probability0.020.120.500.880.98

For our 26 customers, the model learned m = 0.79 and c = −3.69. So for a customer with 6 support calls:

z = 0.79 × 6 − 3.69 = 1.05 → Probability = 0.74

That customer has about a 74% chance of leaving.

4.4From probability to decision: the threshold

A probability is useful, but a business usually needs a decision: do we call this customer with a special offer or not? We use a threshold. If the probability is above the threshold, the answer is "yes".

The default threshold is 0.5. But you can move it, and that changes the results. Try it below.

Try it: move the threshold

Leavers caught
Leavers missed
False alarms
Stayers left alone

The threshold trade-off

Lower threshold (e.g. 0.3)Higher threshold (e.g. 0.7)
EffectMore people predicted "yes"Fewer people predicted "yes"
Good forCatching more real casesBeing more sure when you say "yes"
CostMore false alarmsMore real cases missed
Use whenMissing a case is expensive (fraud, disease screening)A false alarm is expensive (blocking a genuine customer's card)

Think of a smoke alarm

A very sensitive smoke alarm (low threshold) goes off when you make toast. Annoying, but it will never miss a real fire. A less sensitive alarm (high threshold) gives fewer false alarms, but might miss a small fire. Choosing a threshold is a business decision, not just a maths one.

4.5How it learns: log loss

In Module 3, linear regression learned by making the squared errors as small as possible. Logistic regression uses a different measure of "wrongness" called log loss (also called cross-entropy).

The idea is simple: punish confident wrong answers very hard. Imagine a customer who really did leave:

Model's predictionHow wrong?Log loss (penalty)
90% chance of leavingConfident and right0.11 (tiny)
50% chance of leavingUnsure0.69
10% chance of leavingConfident and wrong2.30 (big)
1% chance of leavingVery confident and wrong4.61 (huge)
Log loss for a customer who really left. The loss is near zero when the model predicts close to 1, and shoots up as the prediction gets close to 0.01234500.250.50.751Predicted probability of leaving (customer really left)Loss (penalty)0.9 → 0.110.5 → 0.690.1 → 2.30
Figure 3. The penalty grows slowly at first, then shoots up as the model becomes confident in the wrong answer. Training adjusts m and c (using gradient descent, from Module 3) until the total log loss is as small as possible.

Like a quiz where confidence counts

Imagine a quiz where you bet points on each answer. Betting a little on a wrong answer costs you a little. Betting everything on a wrong answer costs you a lot. Log loss teaches the model to be confident only when it has good reason to be.

4.6Reading the coefficients

Just like linear regression, logistic regression gives each feature a coefficient. The sign tells you the direction:

CoefficientMeaningChurn example
Positive (+)As this feature goes up, the chance of "yes" goes upMore support calls → more likely to leave
Negative (−)As this feature goes up, the chance of "yes" goes downMore months as a customer → less likely to leave
Close to 0This feature makes little differenceProbably not useful for predicting churn

Odds: a handy way to explain the size

The size is a little harder to read than in linear regression, because the S-curve bends. The easiest way is to talk about odds. If you calculate ecoefficient, you get how much the odds are multiplied for each 1-unit increase.

Our coefficient for support calls is 0.79, and e0.79 ≈ 2.2. So in plain English: each extra support call roughly doubles the odds that a customer leaves. That's a sentence a manager can act on.

4.7The decision boundary

With one feature, the threshold of 0.5 is just a single point: customers with more than about 4.7 calls are predicted to leave. With two features, it becomes a line that splits the chart in two. This is called the decision boundary.

Customers plotted by support calls and months with the company. A straight decision boundary separates those likely to leave from those likely to stay.0153045600246810Support calls in the last 3 monthsMonths with usLikely to stayLikely to leave
Figure 4. Each dot is a customer: amber left, blue stayed. The dashed line is where the model's probability is exactly 0.5. New customers who have made lots of calls but only recently joined (bottom right) fall on the "likely to leave" side.

Notice some dots are on the "wrong" side. That's normal. Real life is messy, and no model is perfect. Also notice the boundary is a straight line. That's the main limitation of logistic regression: if the groups can only be separated by a curvy line, you'll need a different algorithm, such as the decision trees or SVMs you'll meet later in this track.

4.8Measuring a classifier

For regression we used MAE and RMSE. For classification, the simplest measure is accuracy: the percentage of predictions that were right.

Accuracy = Correct predictions ÷ Total predictions

A better picture comes from a confusion matrix, which shows exactly which kinds of mistakes the model makes. You already saw one in the threshold lab:

Predicted: stayPredicted: leave
Actually stayedTrue negative
Correctly left alone
False positive
False alarm
Actually leftFalse negative
Missed leaver
True positive
Correctly caught

The accuracy trap

Imagine only 5 in every 100 card payments are fraud. A lazy model that always says "not fraud" would be 95% accurate, and would catch zero fraud. Accuracy alone can hide a useless model when one answer is much more common than the other. Always check the confusion matrix. Module 5 covers precision, recall and other measures that fix this.

4.9Logistic regression in Python

Now let's build a churn model for 1,000 customers, using four features: support calls, months as a customer, monthly bill, and whether they're on a monthly (no fixed) contract. We scale the features first, as you learned in Module 2, because logistic regression trains best that way.

churn_model.py
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix

# 1. Create 1,000 broadband customers
rng = np.random.default_rng(7)
n = 1000
df = pd.DataFrame({
    "support_calls":    rng.poisson(3, n),
    "months":           rng.integers(1, 60, n),
    "monthly_bill":     rng.integers(20, 70, n),
    "monthly_contract": rng.integers(0, 2, n),   # 1 = no fixed contract
})
z = (-4.5 + 1.0 * df["support_calls"] - 0.08 * df["months"]
     + 0.04 * df["monthly_bill"] + 1.5 * df["monthly_contract"])
df["left"] = (rng.random(n) < 1 / (1 + np.exp(-z))).astype(int)
print("Customers who left:", f"{df['left'].mean():.0%}")

# 2. Features (X), target (y) and split
X = df.drop(columns="left")
y = df["left"]
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y)

# 3. Scale (logistic regression works best with scaled features)
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)

# 4. Train the model
model = LogisticRegression()
model.fit(X_train_s, y_train)

# 5. What did it learn? (positive = more likely to leave)
for name, coef in zip(X.columns, model.coef_[0]):
    print(f"{name:17} {coef:+.2f}")

# 6. Test it
pred = model.predict(X_test_s)
print("Accuracy:", round(accuracy_score(y_test, pred), 3))
print("Confusion matrix:")
print(confusion_matrix(y_test, pred))

# 7. Probability for a new customer: 4 calls, 10 months, £45 bill, no contract
new = pd.DataFrame({"support_calls": [4], "months": [10],
                    "monthly_bill": [45], "monthly_contract": [1]})
prob = model.predict_proba(scaler.transform(new))[0, 1]
print(f"Chance this customer leaves: {prob:.0%}")
Output
Customers who left: 33%
support_calls     +1.59
months            -1.19
monthly_bill      +0.59
monthly_contract  +0.83
Accuracy: 0.815
Confusion matrix:
[[113  21]
 [ 16  50]]
Chance this customer leaves: 87%

What the output tells us

  • The coefficients make sense. Support calls (+1.59) push customers towards leaving the most. Months with us (−1.19) keeps them loyal. A higher bill and no fixed contract also increase the risk. Because we scaled the features, we can fairly compare these sizes.
  • Accuracy is 81.5%. Remember, 33% of customers left, so a lazy model that always says "stays" would score 67%. Ours is clearly better.
  • The confusion matrix reads: 113 stayers correctly left alone, 21 false alarms, 16 leavers missed and 50 leavers caught. The model found 50 of the 66 customers who left.
  • predict_proba() gives the probability, not just yes/no. This new customer has an 87% chance of leaving, so the retention team should call them first.

predict() vs predict_proba()

predict() gives the final 0 or 1 using a threshold of 0.5. predict_proba() gives the probabilities, so you can choose your own threshold, or rank customers from most to least likely to leave. In business, the ranked list is often more useful than a simple yes/no.

4.10Logistic regression in the real world

IndustryYes/no questionExample features
Telecoms and subscriptionsWill this customer leave?Support calls, contract type, usage
BankingWill this loan be repaid?Income, existing debt, credit history
HealthcareIs this patient at high risk?Age, blood pressure, test results
MarketingWill this person click the ad?Past clicks, time of day, device
EmailIs this spam?Words used, number of links, sender
RecruitmentWill this candidate accept the offer?Salary gap, notice period, commute

What about more than two categories?

Logistic regression can also handle three or more categories (for example, "cat", "dog" or "bird"). This is called multiclass or multinomial logistic regression. scikit-learn does it automatically when your target has more than two values.

Banks and hospitals especially like logistic regression because it's easy to explain. When a loan is refused, regulators may require the bank to explain why, and "the coefficient for existing debt is strongly positive" is a clear answer.

SummaryKey takeaways

  • Logistic regression is a classification algorithm that predicts the probability of a yes/no outcome.
  • Linear regression fails here because it predicts values below 0 and above 1.
  • The sigmoid function squashes any score into a probability between 0 and 1, making an S-curve.
  • A threshold (0.5 by default) turns a probability into a decision. Lower it to catch more cases; raise it to reduce false alarms.
  • The model learns by minimising log loss, which punishes confident wrong answers heavily.
  • Positive coefficients increase the chance of "yes"; ecoefficient tells you how much the odds change.
  • The decision boundary is a straight line, which is its main limitation.
  • Don't trust accuracy alone; check the confusion matrix.

Check your understanding

Your machine learning roadmap

  1. 01
    Introduction to Machine LearningWhat ML is and how it works
  2. 02
    Preparing Data for Machine LearningFeatures, encoding, scaling, train/test split
  3. 03
    Linear RegressionPredicting numbers
  4. 04
    Logistic RegressionYou are here
  5. 05
    Evaluating ModelsAccuracy, precision, recall, overfitting, cross-validation
  6. 06
    K-Nearest NeighboursLearning from similar examples
  7. 07
    Decision TreesFlowcharts that learn
  8. 08
    Random Forest and Gradient BoostingMany models working together
  9. 09
    Support Vector MachinesFinding the best boundary
  10. 10
    Naive BayesProbability-based classification
  11. 11
    Clustering with K-MeansFinding groups without labels
  12. 12
    Dimensionality Reduction with PCASimplifying big datasets
  13. 13
    Capstone ProjectBuild and present a full ML project