Skip to content

k-近邻与距离度量

1. k-NN:最简单也最深刻的分类器

k-近邻(k-Nearest Neighbors, k-NN)是一种非参数、基于实例的学习算法。它没有显式的训练过程——所有计算都在预测时发生,因此也被称为惰性学习(Lazy Learning)

k-NN 的核心思想极其朴素:"近朱者赤,近墨者黑"。一个样本的类别,由离它最近的 k 个邻居的类别通过投票决定。

1.1 算法流程

给定训练集 D={(x1,y1),(x2,y2),,(xn,yn)} 和一个测试样本 xtest

  1. 计算 xtest 与所有训练样本的距离 d(xtest,xi)
  2. 选出距离最近的 k 个训练样本 Nk(xtest)
  3. 分类:多数投票(Majority Voting)
y^=argmaxcC(xi,yi)Nk(xtest)I(yi=c)
  1. 回归:取 k 个邻居目标值的平均
y^=1k(xi,yi)Nk(xtest)yi

其中 I() 是指示函数,C 是所有可能的类别。

k-NN 分类示意图:展示测试样本(问号标记)与  和  的不同决策结果,直观说明 k 值的影响

1.2 距离加权 k-NN

基础投票中,每个邻居的权重相等。但在实际应用中,距离更近的邻居应该拥有更大的话语权。距离加权 k-NN(Distance-Weighted k-NN)给每个邻居一个与距离反比的权重:

y^=argmaxc(xi,yi)NkwiI(yi=c)

最常见的权重函数是反距离权重

wi=1d(xtest,xi)+ε

其中 ε 是一个极小的正数(如 106),防止除零。另一个常用选择是高斯权重

wi=exp(d(xtest,xi)22σ2)

k 选得足够大时,距离加权 k-NN 等价于一个局部加权核密度估计

1.3 k 值的影响

k 是 k-NN 最重要的超参数:

  • k 太小(如 k=1):决策边界极度曲折,对噪声敏感,低偏差高方差(过拟合)
  • k 太大(如 k=n):决策边界过于平滑,把所有样本都预测为多数类,高偏差低方差(欠拟合)
  • 实践经验:通常取 k=n 或通过交叉验证选择

k 值对决策边界的影响:三栏对比 (复杂边界)/ (适中边界)/ (平滑边界)


2. 距离度量:如何定义"近邻"

选择不同的距离度量会得到不同的近邻集合,从而影响最终的分类/回归结果。以下是四种最常用的距离。

2.1 欧氏距离(Euclidean Distance)

最直观的距离——两点之间的直线距离:

dEuc(x,y)=i=1m(xiyi)2=xy2

欧氏距离假设所有特征同等重要,且各维度之间各向同性(isotropic)。当特征之间的尺度差异很大时,大尺度特征会主导距离计算,因此通常需要先做标准化(Standardization)

2.2 曼哈顿距离(Manhattan Distance)

也称为 L1 距离或城市街区距离——在只能沿坐标轴方向移动的空间中测量:

dMan(x,y)=i=1m|xiyi|=xy1

曼哈顿距离比欧氏距离对异常值更鲁棒(不平方放大差异),在高维空间中有时能提供比欧氏距离更好的近邻关系。

2.3 余弦距离(Cosine Distance)

度量两个向量方向的差异,忽略它们的长度

dCos(x,y)=1cos(θ)=1xyx2y2

余弦距离广泛用于文本分析、推荐系统等信息检索领域。因为文本向量通常用 TF-IDF 或词袋模型表示,两个文档的方向相似比长度相似更有意义——长文档和短文档讨论同一主题时,方向一致但长度可能差很多。

2.4 马氏距离(Mahalanobis Distance)

马氏距离考虑了特征之间的相关性各维度的方差,通过数据协方差矩阵来"校正"尺度:

dMah(x,y)=(xy)TΣ1(xy)

其中 Σ 是数据的协方差矩阵。马氏距离等价于:先将数据变换到一个各向同性的空间(白化),再在该空间中计算欧氏距离。

马氏距离的核心优点:尺度不变性和相关性修正。如果两个特征高度相关,欧氏距离会在该方向上重复计算,而马氏距离通过 Σ1 消去了这种冗余。

