k-NN是一种基本分类回归方法。k近邻法输出为实例类别,可以取多类
k-NN假定给定一个训练集,其中的实例类别已定。分类时,对于新实例,根据其k个最近邻的训练实例的类别,通过多数表决等方式预测。因此,k-NN不具有显式的学习过程
\(k\)的选择、距离度量及分类决策规则(如多数表决)是k-NN的三个基本要素
k-NN使用的模型实际上对应于对特征空间的划分。当训练集、距离度量、k值和分类决策规则确定后,对于任何一个新的输入实例,它所属的类唯一的确定。
K值的选择
- k值的减小:
- 减小“近似误差”,增大“估计误差”
- 整体模型变得复杂,临近点如果恰好是噪声,容易发生过拟合
- k值增大:
- 减小“估计误差”,增大“近似误差”
- 整体模型变得简单,容易欠拟合
- 极端情况\(k=N\)
- 取一个比较小的数值,通常采用交叉验证法来选取最优的\(k\)值
k-NN的实现:kd树
线性扫描:计算输入实例与每一个训练实例的距离,计算量太大
构造kd树
kd树是一种对k维空间中的实例点进行存储以便对其进行快速搜索的树形数据结构。kd树是二叉树,表示对k维空间的一个划分。构造kd树相当于不断地用垂直于坐标轴的超平面将k维空间切分,构成一系列的k维超矩形区域。kd树的每个节点对应于一个k维超矩形区域。
构造平衡kd树
平衡kd树(中位数作为切分点)不一定是搜索效率最优的
- 输入:数据集T,其中\(x_i=(x^{(1),\cdots,x^{(k)}})^T\)
- 输出:kd树
- 开始:构造根节点,根节点对应于包含\(T\)的k维空间的超矩形区域。选择\(x^{(1)}\)为坐标轴,以\(T\)中所有的实例的\(x^{(1)}\)坐标的中位数为且分点,将根节点对应的超矩形区域切分为左右两个子区域。将落在切分超平面上的点保存在根节点。
- 对深度为\(j\)的节点,选择\(x^{(l)}\)作为切分坐标轴,\(l=j(mod \ k)+1\)(依次选取各坐标轴),取该坐标轴实例的中位数作为切分点,继续切分。
- 直到两个子区域没有实例存在时停止,从而形成kd树的区域划分
搜索kd树
kd树的最近邻搜索算法:
- 输入:已构造好的kd树,目标点\(x\)
- 输出:\(x\)的最近邻
- 在kd树种找出包含目标点\(x\)的叶节点:从根节点出发,递归的向下访问。若目标点\(x\)当前维小于且分点坐标,则移动到左节点,否则移动到右节点。
- 以此叶节点作为“当前最近点”
- 递归向上回退,在每个节点进行如下操作:
- 如果该节点保存的实例点比当前最近点距离目标点近,则以该实例点为“当前最近点”
- 当前最近点一定存在于该节点一个子节点对应的区域,检查该子节点的父节点的另一子节点对应的区域是否有更近的点。具体地,检查另一子节点对应的区域是否与以目标点为球心,以目标点与“当前最近点”距离为半径的超球体相交。
- 如果相交,可能在另一个子节点对应的区域内存在距目标点更近的点,移动到另一个子节点,接着递归进行搜索。
- 如果不相交,向上回退
- 回退到根节点时,搜索结束。当前最近点即为\(x\)的最近邻点
如果实例点是随机分布的,kd树搜索的平均复杂度为\(O(\log N)\),\(N\)为训练样本数。kd树适合训练实例数远大于空间维数的情况。当空间维数接近实例数时,效率接近线性扫描