Machine Learning Academy · Les

Afstandsmetrics: Euclidisch, Manhattan en Minkowski

U vergelijkt afstandsmetrics, begrijpt wanneer de Manhattanafstand beter presteert dan de Euclidische afstand en geeft aangepaste metrics door aan KNeighborsClassifier.

Les 3 van 413 stappen

Afstandsmetrics: Euclidisch, Manhattan en Minkowski is een gratis Machine Learning Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Machine Learning Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Machine Learning Academy bevat in totaal 4 lessen.

Waarom afstandsmaten belangrijk zijn in KNN

KNN definieert de dichtstbijzijnde buren met een afstandmaat — een wiskundige functie die kwantificeert hoe ver twee punten in de kenmerkruimte van elkaar liggen. De keuze van de maat bepaalt rechtstreeks welke buren worden geselecteerd en dus wat het model voorspelt. Verschillende maten maken verschillende aannames over de geometrie van de gegevens. De Euclidische afstand gaat ervan uit dat diagonale beweging geldig is; de Manhattan-afstand staat alleen beweging langs assen toe; cosinusgelijkenis negeert de grootte en richt zich op de richting. Geen enkele maat is universeel de beste — de juiste keuze hangt af van de structuur van het probleem.

import numpy as np

A = np.array([0, 0])
B = np.array([3, 4])

# Euclidean: straight-line distance
euclidean = np.sqrt(np.sum((A - B)**2))
print('Euclidean:', euclidean)  # 5.0

# Manhattan: sum of absolute differences
manhattan = np.sum(np.abs(A - B))
print('Manhattan:', manhattan)  # 7

# Chebyshev: maximum single-axis difference
chebyshev = np.max(np.abs(A - B))
print('Chebyshev:', chebyshev)  # 4

Euclidische afstand: L2-norm

De Euclidische afstand (ook L2-afstand of L2-norm genoemd) meet de afstand in een rechte lijn tussen twee punten. In 2D volgt deze de stelling van Pythagoras: sqrt(dx^2 + dy^2). In n dimensies: sqrt(sum of squared differences). Dit is de meest intuïtieve maat en de standaardinstelling in KNeighborsClassifier. De Euclidische afstand werkt goed wanneer kenmerken continu zijn, ongeveer dezelfde schaal hebben en het fysiek zinvol is om nabijheid op een diagonaal te interpreteren — bijvoorbeeld bij geografische coördinaten of sensormetingen.

import numpy as np

def euclidean(a, b):
    return np.sqrt(np.sum((np.array(a) - np.array(b))**2))

# 2D example
print('2D:', euclidean([0, 0], [3, 4]))  # 5.0

# 3D example
print('3D:', euclidean([1, 2, 3], [4, 6, 3]).round(2))  # 5.0

# Using scipy for efficiency
from scipy.spatial.distance import euclidean as sp_euclidean
print('scipy:', sp_euclidean([0, 0], [3, 4]))

Manhattan-afstand: L1-norm

De Manhattan-afstand (L1-norm, stadsblokafstand, taxicabafstand) telt de absolute verschillen langs elke as op: sum(|a_i - b_i|). De naam komt van het rasterpatroon van de straten in Manhattan — je kunt alleen langs straten reizen, niet diagonaal. De Manhattan-afstand is robuuster tegen uitschieters dan de Euclidische afstand, omdat deze absolute waarden gebruikt in plaats van kwadraten. Deze afstand heeft vaak de voorkeur voor gegevens met veel dimensies en voor kenmerken die aantallen, beoordelingen of andere grootheden voorstellen waarbij diagonale beweging fysiek niet betekenisvol is.

import numpy as np

def manhattan(a, b):
    return np.sum(np.abs(np.array(a) - np.array(b)))

print('Manhattan (0,0)-(3,4):', manhattan([0,0], [3,4]))  # 7
print('Euclidean (0,0)-(3,4):', np.linalg.norm([3,4]))    # 5.0

# Manhattan treats 3+4=7 units of travel
# Euclidean takes the diagonal shortcut = 5.0
# In a grid city, only Manhattan is physically achievable

