Skip to main content

Regression, cost and many dimensions

Neighbours can predict a number as well as a label: average the targets of the k nearest. Then count what a prediction costs when the model is the data itself, and see by simulation why neighbours stop being near when there are many features.
ML01.3.4L1 Core25 minIn review

Before this lesson

ML01.3.2 k neighbours and a vote ML01.3.3 Distance and feature scaling

After this lesson you can

  • Predict a number with k-nearest-neighbour regression by averaging the targets of the k nearest examples, by hand and in NumPy.
  • Explain why k-nearest-neighbour regression cannot predict beyond the range of its training targets.
  • Count the numbers stored and the arithmetic done for one brute-force prediction, and compare both with a fitted line.
  • Derive the edge length a neighbourhood needs in order to hold a given share of evenly spread data in d dimensions.
  • Describe from a simulation how the nearest and the farthest distance compare as the number of features grows.

In review. The maths and code on this page are checked by automated tests on every change, but an independent reader has not signed it off yet. Spot a mistake or a confusing step? Tell us.

The question

So far the neighbours have voted for a label. Can they also predict a number, such as a price? And two questions every method must face. What does one prediction cost, when the “model” is the whole training set? Does “nearest” still mean anything when an example has a thousand features instead of two?

From the last lesson

1. Why does a feature recorded in large numbers dominate Euclidean distance?

Show answer

The distance adds squared differences across features without regard to units, so the feature with the largest differences supplies almost all of the sum.

2. How is a feature standardised, and where do the two numbers come from?

Show answer

\({z = (x - \mu) / \sigma}\), with the mean \(\mu\) and the standard deviation \(\sigma\) computed from the training set only.

Intuition

To predict a number, keep everything from lesson 2 except the last step. Find the \(k\) nearest stored examples and, instead of counting labels, average their targets. That is \(k\)-nearest-neighbour regression.

The picture uses the course’s four points, \({x = 1, 2, 3, 4}\) with targets \({y = 2, 3, 5, 6}\). With one feature, “distance” is just how far apart two inputs are on the horizontal axis.

A plot of target y against input x with four blue data points at (1, 2), (2, 3), (3, 5) and (4, 6). A dashed vertical line rises from a new input at x equals 2.6. The two nearest points, at x equals 2 and x equals 3, have yellow discs behind them, with the note its 2 nearest inputs have targets 3 and 5. Thin lines join them to a vermillion diamond at (2.6, 4), labelled prediction: their average, (3 plus 5) divided by 2 equals 4. A thick vermillion staircase shows what k equals 2 predicts for every input: 2.5 for x below 2, then 4 for x between 2 and 3, then 5.5 for x above 3.
ML01.3.4-F1

\(k\)-NN regression with \({k = 2}\). For the new input \({x = 2.6}\) the two nearest stored inputs are \(3\) and \(2\). The prediction is the average of their targets, \(4\). Doing the same for every input gives the staircase.

The prediction is flat wherever the set of neighbours stays the same, and it jumps where one neighbour is swapped for another. No slope was learned. As before, the data are the model.

Build it up

Step 1. Find the \(k\) nearest, exactly as for classification. Distances, sort, keep \(k\). Everything lesson 3 said about scaling the features still applies.

Step 2. Average instead of voting. Add the \(k\) targets and divide by \(k\).

Step 3. The same dial. With \({k = 1}\) the staircase passes through every training point. With \({k = n}\) it is a flat line at the mean of all the targets. In between, a validation set chooses \(k\), as in lesson 2.

Step 4. Count what is stored and what a prediction costs. A fitted line does its work once, in training, and then keeps only its slope and intercept. \(k\)-NN does nothing in training and keeps everything.

A diagram with two rows of three boxes under the column headings training, what is kept and one prediction. Top row, labelled a fitted line: a green box solve for w and b, an arrow to an orange box 2 numbers, an arrow to a vermillion box 1 multiply, 1 add, with the note the same for any n beneath it. Bottom row, labelled k-NN: a grey box nothing to compute, an arrow to a blue box all n rows, an arrow to a vermillion box n distances, then an average, with the note grows with n beneath it.
ML01.3.4-F2

Where the work is done. A fitted line pays in training and predicts almost for nothing. \(k\)-NN pays nothing in training and pays at every prediction, more for every stored row.

To answer one query, the plain method measures the distance to all \(n\) stored examples: about \({n \times d}\) subtractions, and the same again for the next query.

