1、什么是K近邻算法
K近邻算法(KNN)是一种常用的分类和回归方法,它的基本思想是从训练集中寻找和输入样本最相似的k个样本,如果这k个样本中的大多数属于某一个类别,则输入的样本也属于这个类别。
关于KNN算法,一个核心问题是:如何快速从数据集中找到和目标样本最接近的K个样本?
本文将从这个角度切入,介绍常用的K近邻算法的实现方法。具体将从原理、使用方法、时间开销和准确率对比等方面进行分析和实验。
2、距离度量
在介绍具体算法之前,我们先简单回顾一下KNN算法的三要素:距离度量、k值的选择和分类决策规则。
其中机器学习领域常用的距离度量方法,有欧式距离、余弦距离、曼哈顿距离、dot内积等
主流的近邻算法都支持上述不同的距离度量。其中n维特征空间的a、b向量的欧式距离
体现数值上的绝对差异,而余弦距离基于余弦相似度(两个向量间夹角的余弦值),体现方向上的相对差异。如果对向量做归一化处理,二者的结果基本是等价的。
实际应用中,需要根据业务目标来选择合适的度量方法。
3、K近邻算法的实现方法
K近邻的实现方式多达数十种,笔者从中挑选了几种常用、经典的方法作为分析案例。
首先最直观的想法(暴力法),是线性扫描法。将待预测样本和候选样本逐一比对,最终挑选出距离最接近的k个样本即可,时间复杂度O(n)。对于样本数量较少的情况,这种方法简单稳定,已经能有不错的效果。但是数据规模较大时,时间开销严重无法接受。
所以实际应用中,往往会寻找其他类型的数据结构来保存特征,以降低搜索的时间复杂度。
常用的存储结构可以分为树和图两大类。树结构的代表是KDTree,以及改进版BallTree和Annoy等;基于图结构的搜索算法有HNSW等。
4、KDTree和BallTree
KDTree
kd 树是一种对k维特征空间中的实例点进行存储以便对其快速检索的树形数据结构。
kd树是二叉树,核心思想是对 k 维特征空间不断切分(假设特征维度是768,对于(0,1,2,...,767)中的每一个维度,以中值递归切分)构造的树,每一个节点是一个超矩形,小于结点的样本划分到左子树,大于结点的样本划分到右子树。
树构造完毕后,最终检索时(1)从根结点出发,递归地向下访问kd树。若目标点
当前维的坐标小于切分点的坐标,移动到左子树,否则移动到右子树,直至到达叶结点;(2)以此叶结点为“最近点”,递归地向上回退,查找该结点的兄弟结点中是否存在更近的点ÿ