Concepts / Choosing the Number of Neighbors in k-Nearest Neighbors

Choosing the Number of Neighbors in k-Nearest Neighbors

For KNeighborsClassifier, that extracted information is simply the training set itself.

  • Programming
Interactive lab

Try it: k-Nearest Neighbours

How a k-nearest-neighbours classifier labels a new point: measure its distance to every known point, take the K closest, and let them vote.

How it works

  1. Measure the straight-line (Euclidean) distance from the new point to every labelled point.
  2. Rank the points from nearest to farthest.
  3. Keep the K nearest.
  4. Count how many of them belong to each class; the class with the most votes is the prediction (a tie goes to the class of the nearest tied neighbour).

Default run (15 steps): 10 labelled points and a new query point at (5, 3.5). K = 3. … Prediction: class A — A has the most votes.

Simplified: Small 2-D educational dataset (at most 30 points, three classes). Real KNN uses many features and usually scales them first.

Educational simulation

Loading the simulation…

Predicting Before Running the Program

Machine learning libraries make it tempting to call a few functions and accept whatever comes back. When a result is wrong, that habit makes the failure hard to diagnose. This article takes the opposite approach. You will read a short program, predict what it prints, and only then compare your prediction with the actual result. When the two disagree, the gap between your expectation and the output points you to the line where your mental model of the code broke down.

The model in this article is a k-nearest neighbors classifier. It is a classification algorithm that is easy to understand, and scikit-learn provides it. The whole idea is that a new data point receives the label of the training point it most resembles. Keep that idea in mind as you read the code.

Creating the Classifier and Training It

In scikit-learn, every machine learning model is implemented as its own class, called an Estimator class. The k-nearest neighbors algorithm lives in the KNeighborsClassifier class, which belongs to the neighbors module. You cannot use the algorithm until you create an object from that class. Creating the object is also when you choose the model's parameters. The most important parameter is n_neighbors, the number of neighbors the model will consult.

The knn object you create is more than a name for the algorithm. It bundles together the procedure for building the model from training data, the procedure for making predictions, and any information extracted from the training data along the way. For KNeighborsClassifier, that extracted information is simply the training set itself. Calling fit is what hands the training data to this object.

python
Output (expected)
True
[1]
Notes on the code
  • X_train holds the five two-dimensional training points and X_new holds the new point.
  • y_train holds one label for each training point, in the same order.
  • The KNeighborsClassifier call creates the object and sets n_neighbors to 1 at that moment.
  • fit stores the training data in the object and returns the same object.
Unfitted objectparameters set, no trainingdatafit(X_train, y_train)stores training dataFitted objectholds training setpredict(X_new)compares new point withstored pointstraining data passed inreturns same objectnew point passed in
What state is the classifier object in before and after fit, and which calls are allowed in each state?

Notice what fit changes and what it does not. It stores the training data inside the object. It does not produce a separate summary, a learned formula, or a set of weights. The object you created is the same object that fit returned, so the name knn and the name same_object refer to one model, not two separately trained models. The first printed line, True, confirms this.

Finding the Nearest Training Point

A k-nearest neighbors classifier does not learn a formula or a set of weights from the training data. It answers each question by comparing the new point with the stored training points. The algorithm locates the training point closest to the new point and gives the new point that training point's label. This is the simplest version of the method, and it is the version the program above uses, because n_neighbors is set to 1.

Worked example

Predicting the label of X_new = [[4, 4]]

Training points: (0, 0) label 0, (1, 0) label 0, (0, 1) label 0, (5, 5) label 1, (6, 5) label 1. The new point is (4, 4). Which label does a one-neighbor classifier return?

  1. 1
    Measure the distance to each training point

    The distance from (4, 4) to (5, 5) is $\sqrt{2} \approx 1.41$. To (6, 5) it is $\sqrt{5} \approx 2.24$. To (1, 0) and (0, 1) it is $5$. To (0, 0) it is $\sqrt{32} \approx 5.66$.

  2. 2
    Find the closest training point

    The smallest distance is $\sqrt{2}$, which belongs to (5, 5), the point in row 3 of the training data.

  3. 3
    Copy that point's label

    Row 3 has label 1 in y_train, so the one-neighbor prediction is 1.

Result

The classifier predicts 1, because the single closest training point is (5, 5) and its label is 1.

X_new[4, 4]row 0[0, 0] label 0row 1[1, 0] label 0row 2[0, 1] label 0row 3[5, 5] label 1row 4[6, 5] label 1closest, distance about 1.41
Which specific training row is closest to the new point, and how does the model map that query to that row's label?