Step 5. Add features and watch “near” fade. With two features, a query has some stored points very close and others far away. That contrast is what makes the nearest neighbours special. With many features it shrinks.

Two histograms of the distances from one random point to 1,000 other random points, each distance given as a multiple of the average distance. Left panel, titled 2 features: the bars spread widely from 0 to about 1.9. A vertical line marks the nearest point at 0.01 of the average and another marks the farthest at 1.90. Right panel, titled 1,000 features: all the bars are squeezed into a narrow spike at 1.0. The nearest point is at 0.95 of the average and the farthest at 1.06.
ML01.3.4-F3

One query and 1,000 random points in a unit cube. Left: with 2 features the nearest point is at \(0.01\) of the average distance and the farthest at \(1.90\). Right: with 1,000 features every point is at nearly the same distance: the nearest at \(0.95\) of the average, the farthest at \(1.06\).

When every stored example is about as far away as every other, the “nearest” ones are nearest by a hair, and there is little reason to think they resemble the query more than the rest do.

The formal statement

NoteDefinition: k-nearest-neighbour regression

With \(N_k(\vect{x})\) the set of indices of the \(k\) training examples closest to the query \(\vect{x}\), the prediction is the mean of their targets:

\[ \cmodel{\hat{y}(\vect{x})} \;=\; \frac{1}{k} \sum_{i \in N_k(\vect{x})} \ctruth{y_i} . \]

Fact 1: the two ends of the dial. If \({k = 1}\) and the query is a training input \(\vect{x}_i\), its nearest neighbour is itself, so \({\hat{y}(\vect{x}_i) = y_i}\) and the training error is \(0\) (provided no two examples share the same inputs). If \({k = n}\), every example is a neighbour of every query, and \({\hat{y}(\vect{x}) = \frac{1}{n} \sum_i y_i = \bar{y}}\), the mean target.

Fact 2: the prediction never leaves the range of the training targets. Let \(y_{\max}\) be the largest training target. Every \({y_i \le y_{\max}}\), so

\[ \begin{aligned} \hat{y}(\vect{x}) &= \frac{1}{k} \sum_{i \in N_k(\vect{x})} y_i \\ &\le \frac{1}{k} \cdot k \, y_{\max} = y_{\max} . \end{aligned} \]

The same argument with the smallest target gives \({\hat{y}(\vect{x}) \ge y_{\min}}\). So \(k\)-NN regression cannot follow a trend beyond its data. With one feature, every query past the largest input picks the same \(k\) neighbours (exercise 3).

Fact 3: what is stored and what one prediction costs. The training set is \(n\) examples of \(d\) features: \({n \times d}\) numbers are kept, plus \(n\) targets. One squared distance needs \(d\) subtractions and \(d\) multiplications, and a query needs \(n\) of them: about \({n \times d}\) subtractions per prediction. A fitted line keeps \(d\) weights and a bias, \({d + 1}\) numbers, and predicts with \(d\) multiplications, however many examples it was trained on. With a million stored examples and 100 features, \(k\)-NN does \(10^8\) subtractions for one prediction. The line does 100 multiplications.

Fact 4: in many dimensions a neighbourhood must be wide to hold anything. Suppose the data are spread evenly through the unit cube: each of the \(d\) features runs from \(0\) to \(1\). A smaller cube with edge length \(e\) has volume \({e \times e \times \dots \times e = e^d}\), which is also the share of the data inside it. For it to hold a share \(r\),

\[ e^d = r \quad\Longrightarrow\quad e = r^{1/d} . \]

Ask for the nearest \(1\%\) of the data, \({r = 0.01}\):

Features \(d\) Edge needed, \({0.01^{1/d}}\)
\(1\) \(0.01\)
\(2\) \(0.10\)
\(3\) \(0.22\)
\(10\) \(0.63\)
\(100\) \(0.95\)

On a line, \(1\%\) of the data fits in \(1\%\) of the range. With 10 features, the neighbourhood that holds \(1\%\) of the data spans \(63\%\) of the range of every feature. Such neighbours are not local. This is one face of the curse of dimensionality.

Fact 5: every added feature multiplies the data needed. With 100 points spread evenly on a line of length \(1\), neighbours are \(0.01\) apart. A grid with a point every \(0.01\) along each of \(d\) axes needs \(100^d\) points: \(10^{20}\) for \({d = 10}\). No dataset is that large, so in high dimensions every dataset is sparse.

Go deeper: why the distances bunch together

