第三章 k近邻法

三、k近邻法

  • K-NN是一个基本的分类和回归方法,此处讨论基本的分类问题
  • 输入为实例的特征向量,对应于特征空间的点,输出是实例的类别,可以取多个类
  • k近邻是假设给定训练数据集,其中的实例类别已定,分类时根据k个最近邻的训练实例类别通过多数表决的方式进行预测,并没有显式的学习过程
  • k值的选择距离度量分类决策规则是k近邻法的3个基本要素

3.1 k近邻算法

  • 特殊的情况是k=1时,此时为最近邻算法
  • k近邻算法没有显式的学习过程

image-20241005120215675

3.2 k近邻模型与决策规则

3.2.1 模型

  • k近邻模型主要有3个基本要素:距离度量、k值选择和分类决策规则,确定好上述后,给定一个输入实例,就可以唯一地确定它所属类
  • 在特征空间当中,每一个训练实例点xi,距离该点比其他点更近的所有点组成的一个区域叫做单元(cell),一个单元构成对于特征空间的一个划分
    • 最近邻算法是实例xi的类yi作为其单元中所有点的类标记(class label),从而每个单元实例点的类别可以确定,见下图所示

image-20241005121126530

3.2.2 距离度量

  • 两个实例点的距离反应的是两个实例点的相似程度,k近邻特征空间一般是R^n,距离使用的是欧式距离,但更一般的是Lp距离Minkowski距离,定义如下
    • 当p=2时,为欧式距离,当p=1时,为曼哈顿距离,当p=∞时,就是得到坐标距离的最大值

image-20241005121408621

给出一个计算最近邻点的例子

image-20241005121556537

  • 这里需要注意的是,实际应用的时候我们需要进行归一化后,数据特征才会有意义
    • 比如(5, 10000)和(1, 10000)的数据,直接使用距离度量比较,x的偏移特征将会微乎其微

3.2.3 k值选择

  • k值是一个超参数,后续在做实验的时候,特征工程是关键一环
  • k值如果过小,那么几何意义上就是用较小的邻域来进行预测,近似误差过小,模型会过于复杂,容易过拟合
  • k值如果过大,那么几何意义上就是用较大的邻域来进行预测,近似误差过大,模型会过于简单,容易欠拟合
  • 一般我们会选择先取一个较小值,然后使用交叉验证法来选取最优的k值

3.2.4 分类决策规则

  • 往往采用多数表决机制,即选取k个近邻实例中多数的类别,这等价于经验风险最小化,数学解释如下

image-20241005122232282

3.3 k近邻算法实现_kd树

  • 实现k近邻算法最简单的方式是线性扫描,但需要计算输入实例和每个训练实例的距离,训练集大时,计算会很耗时,因此不可行
  • 所以提出使用k近邻算法提高k近邻搜索的效率

3.3.1 构造kd树

  • kd树是一个二叉树,表示对k维空间的一个划分,构造kd树相当于不断地使用垂直于坐标轴的超平面将k维空间切分,构成一系列k维超矩形区域,kd树的一个结点对应于一个k维超矩形的区域
  • 构造kd树的方法
    • 构造根节点,对应于包含所有实例点的超矩形区域
    • 通过下述方式进行递归,不断的对k维空间进行切分,生成子结点
      • 选择一个坐标轴,通过选定的切分点并垂直于选定的坐标轴上的切分点,确定一个超平面,该平面能够切分为左右两个子区域
        (通常是依次选择坐标轴,然后选择中位数切分,注意,平衡的kd树未必是最优)
      • 直至最终子区域没有节点为止,此时终止的结点为叶子节点

image-20241005162609554

给出一个具体的例子

image-20241005162644745

3.3.2 搜索kd树

最近邻搜索

以最近邻为例加以描述,我们的目标是给定目标点,搜索最近邻

  • 首先需要找到包含目标点的叶子结点,然后从叶子节点触发,依次回退到父节点
  • 不断查找与目标点最邻近的节点,当确定不可能存在更近的结点时终止,这样搜索就会限制在空间的局部空间上,效率大幅提高

如下图所示,包含目标点的叶子结点对应于目标点的最小超矩形区域,目标点的最邻近一定是在以目标点为中心并通过当前点的超球体的内部,分为如下情况

  • 如果父结点的另一节点的超矩形区域于超球体相交,那么在相交区域会寻找是否存在更近的实例点,如果存在,就将该点作为新的最近点,转到更上一级的父节点
  • 如果父结点另一结点超矩形区域与超球体不相交,那么不存在比当前点更近的点,停止搜索

具体的算法描述如下:

image-20241005163858241

上述图片的例子

image-20241005164024476

image-20241005163419093

k近邻搜索

对于一般情况下 k近邻的算法详细搜索过程可见:https://zhuanlan.zhihu.com/p/23966698

核心算法思路:一开始我们先 设 L 为一个有 k 个空位的列表,用于保存已搜寻到的最近点。

  • 一、根据 p 的坐标值和每个节点的切分向下搜索(也就是说,如果树的节点是照 xr=a 进行切分,并且 p 的 r 坐标小于 a,则向左枝进行搜索;反之则走右枝)。
  • 二、当达到一个底部节点时,将其标记为访问过,然后根据下述规则判断是否加入列表。
    • 如果 L 里不足 k 个点,则将当前节点的特征坐标加入 L ;
    • 如果 L 不为空并且当前节点的特征与 p 的距离小于 L 里最长的距离,则用当前特征替换掉 L 中离 p 最远的点。
  • 三、如果当前节点不是整棵树最顶端节点,执行 (a);反之,输出 L,算法完成。
    • a. 向上爬一个节点。如果当前(向上爬之后的)节点未曾被访问过,将其标记为被访问过,然后执行 (1) 和 (2);如果当前节点被访问过,再次执行 (a)。
      • \1. 首先根据列表的情况进行判断是否加入该节点
        • 如果此时 L 里不足 k 个点,则将节点特征加入 L;
        • 如果 L 中已满 k 个点,且当前节点与 p 的距离小于 L 里最长的距离,则用节点特征替换掉 L 中离最远的点。
      • \2. 计算 p 和当前节点切分线的距离(李航老师是根据超球体是否相交的方式判断,思路相同但实现不同)。
        • 如果该距离大于等于 L 中距离 p 最远的距离并且 L 中已有 k 个点,则在切分线另一边不会有更近的点,执行 (三);
        • 如果该距离 小于 L 中最远的距离 或者 L 中不足 k 个点,则切分线另一边可能有更近的点,因此在当前节点的另一个枝从 (一) 开始执行。

大概就探讨这个层面吧,暂时就不深究具体代码实现了,后续就是用现成的机器学习包 scikit-learn 来进行计算,做一名合格的调参侠

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值