k-Nearest Neighbors › Formula
Machine Learning from ScratchAll chapters k-Nearest Neighbors › FormulaSection view · Sections in this chapter4 / 10 ↓
Reading tools Definitions, links & notes
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
This section defines the distance and neighborhood rules used by kNN, then examines neighborhood size, weighting, scaling, and computational cost.
Distances and local prediction rules
The whole of kNN is built from two questions. First, how similar is the query to each stored example? Second, which examples are similar enough to count? The first question needs a number, a distance. The second needs a rule, a neighborhood. Everything else, including voting and averaging, follows from how we answer those two questions. It makes sense to build them in that order, because the prediction rule only becomes meaningful once we know which points are allowed to speak.
Suppose our training set is a collection of labeled observations
where each is a vector of features, and is its label or target. The query point is a feature vector with unknown label. Here is bold because it is a vector, and the subscript indexes the training example. In words: is the stored dataset, is the -th training input, and is the corresponding output.
Why start with a distance rather than a probability or a parameter? Because kNN is non-parametric: it does not restrict the regression function or decision boundary to a fixed parametric family. Its predictions compare examples directly, and their usefulness depends on a distance that places inputs with similar targets near one another. A distance is the minimal machinery that turns "these two inputs look alike" into something a computer can sort. Everything we add later is built on this single measurable notion of resemblance.
The Euclidean distance between the query and the -th training point is
where:
- : the -th feature of the query point
- : the -th feature of the -th training point
- : number of features
- : Euclidean distance between two feature vectors
Read it in four moves: take the difference between the query and the training point in each feature ; square it; sum over the features; then take the square root. The squaring does real work: it lets a positive and a negative deviation of the same size count identically, and it lets a few large disagreements outweigh many small ones. The square root returns the total to the original units, so features measured in the same physical unit yield a distance in that unit. With mixed or transformed feature units, the distance is a modeling quantity whose interpretation depends on those scales.
We can also write the same expression compactly using vector notation. Let be the elementwise difference vector. Then
where:
- : the query feature vector
- : the -th training feature vector
- : the elementwise difference vector
- : Euclidean (L2) norm
Here is the dot product of with itself, which equals . This is the same quantity as before, only now expressed as a matrix multiplication. The vector form is also computationally useful. Stack all into an matrix , and the array of distances becomes , where is the -th feature of the query and is the -th column of . That single vectorized expression is what makes brute-force kNN feasible even for moderately large , and it is exactly the computation the code later performs.
Euclidean distance is only one choice. Minkowski distance generalizes it as
where:
- : the Minkowski order parameter controlling how large feature differences are weighted
- : the -th feature of the query point
- : the -th feature of the -th training point
- : number of features
Here recovers Euclidean distance and gives Manhattan distance (sum of absolute differences). Any choice of distance defines a slightly different notion of "closeness", and therefore different neighbors. This is the first hint that the distance is a modeling decision, not a neutral measurement. Euclidean distance is a common starting point for comparably scaled continuous features. Manhattan distance adds absolute coordinate differences, while Euclidean distance combines their squares before taking a square root, so a large coordinate discrepancy can have greater relative influence in Euclidean neighborhoods. Both distances remain sensitive to extreme observations, and standardization does not make their neighbor rankings agree. Compare the metric choices under the same validation protocol.
From distances to a neighborhood
With a distance in hand, every training point carries a single number: how far it sits from the query. The natural next move is to keep the smallest of those numbers, and that is exactly what defines the neighborhood. Formally, the set of the nearest training indices is
where:
- : the set of indices of the nearest training points to the query
- : a subset of training indices with
- : distance from the query to the -th training point
- : number of training points
which reads: "the subset of the training indices of size that minimizes the total distance from the query". In practice we never solve this as an optimization; we simply sort the distances and take the first . The notation is a compact description of the sorted order, not a computational instruction.
Two design choices are hidden inside this definition, and both matter:
- Why fix the count instead of a radius? Because a fixed count lets the neighborhood radius adapt when local density varies. In a dense region, the nearest points sit within a small ball; in a sparse region, the same points spread out over a much larger ball. Fixing therefore lets the neighborhood adapt its radius to local density automatically. A fixed radius would instead yield many neighbors where data is dense and too few, or none, where it is sparse.
- Why rely on locality at all? The locality heuristic is that nearby inputs have similar conditional means or class probabilities in the chosen representation. It motivates local averaging or voting; noise still permits different labels at identical inputs.
The neighborhood depends on the query, the stored training inputs, the metric, and the tie rule. Neighbor lookup is performed for each new query; this is the sense in which kNN is instance-based. There is no fitted global parametric curve to inspect; each prediction requires a local comparison against the stored examples. Ties are the one wrinkle: when two training points are exactly equidistant, the sorted order must break the tie somehow. We return to that in the worked example.
One more design choice deserves a note:
- Distance metric: Euclidean distance suits comparably scaled, roughly symmetric continuous features; Manhattan distance gives large coordinate discrepancies a different relative influence; cosine distance can suit nonzero sparse or text-derived vectors when direction is more relevant than magnitude. The metric defines the neighborhood, so record and reuse it consistently.
Classification votes and regression averages
Once the neighborhood exists, the prediction is a reduction over it. The reduction depends on whether the target is categorical or numeric, and the distinction deserves its own heading because it changes the interpretation even though the machinery stays the same.
For classification with classes, each neighbor casts a vote for its own label. The predicted class is the one receiving the most votes:
where:
- : the predicted class for the query
- : a class label in
- : the label of the -th neighbor
- : indicator function (1 when the condition is true, 0 otherwise)
We can also divide the count by to obtain the local class probability :
The indicator function takes value when the -th neighbor's label equals class , and otherwise. The inner sum therefore counts how many of the neighbors are of class , and selects the class with the largest count. If we also divide by , the inner expression becomes the local class probability . That probability is not required for the hard label, but it is useful for ranking predictions or for calibration.
For regression, each neighbor contributes its numeric label, and the prediction is the local average:
where:
- : the predicted numeric value for the query
- : the numeric target of the -th neighbor
- : number of neighbors in the neighborhood
The average is the continuous analogue of the majority vote: instead of selecting a discrete class with the most votes, we select the value that minimizes the squared error among the neighbors. That connection is worth remembering: the sum of squared errors to the local neighbors is minimized by their mean. To see why, minimize
with respect to the constant . Taking the derivative and setting it to zero,
so , which is exactly the local average above. This is the same logic that underlies ordinary least squares in the earlier OLS chapter. Local averaging is essentially OLS with an implicit neighborhood restriction: one tiny least-squares fit per query, using only the nearest examples.
Both rules are the same weighted sum in disguise. Stack the labels into a vector and let be a sparse matrix whose -th row is nonzero only at the indices of the neighborhood of query :
where:
- : vector of predictions for all queries
- : vector of training labels
- : sparse weight matrix whose -th row selects the neighborhood of query
- : weight of training point for query
- : number of neighbors in the neighborhood
In regression, multiplies the numeric labels; in classification, the same structure applied to one-hot encoded labels reproduces voting exactly. This "weight" view is a useful bridge to the next subsection, where the weights are no longer forced to be equal.
Neighborhood size, weighting, and scaling
Three knobs determine how kNN behaves, and they are easiest to understand in the order they were introduced.
The size . At , every prediction equals the label of the single closest training point. The decision boundary can then trace every jagged detail of the training set with low bias and high variance. Small perturbations of the data, or of the query, can flip the prediction to a completely different neighbor. As grows, voting or averaging uses a larger neighborhood. This can reduce sensitivity to noise while blurring local changes, but boundaries and conditional bias need not change monotonically for every dataset. For independent equal-variance regression errors at fixed training inputs, the noise variance of a uniform -neighbor average is the common error variance divided by . With uniform weights, the extreme makes every query use the full training set: classification predicts a most common class, using the chosen tie rule if needed, and regression predicts the global mean. Distance weights can still produce query-dependent predictions at . At , the selected neighborhood contains every training example, but distance weights can still concentrate influence near the query. That limit is a useful sanity check: both neighborhood size and weighting affect how strongly nearby examples influence the prediction.
The weighting. Uniform voting treats all neighbors equally, even when some are much closer than others. Distance weighting lets proximity affect their influence. The weighted prediction is
where:
- : the distance-weighted prediction for the query
- : the label or target of the -th neighbor
- : the weight assigned to the -th neighbor, inversely proportional to squared distance
- : distance from the query to the -th neighbor
The weights are larger for close neighbors and smaller for distant ones. When all distances are equal, the formula reduces to the simple mean, so weighting is a strict generalization rather than a different algorithm. Closer training points effectively get more votes. This can reduce the influence of more distant targets near a boundary or an unevenly sampled region, but it also concentrates weight on fewer observations and can amplify noise. Whether predictions improve should be checked on held-out data. This chapter uses inverse-squared weights for positive distances; inverse distance is another common choice and is scikit-learn’s built-in weights="distance" convention. For a zero-distance query, we average only the exact matches. For weighted classification, sum the weights separately for each class and select the largest class total.
The scaling. Feature scaling can substantially change kNN neighborhoods when coordinate ranges differ. As described earlier in the standardization chapter, large differences in feature scale can let one coordinate dominate raw distances. If differences in one feature are much larger than those in another, their squared contributions can largely determine the neighbor ranking. Choose scaling so that feature differences have the intended influence on distance, and fit any learned scaling parameters on the training set only. This is the same data leakage discipline described in the validation chapter: computing a mean or standard deviation using the test set and then using those values to scale the training set leaks test-distribution information into preprocessing. The resulting score no longer evaluates a procedure fitted solely on the training data; the direction of the score difference is not guaranteed in every realized split. Any chosen scaling transform becomes part of the distance definition and must also be applied to future queries.
Computational cost and the curse of dimensionality
The cost of kNN has two faces: computation and geometry. They are easy to confuse.
The computational face is straightforward. Computing all brute-force distances requires operations per query. Our full-sort implementation adds neighbor-ordering work per query, giving work for queries, before vote aggregation. A partial-selection implementation can avoid sorting all distances. This repeated distance calculation and sorting make our implementation expensive at inference. Our brute-force implementation scans every stored training point for each query. Exact or approximate search indexes can reduce this search work. Dimensionality reduction can reduce the work per distance, but brute-force prediction still scans the transformed training set. Exact trees trade construction and storage costs for query pruning while preserving the neighbor set. Approximate search can change that set; dimensionality reduction changes the feature representation and can change its distances. Evaluate suitability from measured storage, index-building, and query costs under a representative workload.
The geometric face is the curse of dimensionality, and it is more fundamental. Under the independent centered Gaussian feature-difference model below, with fixed variance , query-to-training distances concentrate in relative terms as grows. To see the effect quantitatively, consider the squared Euclidean distance between a query and a training point,
where:
- : the -th feature of the query point
- : the -th feature of the -th training point
- : number of features
- : squared Euclidean (L2) norm
If the feature differences are independent centered Gaussian variables with variance , then the sum of their squares has mean and variance . The standard deviation of the squared distance is therefore , which grows more slowly than the mean . Their ratio,
shrinks as , so the squared distance concentrates around its mean as grows. Taking the square root carries this concentration over to the distances themselves. For a fixed finite number of training points under this independent Gaussian model, the nearest-to-farthest distance ratio approaches one in probability as grows. Correlated features, a low-dimensional representation, or a training-set size that grows with require separate analysis.
The concentration argument can be checked numerically. The next simulation draws independent standard normal training and query points, computes the nearest-to-farthest distance ratio for each query, and averages those ratios across queries at each dimension.
PythonIn [3]Expand
# Distance-concentration simulation: independent standard normal features,
# 400 training points, and 50 queries per dimension. The plotted value is the
# mean over queries of nearest distance divided by farthest distance.
concentration_dims = np.array([2, 4, 8, 16, 32, 64, 128, 256, 512])
concentration_train_n = 400
concentration_query_n = 50
concentration_seed = 2024
concentration_rng = np.random.default_rng(concentration_seed)
concentration_ratios = []
for p in concentration_dims:
X_sim_train = concentration_rng.normal(size=(concentration_train_n, int(p)))
X_sim_query = concentration_rng.normal(size=(concentration_query_n, int(p)))
diffs = X_sim_query[:, None, :] - X_sim_train[None, :, :]
dists = np.sqrt((diffs**2).sum(axis=2))
ratios = dists.min(axis=1) / dists.max(axis=1)
concentration_ratios.append(float(ratios.mean()))
concentration_ratios = np.array(concentration_ratios)VisualizationOut [4]Expand