四种距离度量的几何直观对比:欧氏(圆)、曼哈顿(菱形)、余弦(角度)、马氏(椭圆),展示各单位距离轮廓(等距线)


3. 维数灾难(Curse of Dimensionality)

3.1 直觉:高维空间中的距离失效

k-NN 严重依赖"距离"的概念,但在高维空间中,距离的概念会逐渐失效

假设数据均匀分布在一个 d 维单位超立方体 [0,1]d 中。要覆盖总体积的 f 比例(如 10%),需要的超立方体边长 ed(f) 为:

ed(f)=f1/d

d=1 时,e1(0.1)=0.1(10% 长度覆盖 10% 体积) 当 d=10 时,e10(0.1)=0.10.10.80

在 10 维空间中,要覆盖 10% 的数据,需要每条边取 80% 的长度!换句话说,几乎所有点都彼此远离——"近邻"的概念失去了意义。

3.2 最小/最大距离之比趋近 1

在高维空间中,任意两点之间的最大距离和最小距离之间的差异会急剧缩小:

limdmaxi,jd(xi,xj)mini,jd(xi,xj)mini,jd(xi,xj)=0

这意味着所有点之间的距离几乎相等。当所有距离都一样时,k-NN 的分类效果退化到随机猜测。

3.3 降维与特征选择

应对维数灾难的主要策略:

  • PCA / t-SNE / UMAP:将高维数据投影到低维流形,尽量保留近邻关系
  • 特征选择:通过互信息、卡方检验等方法剔除不相关特征
  • 稀疏正则化:L1 正则化使部分特征权重为零,实现嵌入式特征选择

维数灾难示意:对比低维()近邻有效和高维()所有距离趋同的两种情况


4. 加速搜索:k-d 树与 Ball 树

暴力搜索的复杂度为 O(nd)n 个样本,d 维特征),当 n 很大时效率低下。两种主流的空间索引结构可以加速近邻搜索。

4.1 k-d 树(k-dimensional Tree)

k-d 树是一种二叉树结构,每个节点对应 k 维空间中的一个超矩形区域。

构建过程

  1. 选择方差最大的维度作为分割维度
  2. 在该维度上取中位数点作为分割点
  3. 左子树包含小于中位数的点,右子树包含大于中位数的点
  4. 递归直到区域中点数少于阈值

查询过程(平均 O(logn),最坏 O(n)):

  1. 从根节点沿树向下走,根据分割维度确定目标点所属的子树
  2. 到达叶节点后,计算当前最近距离
  3. 回溯:检查兄弟节点对应的区域是否可能与当前最近距离相交
  4. 如果有交集,递归搜索兄弟子树;否则剪枝

k-d 树结构示意:二维空间划分和对应的二叉树结构

局限性:当维度 d>20 时,k-d 树的性能急剧下降,因为"超矩形相交"的情况频繁出现,导致大量回溯,最终退化到 O(n)

4.2 Ball 树

Ball 树使用**超球体(ball)**而不是超矩形来划分空间,在高维场景下表现更好。

构建过程

  1. 找到距离最远的两个点作为"锚点"
  2. 将数据按离两个锚点的远近分为两个簇
  3. 对每个簇,计算最小包络球(圆心 + 半径)
  4. 递归直到球内点数少于阈值

查询优势:Ball 树使用三角不等式来判断是否需要搜索一个球。判断条件为 dcenterrball>dcurrent_best,如果成立则可安全跳过此球中的所有点。

Ball 树在高维空间中的剪枝效率高于 k-d 树,是 sklearn 中 BallTree 的实现基础。

算法空间划分复杂度(查询)适用维度优点
暴力搜索O(nd)不限实现简单,精确
k-d 树超矩形平均 O(logn)d20低维时效率极高
Ball 树超球体平均 O(logn)d100比 k-d 树更适应高维
LSH哈希桶近似 O(1)可极高维牺牲精度换速度

5. 从零实现 k-NN

5.1 核心实现思路

python
class KNNClassifier:
    def __init__(self, k=3, metric='euclidean', weights='uniform'):
        self.k = k
        self.metric = metric
        self.weights = weights
    
    def fit(self, X, y):
        self.X_train = X
        self.y_train = y
    
    def predict(self, X_test):
        # 对每个测试样本:
        # 1. 计算到所有训练样本的距离矩阵
        # 2. 找出最近的 k 个训练样本索引
        # 3. 投票或取平均
        # 4. 如果 weights='distance',用反距离权重加权