from scipy.spatial.distance import cityblock
print('scipy cityblock:', cityblock([0,0], [3,4]))

Minkowski-afstand: L1 en L2 generaliseren

De Minkowski-afstand is een generalisatie die de Euclidische en Manhattan-afstand verenigt in één formule: (sum(|a_i - b_i|^p))^(1/p). Bij p=1 is deze gelijk aan de Manhattan-afstand. Bij p=2 is deze gelijk aan de Euclidische afstand. Bij p → infinity nadert deze de Chebyshev-afstand (het maximale verschil langs één as). In scikit-learn gebruikt KNeighborsClassifier standaard Minkowski met p=2. Je kunt andere waarden voor p als hyperparameter onderzoeken, hoewel waarden van p anders dan 1 en 2 in de praktijk zelden worden gebruikt.

import numpy as np

def minkowski(a, b, p):
    a, b = np.array(a), np.array(b)
    return np.sum(np.abs(a - b)**p)**(1/p)

a, b = [0, 0], [3, 4]

for p in [1, 2, 3, 10, 100]:
    d = minkowski(a, b, p)
    print(f'p={p}: {d:.4f}')

# p=1  -> 7.0 (Manhattan)
# p=2  -> 5.0 (Euclidean)
# p->inf -> 4.0 (Chebyshev = max(3,4))

Maten doorgeven aan KNeighborsClassifier

Met Scikit-learn kun je de afstandsmaat opgeven via de parameter metric. Veelgebruikte tekenreeksopties zijn 'euclidean', 'manhattan', 'minkowski' (met de aanvullende parameter p), 'chebyshev' en 'cosine'. Je kunt ook een aanroepbare Python-functie als aangepaste maat doorgeven. Gebruik bij niet-standaardmaten algorithm='ball_tree' of algorithm='kd_tree' voor efficiënt zoeken naar buren, of algorithm='brute' voor een gegarandeerd correcte maar tragere volledige zoekopdracht.

from sklearn.neighbors import KNeighborsClassifier

# Euclidean (default)
knn_l2 = KNeighborsClassifier(n_neighbors=5, metric='euclidean')

# Manhattan
knn_l1 = KNeighborsClassifier(n_neighbors=5, metric='manhattan')

# Minkowski with p=1.5
knn_mk = KNeighborsClassifier(n_neighbors=5, metric='minkowski', p=1.5)

# Chebyshev
knn_ch = KNeighborsClassifier(n_neighbors=5, metric='chebyshev')

# Cosine similarity (for text/angle-based)
knn_cos = KNeighborsClassifier(n_neighbors=5, metric='cosine',
                                algorithm='brute')

Euclidisch tegenover Manhattan: een praktische vergelijking

Bij een empirische vergelijking van Euclidisch en Manhattan wordt het verschil het duidelijkst bij kenmerken met uitschieters. De Euclidische afstand kwadrateert verschillen, waardoor één grote afwijking de totale afstand domineert. De Manhattan-afstand telt absolute waarden op, waardoor alle afwijkingen proportioneel worden behandeld. In de praktijk wint de Euclidische afstand vaak bij afbeeldingsgegevens of continue fysieke metingen. Bij hoogdimensionale schaarse gegevens (tekst, beoordelingen van gebruikers en items, aantallen) is Manhattan meestal stabieler, omdat deze de invloed van geen enkele dimensie versterkt.

from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_wine

X, y = load_wine(return_X_y=True)

for metric in ['euclidean', 'manhattan', 'chebyshev']:
    pipe = Pipeline([
        ('sc', StandardScaler()),
        ('knn', KNeighborsClassifier(n_neighbors=5, metric=metric))
    ])
    score = cross_val_score(pipe, X, y, cv=10).mean()
    print(f'{metric:12}: {score:.3f}')

Cosinusgelijkenis voor tekstgegevens