Practically, this means:
- In high dimensions, kNN may appear to have many "close" neighbors that are far away, causing predictions to be dominated by seemingly unrelated points.
- Feature aggregation does not rescue the situation unless the resulting representation preserves information about the target. Extra noise coordinates can weaken the relative distance contrast.
- In high-dimensional settings, kNN is often combined with feature selection or with a learned low-dimensional representation before prediction.
Mathematical Properties
The kNN predictor is closely related to a classical non-parametric estimator. For a concrete regression result, suppose the training observations are iid, the feature domain is bounded, and with Lipschitz with constant . Conditional on the training inputs, assume the errors are independent, have mean zero, and have common finite variance . Conditional on the training inputs, the uniform kNN average has noise variance and absolute bias bounded by , where is the distance to the -th neighbor. At a query in the distributional support, and make its mean squared estimation error tend to zero. With the additional local mass condition for a positive constant and sufficiently small , a representative bound is ; balancing the terms gives . This regularity-based bound is slower than the estimation-error rate of regular, correctly specified finite-dimensional parametric models; it is not a claim that every individual kNN problem converges strictly more slowly. For classification, Cover and Hart’s large-sample result bounds the error of the one-nearest-neighbor rule by twice the Bayes error under their sampling and regularity conditions. The Bayes error is a property of the underlying distribution, not of the fitted classifier. This bound does not imply that another classifier must outperform nearest neighbors.
The relationship between uniform and weighted kNN also has a precise form. Under kernel weighting, the local estimator is a Nadaraya-Watson-type kernel regression estimator, and the weights satisfy when normalized. Nonnegative weights with a positive total, normalized to sum to one, keep regression predictions within the convex hull of the neighbor targets. Dividing all class-vote totals by that same positive total leaves their ranking unchanged. These connections show that kNN is a non-parametric estimator with asymptotic results under stated sampling and regularity conditions.
Comments
Add to the conversation
A question, a correction, or an example from your own work.
No comments yet. Be the first to share your thoughts!