Machine Learning Slides 📂 Introduction · 16 of 17 51 min read

K-Nearest Neighbors Explained

A visual, beginner-friendly guide to K-Nearest Neighbors — the lazy learner that classifies by asking its closest neighbours to vote. Learn the four-step process, how K trades bias for variance, the distance metrics (Euclidean, Manhattan, Minkowski, cosine, Hamming), why feature scaling is mandatory, distance-weighted voting, the curse of dimensionality, efficient search with KD-Tree and Ball-Tree, sklearn code and six golden rules.

📍

K-Nearest Neighbors

The lazy learner that never trains — it just remembers everything, then classifies each new point by asking its closest neighbours to vote. Simple, non-linear, and endlessly explainable.
Neighbours Vote Distance Metrics Choosing K Curse of Dimensionality

Press Next → or use ← → arrow keys

Section 01

What Is K-Nearest Neighbors?

"You are the average of the five people nearest to you"
Want to guess a stranger's taste in music? Look at the five people who live closest, share their commute, and shop in the same places — and assume the newcomer is like them. No theory, no model — just similarity.

K-Nearest Neighbors does exactly this. It stores every training example, and to classify a new point it finds the K most similar stored points and lets them vote. There's no "training" in the usual sense — the data is the model.
💡
The Working Definition

KNN is an instance-based, lazy learner: it memorises the whole training set and defers all computation to prediction time. To classify, it finds the K nearest points and takes a majority vote; to regress, it takes their average.

0Training time · fit is instant
KNeighbours that vote
√nCommon starting K
100%Explainable · show the neighbours
Section 02

How KNN Works — Four Steps

STEP 1 ⚙️ Choose K & metric how many · how to measure STEP 2 📐 Distance to all measure every training point STEP 3 🎯 Keep K nearest sort · take smallest K STEP 4 🗳️ Vote / Average majority · or · mean
🗳️
Classification
majority vote
3 neighbours vote "Spam", 2 vote "Ham" → predict Spam. Plurality wins.
📊
Regression
average the values
5 nearby houses priced ₹85–95L → predict the mean (or distance-weighted mean).
💤
Lazy Learner
no training phase
fit() just stores the data. All the work happens at predict() — fast to fit, slow to query.
Section 03

The K-Neighbourhood — Who Gets To Vote?

Feature 1 → Feature 2 → K = 5 nearest ? new point inside ring: 3 green · 2 red → vote GREEN
🗳️
The Ring Grows With K

K controls how wide the neighbourhood circle is. A small K listens only to the very closest points (sensitive to noise); a large K polls a broad crowd (smooths everything out). Here K=5 captures 3 green and 2 red — the new point is classified green.

Section 04

Choosing K — The Goldilocks Problem

K = 1 · jagged memorises every point · overfits high variance K = 15 · smooth respects structure · generalises sweet spot ✅ K = N · flat always predicts majority · underfits high bias
K valueBoundaryBehaviourRisk
K = 1Jagged · noisyMemorises each pointOverfits
K = 3–5Locally flexibleRespects local structureGood for small clean data
K = 11–21SmoothWell-generalisedUsually optimal
K = NFlatAlways majority classUnderfits completely
🎯
Pick K With Cross-Validation, Not A Guess

Test odd values from 1 to √n, plot CV accuracy vs K, and pick the elbow where accuracy peaks and flattens. Use odd K for binary problems to avoid tie votes.

Section 05

Distance Metrics — How "Near" Is Measured

Euclidean: √Σ(xᵢ−yᵢ)² Manhattan: Σ|xᵢ−yᵢ| A B Metrics Euclidean → continuous Manhattan → high-dim/noisy Hamming → categorical Cosine → text vectors
Euclidean · p=2 · default
d = √ Σ (xᵢ − yᵢ)²
Straight-line distance. Best for continuous, normally-distributed features. Sensitive to outliers.
Manhattan · p=1
d = Σ | xᵢ − yᵢ |
Grid-walk distance. More robust on high-dimensional or noisy data than Euclidean.
Minkowski · general
d = ( Σ |xᵢ − yᵢ|ᵖ )^(1/p)
The parent of both — tune p as a hyperparameter. p=1 → Manhattan, p=2 → Euclidean.
Cosine & Hamming
direction · differing positions
Cosine for text (magnitude-invariant). Hamming for binary / one-hot categorical data.
Section 06

Feature Scaling — Mandatory, Not Optional

❌ Unscaled — income dominates Income (₹, in lakhs) → Age → age difference is invisible · only income counts ✅ StandardScaler — fair distances Income (z-score) → Age (z-score) → both features contribute equally
📏
Why Scaling Is Fatal To Skip