Take two random points in the unit cube, and call one coordinate of each \(U\) and \(V\), independent and evenly spread between \(0\) and \(1\). Then \({\E[U] = \tfrac12}\) and \({\E[U^2] = \int_0^1 u^2 \, du = \tfrac13}\), the same for \(V\), and independence gives \({\E[UV]} = {\E[U]\,\E[V]} = \tfrac14\). So

\[ \begin{aligned} & \E[(U - V)^2] \\ &\quad = \E[U^2] - 2\,\E[UV] + \E[V^2] \\ &\quad = \tfrac13 - 2 \cdot \tfrac14 + \tfrac13 = \tfrac16 . \end{aligned} \]

With \(d\) coordinates the expected squared distance is \({d / 6}\), so the square root of the average squared distance is \({\sqrt{d / 6}}\): \(0.58\) for \({d = 2}\) and \(12.9\) for \({d = 1000}\). In the simulation below, the gap between the farthest and the nearest of 1,000 points stays near \(1.4\) from \({d = 10}\) upwards, while the distances themselves keep growing.

Frontier note: how nearest-neighbour search survives in practice

Real data are not spread evenly through a cube: images and sentences occupy a small, structured part of their space. Beyer and colleagues, who proved that under broad conditions the farthest distance divided by the nearest tends to 1, also identify workloads where it does not.

Nor need the search be exhaustive. scikit-learn can index the data with a KD tree, fast below about twenty features, and approximate nearest-neighbour libraries trade a little accuracy for much more speed.

Worked example

Predict the target at \({x = 2.6}\) from the four points, for every \(k\).

Step 1: the distances. From \(2.6\) to the inputs \({1, 2, 3, 4}\) the distances are \({\abs{1 - 2.6} = 1.6}\), \({\abs{2 - 2.6} = 0.6}\), \({\abs{3 - 2.6} = 0.4}\) and \({\abs{4 - 2.6} = 1.4}\).

Step 2: sort. Nearest first: \({x = 3}\) (target \(5\)), \({x = 2}\) (target \(3\)), \({x = 4}\) (target \(6\)), \({x = 1}\) (target \(2\)).

Step 3: average the first \(k\) targets.

A table drawn as a figure, with one row for each k from 1 to 4. Its columns are k, the k-th nearest input and its target, its distance, the targets collected so far drawn as boxes, their average as a fraction, and the prediction. Row 1: x equals 3 with target 5, distance 0.4, one box holding 5, average 5 over 1, prediction 5. Row 2: x equals 2 with target 3, distance 0.6, boxes 5 and 3, average 8 over 2, prediction 4. Row 3: x equals 4 with target 6, distance 1.4, boxes 5, 3 and 6, average 14 over 3, prediction 4.67. Row 4: x equals 1 with target 2, distance 1.6, boxes 5, 3, 6 and 2, average 16 over 4, prediction 4.
ML01.3.4-F4

The neighbours arrive nearest first, and the average is taken again after each. This is the voting table of lesson 2 with a mean in place of a count.

  • \({k = 1}\): \({\hat{y} = 5}\).
  • \({k = 2}\): \({\hat{y} = (5 + 3) / 2 = 4}\).
  • \({k = 3}\): \({\hat{y} = (5 + 3 + 6) / 3} = {14/3} \approx 4.67\).
  • \({k = 4}\): \({\hat{y} = (5 + 3 + 6 + 2) / 4} = 4\), the mean of all four targets, as Fact 1 says.

The least-squares line through these points, \({\hat{y} = 1.4x + 0.5}\), gives \({1.4 \times 2.6 + 0.5 = 4.14}\) here, close to the \(k\)-NN answers.

Now go outside the data. At \({x = 8}\) the two nearest inputs are \(4\) and \(3\), with targets \(6\) and \(5\), so \({k = 2}\) predicts \(5.5\), and it predicts \(5.5\) at \({x = 80}\) as well. The line predicts \({1.4 \times 8 + 0.5 = 11.7}\). By Fact 2, no \(k\) can make \(k\)-NN answer more than \(6\).

Code

From scratch: the distances are absolute differences, and the vote is replaced by a mean.

import numpy as np

x = np.array([1.0, 2.0, 3.0, 4.0])
y = np.array([2.0, 3.0, 5.0, 6.0])

def knn_regress(x, y, query, k):
    order = np.argsort(np.abs(x - query), kind="stable")      # nearest first
    return y[order[:k]].mean()

print("  k   at x = 2.6   at x = 8")
for k in [1, 2, 3, 4]:
    print(f"  {k}   {knn_regress(x, y, 2.6, k):9.2f}   {knn_regress(x, y, 8.0, k):8.2f}")
