k-Nearest Neighbors Algorithm
Algorithm · Stretch
Step through it: Top K Elements pattern
Step 1 of 6
Goal: find the 3 biggest numbers. Sorting everything works but does more than needed. Instead keep a small club of the best 3 so far and always know its weakest member, the first to be kicked out. (A min-heap gives you the weakest in one step.)
Step 2 of 6
Take in 5, 1 and 9. The club is full: 1, 5, 9. The weakest member is 1.
Step 3 of 6
Next is 3. It beats the weakest (1), so 1 leaves and 3 joins: 3, 5, 9.
Step 4 of 6
7 beats the new weakest (3). Club: 5, 7, 9.
Step 5 of 6
2 is smaller than the weakest (5), so ignore it. The club is the answer: 5, 7, 9. Each number costs one quick heap update, about n log k steps in all. This is the Top K pattern.
Step 6 of 6
Your turn.
The k-nearest neighbors algorithm (k-NN) is a supervised Machine Learning algorithm. It's a classification algorithm, determining the class of a sample vector using a sample data.
In k-NN classification, the output is a class membership. An object is classified by a plurality vote of its neighbors, with the object being assigned to the class most common among its k nearest neighbors (k is a positive integer, typically small). If k = 1, then the object is simply assigned to the class of that single nearest neighbor.
The idea is to calculate the similarity between two data points on the basis of a distance metric. Euclidean distance is used mostly for this task.
Image source: Wikipedia
The algorithm is as follows:
- Check for errors like invalid data/labels.
- Calculate the euclidean distance of all the data points in training data with the classification point
- Sort the distances of points along with their classes in ascending order
- Take the initial
Kclasses and find the mode to get the most similar class - Report the most similar class
Here is a visualization of k-NN classification for better understanding:
Image source: Wikipedia
The test sample (green dot) should be classified either to blue squares or to red triangles. If k = 3 (solid line circle) it is assigned to the red triangles because there are 2 triangles and only 1 square inside the inner circle. If k = 5 (dashed line circle) it is assigned to the blue squares (3 squares vs. 2 triangles inside the outer circle).
Another k-NN classification example:
Image source: GeeksForGeeks
Here, as we can see, the classification of unknown points will be judged by their proximity to other points.
It is important to note that K is preferred to have odd values in order to break ties. Usually K is taken as 3 or 5.
Code
/**
* Classifies the point in space based on k-nearest neighbors algorithm.
*
* @param {number[][]} dataSet - array of data points, i.e. [[0, 1], [3, 4], [5, 7]]
* @param {number[]} labels - array of classes (labels), i.e. [1, 1, 2]
* @param {number[]} toClassify - the point in space that needs to be classified, i.e. [5, 4]
* @param {number} k - number of nearest neighbors which will be taken into account (preferably odd)
* @return {number} - the class of the point
*/
import euclideanDistance from '../../math/euclidean-distance/euclideanDistance';
export default function kNN(
dataSet,
labels,
toClassify,
k = 3,
) {
if (!dataSet || !labels || !toClassify) {
throw new Error('Either dataSet or labels or toClassify were not set');
}
// Calculate distance from toClassify to each point for all dimensions in dataSet.
// Store distance and point's label into distances list.
const distances = [];
for (let i = 0; i < dataSet.length; i += 1) {
distances.push({
dist: euclideanDistance([dataSet[i]], [toClassify]),
label: labels[i],
});
}
// Sort distances list (from closer point to further ones).
// Take initial k values, count with class index
const kNearest = distances.sort((a, b) => {
if (a.dist === b.dist) {
return 0;
}
return a.dist < b.dist ? -1 : 1;
}).slice(0, k);
// Count the number of instances of each class in top k members.
const labelsCounter = {};
let topClass = 0;
let topClassCount = 0;
for (let i = 0; i < kNearest.length; i += 1) {
if (kNearest[i].label in labelsCounter) {
labelsCounter[kNearest[i].label] += 1;
} else {
labelsCounter[kNearest[i].label] = 1;
}
if (labelsCounter[kNearest[i].label] > topClassCount) {
topClassCount = labelsCounter[kNearest[i].label];
topClass = kNearest[i].label;
}
}
// Return the class with highest count.
return topClass;
}References
Practice
Top K Elements
- Kth Largest Element in a StreamEasy
- Last Stone WeightEasy
- Kth Largest Element in an ArrayMedium
- Top K Frequent ElementsMedium
- Top K Frequent WordsMedium
- K Closest Points to OriginMedium
- Sort Characters By FrequencyMedium
- Task SchedulerMedium
- Reorganize StringMedium
- Find K Pairs with Smallest SumsMedium
- Kth Smallest Element in a Sorted MatrixMedium
- Meeting Rooms IIMedium
- Furthest Building You Can ReachMedium
- Merge k Sorted ListsHard
- Find Median from Data StreamHard
- Smallest Range Covering Elements from K ListsHard
Spotted a mistake or something unclear? Report it on GitHub.