2019-06-04 | 统计学习方法笔记 | UNLOCK

读书笔记:k近邻

宏观层面

k近邻(k nearest neighbor, knn)算是一种简单的分类和回归算法,利用元素最近的k个值来决定自身的类别或回归值。

  • 分类问题,对新的样本,通过寻找离样本最近的k个样本,基于少数服从多数的原则确定当前样本的label
  • 回归问题,对新样本,通过寻找离样本最近的k个样本,计算k个样本对应值的平均值作为预测值

算法基本思想和原理是什么?

knn算法主要用于解决分类问题,属于非参数模型,没有显示的学习过程,k只是超参数。该算法主要关注三个问题,

  • k值的选择
    在knn算法中k是一个超参数,需要根据期望来进行不断调整.一般k值越小,意味着只寻找较少的样本值作为参考,极端情况下$k=1$,为最近邻算法,k值越小,偏差越小(只跟最近的几个值有关系),方差越大(受波动影响越大),模型越复杂,容易造成过拟合。预测值只跟最近的几个点有关系,如果最近点是噪声,则预测值很容易受到影响。如果k值增大,则预测结果偏差增大(预测值参考范围扩大)(增大学习的偏差),方差越小(波动变下),泛华能力提高。在实际使用中k值通常会选取一个很小的值,通过交叉验证法确定k值。

  • 距离度量方式
    度量方式是用来寻找k个最近邻的计算方式,常见的距离度量方式有公式为

    $x$为输入样本特征向量,共有$n$个维度。

    • $p=1$, 时为曼哈顿距离(Manhattan distance),
    • $p=2$, 欧几里得距离(Euclidean distance)
    • $p=\infty$,为各个坐标距离的最大值
  • 分类决策规则
    决策规则是指在寻找到最近k个样本之后,如何利用这些样本点的信息来预测当前样本的标签或值。

    • 少数服从多数,根据k个样本中出现类别数最都的类别作为预测类别,等价于经验风险最小化,$argmax\sum{I(y_i=c_i)}$
    • 少数服从多数,也可以根据距离远近对样本权重进行加权计算
  • 回归决策规则
    • 回归决策通常采用均值回归,也可以根据距离远近进行加权,距离近的权重高
    • 均值回归等价于经验风险最小化

个人理解是什么?

knn算法是最简单的分类和回归算法,没有显示的训练过程,只需要准备训练样本集,在预测时全部载入,根据预测样本进行搜索k个最近邻点,来觉得预测值。如果样本集特别大,这就存在搜索时间的问题,需要构建一个$M \times N$ 的矩阵,时间复杂度为$O(N^2)$, 当样本数据量为百万级别是,这个计算成本相当高,难易接受。因此需要对算法做一些优化。如下文所述kdtree。

微观层面:

公式详细推导过程是否领会和记忆?

  • k近邻分类算法

    输入:训练集

    其中,$x_i$为输入特征向量,维度为$d$, 类别$y = \{c_1, c_2,\cdots, c_M\}$,
    输出:给定待预测样本$x$,输出其对应类别
    步骤:
    (1) 根据给定的度量方式,在训练集$T$中,寻找k个最近点集$N_k(x)$
    (2) 在点集合中统计各个类别出现的次数,选择具有最多次数的类别$c$作为预测结果$y$返回,即

  • k近邻回归算法

    输入:训练集

    其中,$x_i$为输入特征向量,维度为$d$, 类别$y = \{c_1, c_2,\cdots, c_M\}$,
    输出:给定待预测样本$x$,输出其对应类别
    步骤:
    (1) 根据给定的度量方式,在训练集$T$中,寻找k个最近点集$N_k(x)$
    (2) 在点集合中计算样本y的均值,作为预测结果$y$返回,即

KDTree 算法实现

