zoukankan      html  css  js  c++  java
  • 1. K近邻算法(KNN)

    1. K近邻算法(KNN)

    2. KNN和KdTree算法实现

    1. 前言

    K近邻法(k-nearest neighbors,KNN)是一种很基本的机器学习方法了,在我们平常的生活中也会不自主的应用,就是“物以类聚,人以群分”。比如,我们判断一个人的人品,只需要观察他来往最密切的几个人的人品好坏就可以得出了。这里就运用了KNN的思想。KNN方法既可以做分类,也可以做回归,这点和决策树算法相同。

    KNN做回归和分类的主要区别在于最后做预测时候的决策方式不同。KNN做分类预测时,一般是选择多数表决法,即训练集里和预测的样本特征最近的K个样本,预测为里面有最多类别数的类别。而KNN做回归时,一般是选择平均法,即最近的K个样本的样本输出的平均值作为回归预测值。由于两者区别不大,虽然本文主要是讲解KNN的分类方法,但思想对KNN的回归方法也适用。本文后面主要介绍的是KNN的分类问题。

    2. KNN算法原理

    给定一个训练集,对新输入的实例,在训练集中找到与该实例最邻近的k个实例,这k个实例的多数属于某个类,我们就把该输入实例分为这个类。
    image

    2.1 算法描述

    输入:训练数据集(T={(x_1,y_1),(x_2,y_2),...,(x_N,y_N)}),其中(x_iin{chi})为实例的特征向量,(y_iin{{c_1,c_2,...,c_m}})为实例的类别;实例特征向量x

    输出:实例x所属的类别y

    1. 根据给定的距离度量方式,在训练集T中找到与x最邻近的k个点,涵盖着k个点的x的领域记住(N_k(x))
    2. (N_k(x))中根据分类决策规则决定x的类别y

    [y=argmax_{c_j}sum_{x_iin{N_k(x)}}I(y_i=c_j) ]

    其中(I(y_i=c_j))为指示函数,当(y_i=c_j)的时候(I=1),后者(I=0)

    3. KNN的基本要素

    对于一个确定的训练集,只要确定了距离度量、k值和分类决策规则,就能对任何一个新的实例,确定它的分类。

    3.1 距离度量

    距离度量是描述特征空间中两个实例的距离,也是这两个实例的相似程度。在n维实数向量空间中,我们主要使用的距离度量方式是欧式距离,但也可以使用更加一般化(L_p)距离(闵可夫斯基距离)。

    在特征空间中,取出两个特征(x_i)(x_j),它们分别是n维的特征向量。

    3.1.1 欧氏距离

    [L_2(x_i,x_j)=(sum_{l=1}^n|x_i^l-x_j^l|)^{frac{1}{2}} ]

    3.1.2 曼哈顿距离

    [L_1(x_i,x_j)=sum_{l=1}^n|x_i^l-x_j^l| ]

    3.1.3 闵可夫斯基距离

    [L_p(x_i,x_j)=(sum_{l=1}^n|x_i^l-x_j^l|)^{frac{1}{p}} ]

    从上式可以看出,欧氏距离和曼哈顿距离分别是闵可夫斯基距离的((p=2,p=1))特殊情况

    3.2 k值的选择

    对于k值的选择,没有一个固定的经验,一般根据样本的分布,选择一个较小的值,然后通过交叉验证选择一个合适的k值

    • 选择较小的k值,就相当于用较小的领域中的训练实例进行预测,训练误差会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是泛化误差会增大。换句话说,k值的减小就意味着整体模型变得复杂,容易发生过拟合。
    • 选择较大的k值,就相当于用较大领域中的训练实例进行预测,其优点是可以减少泛化误差,但缺点是训练误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误。换句话说,k值的增大就意味着整体的模型变得简单,容易发生欠拟合。

    一个极端是k等于样本数m,则完全没有分类,此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的类,模型过于简单。

    3.3 分类决策规则

    对于分类决策规则,一般都是使用前面提到的多数表决法。

    4. kd树

    KNN算法最简单的实现方式,就是好计算输入实例和所有训练实例的距离,然后进行排序,取前k个,进行分类。但是训练集特别大的时候,这种方式非常耗时,不可行。下面介绍kd树的方式,kd树是通过减少输入实例和训练实例的计算次数来达到优化的目的。

    kd树算法包括三步,第一步是建树,第二部是搜索最近邻,最后一步是预测。

    4.1 构造kd树

    kd树是一种对n维空间的实例点进行存储,以便对其进行快速检索的树形结构。kd树是二叉树,构造kd树相当于不断的用垂直于坐标轴的超平面将n维空间进行划分,构成一系列的n维超矩阵区域。

    我们首先来看建树的方法。kd树建树采用的是从m个样本的n维特征中,分别计算n个特征的取值的方差,用方差最大的第k维特征(n_k)来作为根节点。对于这个特征,我们选择特征nk的取值的中位数(n_{kv})对应的样本作为划分点,对于所有第k维特征的取值小于(n_{kv})的样本,我们划入左子树,对于第k维特征的取值大于等于(n_{kv})的样本,我们划入右子树,对于左子树和右子树,我们采用和刚才同样的办法来找方差最大的特征来做更节点,递归的生成kd树。

    下面的流程图更加清晰的描述了kd树的构建过程:

    image

    构建好的kd树,大概如下:

    image

    4.2 kd树搜索最近邻

    当我们生成kd树以后,就可以去预测测试集里面的样本目标点了。预测的过程如下:

    1. 对于一个目标点,我们首先在kd树里面找到包含目标点的叶子节点。以目标点为圆心,以目标点到叶子节点样本实例的距离为半径,得到一个超球体,最近邻的点一定在这个超球体内部。
    2. 然后返回叶子节点的父节点,检查另一个子节点包含的超矩形体是否和超球体相交,如果相交就到这个子节点寻找是否有更加近的近邻,有的话就更新最近邻,并且更新超球体。如果不相交那就简单了,我们直接返回父节点的父节点,在另一个子树继续搜索最近邻。
    3. 当回溯到根节点时,算法结束,此时保存的最近邻节点就是最终的最近邻。

    从上面的描述可以看出,kd树划分后可以大大减少无效的最近邻搜索,很多样本点由于所在的超矩形体和超球体不相交,根本不需要计算距离。大大节省了计算时间。

    搜索过程,大致如下:

    image

    4.3 kd树预测

    有了kd树搜索最近邻的办法,kd树的预测就很简单了,在kd树搜索最近邻的基础上,我们选择到了第一个最近邻样本,就把它置为已选。在第二轮中,我们忽略置为已选的样本,重新选择最近邻,这样跑k次,就得到了目标的k个最近邻。然后根据多数表决法,如果是KNN分类,预测为k个最近邻里面有最多类别数的类别。如果是KNN回归,用k个最近邻样本输出的平均值作为回归预测值。

  • 相关阅读:
    洛谷 P1226 【模板】快速幂||取余运算 题解
    洛谷 P2678 跳石头 题解
    洛谷 P2615 神奇的幻方 题解
    洛谷 P1083 借教室 题解
    洛谷 P1076 寻宝 题解
    洛谷 UVA10298 Power Strings 题解
    洛谷 P3375 【模板】KMP字符串匹配 题解
    Kafka Shell基本命令
    Mybatis与Hibernate的详细对比
    MyBatis简介
  • 原文地址:https://www.cnblogs.com/huangyc/p/9716079.html
Copyright © 2011-2022 走看看