The Adaptive k-Nearest Neighbors (k-NN) Classifier is an extension of the traditional k-NN algorithm, which is widely used for classification and regression tasks in machine learning. Unlike the standard k-NN that uses a fixed number of nearest neighbors for all predictions, the Adaptive k-NN algorithm adjusts the number of neighbors (k) based on the local density of points, aiming to improve classification accuracy, especially in areas where data points are not uniformly distributed.
The k-NN algorithm operates on a simple principle: it classifies a new sample based on the majority vote of its k nearest neighbors in the feature space. The standard k-NN algorithm uses a fixed k value, which can be suboptimal in varying density regions. The Adaptive k-NN Classifier, however, dynamically adjusts k for each query point, taking into consideration the local density of neighbors. This adjustment allows for more flexible decision boundaries and can lead to improved performance in heterogeneous datasets.
Let be the set of training samples and be the query point. The local density at is estimated by:
where:
The adaptive number of neighbors , to be considered for classifying is defined as:
where:
The classification of the query point is determined by the majority vote among its nearest neighbors:
where denotes the class label of the th nearest neighbor of .
n_density
: int
, default = 10min_neighbors
: int
, default = 5max_neighbors
: int
, default = 20Test with iris flower dataset and reduce dimensionality via SFS
using GaussianNaiveBayes
as a base estimator:
from luma.classifier.naive_bayes import GaussianNaiveBayes
from luma.classifier.neighbors import AdaptiveKNNClassifier
from luma.preprocessing.scaler import StandardScaler
from luma.reduction.selection import SFS
from luma.model_selection.split import TrainTestSplit
from luma.model_selection.search import GridSearchCV
from luma.visual.evaluation import DecisionRegion, ConfusionMatrix
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import numpy as np
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = TrainTestSplit(X, y,
test_size=0.2,
random_state=42).get
sc = StandardScaler()
X_train_std = sc.fit_transform(X_train)
X_test_std = sc.fit_transform(X_test)
sfs = SFS(estimator=GaussianNaiveBayes(),
n_features=2,
test_size=0.2,
cv=5,
random_state=42,
verbose=True)
sfs.fit(X_train_std, y_train)
X_train_sfs = sfs.transform(X_train_std)
X_test_sfs = sfs.transform(X_test_std)
param_grid = {'n_density': range(2, 20)}
grid = GridSearchCV(estimator=AdaptiveKNNClassifier(),
param_grid=param_grid,
cv=5,
refit=True,
random_state=42)
grid.fit(X_train_sfs, y_train)
knn_best = grid.best_model
X_concat = np.concatenate((X_train_sfs, X_test_sfs))
y_concat = np.concatenate((y_train, y_test))
fig = plt.figure(figsize=(10, 5))
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2)
dec = DecisionRegion(knn_best, X_concat, y_concat)
dec.plot(ax=ax1)
conf = ConfusionMatrix(y_concat, knn_best.predict(X_concat))
conf.plot(ax=ax2, show=True)
# Best params: {'n_density': 5}
# Best score: 0.9583333333333334
The Adaptive k-NN Classifier is particularly useful in scenarios where data points are unevenly distributed across the feature space, such as:
For those interested in exploring beyond the basics of the Adaptive k-NN Classifier, the following topics are recommended:
- Cover, T., and Hart, P. "Nearest neighbor pattern classification." IEEE transactions on information theory 13.1 (1967): 21-27.
- Hastie, T., Tibshirani, R., and Friedman, J. "The Elements of Statistical Learning." Springer Series in Statistics (2009).
- Samworth, R. "Optimal weighted nearest neighbour classifiers." Annals of Statistics 39.5 (2011): 2733-2763.