k-NN 的 "training"(fit)只需存储数据——这就是惰性学习的本质。

5.2 距离度量的 NumPy 实现

欧氏距离(向量化):

python
# X_test: (m, d), X_train: (n, d)
# distances: (m, n)
distances = np.sqrt(
    np.sum(X_test**2, axis=1, keepdims=True) +   # (m, 1)
    np.sum(X_train**2, axis=1) -                  # (n,)
    2 * X_test @ X_train.T                        # (m, n)
)

这个展开公式来自 (ab)2=a2+b22ab,避免了显式广播,内存效率更高。

曼哈顿距离

python
distances = np.sum(np.abs(X_test[:, np.newaxis, :] - X_train), axis=2)

余弦距离

python
norm_test = np.linalg.norm(X_test, axis=1, keepdims=True)
norm_train = np.linalg.norm(X_train, axis=1)
cos_sim = (X_test @ X_train.T) / (norm_test @ norm_train[np.newaxis, :])
distances = 1 - cos_sim

5.3 决策边界可视化

二维数据上,k-NN 的决策边界由 Voronoi 图决定。对于均匀权重,决策边界是分段线性的;对于 k>1 的投票机制,边界变得更加平滑。

通过在不同 k 值下绘制决策边界,可以直观理解 k 值的正则化效果:k=1 时边界紧贴每个训练样本(过拟合),k 增大后边界逐渐平滑。


本章总结

概念公式/描述关键点
k-NN 分类y^=argmaxcNkI(yi=c)多数投票,惰性学习
k-NN 回归y^=1kNkyi近邻均值
距离加权wi=1/(di+ε)近邻权重大,远邻权重小
欧氏距离d=(xiyi)2L2 范数,各向同性
曼哈顿距离d=|xiyi|L1 范数,对异常值鲁棒
余弦距离d=1xy|x||y|度量方向差异,忽略大小
马氏距离d=(xy)TΣ1(xy)考虑特征相关性
维数灾难ed(f)=f1/d高维空间中所有点都远离
k-d 树二叉树 + 超矩形剖分低维高效,d20
Ball 树聚类 + 超球体剖分中高维优于 k-d 树
k 值选择n 或交叉验证小 k:过拟合;大 k:欠拟合

参考

  1. Cover, T., & Hart, P. (1967). Nearest neighbor pattern classification. IEEE Transactions on Information Theory, 13(1), 21-27.
  2. Fix, E., & Hodges, J. L. (1951). Discriminatory analysis, nonparametric discrimination: Consistency properties. USAF School of Aviation Medicine, Report No. 4.
  3. Friedman, J. H., Baskett, F., & Shustek, L. J. (1975). An algorithm for finding nearest neighbors. IEEE Transactions on Computers, C-24(10), 1000-1006.
  4. Hastie, T., Tibshirani, R., & Friedman, J. (2009). The Elements of Statistical Learning (2nd ed.). Springer. DOI: 10.1007/978-0-387-84858-7
  5. Bishop, C. M. (2006). Pattern Recognition and Machine Learning. Springer. DOI: 10.1007/978-0-387-45528-0
  6. Omohundro, S. M. (1989). Five balltree construction algorithms. ICSI Technical Report.
  7. Mahalanobis, P. C. (1936). On the generalized distance in statistics. Proceedings of the National Institute of Sciences of India, 2(1), 49-55.
  8. Bellman, R. E. (1961). Adaptive Control Processes. Princeton University Press. DOI: 10.1515/9781400874668(维数灾难概念的起源)
  9. Duda, R. O., Hart, P. E., & Stork, D. G. (2001). Pattern Classification (2nd ed.). Wiley.
  10. Liu, T., Moore, A. W., & Gray, A. (2006). New algorithms for efficient high-dimensional nonparametric classification. Journal of Machine Learning Research, 7, 1135-1158. arXiv: cs/0605089

📥 Code

下一章: ml02 贝叶斯决策理论


小贴士:运行前请确保已安装依赖:

bash
pip install numpy matplotlib scikit-learn