Explain what logistic regression is, what kind of problem it solves, and what its raw output is.
Contrast logistic regression with linear regression and state the rule for choosing between them.
Recognize the problems logistic regression is built for and explain why it works for them.
Give the problems with fitting a straight line to class labels and what logistic regression does instead.
Write the sigmoid, explain what it does, and give its value at the three landmark inputs.
Show how a row of feature values becomes a probability, and name what the model learns.
Turn a probability into a class, and explain when to move the threshold.
Write the cost function, explain what it rewards and punishes, and how the model minimizes it.
Classify a problem as one of the three types of logistic regression.
Match logistic regression to its real-world uses and summarize how it works end to end.
Explain the import and data-loading cells of the class notebook.
import numpy as np · import matplotlib.pyplot as plt · import pandas as pd.dataset = pd.read_csv('Social_Network_Ads.csv'): 400 rows; columns Age, EstimatedSalary, Purchased.X = dataset.iloc[:, :-1].values: all rows, every column except the last (Age, EstimatedSalary). Uppercase X = 2-D matrix.y = dataset.iloc[:, -1].values: all rows, last column only (Purchased). Lowercase y = 1-D vector.Explain the train/test split and feature-scaling cells, including why scaling is fit on training data only.
train_test_split(X, y, test_size = 0.25, random_state = 0) → 300 training rows, 100 test rows.X_train, X_test, y_train, y_test.sc = StandardScaler() · X_train = sc.fit_transform(X_train) · X_test = sc.transform(X_test).Explain how the model object is created and trained, and connect fit() to the theory.
from sklearn.linear_model import LogisticRegression.classifier = LogisticRegression(random_state = 0) builds an untrained model object.classifier.fit(X_train, y_train) learns from the scaled training features and their labels.fit never sees X_test or y_test; those are saved for checking the model.fit is where the model learns the best weights and bias by minimizing log loss.Explain the two prediction cells and how to read their output.
classifier.predict(sc.transform([[30, 87000]])) → [0]: a 30-year-old earning 87,000 is predicted not to purchase.sc.transform, because the model was trained on scaled numbers.[[30, 87000]] is one row with two feature values, shaped like X.y_pred = classifier.predict(X_test) returns a 0/1 prediction for all 100 test rows.np.concatenate((y_pred.reshape(len(y_pred),1), y_test.reshape(len(y_test),1)),1) prints predicted (left) next to actual (right).Explain the evaluation cell and read the class result correctly.
from sklearn.metrics import confusion_matrix, accuracy_score · cm = confusion_matrix(y_test, y_pred).[[65 3] [8 24]].accuracy_score(y_test, y_pred) = 0.89 = (65 + 24) / 100.Explain what the visualization cell builds and how to read the chart.
X_set = sc.inverse_transform(X_train) so the axes show real ages and salaries.np.meshgrid builds a dense grid of points covering the chart (age ±10, salary ±1000 past the data, step 0.25).plt.contourf paints class 0 red and class 1 green.plt.scatter plots the real training points in their true colors (red = 0, green = 1).Social_Network_Ads.csv), whose outputs were reproduced to confirm every number. The notebook has no written explanations, so code behavior there comes from the scikit-learn / NumPy / Matplotlib documentation (links on the Notes tab). Purple Study aid boxes are memory tricks, OOP reminders, and links to earlier modules — not lecture content.The name is genuinely confusing: logistic regression is built on regression math, but it solves classification problems.
| Linear regression | Logistic regression | |
|---|---|---|
| Predicts | A continuous number | A category — by predicting the probability of belonging to a class |
| Examples | A price, a temperature, a score | Yes / no, spam / not spam |
| Use when the target is… | Continuous | Categorical |
Best suited for binary classification — problems with exactly two possible outcomes. It can also be extended to multi-class problems (see the types in Part 3).
| Area | The two outcomes |
|---|---|
| Spam or not spam | |
| 🩺 Medical | Disease present or not present |
| 🏦 Finance | Loan approved or denied |
| 📣 Marketing | Customer will churn or stay |
Why it works: it models the relationship between the features and the probability of an outcome using an S-shaped (sigmoid) curve.
It takes any real number z (from −∞ to +∞) and "squashes" it into a range between 0 and 1. The output is read directly as a probability.
| Input z | σ(z) | Meaning |
|---|---|---|
| Large positive (e.g., 6) | ≈ 1 (0.9975) | Very likely Class 1 |
| 0 | exactly 0.5 | Equally unsure — the most uncertain point |
| Large negative (e.g., −6) | ≈ 0 (0.0025) | Very likely Class 0 |
| Step | Formula | What happens |
|---|---|---|
| 1 · Linear part | z = w₁x₁ + w₂x₂ + … + wₙxₙ + b | A weighted sum of the inputs — exactly like linear regression |
| 2 · Squash | p = σ(z) = 1 / (1 + e^(−z)) | Pass z through the sigmoid to get a probability |
| Weights | Input | z | p = σ(z) | Class (0.5 threshold) |
|---|---|---|---|---|
| w₁ = 2, w₂ = −1, b = 1 | x₁ = 1, x₂ = 3 | 2 − 3 + 1 = 0 | 0.5 | Class 1 (p ≥ 0.5) — but the model is equally unsure |
| x₁ = 3, x₂ = 1 | 6 − 1 + 1 = 6 | ≈ 0.9975 | Class 1 |
| Move the threshold… | Effect | Choose this when… |
|---|---|---|
| Lower (below 0.5) | Fewer false negatives · more false positives | Missing a real positive is the worse mistake |
| Higher (above 0.5) | Fewer false positives · more false negatives | A false alarm is the worse mistake |
| Model's p → | 0.20 | 0.40 | 0.55 | 0.65 | 0.90 | Predicted Class 1 |
|---|---|---|---|---|---|---|
| Threshold 0.3 | 0 | 1 | 1 | 1 | 1 | 4 of 5 — catches more, more false alarms |
| Threshold 0.5 | 0 | 0 | 1 | 1 | 1 | 3 of 5 — the default |
| Threshold 0.7 | 0 | 0 | 0 | 0 | 1 | 1 of 5 — fewer false alarms, misses more |
| Type | Classes | Example |
|---|---|---|
| Binary | Exactly two — the most common case | Spam vs. not spam · 0 vs. 1 |
| Multinomial | Three or more, no natural order | Cat vs. dog vs. bird |
| Ordinal | Three or more, with a natural order | Low vs. medium vs. high risk |
| Use case | The question it answers |
|---|---|
| Spam detection | Is this email spam, or not spam? |
| Medical diagnosis | Is a disease present, or absent? |
| Credit scoring | Should this loan be approved, or denied? |
| Customer churn | Will this customer stay, or leave? |
| Ad targeting | Will this user click the ad, or not? |
LogisticRegression, .fit, .predict, the evaluation tools, and the plot.concatenate, meshgrid, arange).| Age | EstimatedSalary | Purchased |
|---|---|---|
| 19 | 19000 | 0 |
| 35 | 20000 | 0 |
| 26 | 43000 | 0 |
| … | … | … |
| 400 rows total · 257 rows with 0, 143 rows with 1 (counted from the class CSV) | ||
iloc[:, :-1] — all rows, every column except the last → the features.iloc[:, -1] — all rows, last column only → the target..values — hands back the plain NumPy array.X_train, X_test, y_train, y_test, y_pred.test_size = 0.25 — 25% of 400 rows → 100 test rows, 300 training rows.X_train, X_test, y_train, y_test (both X pieces, then both y pieces).random_state = 0 — fixes the shuffle so the same rows land in the test set every run.y_test).| Age | EstimatedSalary | |
|---|---|---|
| First training row, before | 44 | 39000 |
| Same row, after scaling | 0.58164944 | −0.88670699 |
sc = StandardScaler() creates an object (an instance of the StandardScaler class, like new StandardScaler() in Java). fit_transform stores the training mean and standard deviation inside sc (its fields). Every later sc.transform(...) — on X_test, on the new person, on the plot grid — reuses those stored values. That's why the same sc object shows up four times in the notebook..fit..fit learns — the weights (one per feature: Age, EstimatedSalary) and the bias from Part 2's z = w₁x₁ + w₂x₂ + b, by minimizing log loss..fit sees X_train and y_train; the test set stays hidden for grading the model.classifier is an object; .fit() is a method called on it. Like a Java method that updates private fields, fit stores the learned weights inside classifier. Afterward, .predict() — another method on the same object — uses them. Same object, two methods: one to learn, one to answer.random_state on LogisticRegression only matters for certain solvers; with the default solver it changes nothing. It's in the class code for consistency.[[30, 87000]] → sc.transform scales it → classifier.predict → print.[0]: a 30-year-old earning 87,000 is predicted not to purchase.predict returns the class (0 or 1), with the threshold already applied — not the probability.classifier.predict_proba(...). On this same person it returns about [[0.887 0.113]]: an 11% chance of Purchased = 1. That's below 0.5, so predict said 0 — Part 2's threshold rule in action. Not on the quiz.y_pred — one 0/1 prediction for each of the 100 test rows..reshape(len(y_pred), 1) — turns the flat array of 100 values into one column (100 × 1).np.concatenate((a, b), 1) — glues the two columns side by side (the 1 means "join as columns"), giving a 100 × 2 table.y_pred.reshape(...) is a method: y_pred is a NumPy array object and reshape belongs to it. np.concatenate(...) is a function from the np module — no object before the dot, just the library name. Rule of thumb: object.method() vs. library.function().scikit-learn's layout: rows = actual, columns = predicted, class 0 first.
| Predicted 0 | Predicted 1 | |
|---|---|---|
| Actual 0 | TN = 65 correctly said "won't buy" | FP = 3 said "buy" — didn't |
| Actual 1 | FN = 8 said "won't buy" — did | TP = 24 correctly said "buy" |
[[TN FP] [FN TP]] — TN top-left, TP bottom-right. Same four numbers, flipped positions. The layout itself is from the scikit-learn documentation; the notebook doesn't label it.| Same result in Module 5's layout | Predicted positive (1) | Predicted negative (0) |
|---|---|---|
| Actual positive (1) | TP = 24 | FN = 8 |
| Actual negative (0) | FP = 3 | TN = 65 |
confusion_matrix(y_test, y_pred) has no object in front of it. It was imported straight from sklearn.metrics, so you call it like a static utility function in Java. Compare classifier.predict(...), which needs the trained classifier object.| Piece | What it does |
|---|---|
A · sc.inverse_transform(X_train) | Undoes the scaling so the axes show real ages and salaries. |
B · np.meshgrid(np.arange(...), np.arange(...)) | Builds a dense grid of (age, salary) points covering the chart: from 10 years below the youngest to 10 above the oldest, and 1,000 below to 1,000 above the salary range, in steps of 0.25. X1 holds each point's age, X2 its salary. |
C · plt.contourf(...) | ravel() flattens the grids, np.array([...]).T stacks them into rows of (age, salary), sc.transform scales them, classifier.predict labels every point, and .reshape(X1.shape) folds the answers back into the grid. contourf then fills the background: red = predicted 0, green = predicted 1 (alpha = 0.75 = slightly see-through). |
D · plt.scatter loop | Plots each real training point, colored by its true label: red for 0, green for 1. enumerate(np.unique(y_set)) loops over the two classes. |
| Labels | Title, axis names, and a legend showing 0 (red) and 1 (green). |
UserWarning about the c argument. It's harmless; the chart still draws.X1 and X2 are grid coordinates (every age and every salary on the chart), not new features. X_set / y_set are just the unscaled training features and target, renamed for plotting.