Machine learningLoading progress…

Scaling and metrics

Compare nearest-neighbor, naive Bayes and margin-based predictions using their actual assumptions.

Distance adds up every feature, in its own units

Euclidean distance squares the gap in each feature and adds them. If one feature is measured in tens of thousands and another in tens, the big one decides everything. Take a query person aged 30 earning 52,000 dollars. Person A is 28 years older but earns 51,000. Person B is a year older and earns 58,000. Who is "closer"?

In dollars, A is 1000.3919 away and B is 6000.0001 away: the 28-year age gap is invisible next to a 1,000-dollar income gap. Express income in thousands and the same people give A at 28.0179 and B at 6.0828: now B is nearest. Nothing about the people changed, only a unit.

Query: a person with income 52000 dollars and age 30. The bar shows what share of each squared distance comes from income (blue) and from age (orange).

rankpersonincomeagebuys?distancefrom income / age
1A5100058no1000.3919
2E4700045no5000.0225
3B5800031yes6000.0001
4F6600029yes14000
5C3800027yes14000.0003
6H7200041yes20000.003
7G3000052no22000.011
8D9000033no38000.0001
Nearest neighbour: A. The 3 nearest (shaded) vote: does not buy.
Switch the income unit, then tick the standardise box. The blue part of each bar is the share of the squared distance that comes from income, the orange part from age.

The fix: put features on one scale, using the training data only

Standardising rewrites each feature as how many standard deviations it sits from the training mean: z = (x − mean) / std. The mean income here is 56500 and the standard deviation 18096.9611; for age they are 39.5 and 10.6771. After this, a gap of one standard deviation counts the same whether it is in dollars or years, and the nearest neighbour is B (0.3445 away) whatever unit you started from. Try all three units with the box ticked.

Predict first. You convert a distance feature from metres to millimetres and leave the other features alone. Can the nearest neighbours change?

Other metrics change who is near

The scale is only half of the choice. Euclidean distance is the straight line. Manhattan distance adds the absolute gaps, like walking along a grid, so it does not favour diagonal moves. Cosine distance (1 minus the cosine of the angle) ignores how far from the origin a point is and only compares directions, which suits word-count vectors where length depends on document size. With the same six points and the same query, all three metrics pick a different neighbour:

0022446688abcdefquery (4, 4)

The dotted purple line is the direction of the query from the origin.

rankpointeuclidean distance
1c1.4422
2a1.9
3f2.1213
4d3.6056
5e3.6056
6b4.4598
Nearest under euclidean: c
Pick a metric. The green link joins the query to its nearest point under that metric.

Euclidean picks c (1.4422), Manhattan picks a (1.9) and cosine picks b, which is far away but almost exactly in the query's direction.

The common mistake: leaking the test set into the scaler

mu = X_train.mean(axis=0)
sd = X_train.std(axis=0)          # a column with sd == 0 needs care
Z_train = (X_train - mu) / sd
Z_test  = (X_test  - mu) / sd     # the same mu and sd, never recomputed
Chapter context

Different model families turn different notions of similarity into predictions. A geometric distance, a conditional-independence assumption and a kernel are distinct modeling decisions rather than variations of the same formula.

Chapter reference: math, worked example & code

This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.

Math and notation

∥x−y∥22=∑j(xj−yj)2,K(x,y)=exp⁡(−γ∥x−y∥2),  γ>0.\|x-y\|_2^2=\sum_j(x_j-y_j)^2,\quad K(x,y)=\exp(-\gamma\|x-y\|^2),\;\gamma>0.

For SVM canonical boundary planes wTx+b=±1w^Tx+b=\pm1, their separation is 2/∥w∥2/\|w\|. A naive-Bayes posterior is proportional to P(c)∏jP(xj∣c)P(c)\prod_jP(x_j\mid c).

A numerically convenient naive-Bayes decision rule is

c^=arg⁡max⁡c[log⁡P(c)+∑jlog⁡P(xj∣c)].\hat c=\arg\max_c\left[\log P(c)+\sum_j\log P(x_j\mid c)\right].

This avoids multiplying many small probabilities, but it does not remove the need to handle zero likelihoods or choose an appropriate feature distribution.

Worked example

For query [1,1], squared distances to [0,0], [2,1] and [3,3] are 2, 1 and 8. The nearest point is [2,1]. Separately, a canonical SVM with w=[3,4] has norm 5 and margin width 2/5=0.4.

Reference code

The following example uses the Python standard library and does not call a remote service.

from math import sqrt, isclose
q = [1,1]
points = [[0,0],[2,1],[3,3]]
distances = [sum((a-b)**2 for a,b in zip(q,p)) for p in points]
assert distances == [2,1,8]
assert distances.index(min(distances)) == 1
assert isclose(2/sqrt(3**2+4**2), .4)

Python examples are provided for study and local execution; this page does not execute Python.

Common mistakes

Changing feature scale can change neighbors. Kernel similarity is not automatically calibrated probability. The SVM margin formula assumes a particular normalization of the separating planes.