Cosinusovereenkomst meet de hoek tussen twee vectoren in plaats van hun grootte. Twee documenten worden als vergelijkbaar beschouwd als ze in dezelfde richting wijzen in de kenmerkruimte, ongeacht de lengte van het document. Cosinusafstand = 1 - cosinusovereenkomst. Dit is de voorkeursmaatstaf voor tekstclassificatie met TF-IDF-vectoren, waarbij twee documenten sterk in lengte kunnen verschillen maar dezelfde woordenschat in vergelijkbare verhoudingen gebruiken. Let op: cosinusafstand is geen echte metriek (de driehoeksongelijkheid wordt geschonden), maar werkt in de praktijk goed voor KNN op tekst.

import numpy as np

def cosine_distance(a, b):
    a, b = np.array(a, dtype=float), np.array(b, dtype=float)
    cos_sim = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
    return 1 - cos_sim

# Long and short documents with same topic should be close
doc1 = [2, 1, 0, 3]  # counts of words: 'python', 'ml', 'java', 'data'
doc2 = [4, 2, 0, 6]  # same proportions, longer document
doc3 = [0, 0, 5, 1]  # different topic

print('doc1 vs doc2 (same topic):', cosine_distance(doc1, doc2).round(3))  # near 0
print('doc1 vs doc3 (diff topic):', cosine_distance(doc1, doc3).round(3))  # larger

Hammingafstand voor categorische en binaire kenmerken

Hammingafstand telt het aantal posities waarop twee vectoren van elkaar verschillen. Deze afstand is ideaal voor binaire of categorische kenmerken, waarbij het concept van een verschil in grootte betekenisloos is. Als je bijvoorbeeld twee patiëntendossiers vergelijkt die zijn gecodeerd als binaire symptoomvectoren (1=aanwezig, 0=afwezig), telt de Hammingafstand hoeveel symptomen verschillen. Geef in scikit-learn metric='hamming' door aan KNeighborsClassifier. Hammingafstand wordt ook gebruikt voor het vergelijken van DNA-sequenties, foutdetectie in binaire codes en genetische vingerafdrukken.

import numpy as np

def hamming(a, b):
    a, b = np.array(a), np.array(b)
    return np.sum(a != b) / len(a)

# Binary symptom vectors: [fever, cough, headache, fatigue]
patient1 = [1, 1, 0, 1]
patient2 = [1, 1, 1, 1]  # only headache differs
patient3 = [0, 0, 1, 0]  # very different

print('p1 vs p2:', hamming(patient1, patient2))  # 0.25
print('p1 vs p3:', hamming(patient1, patient3))  # 0.75

# sklearn usage
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3, metric='hamming')

De vloek van dimensionaliteit en afstand

Naarmate het aantal kenmerken (dimensies) groeit, krijgen alle op afstand gebaseerde methoden te maken met de vloek van dimensionaliteit: in hoge dimensies komt de afstand tussen willekeurige punten steeds dichter bij dezelfde waarde, waardoor alle punten op gelijke afstand lijken te liggen. Wanneer afstanden niet meer van elkaar te onderscheiden zijn, verliest het concept van de 'dichtstbijzijnde buur' zijn betekenis. Daarom presteert KNN doorgaans het best op gegevenssets met minder dan 20-50 kenmerken en wordt in omgevingen met veel dimensies vaak dimensionale reductie (PCA, kenmerkselectie) toegepast vóór KNN.

import numpy as np

np.random.seed(42)

for d in [2, 10, 50, 100, 500]:
    # Random points in d-dimensional unit hypercube
    X = np.random.rand(1000, d)
    query = np.random.rand(d)
    dists = np.linalg.norm(X - query, axis=1)
    # High-dimensional: max/min ratio -> 1 (all distances similar)
    ratio = dists.max() / dists.min()
    print(f'd={d:3}: min={dists.min():.2f}, max={dists.max():.2f}, ratio={ratio:.2f}')

# As d grows, ratio approaches 1: distances become indistinguishable

Een metriek kiezen: een praktische handleiding