Age differs by ~1 (distance² = 1). Income differs by ₹40,000 (distance² = 1.6 billion). Without scaling, income silently swamps every distance and age becomes invisible. Use StandardScaler (or RobustScaler for outlier-heavy data) inside a Pipeline to prevent leakage.

Section 07

Weighted Voting — Let Closer Neighbours Speak Louder

Plain KNN gives all K neighbours an equal vote — even the one sitting right on the edge of the ring. Distance-weighting fixes that: the nearer a neighbour, the louder its vote.

Uniform Weights · default
weight = 1 / K (all equal)
Every one of the K neighbours counts the same, regardless of how close it is.
Distance Weights · recommended
weight = 1 / distance
Closer neighbours dominate. Almost always beats uniform at negligible extra cost.
🔊
Set weights='distance' By Default

Distance-weighted voting is especially valuable when the K-th neighbour is much farther than the first — you don't want a distant, barely-relevant point overruling a very close one. Start with weights='distance'; only switch to uniform if validation says otherwise.

📍
Nearest Neighbour
distance 0.5 → weight 2.0
Very close → very loud vote. Dominates the tally as it should.
📌
Middle Neighbour
distance 2.0 → weight 0.5
Moderate influence — contributes but doesn't dominate.
🔭
Edge Neighbour
distance 8.0 → weight 0.125
Barely inside the ring → whisper of a vote. Rightly near-ignored.
Section 08

The Curse Of Dimensionality

1D · a line neighbours truly near 2D · a plane still close-ish 10D · declining neighbours drifting away 100D · breaks down all points ≈ equidistant nearest-to-farthest distance ratio → approaches 1 as dimensions grow → "near" loses all meaning
🧊
In High Dimensions, Everything Is Equally Far

As features multiply, the distance to your nearest point and your farthest point converge — so "nearest neighbour" carries no signal. Mitigate: apply PCA (or UMAP) before KNN when features exceed 20–30, and prune irrelevant features with Random-Forest importance or SelectKBest.

Section 09

Making Prediction Fast — Search Structures

Every prediction compares the query to every stored point. On big data that's crippling — so sklearn offers smarter search than brute force.

🐢
Brute Force
O(n × d)
Compare to all points. Works with any metric. Fine for small data (< 1,000 rows), slow beyond.
🌲
KD-Tree
O(log n) · d ≤ 20
Partitions space into rectangles, prunes whole regions. Excellent in low dimensions.
🔮
Ball-Tree
O(log n) · d > 20
Partitions into hyperspheres. Handles higher dimensions better than KD-Tree; slower to build.
Default To 'auto' · Go Approximate At Scale

algorithm='auto' lets sklearn choose based on data size, dimensionality, and metric. For datasets beyond ~100k points where exact search is too slow, switch to Approximate Nearest Neighbour libraries — FAISS (Meta), Annoy (Spotify), ScaNN (Google) — for millisecond queries at billion scale.

Section 10

Implementation — Sklearn, Pipeline & Best-K Search

from sklearn.neighbors import KNeighborsClassifier, KNeighborsRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score

# ── Classification · always scale inside a pipeline ──────
knn = Pipeline([
    ('scaler', StandardScaler()),
    ('knn', KNeighborsClassifier(
        n_neighbors=5,
        weights='distance',     # closer = louder
        metric='euclidean',
        n_jobs=-1,
    )),
])
knn.fit(X_train, y_train)

# ── Find the best K with cross-validation ────────────────
best_k, best_score = 1, 0
for k in range(1, 32, 2):            # odd values only
    pipe = Pipeline([
        ('scaler', StandardScaler()),
        ('knn', KNeighborsClassifier(n_neighbors=k)),
    ])
    score = cross_val_score(pipe, X_train, y_train, cv=5).mean()
    if score > best_score:
        best_k, best_score = k, score
print(f"best K = {best_k}  ({best_score:.3f})")

# ── Regression · distance-weighted mean ──────────────────
reg = Pipeline([
    ('scaler', StandardScaler()),
    ('knn', KNeighborsRegressor(n_neighbors=10, weights='distance')),
]).fit(X_train, y_train)
💧
The Scaler MUST Live In The Pipeline

Fit StandardScaler only on each CV fold's training partition — that's what the Pipeline guarantees. Scale the whole dataset up front and test-set statistics leak into training, quietly inflating your reported accuracy.

Section 11

Strengths & Weaknesses

