K-近邻(K-NN)算法的原理与实现
字数 1333 2025-11-25 10:01:24
K-近邻(K-NN)算法的原理与实现
题目描述
K-近邻(K-Nearest Neighbors, K-NN)是一种基本的分类与回归方法。其核心思想是:给定一个测试样本,在训练集中找到与之最相似的K个样本(即“近邻”),然后根据这K个样本的标签(分类问题中投票,回归问题中取均值)来预测测试样本的标签。K-NN是一种懒惰学习(lazy learning)算法,没有显式的训练过程。
解题过程循序渐进讲解
1. 算法核心思想
- 相似度度量:通常使用欧氏距离(Euclidean Distance)计算样本间的相似度。对于两个n维向量 \(x_i = (x_{i1}, x_{i2}, ..., x_{in})\) 和 \(x_j = (x_{j1}, x_{j2}, ..., x_{jn})\),欧氏距离公式为:
\[ d(x_i, x_j) = \sqrt{\sum_{k=1}^{n}(x_{ik} - x_{jk})^2} \]
- 投票机制:在分类问题中,对K个近邻的标签进行统计,将出现次数最多的标签作为预测结果(多数表决)。
- K值选择:K是超参数,需通过交叉验证确定。K太小容易过拟合,太大可能欠拟合。
2. 算法步骤详解
- 输入:训练数据集 \(D = \{(x_1, y_1), (x_2, y_2), ..., (x_N, y_N)\}\),其中 \(x_i\) 是特征向量,\(y_i\) 是标签;测试样本 \(x\);近邻数 \(K\)。
- 步骤:
- 计算距离:计算测试样本 \(x\) 与训练集中每个样本 \(x_i\) 的距离 \(d(x, x_i)\)。
- 排序:将距离按升序排序,选出距离最小的K个训练样本。
- 投票/平均:
- 分类问题:统计K个样本中每个标签的出现次数,取次数最多的标签作为预测结果。
- 回归问题:取K个样本标签的均值作为预测结果。
- 输出:预测标签 \(y\)。
3. 关键问题与优化
- 距离度量选择:除欧氏距离外,可根据数据特性选择曼哈顿距离、余弦相似度等。
- 特征标准化:若特征量纲差异大,需先进行标准化(如Z-score标准化),避免某些特征主导距离计算。
- 高效查找近邻:暴力计算所有距离的复杂度为 \(O(N)\)(N为训练样本数),难以应对大规模数据。常用优化方法:
- KD树(KD-Tree):对训练数据构建二叉树结构,将搜索复杂度优化至 \(O(\log N)\)(低维数据)。
- 球树(Ball Tree):适用于高维数据,通过球形区域划分数据。
- 局部敏感哈希(LSH):近似算法,牺牲精度换取速度,适用于海量数据。
4. 代码实现示例(Python)
import numpy as np
from collections import Counter
class KNN:
def __init__(self, k=3):
self.k = k
def fit(self, X, y):
self.X_train = X
self.y_train = y
def predict(self, X):
predictions = [self._predict(x) for x in X]
return np.array(predictions)
def _predict(self, x):
# 计算所有距离
distances = [np.linalg.norm(x - x_train) for x_train in self.X_train]
# 取K个最近邻的索引
k_indices = np.argsort(distances)[:self.k]
k_labels = [self.y_train[i] for i in k_indices]
# 多数表决
most_common = Counter(k_labels).most_common(1)
return most_common[0][0]
5. 算法特点与应用场景
- 优点:简单易实现,无需训练过程,对异常值不敏感。
- 缺点:计算开销大(需存储全部训练数据),对高维数据效果差(维度灾难)。
- 应用:推荐系统、图像分类、异常检测等。
总结
K-NN通过局部相似性进行预测,其效果依赖于K值选择、距离度量和数据预处理。在实际应用中,需结合KD树等结构优化性能,并注意维度灾难问题。