print(f"line   {1.4 * 2.6 + 0.5:9.2f}   {1.4 * 8 + 0.5:8.2f}")
  k   at x = 2.6   at x = 8
  1        5.00       6.00
  2        4.00       5.50
  3        4.67       4.67
  4        4.00       4.00
line        4.14      11.70

Now scikit-learn’s KNeighborsRegressor, on the same four points and then on real data: the diabetes dataset, 442 patients with 10 measurements each and a target measuring how far the disease has progressed a year later. The features are standardised inside a pipeline, as lesson 3 requires.

from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

tiny = KNeighborsRegressor(n_neighbors=2).fit(x.reshape(-1, 1), y)
print("four points, k = 2, at x = 2.6 and x = 8:", tiny.predict([[2.6], [8.0]]))

data = load_diabetes(scaled=False)
X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=0)

def mse(model, X, target):
    return np.mean((model.predict(X) - target) ** 2)

results = {}
for k in [1, 5, 20, 100, len(X_train)]:
    model = make_pipeline(StandardScaler(), KNeighborsRegressor(n_neighbors=k)).fit(X_train, y_train)
    results[k] = (mse(model, X_train, y_train), mse(model, X_test, y_test))
    print(f"k = {k:3d}   training MSE {results[k][0]:5.0f}   test MSE {results[k][1]:5.0f}")

line = LinearRegression().fit(X_train, y_train)
baseline = np.mean((y_train.mean() - y_test) ** 2)
print(f"a fitted line       training MSE {mse(line, X_train, y_train):5.0f}   test MSE {mse(line, X_test, y_test):5.0f}")
print(f"always predict the training mean                 test MSE {baseline:5.0f}")
four points, k = 2, at x = 2.6 and x = 8: [4.  5.5]
k =   1   training MSE     0   test MSE  8104
k =   5   training MSE  2317   test MSE  4195
k =  20   training MSE  2882   test MSE  3432
k = 100   training MSE  3549   test MSE  3584
k = 353   training MSE  6131   test MSE  5135
a fitted line       training MSE  2735   test MSE  3424
always predict the training mean                 test MSE  5135

The dial behaves as Fact 1 says. At \({k = 1}\) the training error is \(0\) and the test error, \(8104\), is the worst in the table: worse than \(5135\), the error of always predicting the training mean. At \({k = 353}\), \(k\)-NN is that mean. In between, \({k = 20}\) gives \(3432\), level with the fitted line’s \(3424\). (To pick \(k\) for real, use a validation set.)

Next, the cost of answering the 89 test patients.

n, d = X_train.shape
m = len(X_test)
print(f"the line keeps {line.coef_.size + 1} numbers; k-NN keeps {X_train.size} feature values and {n} targets")
print(f"k-NN, one query: {n} distances = {n * d:,} subtractions.  All {m} queries: {m * n * d:,}")
print(f"the line, one query: {d} multiplications.  All {m} queries: {m * d}")
print(f"a million stored examples with 100 features: {10**6 * 100:,} subtractions for one query")
the line keeps 11 numbers; k-NN keeps 3530 feature values and 353 targets
k-NN, one query: 353 distances = 3,530 subtractions.  All 89 queries: 314,170
the line, one query: 10 multiplications.  All 89 queries: 890
a million stored examples with 100 features: 100,000,000 subtractions for one query

Last, the simulation behind the histogram figure: 1,000 random points in the unit cube, 100 random queries, and the average nearest and farthest distance.

def distance_spread(d, n=1000, queries=100, seed=0):
    rng = np.random.default_rng(seed)
    points, ask = rng.random((n, d)), rng.random((queries, d))
    # squared distances for every query and point, from |a - b|^2 = |a|^2 - 2 a.b + |b|^2
    squared = (ask ** 2).sum(axis=1)[:, None] - 2 * ask @ points.T + (points ** 2).sum(axis=1)[None, :]
    dist = np.sqrt(np.maximum(squared, 0))
    return dist.min(axis=1).mean(), dist.max(axis=1).mean(), (dist.min(axis=1) / dist.max(axis=1)).mean()

print("   d   nearest  farthest  nearest/farthest   edge for 1%")
spread = {}
for d in [1, 2, 3, 10, 100, 1000]:
    spread[d] = distance_spread(d)
    print(f"{d:4d}   {spread[d][0]:7.3f}   {spread[d][1]:7.3f}   {spread[d][2]:16.3f}   {0.01 ** (1 / d):11.2f}")
   d   nearest  farthest  nearest/farthest   edge for 1%
   1     0.001     0.748              0.001          0.01
   2     0.017     1.059              0.017          0.10
   3     0.058     1.210              0.048          0.22
  10     0.499     1.908              0.261          0.63
 100     3.328     4.772              0.697          0.95