Zero Training Time
Fit is instant — just store the data. New points can be appended without retraining (online learning).
🔍
Fully Explainable
Justify any prediction by showing the actual K neighbours. Gold for medical, legal, regulatory use.
🌀
Non-Linear & Multi-Class
No distributional assumptions. Learns any boundary shape; handles many classes without modification.
🐢
Slow Prediction
O(n × d) per query — stores the whole training set. Painful past ~100k rows without ANN libraries.
📏
Scaling-Sensitive
Forget to scale and it silently fails. Irrelevant features pollute distances since all count equally.
🧊
Curse Of Dimensionality
Breaks down as features multiply. Also biased toward the majority class on imbalanced data.
🎯
When To Reach For KNN

Use it for low-dimensional data (< 20–30 features), small clean datasets, quick baselines, and explainability-critical problems. Avoid it for large-scale (> 100k), high-dimensional (text, images, genomics), or low-latency real-time inference — reach for SVM, tree ensembles, or ANN libraries instead.

Section 12

Where KNN Shines In The Real World

🎬
Recommendation Systems
"Users like you also watched…" — user-based collaborative filtering. Item similarity for Netflix, Amazon, Spotify.
🩺
Medical Diagnosis
Find similar patient records for reference. Explainable output — show the actual comparable cases to a clinician.
🔢
Image Recognition
MNIST digit classification (> 95%), reverse image search, face verification (with PCA preprocessing).
🚨
Anomaly Detection
Flag points that sit far from all their neighbours — unusual transactions, faulty sensors, outliers.
💰
Credit & Risk
Compare a new applicant to similar historical profiles — transparent, easy to audit.
🧪
Quick Baseline
Before investing in complex models, fit KNN in five lines to set the accuracy floor everything else must clear.
Section 13

Common Pitfalls — What Silently Sinks KNN

📏
Forgetting To Scale
the fatal mistake
Large-range features dominate distance silently. Always StandardScaler inside a Pipeline.
🎲
Guessing K
K=1 or K=N blunders
Never eyeball K. Cross-validate odd values 1 → √n and read the elbow of the accuracy curve.
🧊
Ignoring Dimensionality
high-d breaks it
Past ~20 features, "near" loses meaning. Apply PCA first, or pick a different algorithm.
🔊
Uniform Weights
leaving accuracy on table
weights='distance' beats uniform in almost every case. Make it your default.
⚖️
Class Imbalance
majority hijacks votes
The majority class wins ties by sheer numbers. Rebalance (SMOTE), and score with F1/AUC, not accuracy.
🗑️
Irrelevant Features
noise pollutes distance
Every feature votes equally, so junk columns corrupt the metric. Prune with feature-importance first.
Section 14

Golden Rules — Six Habits For KNN

📍 K-NEAREST NEIGHBORS DISCIPLINE
1
Always scale features — no exceptions. Wrap StandardScaler (or RobustScaler for outliers) inside a Pipeline. This single step is the most impactful thing you can do for KNN.
2
Tune K with cross-validation — never guess. Test odd values from 1 to √n, plot accuracy vs K, and choose the elbow where it peaks and flattens.
3
Default to weights='distance'. Closer neighbours are genuinely more relevant. Distance weighting almost always wins at near-zero cost.
4
Reduce dimensions before KNN when features > 20. Add PCA inside the pipeline (scaler → PCA → KNN), and drop irrelevant features — they all vote equally, so noise directly corrupts distances.
5
Handle class imbalance explicitly. The majority class dominates the vote. Oversample minorities (SMOTE) or use custom voting; evaluate with F1 or AUC, not raw accuracy.
6
At scale, go approximate — and lean on explainability. Beyond ~100k points use FAISS / Annoy / ScaNN. And whenever a decision must be justified, show the actual K neighbours — KNN's uniquely transparent superpower.
FINAL

KNN — Simplicity That Still Earns Its Keep

VoteNeighbours decide
KTune via CV · odd values
📏Scale · always first
1/dDistance-weighted votes
< 20Features · stay low-dim
6Golden rules
🎯
The Foundation Is Set

You now understand instance-based learning, the four-step vote, how K trades bias for variance, why scaling is non-negotiable, the distance metrics, and how the curse of dimensionality breaks "nearness". KNN is the most intuitive classifier in ML — and still a strong baseline on the right data.

📚
Where To Go Next

Study PCA (to rescue KNN in high dimensions), then SVM and Random Forest for when KNN's cost or dimensionality becomes a problem. For scale, explore FAISS and approximate nearest-neighbour search. Practise on Iris, MNIST, and the Wine dataset.

📍 End of tutorial · Press to review, or click Restart