k 近邻法


k​​​​ 近邻法(knearest neighbor, kNN​​​​​​​)即可用于分类,也可用于回归。

KNN​ 做分类还是回归区别在预测时的决策方式。做分类时,用多数表决法;做回归时,用平均法。

sklearn-learn 中只使用了 蛮力实现(bruteforce​​)、kd​​ 树(KDTree​​)、球树(BallTree​​)。

本文只讨论 k​​​ 近邻法在分类问题上的应用。


一、k 近邻法

k​​​​ 近邻法思想:对于预测样本,在训练集中找到与该预测样本最邻近的 k​​​​​​ 个,这 k​​​​ 个样本的多数属于哪个类,就把该预测样本分为这个类。

k 近邻法中,当 k=1时,称为最近邻算法

输入:训练集:T=(x1,y1),(x2,y2),...,(xN,yN)i=1,2,,N

其中,xi​​ 为预测集样本, yiY={c1,c2,,cK}​​​​​ 为样本的类别​​。

输出:样本 xi​​ 所属类别 yi​​。

(1)根据给定的距离度量,在训练集 T​​​​ 中找出与 xi​​​​ 最近邻的 k​​​ 个点,涵盖这 k​​​ 个点的 xi​​​ 的邻域记作 Nk(xi)​​​。

(2)在 Nk(xi)​​ 中根据分类决策树规则(如多数表决)决定 xi​​ 的类别 yi​​​​。



二、k 近邻模型

k​​ 近邻模型三要素:距离度量、k​值的选择、分类决策规则


1. 距离度量

常用:曼哈顿距离、欧式距离、闵可夫斯基距离(曼哈顿距离是闵可夫斯基距离在 p=1​​ 的特例,欧式距离是p=2​​ 的特例)。

两个 n 维样本 xi=(xi(1),xi(2),...,xi(n))Txj=(xj(1),xj(2),...,xj(n))T

曼哈顿距离:

L1(xi,xj)=l=1n|xi(l)xj(l)|

欧式距离:

L2(xi,xj)=(l=1n|xi(l)xj(l)|2)12

闵可夫斯基距离:

Lp(xi,xj)=(l=1n|xi(l)xj(l)|p)1p

13个点 x1=(1,1)T​​,x2=(5,1)T​​,x3=(4,4)T​​,求 p​​ 取不同值时,距离 x1​ 的最近邻点。

解:因为 x1​​​​ 和 x2​​​​ 只有第一维的值不同, 所以 p​​​​ 为任何值时, Lp(x1,x2)=4​​​​ 。而 L1(x1,x3)=6

L2(x1,x3)=4.24L3(x1,x3)=3.78L4(x1,x3)=3.57​​​​​,

于是得到: p​​​​ 等于 1​​ 或 2​​ 时, x2​​ 是 x1​​ 的最近邻点;p​​ 大于等于 3 时, x3x1​​​​​ 的最近 邻点。


2. k 值的选择

k​​​ 值较小,会用较小的领域的数据来训练,训练误差减小;预测时数据也较少,如果近邻的样本恰巧是噪声,预测出错,估计误差增大。

k 值较大,训练误差增大,估计误差减小。

极端情况 k=N,无论测试集是什么,结果都是训练集中最多的类。

通常采用交叉验证法选取 k 值。


3. 分类规则

分类决策规则一般采用多数表决法


三、k 近邻法蛮力实现

计算预测样本和训练集中所有样本的距离,然后得到最小的 k​​​ 个距离即可,接着多数表决,做出预测。

该方法简单,适合样本量少,样本特征少的情况。


四、kd ​树

k 近邻法最简单的实现方法是线性扫描(即蛮力实现)。当训练集很大时,该方法不可行。为提高 k 近邻搜索效率,引入 kd​ 树。

kd 树就是 k 个特征维度的树。KNNk 表示 k 个样本,kd 树中 k 表示特征维数。

kd 树算法包括3步:第一建树、第二搜索最近邻、第三预测。


1. 构造 kd 树

构造 kd​​ 树方法:kd​​​ 树实质是二叉树,其切分点的选取与 CART​​ 树类似,即选取使样本复杂度降低最多的特征。kd​​​ 树认为特征方差越大,则该特征的复杂度越大,优先对该特征进行切分,切分点是样本在该特征的中位数。重复该切分步骤,直到切分后子区域无样本则终止切分,终止时的样本为叶结点。


2训练集 T=(2,3)T,(5,4)T,(9,6)T,(4,7)T,(8,1)T,(7,2)T ,构造 kd 树。

解:(1)找到切分特征。6个数据在第一个特征 x(1)、第二个特征 x(2) 的方差为 6.975.37,所以用 x(1) 构造 kd​ 树。

(2)确定切分点。6个数据在 x(1)​​ 的中位数是 7,所以切分点是(7,2)。​

(3)确定左、右子区域。以平面 x(1)=7​ 将空间划分为左、右两个子区域,{(2,3),(5,4),(4,7)}​、{(9,6),(8,1)}​。

如此递归,直到两个子区域没有样本存在时停止。得到特征空间划分(图3.3)和 kd 树(图3.4)。​


2. 搜索 kd 树

kd​ 树可以省去大部分数据点的搜索。

kd 树的最近邻搜索:

输入:kd 树,目标点 x​。

输出:x 的最近邻。

(1)kd 树中找出包含目标点 x 的叶结点

(2)以此叶结点为 “当前最近点”。

(3)递归地向上回退。在每个结点上进行以下操作:

  • 以目标点为圆心,目标点到叶结点的距离为半径,得到一个超球体,如果该超球体内的样本点比叶结点距离目标更近,则以该样本点为 ”当前最近点“。
  • 检查该叶结点的父结点的另一个子结点对应的区域是否有更近的点。具体地,检查另一子结点对应的超矩形体和超球体是否相交。如果相交,可能在超矩形体内存在距目标点更近的点,移动到另一个子结点。接着递归地进行最近邻搜搜。如果不想交,向上回退。
  • 当回退到根节点时,搜索结束。最后的 “当前最近点” 为 x 的最近邻点。

如果样本点是随机分布的,kd 树搜索的计算复杂度是 O(logN)N​ 是训练集样本数。

kd 树适用于训练集样本数远大于空间维数的 k​ 近邻搜索。当空间维数接近训练集样本数时,效率几乎接近线性扫描。


3​​​:如图 3.5​ 的 kd​ 树,根节点 A​,它的子结点为 B​、C​。树上总共 7 个样本点,目标点 S,求​ S 的最近邻。

解:kd 树中找到包含点 S 的叶结点 D , 以点 D 作为 近似最近邻。真正最近邻一定在以点 S 为中心通过点 D

的圆的内部。然后返回结点 D 的父结点 B, 在结点 B 的另一子结点 F 的区域内搜索最近邻。结点 F 的区域与圆

不相交, 不可能有最近邻点。继续返回上一级父结点 A, 在结点 A 的另一子结点 C 的 区域内搜索最近邻。结点 C

的区域与圆相交; 该区域在圆内的实例点有点 E, 点 E 比 点 D 更近, 成为新的最近邻近似。最后得到点 E 是点 S

的最近邻。


3. kd 树预测

kd​​​​ 树搜索最近邻时,选择第一个最近邻样本,把它置为已选。在第二轮选择中,忽略置为已选的样本,重新选择最近邻,这样跑 k 次,得到了 k 个最近邻,

如果是分类问题,根据多数表决法,预测为最多类别数的类别;

如果是回归问题,根据平均法,k 个最近邻样本的平均值作为回归预测值。



posted @   做梦当财神  阅读(746)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示