1000    12.175    13.637              0.893          1.00

With 2 features the nearest point is at about \(0.02\) of the distance of the farthest. With 10 features the ratio is already \(0.26\), with 100 it is \(0.70\), and with 1,000 it is \(0.89\): the “nearest” neighbour is only about a tenth closer than the farthest point.

Explore

The neighbour explorer in lesson 2 classifies, but its dial is this lesson’s dial too. On the noisy data, push \(k\) to its largest value: the vote ties everywhere, whatever the query, as the staircase goes flat when \({k = n}\). Each time you move the query, the explorer measures the distance to every stored point again. With 40 points that is instant. Fact 3 says what happens with 40 million.

Pitfalls

Two panels, each a plot of target y against input x with the four data points at x equals 1 to 4 and a grey band to the right of x equals 4 marked no data here. The left panel is marked with a cross and titled Hoped for: the trend. A dashed vermillion line through the points carries on rising across the grey band to a diamond at x equals 8, labelled 11.7. The right panel is marked with a tick and titled What k-NN does: flat. A vermillion staircase follows the points and then runs level across the grey band at 5.5 to a diamond at x equals 8, labelled at x equals 8: 5.5, the average of the last 2 targets.
ML01.3.4-F5

Wrong beside right. Beyond the data a fitted line carries the trend on. \(k\)-NN has no trend to carry: it repeats the average of the last few targets for ever.

“The targets are rising, so \(k\)-NN will predict higher values further out.”

By Fact 2 its prediction is an average of stored targets and cannot exceed the largest of them. At \({x = 8}\) the line says \(11.7\) and \(k\)-NN with \({k = 2}\) says \(5.5\). Neither is sure to be right, but only the line can express “the trend continues”. Use \(k\)-NN to fill in between examples, not to forecast beyond them.

“There is no training, so \(k\)-NN is the cheap option.”

The cost has moved, not gone. Every prediction touches every stored example, and all of them must be kept in memory. For a model that answers millions of queries, slow training and fast answers are the better deal.

“More features mean more information, so they can only help.”

Every feature adds a term to every distance, whether or not it has anything to do with the target. Add enough of them and all the distances look alike, as the simulation showed. \(k\)-NN works best with a few well-chosen, scaled features, and needs far more data as their number grows.

Check yourself

Recall

1. How does \(k\)-nearest-neighbour regression make a prediction?

Show answer

It returns the mean target of the \(k\) training examples closest to the query.

2. What does it predict when \(k\) equals the number of training examples?

Show answer

The mean of all the training targets, for every query.

3. Why can it not predict a value larger than the largest training target?

Show answer

It is an average of training targets, and an average never exceeds its largest value.

4. What does brute-force \(k\)-NN keep, and what does it compute for one prediction?

Show answer

It keeps all \(n\) training examples. For one query it computes \(n\) distances, about \({n \times d}\) subtractions and multiplications, then picks the \(k\) smallest.

5. Data are spread evenly in a 10-dimensional unit cube. What edge must a sub-cube have to hold \(1\%\) of them?

Show answer

\({0.01^{1/10} \approx 0.63}\): the neighbourhood spans \(63\%\) of the range of every feature, so “near” neighbours are not near.

Exercises

1. ★ With the four points, predict the target at \({x = 1.8}\) for \({k = 1}\), \(2\) and \(3\).

Show solution

The distances from \(1.8\) to the inputs \({1, 2, 3, 4}\) are \({0.8,\ 0.2,\ 1.2,\ 2.2}\). Nearest first: \({x = 2}\) (target \(3\)), \({x = 1}\) (target \(2\)), \({x = 3}\) (target \(5\)). So \({k = 1}\) gives \(3\), \({k = 2}\) gives \({(3 + 2) / 2 = 2.5}\) and \({k = 3}\) gives \({(3 + 2 + 5) / 3 \approx 3.33}\). The line gives \({1.4 \times 1.8 + 0.5 = 3.02}\).

2. ★★ (a) A system stores 2 million examples with 50 features each. How many subtractions does brute-force \(k\)-NN perform to answer 1,000 queries? At \(10^9\) a second, how long is that? (b) Data are spread evenly in a unit cube with 10 features. What share lies in a sub-cube with edge \(0.5\)? What edge is needed to hold \(10\%\)?

