Explain how a feature representation and a distance measure define what it means for examples to be similar.
Describe how \(k\)-nearest neighbours makes classification and regression predictions.
Explain how small and large values of \(k\) affect underfitting and overfitting.
Explain why feature scaling and irrelevant features matter for distance-based models.
Describe the curse of dimensionality and its consequences for nearest-neighbour methods.
Give a high-level description of an RBF support vector machine and the role of support vectors.
Relate gamma and C to the fundamental trade-off and explain why they should be tuned jointly.
Chapter 3 developed a workflow for choosing a model without using the test set: compare model configurations using cross-validation, refit the selected configuration on all the training data, and evaluate it once on the test set. We will now apply that workflow to models built around a familiar idea: new examples are often similar to examples we have seen before.
This chapter begins with \(k\)-nearest neighbours (\(k\)-NN), for which similarity is the prediction rule itself. We then introduce an RBF support vector machine (RBF SVM), which learns a smoother prediction rule based on similarities to selected training examples. Both models will expose an important question: what makes two examples similar?
Suppose we are given labeled images of faces and asked to label a new image. One natural strategy is to find a training image that looks similar and reuse its label.
This reasoning by analogy appears in tasks such as finding related products, recommending items, and recognizing images. To turn the idea into an algorithm, however, we must say exactly how examples are represented and what we mean by similar.
Feature vectors and feature space
Consider the dataset of Canadian and U.S. cities from Chapter 3. Each row contains a city’s longitude, latitude, and country. We will use the coordinates to predict the country.
The first city has longitude \(-123.0780\) and latitude \(48.9854\), so we can represent it as [-123.0780, 48.9854]. This ordered list of feature values is its feature vector. Plotting all such vectors gives us a two-dimensional feature space, with one dimension for each feature.
The same idea applies with \(d\) features: each example is a point in a \(d\)-dimensional feature space, even when we cannot draw it.
Now suppose a new city is at [-123.0, 49.0]. It seems more similar to a city at [-122.7, 49.1] than to one at [-80.0, 25.0]. A distance measure captures this comparison numerically: smaller distances indicate greater similarity.
Common choices include Euclidean distance (straight-line separation), Manhattan distance (movement along each coordinate), and measures based on cosine similarity (the angle between vectors). The appropriate choice depends on what the features represent.
We will begin with Euclidean distance, which we can see directly in the city plot above.
Euclidean distance
For numerical feature vectors, one common measure of separation is Euclidean distance. For vectors \(u = (u_1,\ldots,u_d)\) and \(v=(v_1,\ldots,v_d)\), it is
We subtract the corresponding feature values, square the differences, add them, and take the square root. The result is always non-negative, and it is zero only when the two vectors have identical feature values.
Scikit-learn can calculate the same quantity. Here we compare one query coordinate with five training cities; the smallest value identifies its nearest neighbour.
Euclidean distance is only one possible distance measure. Choosing it is a modeling decision, not a neutral calculation: it declares that squared numerical differences across the included features are a useful definition of separation.
Distance depends on the representation
Consider a query customer and two candidates described by age and annual income. Candidate A is much closer in age; candidate B is much closer in income. If income is recorded in dollars, its much larger numerical scale dominates the Euclidean distance.
Candidate B is declared closer almost entirely because of income, even though the age difference is much larger. Changing dollars to thousands of dollars could reverse the result without changing the underlying customers.
This illustrates a central lesson of the chapter:
Important
A distance is meaningful only relative to a feature representation. Which features we include, how we encode them, and how we scale them determine which examples count as similar.
The longitude and latitude in our cities example have comparable numerical scales, which makes them convenient for building intuition. Most real datasets require deliberate preprocessing. The next chapter will show how to learn and apply scaling inside a scikit-learn pipeline so that it is handled correctly during cross-validation.
\(k\)-nearest neighbours
The \(k\)-nearest neighbours classifier predicts a query example in two steps:
Find the \(k\) training examples closest to the query according to the chosen distance.
Predict the class receiving the most votes among those neighbours.
The query is compared with training examples, never with test examples whose targets should be unknown to the model. The value \(k\) is the n_neighbors hyperparameter in scikit-learn.
With \(k=1\), the closest training city determines the prediction. With \(k=3\), the three closest cities vote, so the result can change.
for k in [1, 3]: model = KNeighborsClassifier(n_neighbors=k) model.fit(X_small_cities, y_small_cities)print(f"Prediction with k={k}: {model.predict(test_point)[0]}")
Prediction with k=1: USA
Prediction with k=3: Canada
How \(k\) controls model complexity
A small \(k\) makes predictions highly local. A single unusual training example can change the prediction in its immediate neighborhood, producing a flexible boundary that may overfit.
A larger \(k\) averages across a broader neighborhood. This produces a smoother, less flexible boundary, but a value that is too large can wash out useful local structure and underfit. At the extreme, if every training example votes, the model predicts the overall majority class everywhere—behavior resembling a most-frequent baseline.
The slider below records all ten plots in the notebook output. After the book is rendered, JavaScript switches among these precomputed states; it does not require a running Python kernel.
We should not choose \(k\) by looking at the test score or by selecting whichever boundary looks appealing. Following Chapter 3, we first reserve a test set and use cross-validation only on the training set.
results_df[["mean_train_score", "mean_cv_score"]].plot(marker="o")plt.ylabel("accuracy")plt.title("Training and cross-validation accuracy");
Training accuracy is highest for the smallest values of \(k\). Cross-validation performance identifies a value that better balances underfitting and overfitting. Once selected, we refit that configuration on the complete training set and evaluate it once on the test set.
Selected k: 6
Mean cross-validation accuracy: 0.802
Test accuracy: 0.857
The test and cross-validation scores need not match. Both estimate performance using finite samples, so differences caused by which examples appear in each subset are expected. The test result remains informative because it did not influence our selection of \(k\).
Exercise 4.1: Distance and model complexity
Select all true statements. Assume uniform voting unless stated otherwise.
A \(k\)-NN model searches the test set for examples similar to its query.
Changing the units of one feature can change which training example is nearest.
Increasing \(k\) usually makes the decision boundary more flexible.
Much higher training accuracy than validation accuracy can indicate that \(k\) is too small.
If \(k\) includes the complete training set, predictions approach the overall majority class.
TipSolution
B, D, and E are true. The model compares a query with training examples. Larger values of \(k\) generally make the boundary less flexible.
Uniform and distance-weighted neighbours
The default weights="uniform" gives every selected neighbour one vote. With weights="distance", closer neighbours receive more influence than farther ones. Weighting changes the prediction rule and is therefore another hyperparameter choice to evaluate using validation data.
\(k\)-NN regression
Suppose we want to predict the price of a house. Nearby houses in feature space do not vote for a class; instead, their prices provide plausible values for the new house. A KNeighborsRegressor predicts the mean target among the \(k\) nearest training examples. With distance weighting, closer neighbours contribute more strongly to that mean.
The example below has one input feature, so we can plot the entire prediction function. Each dot is a training example, and the orange line shows the prediction at each feature value.
With \(k=1\), the prediction is simply the target of the nearest training example. The line changes abruptly whenever a different example becomes nearest, making the model sensitive to individual training points.
With \(k=3\), each prediction averages three nearby targets. The result is smoother and less sensitive to any one example, but it can also hide real local variation. This is the same flexibility trade-off we saw in classification: small \(k\) can overfit, while large \(k\) can underfit. We therefore choose \(k\) using validation data rather than selecting it from the training plot.
Practical trade-offs
\(k\)-NN is attractive because its prediction rule is concrete, it can learn complicated boundaries, and fitting is usually inexpensive: the model mainly validates and stores the training data.
That design shifts work to prediction. To classify a query, the model may need to compare it with many stored examples, so prediction and storage can become costly as the training set grows. Its performance also depends strongly on feature scale, irrelevant features, the distance measure, and the overall representation.
The curse of dimensionality
Suppose two cities are close in longitude and latitude. If we add many unrelated numerical features, each one contributes an accidental difference to their distance. The cities can then appear far apart even though they are similar in the ways that matter.
More generally, a fixed number of examples becomes increasingly spread out as the number of dimensions grows. Nearby examples become harder to find, and the difference between the nearest and farthest examples can become less meaningful. This collection of problems is called the curse of dimensionality. It is especially troublesome for \(k\)-NN because its predictions depend directly on distance.
The experiment below keeps 2,000 examples and two informative features, then adds irrelevant features.
As irrelevant features are added, \(k\)-NN’s validation accuracy falls toward the dummy classifier’s baseline. The useful information has not been removed; it has been overwhelmed by noise in the distance calculation. The plot illustrates why adding features can make a model worse and why feature selection and representation matter for distance-based models.
Exercise 4.2: Choosing a representation
A dataset describes houses using floor area, number of bedrooms, postal code, and the listing agent’s identification number. Before using Euclidean \(k\)-NN, explain which features require scaling, which might need a different representation, and which may be irrelevant or actively misleading.
TipDiscussion
Floor area and bedroom count require attention to scale. Postal code is not an ordinary numerical measurement: numerical closeness between codes need not mean geographic closeness. The agent identifier is an arbitrary label and may inject meaningless differences. The right treatment depends on the prediction problem, but passing all four raw numbers directly to Euclidean distance is difficult to justify.
RBF support vector machines
\(k\)-NN predicts by consulting nearby training examples directly and letting them vote. This produces an intuitive model, but it can create jagged boundaries and make prediction expensive. An RBF support vector machine (SVM) also uses similarity, but it learns a different kind of prediction rule. During fitting, it identifies training examples that are especially important for determining the decision boundary. These examples are called support vectors.
Our goal here is deliberately operational. We will not derive the SVM optimization problem or the kernel trick. We want enough intuition to use scikit-learn’s support vector classifier (SVC) and regressor (SVR), recognize support vectors, and reason about the gamma and C hyperparameters of an RBF SVM.
From distance to RBF similarity
The radial basis function (RBF) kernel converts distance into similarity. Two examples that are close have an RBF similarity near one. As their squared Euclidean distance grows, their similarity approaches zero. The RBF kernel is therefore a similarity function built from distance, not another distance metric.
To classify a query, the fitted model measures its RBF similarity to the support vectors and combines their influences. Support vectors from the two classes push the prediction in different directions, and the resulting score determines the predicted class.
It can be helpful to picture an RBF SVM as a smoother relative of \(k\)-NN, but this is only an analogy. A \(k\)-NN model selects neighbours and lets them vote at prediction time. An SVM selects support vectors and learns how strongly they contribute during fitting.
Support vectors are often training examples close to the decision boundary because such examples help determine exactly where the boundary should go. In the cities problem, a city far inside Canada tells us relatively little about the precise location of the Canada–USA boundary. Cities near the border, such as White Rock or Buffalo, are potentially much more informative.
This is useful intuition rather than a complete definition. Difficult or misclassified examples can also be support vectors, and an SVM does not necessarily end up with only a small number of them. More precisely, support vectors are the training examples that contribute directly to the fitted decision function. Whether an example becomes a support vector is determined during fit. The highlighted examples below are the support vectors for this fitted model.
Here \(x_i\) is a support vector, \(y_i\) indicates its class, \(\alpha_i\) determines how strongly it contributes, \(K(x_i,x_{\text{new}})\) measures its similarity to the query, and \(b\) shifts the decision threshold. The sign of the resulting score determines the predicted class.
You are not expected to calculate this function by hand. Its purpose is to make the main idea precise: an RBF SVM combines learned contributions from support vectors rather than taking a neighbour vote.
gamma: how local is the similarity?
The RBF similarity between a support vector \(x_i\) and a query \(x_{\text{new}}\) is
The value is 1 when the two feature vectors are identical and approaches 0 as they move farther apart. You can imagine placing a smooth bump over each support vector. The bump is highest at the support vector and falls as we move away; the similarity is the height of the bump at the query.
gamma controls the width of these bumps:
A small gamma creates wide bumps, so each support vector influences a broad region. This usually produces a smoother boundary.
A large gamma creates narrow bumps, so each support vector has highly local influence. This allows a more detailed boundary.
As a broad tendency, increasing gamma increases flexibility and can move the model from underfitting toward overfitting. Because RBF similarity is calculated from distance, feature scaling affects these regions of influence.
C controls how strongly fitting penalizes mistakes on the training data.
A small C tolerates more training mistakes, allowing a smoother boundary. If C is too small, the model may underfit.
A large C puts more pressure on the model to classify difficult training examples correctly, often producing a more detailed boundary. If C is too large, the model may overfit.
This is again a broad tendency rather than a guarantee about validation performance.
The two hyperparameters answer different questions:
gamma: How far does each support vector’s influence extend?
C: How strongly should fitting try to avoid training mistakes?
Their effects interact. Changing the penalty for mistakes can have a different effect when every support vector has broad influence than when each has highly local influence. We therefore cannot reliably tune one, freeze it, and then tune the other.
A later chapter will introduce tools such as GridSearchCV and RandomizedSearchCV for evaluating combinations of hyperparameters. The same Golden Rule still applies: the search uses training and validation data, while the test set remains untouched until the complete workflow has been selected.
The model selects support vectors and learns how strongly they contribute.
How is a classification prediction formed?
The selected neighbours vote.
Learned, weighted similarities are combined.
Main hyperparameters here
n_neighbors, weights
C, gamma
Main computational concern
Prediction can be costly for large training sets.
Fitting can be costly for large datasets.
Neither model is universally better. Their performance depends on the representation, sample size, hyperparameters, and structure of the problem.
Classification, regression, and text data
Just as scikit-learn provides KNeighborsClassifier and KNeighborsRegressor, it provides SVC for classification and SVR for regression.
RBF SVMs can learn nonlinear decision boundaries and often work well on appropriately preprocessed small- to medium-sized datasets. Fitting can become expensive as the number of examples grows, and the results are sensitive to feature scaling, C, and gamma.
SVMs can also be effective with high-dimensional text representations. For large sparse text datasets, a linear SVM is often a more scalable baseline than an RBF SVM. We retain the RBF model here because it makes similarity visible and provides two interacting hyperparameters for practice. The next chapter will show how text and other non-numerical columns can be transformed as part of a complete modeling pipeline.
Exercise 4.3: Reasoning about an RBF SVM
Select all true statements.
Increasing gamma makes each training example’s RBF influence more local.
Increasing C always improves validation accuracy.
The best C can depend on the selected gamma.
An RBF kernel is a distance metric.
An RBF SVM uses all nearby examples in an unweighted majority vote.
TipSolution
A and C are true. Larger C may overfit, an RBF kernel is a similarity function built from distance, and an SVM combines learned weighted similarities rather than using a \(k\)-NN vote.
Summary
A numerical example can be represented as a point in feature space, but closeness depends on the selected features, their encodings, their scales, and the distance measure.
\(k\)-NN classification uses a vote among nearby training examples; \(k\)-NN regression averages their targets.
Small \(k\) usually produces a more flexible model, while large \(k\) produces a smoother model that can underfit.
Feature scaling, irrelevant features, and high dimensionality can make Euclidean distance misleading.
An RBF SVM selects support vectors and learns how strongly they contribute, rather than using a direct neighbour vote.
gamma controls how local RBF influence is, while C controls how strongly training mistakes are penalized. Their interaction means they should be tuned jointly.
Similarity-based models are only as meaningful as the representation on which similarity is computed. Real datasets contain features with incompatible scales, categories, missing values, and text. The next chapter develops pipelines and column transformers for building those representations without leaking information across data splits.