k近邻算法关键点是如何对训练集进行快速k近邻搜索。为了提高搜索效率,对训练集采用特殊结构进行存储,即kdtree.

  • kd tree 是一个二叉树,表示k维空间的一个划分
  • kd tree的构造等价不断的用垂直于坐标轴的超平面将k维空间切分

kd tree 构造

输入:k维空间数据集$T=\{x_1, x_2, \cdots, x_N\}$,其中$x_i=(x_1^{(1)}, x_1^{(2)}, \cdots, x_1^{(k)})$
输出: kd tree
(1) 开始构造跟节点
选择$x_1^{(1)}$所在坐标轴的中位数$x_1^{(1*)}$为切分点划分超平面,生成深度为1的左、右子节点

- 左子节点对应于$x_i^{(1)} < x_1^{(1*)}$的区域
- 右子节点对应于$x_i^{(1)} > x_1^{(1*)}$的区域

(2) 重复,对于深度为j的节点,选择$x^{(l)}$为切分坐标轴, $l=j (mod k) + 1$,以该坐标中位数作为切分点,切分之后树的深度变为j+1。这里之所以不用$l=j+1$来选择坐标轴,是因为树的深度j可能超过空间维度k,这样就轮转坐标轴进行切分。
(3) 递归直到左右两个子区域没有实例存在时停止。
备注:这种按照中坐标位数为切分点,构造出来的树为平衡二叉树,但搜索时的效率未必是最优的。

kd tree 搜索

输入:已构造的kd tree, 目标点$x$
输出:$x$的最近邻点(k近邻类似)
(1) 初始化,当前最近点$x_{nst}=null $, 最近点距离$d_{nst}= +\infty$
(2) 在kd树中找到包含目标点的叶子节点,
从根节点出发,递归向下访问kdtree,执行二叉树搜索

- 目标点x当前维度的坐标小于切分点坐标,则移动到左子节点
- 目标点x当前维度的坐标大于切分点坐标,则移动到右子节点

(这里访问节点时是按照切分维度进行比较,因此需要记录下切分维度?)
在访问过程中记录下访问各节点的顺序,存放在先进后出$Queue$中,便于后面的回退。
(3) 递归向上回退,结束条件$Queue$为空
(a) 从$Queue$中弹出一个节点,记作$x_q$,计算$x \rightarrow x_q$的距离,记作$d_q$
(b) 如果$d_q < d_{nst}$, 则更新最近点和最近距离

$$x_{nst}=x_q, d_{nst}=d_q$$
(c) 如果$x_q$ 为节点(超平面上的点),则考察以$x$为球心,$d_{nst}$为半径的超球体是否与$x_q$所在超平面相交,如果相交
- 若$Queue$中已经访问过$x_q$的左子树,则继续二叉搜索$x_q$右子树
- 若$Queue$中已经访问过$x_q$右子树,则继续二叉搜索其左子树
将搜索记录依然存放在$Queue$,循环结束时,$x_{nst}$就是最近邻点

备注:1) 训练集中的点是随机分布是,搜索时间复杂度是$O(logN)$ 2) 当训练集大小和特征空间维度接近是,搜索效率下降,接近于线性扫描

优缺点是什么?

优点

  • 模型简单,可以快速构建baseline
  • 不需要显示训练过程,操作简便

缺点:

  • 模型过于简单,准确率很难达到最优
  • 如果训练集大,则搜索效率下降
  • k值选择,和样本特征选择很关键,需要不断的验证

应用层面

算法的使用场景或任务有哪些?

knn最早是在2015年实习时接触,对商品类目预测,采用的方式是,对商品title,descrption文本进行关键词提取,筛选为特征,将每个商品表示为一个固定长度的特征向量,通过余弦距离,对新商品通过knn算法确定商品类别。
knn算法效果很高,但准确率只能到85%+,最终效果依赖数据集、特征构造,度量方式选择。

问题思考

参考文献

  1. 统计机器学习方法 第二版
  2. AI算法工程师手册

评论加载中