前言
提到K近邻,K-nearest neighbors(它的K是指有多少个邻居),总是容易想起另外一个叫K-means的聚类算法(它的K指有多少个质心),容易搞混淆,它们有一部分思路也很接近,但是KNN能做分类和回归。
K近邻之所以叫K近邻,是因为它的思想就是“你与你的邻居很相似”。所以对于分类来说,找到K个最近的邻居,用投票法找出最多数的类别,就将数据点预测为该类别。同理,回归的话输出最近的K个样本的平均值作为预测值。
内部细节
距离是一个很重要的概念,通过距离才能找到最近的K个邻居。
最常用的是欧式距离:
也可以用曼哈顿距离:
甚至通用的闵可夫斯基距离:
可以看到欧氏距离和曼哈顿距离分别就是闵氏距离当p = 2 和p = 1时的特殊情况。
在定义了距离后,需要设置K的值,当K越小时,找到的邻居就越少,无法保证数据的多样性,模型的复杂度越大,这时候偏差小,但是带来的问题是泛化能力变差,方差较大,容易发生过拟合。
当K越大时,会有更多的邻居参与计算,虽然偏差更大,但这时候可以保证数据的多样性,同时增强泛化能力,模型变得更加简单。极端情况是K等于样本总数,这时候只是简单预测为在训练实例中最多的类,模型过于简单。
综上,找到一个合适的K值很重要,一般来说,根据样本分布选择一个较小的K值,再通过交叉验证对K值进行优化。
但是,如果如上述方式来进行计算, 在样本量少,特征少的时候简单有效。但遇到样本量几十万以上,特征数上千,算法的时间效率就很成问题。因此为了解决这样的问题,采取了两种办法,一种是KD树,一种是球树。
KNN——KD树
KNN中的K代表最近的K个样本,kd(k-dimension)树中的k代表特征的维数。kd树是二叉树,是一种对k维空间中实例点进行存储以便对其进行快速检索的树形数据结构。kd树表示对k维空间的一个划分(partition),构造kd树相当于不断地用垂直于坐标轴的超平面将k维空间切分,构成一系列的k维超矩形区域。kd树的每个结点对应于一个k维超矩形区域。
构建步骤
(1)对所有特征进行方差排序,找到方差最大的特征
(2)找到上述特征的中位数,对小于等于中位数的所有点划分到左子树,大于中位数的所有点划分到右子树
(3)返回步骤(1),用同样的方法划分左右子树
假设数据点为6个,{(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)},最后得到类似划分的二叉树(就是KD树)以及划分的特征空间。
所有点最后就变成了对应的叶子节点。
寻找最近邻
假设要查找的点(2, 4.5)。根据构建的KD树,先从根节点(7,2)开始,然后查询到(5,4),而这个点是通过第二维划分空间的(该维方差更大),即y = 4来划分,于是由于4.5大于4,查找到了(4,7),为叶子节点,此时搜索路径为<(7,2),(5,4),(4,7)>,并计算当前叶子节点到查找点的距离,假设为a,回溯一个点(5,4),计算查找点到回溯点的距离,假设为b。若a小于b,则最近邻点就为当前叶子点。若a大于b,则回溯到回溯点,此时搜索路径为<(7,2),(5,4)>,并以b为半径做超球面,进入回溯点(5,4)的左半空间进行查找到(2,3),此时搜索路径为<(7,2),(5,4),(2,3)>,(2,3)比(5,4)更近,所以最近邻点更新为(2,3)。以1.5为半径作圆,回溯至(5,4),不与y = 4相交,然后回溯至(7,2),不与x = 7相交。至此搜索结束,返回最近邻点(2,3),最近距离1.5。
接下来忽略已选的样本,重新选最近邻,继续跑K-1次,一共得到K个最近邻,根据多数表决法预测为K个最近邻里有最多类别数的类别。回归的话直接求K个最近邻的平均值作为回归预测值。
KD树划分后大大减少无效的最近邻搜索,很多样本点由于所在超矩形和超球体不相交,根本不需要计算距离,节省了时间。
KNN——球树
kd树使用超矩形,有棱角,可能有的半径稍微大一点就会与划分线相交,这导致可能出现很多冗余的计算。
而球树,内部二叉树对应的不再是超矩形,而是超球体。
构建步骤
(1)先构建包含所有样本的超球体
(2)通过找到离球心最远的点A,然后找到离A最远的点B,对所有点找到离这两个点中最近的一个进行聚类,然后计算新的聚类中心,并计算每个聚类能够包含所有数据点所需的最小半径。新生成的两个超球体与Kd树里的左右子树对应。
(3)返回(2),在新生成的超球体里继续分裂、聚类,最终形成球树。
寻找最近邻
首先找到包含目标点的叶子节点。然后找到超球体里离目标节点最邻近的点。然后检测兄弟节点,若目标点到兄弟节点中心的距离超过兄弟节点半径和当前上限值之和,则兄弟节点里不存在一个更近的点。检查完兄弟节点后,继续向父节点回溯,继续搜索最小邻近值,当回溯到根节点时,此时的最小邻近值就是最终搜索结果。
球树使用两边之和大于第三边来判断,相对于kd树仅仅比较两点距离更加复杂,但却避免了更多搜索,两种方案各有好处。
KNN与特殊情况
当遇到样本不均衡的情况时,这导致稀有类别样本在找K个最近邻时,会把距离较远的其它样本考虑进来,而导致预测不准确。为此限定一个最大距离,只在一个距离范围内搜索所有的最近邻。这个距离称为限定半径。
质心算法:对每个类的所有数据求质心,也就是N维特征求平均值。最终每个类都有一个质心点。做预测时仅仅比较样本与质心的距离,最小的距离对于质心类别即为预测的类别。通常在文本分类中使用这个算法。
小结
优点:
(1)理论成熟,思想简单
(2)可用于非线性分类
(3)时间复杂度比支持向量机低,仅为O(n)
(4)对异常点不敏感
缺点:
(1)只适合样本容量大的自动分类,而样本容量小的类(不均衡样本)容易误分
(2)在特征数多的时候计算量大
(3)kd树、球树需要大量内存
(4)预测时速度比逻辑回归之类的算法慢
(5)相比决策树,KNN模型可解释性不强