The stored training set is consulted every time a prediction is made. This is why a model with no learned weights can still produce a prediction: the training data itself is the model. Every prediction is a lookup against that stored set, followed by a copy of a label.

What n_neighbors Controls

The letter k generalizes the rule. Instead of consulting only the single closest neighbor, the method may consult any fixed number k of neighbors, such as the three or five closest training points. The prediction is then the majority class among those neighbors. When k is 1, the majority is simply the label of the one neighbor, which is why the program's answer depends on one training point alone. In scikit-learn, this number is the n_neighbors parameter.

(5, 5) label 1distance about 1.41(5, 5) label 1distance about 1.41Vote result: 1one vote(6, 5) label 1distance about 2.24(1, 0) label 0distance 5Vote result: 1two votes for 1, one for 0majority of onemajority of three
When n_neighbors is 1 versus 3, which training points are consulted for the same query point [4, 4], and how does the vote come out?

The comparison above shows that changing n_neighbors changes which points vote, even when the final label happens to stay the same. With three neighbors, the two points at distance about 2.24 and 1.41 are both labeled 1, and only one vote goes to a label 0 point. Point (0, 1) is also at distance 5, tied with (1, 0), and both carry label 0, so the choice between them does not change the vote here. In general, a different k can change the answer, so the value is a decision that has to be made deliberately.

Tracing Where the Output Comes From

What do you think happens?

After fit has run on the five training points, what does the last line print for X_new = [[4, 4]] with n_neighbors=1?

  • [0]

  • [1]

Reveal answer
Answer:

[1]

The closest training point to (4, 4) is (5, 5), which is in row 3 and has label 1, so predict returns [1].

KNeighborsClassifier(n_neighbors=1)create object, setparameterfit(X_train, y_train)store training datapredict(X_new)nearest point, copy label[1]printed resultsame object passed onfitted object usedlabel returned
What happens first, second, and third in the program, and at which line does the wrong output first show up?

Read the program in that order. The construction line creates the object and fixes n_neighbors=1. The fit line stores the training data. The predict line compares X_new against the stored points and returns a label. If the printed value were not what you predicted, the first thing to check is which of these three stages produced a different state than you assumed. A useful habit is to print the parameters of the fitted object: printing a fitted model shows a long listing of its parameters, most of them defaults you did not set, and the n_neighbors=1 you did set should appear in that same list.

EASY

Keep the same five training points and labels, change the new point to X_new = [[1, 3]], and keep n_neighbors=1. Before running anything, identify the single closest training row and predict the printed output. Then explain your answer by naming the row.

Hints
  • Compute the distance from (1, 3) to each of the five training points, and compare the smallest values.
  • The point (0, 1) is at distance $\sqrt{5} \approx 2.24$, and no other training point is closer.

Mistakes Beginners Make with fit and n_neighbors

  • Common mistake

    Expecting fit to return a brand-new model

    What it looks like
    model2 = knn.fit(X_train, y_train) and then assuming that changing model2 leaves knn untouched.
    Why it fails

    fit works on the object in place and returns that same object, so both names refer to one model.

    Do this instead

    Treat the return value of fit as another reference to the same object, and create a second KNeighborsClassifier if you want a separate model.

  • Common mistake

    Treating n_neighbors=1 as the final choice for every problem

    What it looks like

    Keeping n_neighbors=1 without ever asking whether a single closest point is a reliable basis for the label.

    Why it fails

    A one-neighbor prediction depends entirely on one training point, so it cannot average out the influence of an unusual point.

    Do this instead

    Use n_neighbors=1 to understand the mechanism, then treat the choice of the number of neighbors as a separate decision.

  • Common mistake

    Expecting a prediction before the model has been fitted

    Why it fails

    An unfitted object has no stored training data, so there is nothing for predict to compare the new point against.

Key Takeaways

  • A KNeighborsClassifier comes from the neighbors module and must be created as an object before use; parameters such as n_neighbors are set at construction.
  • fit stores the training data inside the object and returns that same object, so training happens in place.
  • With n_neighbors=1, the prediction is the label of the single training point closest to the new point, which you can identify by measuring distances.
  • n_neighbors sets how many nearby training points vote; n_neighbors=1 is a clear starting point for understanding the method, not a final choice.
  • When output is unexpected, check construction, fitting, and prediction in that order to find the first step where your expectation and the program diverge.

Related concepts

More concepts starting with C