k k k近邻法是一种基本的分类方法。 k k k近邻法的输入为实例的特征向量,对应于特征空间的点;输出为实例的类别。 k k k近邻法实际上利用训练数据集对特征向量空间进行划分,并作为其分类的“模型”,所以说不具有显示的学习过程。 k k k值得选择、距离度量及分类决策规则是 k k k近邻法得三个基本要素。
输入:训练数据集
T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ , ( x N , y N ) } T =\{(x_1,y_1),(x_2,y_2),\cdots,(x_N,y_N)\} T={(x1,y1),(x2,y2),⋯,(xN,yN)}
其中, x i ∈ χ ⊆ R n x_i\in \chi \sube \bm{R}^n xi∈χ⊆Rn为实例的特征向量, y i ∈ Y = { c 1 , c 2 , ⋯ , c K } y_i\in Y= \{c_1,c_2,\cdots, c_K\} yi∈Y={c1,c2,⋯,cK}为实例的类别, i = 1 , 2 , ⋯ , N i=1,2,\cdots,N i=1,2,⋯,N。
输出:实例 x x x所属的类 y y y。
k k k近邻法的特殊情况是 k = 1 k=1 k=1的情形,称为最邻近算法。
k k k近邻模型的特征空间一般是 n n n维实数向量空间 R n \bm{R}^n Rn。使用的是欧氏距离,但也可是其他距离。如更一般的 L p L_p Lp距离。定义空间中两点 x 1 = ( x 1 1 , x 1 2 , ⋯ , x 1 n ) T , x 2 = ( x 2 1 , x 2 2 , ⋯ , x 2 n ) T x_1=(x_1^1,x_1^2,\cdots,x_1^n)^T,x_2=(x_2^1,x_2^2,\cdots,x_2^n)^T x1=(x11,x12,⋯,x1n)T,x2=(x21,x22,⋯,x2n)T的 L p L_p Lp距离定义为
L p ( x 1 , x 2 ) = ( ∑ l = 1 n ∣ x 1 l − x 2 l ∣ p ) 1 p L_p(x_1,x_2)=\left(\sum_{l=1}^{n}|x_1^l-x_2^l|^p\right)^\frac{1}{p} Lp(x1,x2)=(l=1∑n∣x1l−x2l∣p)p1
当 p = 2 p=2 p=2时,称为欧氏距离,当 p = 1 p=1 p=1时,称为曼哈顿距离。
k k k值得选择会对 k k k近邻法的结果产生重大影响。
如果选择较小的 k k k值,就相当于用较小的邻域中的训练实例进行预测,预测结果会对近邻的实例点非常敏感。如果临近的实例点恰巧是噪声,预测就会出错。换句话说, k k k值得减小就意味着整体模型变得复杂,容易发生过拟合。
如果选择较大的 k k k值,就相当于用较大邻域中的训练实例进行预测,这时与输入实例较远的(不相似的)训练实例也会对预测起作用,使预测发生错误。 k k k值的增大就意味着整体模型变得简单。
在应用中, k k k值一般取一个比较小的数值。通常采用交叉验证法来选取最优的 k k k值。
这里的分类决策规则就是多数表决,即由输入实例的 k k k个邻近的训练实力中的多数类决定输入实力的类。
通过上面的学习,我们就已经明白了 k k k近邻算法的具体步骤,这时你可以采用python等语言的编程实现 k k k近邻算法。
但是如果训练集中的实例的维数很大以及训练数据容量很大时,我们如果一一计算训练集中的实例点与预测点之间的欧氏距离,并且找出 k k k个近邻时计算非常耗时,这种方法是不可行的。为了提高 k k k近邻搜索的效率,可以考虑使用特殊的结构存储训练数据,以减少计算距离的次数。具体方法很多,这里介绍其中一种 k d kd kd树的方法。
构造平衡 k d kd kd树。
我们直接使用一个例子来展示如何构造 k d kd kd树。
给定一个二维空间的训练数据集
T = { ( 2 , 3 ) T , ( 5 , 4 ) T , ( 9 , 6 ) T , ( 4 , 7 ) T , ( 8 , 1 ) T , ( 7 , 2 ) T } T=\{(2,3)^T,(5,4)^T,(9,6)^T,(4,7)^T,(8,1)^T,(7,2)^T\} T={(2,3)T,(5,4)T,(9,6)T,(4,7)T,(8,1)T,(7,2)T}
构造一个平衡 k d kd kd树。
至此我们发现所有的区域中已经没有实例存在(也就是说没有实例点可以进行划分),所以停止 k d kd kd树的区域划分。
上一节我们已经介绍了如何构造 k d kd kd树,本节我们介绍如何使用 k d kd kd树进行最近邻搜索。
算法如下:
输入:已构造的 k d kd kd树,目标点 x x x。
输出: x x x的最近邻。
我们用一个实例来演示 k d kd kd树进行最近邻搜索的过程。目标点是 x ( 2 , 4.5 ) x(2,4.5) x(2,4.5),要找到 x x x的最近邻。
按照算法流程,第一步结束后,我们移动到 ( 4 , 7 ) (4,7) (4,7)点。移动路径是: ( 7 , 2 ) − ( 5 , 4 ) − ( 4 , 7 ) (7,2)-(5,4)-(4,7) (7,2)−(5,4)−(4,7)。
第二步:令叶节点 ( 4 , 7 ) (4,7) (4,7)为当前最近点 o o o。目标点与最近点 o o o的距离是为3.202。
第三步:递归向上回退,回退到 ( 5 , 4 ) (5,4) (5,4)点。(a)目标点与(5,4)之间的距离为:3.041,所以 ( 5 , 4 ) (5,4) (5,4)点比当前最近点 o o o距离目标点 x x x更近,则更新当前最近点 o o o为 ( 5 , 4 ) (5,4) (5,4)。(b)以目标点 x x x为圆心,以目标点与“当前最近点 o o o”间的距离为半径的圆与当前最近点 o ( 5 , 4 ) o(5,4) o(5,4)的另一个子节点 ( 2 , 3 ) (2,3) (2,3)对应的区域相交。所以我们移动到 ( 2 , 3 ) (2,3) (2,3)点, ( 2 , 3 ) (2,3) (2,3)点距离目标点比当前的最近点 o ( 5 , 4 ) o(5,4) o(5,4)要近,所以最近点o更新为 ( 2 , 3 ) (2,3) (2,3)。接着继续往上回退为 ( 7 , 2 ) (7,2) (7,2)点, ( 7 , 2 ) (7,2) (7,2)点距离目标点比 ( 2 , 3 ) (2,3) (2,3)点距离目标点要远。
第四步:回退到根结点,搜索结束。此时最近点 o ( 2 , 3 ) o(2,3) o(2,3)为目标点 x ( 2 , 4.5 ) x(2,4.5) x(2,4.5)的最近邻点。
整体的思路大概就是;
代码链接:https://github.com/zgaxddnhh/lihang-code
参考书籍:机器学习方法.李航