Hier is een keuzehulp voor het kiezen van een afstandsmetriek: gebruik Euclidisch (L2) voor continue kenmerken op vergelijkbare schalen (na StandardScaler); gebruik Manhattan (L1) voor schaarse gegevens of gegevens met veel dimensies en wanneer robuustheid tegen uitschieters nodig is; gebruik Cosinus voor tekst- en TF-IDF-vectoren wanneer de grootte niet van belang hoort te zijn; gebruik Hamming voor binaire of categorische kenmerken; gebruik Minkowski met aangepaste p alleen als je over domeinkennis beschikt die op een specifieke geometrie wijst. Probeer in de praktijk eerst Euclidisch en Manhattan met kruisvalidatie en kies de beste.

def recommend_metric(data_type, is_sparse, has_outliers):
    if data_type == 'text':
        return 'cosine'
    elif data_type == 'binary' or data_type == 'categorical':
        return 'hamming'
    elif is_sparse or has_outliers:
        return 'manhattan'
    else:
        return 'euclidean'  # default, safe choice

print(recommend_metric('text', False, False))       # cosine
print(recommend_metric('binary', False, False))     # hamming
print(recommend_metric('continuous', True, False))  # manhattan
print(recommend_metric('continuous', False, False)) # euclidean

De metriek opnemen in een rasterzoekopdracht

Je kunt de parameter metric opnemen in je GridSearchCV om de beste combinatie van k en afstandsmetriek tegelijkertijd te vinden. Zo voorkom je handmatig uitproberen van verschillende metrieken. Als je zoekt over metrieken die extra parameters vereisen (zoals Minkowski's p), neem je die ook op in het parameterrooster. De beste metriek hangt af van de gegevens en is vaak niet uitsluitend op basis van domeinkennis vast te stellen — kruisvalidatie laten beslissen is zowel principieel als praktisch.

from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

pipe = Pipeline([('sc', StandardScaler()), ('knn', KNeighborsClassifier())])

param_grid = [
    {'knn__n_neighbors': [3, 5, 7, 11],
     'knn__metric': ['euclidean', 'manhattan'],
     'knn__weights': ['uniform', 'distance']},
    {'knn__n_neighbors': [3, 5, 7],
     'knn__metric': ['minkowski'],
     'knn__p': [1, 1.5, 2, 3]}
]

grid = GridSearchCV(pipe, param_grid, cv=10, scoring='accuracy', n_jobs=-1)
grid.fit(X_train, y_train)
print('Best params:', grid.best_params_)

Korte controle

Toets je begrip van de concepten uit deze les over Machine Learning met Python.

Samenvatting van de les

In deze les heb je geleerd: waarin Euclidische, Manhattan- en Minkowski-afstanden wiskundig verschillen en wanneer je elke afstand gebruikt, cosinusovereenkomst voor tekstgegevens en Hamming voor binaire kenmerken, en de vloek van dimensionaliteit waardoor alle afstanden in ruimten met veel dimensies naar elkaar toe convergeren. Hierna bekijken we KNN voor regressietaken en de beperkingen op het gebied van schaalbaarheid bij grote gegevenssets.

Gratis beginnen

Leer Python met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
30
Lessen
120

Veelgestelde vragen

Is de les “Afstandsmetrics: Euclidisch, Manhattan en Minkowski” gratis?

Ja — de volledige tekst van “Afstandsmetrics: Euclidisch, Manhattan en Minkowski” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Machine Learning Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Machine Learning Academy bevat in totaal 4 lessen.

Wat leer ik in “Afstandsmetrics: Euclidisch, Manhattan en Minkowski”?

U vergelijkt afstandsmetrics, begrijpt wanneer de Manhattanafstand beter presteert dan de Euclidische afstand en geeft aangepaste metrics door aan KNeighborsClassifier. Je oefent met Machine Learning Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Machine Learning Academy te beginnen?

Ervaring vooraf is niet nodig. Machine Learning Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.

Hoe lang duurt de les “Afstandsmetrics: Euclidisch, Manhattan en Minkowski”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Machine Learning Academy?

Ja. Elke les over Machine Learning Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Hoe KNN werkt: afstand, buren en stemmen
  2. k kiezen: de elleboogmethode en validatiecurves
  3. Afstandsmetrics: Euclidisch, Manhattan en Minkowski
  4. KNN voor regressie en schaalbaarheidsbeperkingen
← Terug naar Machine Learning Academy