1. 介绍
    1. 定义
    2. 起源
    3. 优点
    4. 缺点
    5. 应用领域
  2. 相关
  3. 解法
  4. 实现
    1. Python
  5. 应用
  6. 参考

K-Nearest Neighbor algorithm K最邻近结点算法

介绍

定义

  在模式识别领域中,最近邻居法(k-Nearest Neighbors algorithm,KNN算法,又译K-近邻算法)12是一种用于分类和回归的非参数统计方法。

  • k-NN分类

    输入:包含特征空间中的 k 个最接近的训练样本。

    输出:一个分类族群。

  • k-NN回归

    输入:包含特征空间中的 k 个最接近的训练样本。

    输出:该对象的属性值。该值是其 k 个最近邻居的值的平均值。

起源

  TODO

优点

  1. 简单,易于理解,易于实现,无需估计参数,无需训练;
  2. 适合对稀有事件进行分类;
  3. 特别适合于多分类问题(multi-modal,对象具有多个类别标签)。

缺点

  1. 主要的不足:当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。 该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。
  2. 计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。
  3. 可理解性差,无法给出像决策树那样的规则。

应用领域

  文本分类,聚类分析,数据挖掘,机器学习,预测分析,减少维度,模式识别,图像处理

相关

  然而k最近邻居法因为计算量相当的大,所以相当的耗时,Ko与Seo提出一算法TCFP(text categorization using feature projection),尝试利用特征投影法来降低与分类无关的特征对于系统的影响,并借此提升系统效能,其实实验结果显示其分类效果与k最近邻居法相近,但其运算所需时间仅需k最近邻居法运算时间的五十分之一。

  除了针对文件分类的效率,尚有研究针对如何促进k最近邻居法在文件分类方面的效果,如Han等人于2002年尝试利用贪心法,针对文件分类实做可调整权重的k最近邻居法WAkNN(weighted adjusted k nearest neighbor),以促进分类效果;而Li等人于2004年提出由于不同分类的文件本身有数量上有差异,因此也应该依照训练集合中各种分类的文件数量,选取不同数目的最近邻居,来参与分类。

解法

  • 思路

    如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。

  • 步骤

    1. 准备数据,对数据进行预处理
    2. 选用合适的数据结构存储训练数据和测试元组
    3. 设定参数,如k
      4.维护一个大小为k的的按距离由大到小的优先级队列,用于存储最近邻训练元组。随机从训练元组中选取k个元组作为初始的最近邻元组,分别计算测试元组到这k个元组的距离,将训练元组标号和距离存入优先级队列
    4. 遍历训练元组集,计算当前训练元组与测试元组的距离,将所得距离L 与优先级队列中的最大距离Lmax
    5. 进行比较。若L>=Lmax,则舍弃该元组,遍历下一个元组。若L < Lmax,删除优先级队列中最大距离的元组,将当前训练元组存入优先级队列。
    6. 遍历完毕,计算优先级队列中k 个元组的多数类,并将其作为测试元组的类别。
    7. 测试元组集测试完毕后计算误差率,继续设定不同的k值重新进行训练,最后取误差率最小的k 值。

实现

Python

  • Scikit-Learn

    http://scikit-learn.org/stable/modules/neighbors.html

    KNN分类器使用sklearn.neighbors.KNeighborsClassifier,参数设置参考 http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html

    • knn_classification_example.py

      1
      2
      3
      4
      5
      6
      7
      8
      X = [[0, 100], [1, 99], [99, 1], [100, 0]]
      y = [0, 0, 1, 1]
      from sklearn.neighbors import KNeighborsClassifier
      classifier = KNeighborsClassifier(n_neighbors=3)
      classifier.fit(X, y)
      print(classifier.predict([[10, 90], [90, 10]]))
      print(classifier.predict_proba([[10, 90], [90, 10]]))
      print(classifier.kneighbors([[10, 90], [90, 10]], return_distance=False))

    • output

      1
      2
      3
      4
      5
      6
      7
      8
      >>> print(classifier.predict([[10, 90], [90, 10]]))
      [0 1]
      >>> print(classifier.predict_proba([[10, 90], [90, 10]]))
      [[ 0.66666667 0.33333333]
      [ 0.33333333 0.66666667]]
      >>> print(classifier.kneighbors([[10, 90], [90, 10]], return_distance=False))
      [[1 0 2]
      [2 3 1]]

    KNN回归器使用sklearn.neighbors.KNeighborsRegressor,参数设置参考 http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsRegressor.html

    • knn_regression_example.py

      1
      2
      3
      4
      5
      6
      X = [[0], [1], [2], [3]]
      y = [0, 0, 1, 1]
      from sklearn.neighbors import KNeighborsRegressor
      regressor = KNeighborsRegressor(n_neighbors=2)
      regressor.fit(X, y)
      print(regressor.predict([[1.5]]))

    • output

      1
      [ 0.5]

应用

  TODO

参考


  1. https://zh.wikipedia.org/wiki/最近鄰居法↩︎

  2. http://baike.baidu.com/view/1485833.htm↩︎