Show solution

(a) \({m \times n \times d} = {1000 \times 2{,}000{,}000 \times 50} = 10^{11}\) subtractions: \(100\) seconds. A fitted line would need \({1000 \times 50 = 50{,}000}\) multiplications.

(b) The share is the volume, \({0.5^{10} = 1/1024 \approx 0.001}\): a tenth of one percent. For \(10\%\), \({e = 0.1^{1/10} \approx 0.79}\).

3. ★★★ A training set has one feature, with all inputs different and largest input \(x_{\max}\). Show that for every query \({x > x_{\max}}\), \(k\)-NN regression gives the same prediction, and say what it is.

Show solution

Take any query \({x > x_{\max}}\). Every training input satisfies \({x_i < x}\), so its distance from the query is \({\abs{x - x_i} = x - x_i}\). Input \(i\) is nearer than input \(l\) exactly when \({x - x_i < x - x_l}\), that is, when \({x_i > x_l}\). The query has dropped out of the comparison, so beyond \(x_{\max}\) the training inputs are always ranked in the same order, largest first.

The \(k\) nearest are therefore always the \(k\) largest training inputs, and the prediction is the mean of their targets, a constant. For the four points with \({k = 2}\) it is \({(6 + 5) / 2 = 5.5}\), at \({x = 8}\) and at \({x = 80}\) alike.

Summary card

For a number, average the neighbours. The data are the model, and that has a price.

The anchor figure again: four data points, a new input at x equals 2.6, its two nearest points highlighted, and the prediction 4 as the average of their targets 3 and 5, on a vermillion staircase of predictions.
ML01.3.4-F1

Average the nearest targets.

  • Rule. \({\hat{y}(\vect{x}) = \frac{1}{k} \sum_{i \in N_k(\vect{x})} y_i}\). At \({k = n}\) it is the mean target \(\bar{y}\).
  • Limits. \({y_{\min} \le \hat{y} \le y_{\max}}\): no extrapolation. At \({x = 8}\) the line says \(11.7\), \(k\)-NN says \(5.5\).
  • Cost. Keep \({n \times d}\) numbers. One prediction needs about \({n \times d}\) subtractions. A line keeps \({d + 1}\) numbers.
  • Many features. To hold a share \(r\) of evenly spread data needs edge \({r^{1/d}}\): \(0.63\) for \(1\%\) when \({d = 10}\).
  • Simulation. Nearest over farthest distance: \(0.02\) with 2 features, \(0.89\) with 1,000.

Sources and next steps

Sources. Each was opened and checked against this lesson on 12 November 2026.

  • scikit-learn 1.9 user guide, Sections 1.6.3 and 1.6.4. A query’s value is the mean of the values of its nearest neighbours. Brute-force query time grows as \(O[DN]\) for \(N\) samples in \(D\) dimensions, and a KD tree is very fast below about 20 dimensions but inefficient beyond.
  • scikit-learn 1.9 documentation, KNeighborsRegressor. The target is predicted by local interpolation of the targets of the nearest neighbours.
  • Trevor Hastie, Robert Tibshirani and Jerome Friedman, The Elements of Statistical Learning, 2nd edition. Equation 2.8 (Section 2.3.2) defines the \(k\)-nearest-neighbour fit as an average. Section 2.5 gives the edge length \({r^{1/p}}\) for \(p\) inputs, with \(0.63\) for \({r = 0.01}\) and ten inputs, and the count \(100^{10}\).
  • Kevin Beyer, Jonathan Goldstein, Raghu Ramakrishnan and Uri Shaft, When Is “Nearest Neighbor” Meaningful?, Technical Report 1377, University of Wisconsin-Madison, June 1998. Under broad conditions, as dimensionality increases, the distance to the nearest data point approaches the distance to the farthest, though not for every workload.
  • Stanford University, CS231n: Deep Learning for Computer Vision, course notes: Image Classification. Approximate nearest-neighbour libraries speed up retrieval at some cost in accuracy.

The diabetes data are scikit-learn’s load_diabetes(scaled=False): 442 patients, 10 features, and a target measuring disease progression one year after baseline.

Next. Module ML01.4, Linear regression as a learning algorithm, takes the opposite approach: it compresses the training set into a few numbers, and can therefore extrapolate.

This lesson unlocks

ML01.4 Linear regression as a learning algorithm

Your progress is saved in this browser only. No account, no tracking.
Back to top