Lab 19 — Classification I: k-NN & Logistic Regression¶
Session: Week 10 · Session 19 · 90 min CLO: CLO-2 Difficulty: Intermediate
Learning objectives¶
By the end of this lab you can:
- Train and evaluate k-NN and logistic regression classifiers.
- Read a confusion matrix and compute accuracy/precision/recall.
- Explain the effect of
kand of feature scaling on k-NN. - Compare two classifiers on the same split, honestly.
Problem statement¶
A marine lab needs an automatic species ID from two measurements:
bill_length_mm and flipper_length_mm. Two candidate models (k-NN and
logistic regression) must be compared on the same train/test split,
with the same random state, and the winner reported with evidence — not
vibes.
Dataset requirements¶
Seaborn built-in penguins, dropna() (333 rows). Target: species
(3 classes). Features: bill_length_mm, flipper_length_mm.
Step-by-step tasks¶
- Prep: dropna, define
X(2 features) andy(species). Split test_size=0.3, random_state=42,stratify=y— comment on why stratify matters with 3 classes. - Scale: fit
StandardScaleron train only; transform train and test. Print the mean/std of the scaled train features (should be ≈0/1). Comment: why must the scaler learn from train only? - k-NN:
KNeighborsClassifier(n_neighbors=5); fit, predict, printaccuracy_score. Then trykin [1, 3, 5, 11, 21] and print a small table of test accuracy per k. Which k wins? - Logistic regression:
LogisticRegression(max_iter=1000); fit, predict, print accuracy. - Confusion matrix:
confusion_matrix(y_test, pred)for the better model; print it withpd.DataFrame(cm, index=y_test classes, columns=y_test classes). Which pair of species gets confused most? - Per-class report:
classification_report(y_test, pred)— report precision, recall, and f1 for each species. Which class is hardest to get right? - Verdict (markdown): which model wins, by how much, and would you trust the difference? (Consider that a 1–2 point accuracy gap on 100 test rows is not decisive.)
Starter code¶
import pandas as pd
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (accuracy_score, confusion_matrix,
classification_report)
penguins = sns.load_dataset("penguins").dropna()
X = penguins[["bill_length_mm", "flipper_length_mm"]]
y = penguins["species"]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y)
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)
# your code here: k-NN sweep, logistic regression, matrix, report, verdict
Expected output¶
- Split: 233 train / 100 test rows.
- Scaled train features: mean ≈ 0, std ≈ 1.
- k-NN: accuracy ≈ 0.94–0.98 at k=5; the sweep shows k=1 overfits slightly, larger k slightly worse.
- Logistic regression accuracy ≈ 0.95–0.99.
- Confusion matrix mostly diagonal; Chinstrap↔Adelie are the most confused pair.
classification_report: Chinstrap typically has the lowest recall.- A written verdict naming the winner and its margin.
Questions¶
- Why does
stratify=ymatter with 3 classes and 344 rows? - Why must
StandardScalerbe fit on train only? What leaks if you fit on all data? - What happens to k-NN if features are unscaled and one has a much larger range?
- Accuracy vs recall: which would you watch if missing a penguin species were costly? Why?
- Two models differ by 1 accuracy point on 100 test rows — why be cautious about declaring a winner?
Challenge task¶
Repeat the k-NN sweep without scaling and print the same table. Then answer: how much does scaling change k-NN accuracy here, and why does it matter less for logistic regression? (Hint: think about what each algorithm computes — distances vs. weighted sums.)
Marking rubric¶
| Criteria | Max | Notes |
|---|---|---|
| Prep + stratified split | 3 | 233/100 + comment |
| Scaling on train only | 4 | mean≈0/std≈1, no leakage |
| k-NN sweep table | 4 | best k identified |
| Logistic regression + accuracy | 3 | max_iter noted |
| Confusion matrix read | 3 | confused pair named |
| classification_report read | 3 | hardest class named |
| Written verdict | 3 | winner + margin + caution |
| Answers to questions | 3 | Q2, Q3, Q4 correct |
| Challenge: unscaled comparison | 4 | table + explanation |
| Total | 30 |