K近邻法(k-nearest neighbors)
- KNN做回归和分类的主要区别在于最后做预测时候的决策方式不同。
- KNN做分类时,一般是选择多数表决法,即训练集里和预测的样本特征最近的K个样本,预测为里面有最多类别数的类别。
- KNN做回归时,一般是选择平均法,即最近的K个样本的样本输出的平均值作为回归预测值。
KNN
- 对于k值的选择,一般根据样本的分布,通过交叉验证选择一个合适的k值。
选择较小的k值,相当于用较小领域中的训练实例进行预测,训练误差会减小,与此同时带来的问题是泛化误差会增大,整体模型变得复杂,容易发生过拟合。(反之同理) - 对于距离的度量,最常用的是欧式距离: D ( x , y ) = ∑ i = 1 n ( x i − y i ) 2 D(x,y) = \sqrt{\sum\limits_{i=1}^{n}(x_i-y_i)^2} D(x,y)=i=1∑n(xi−yi)2曼哈顿距离: D ( x , y ) = ∑ i = 1 n ∣ x i − y i ∣ D(x,y) = {\sum\limits_{i=1}^{n}|x_i-y_i|} D(x,y)=i=1∑n∣xi−yi∣闵可夫斯基距离(Minkowski Distance) D ( x , y ) = ∑ i = 1 n ( ∣ x i − y i ∣ ) p p D(x,y) = \sqrt[p] {\sum\limits_{i=1}^{n}(|x_i-y_i|)^p} D(x,y)=pi=1∑n(∣xi−yi∣)p
KNN蛮力实现(brute-force)
- 计算预测样本和所有训练集中的样本的距离,然后计算出最小的k个距离,接着多数表决做出预测。
- 方法简单直接,仅在样本量少,样本特征少的时候有效。
KD树实现(KDTree)
所谓的KD树就是K个特征维度的树,这里的K和KNN中的K不同。KNN中的K代表最近的K个样本,KD树中的K代表样本特征的维数。
KD树的建立
- 从m个样本的n维特征中,分别计算n个特征取值的方差,用方差最大的第k维特征 n k n_k nk来作为根节点。
- 对于这个特征,选择特征 n k n_k nk取值的中位数 n k m n_{km} nkm对应的样本作为划分点,将所有第k维特征取值小于 n k m n_{km} nkm的样本划入左子树,大于等于 n k m n_{km} nkm的样本划入右子树。
- 对于左子树和右子树,采用同样的办法迭代寻找更节点,递归生成KD树。
KD树搜索最近邻
- 对于一个目标点,首先在KD树里面找到包含目标点的叶子节点。以目标点为圆心,以目标点到叶子节点样本实例的距离为半径,得到一个超球体,最近邻的点一定在这个超球体内部。
- 然后返回叶子节点的父节点,检查另一个子节点包含的超矩形体是否和超球体相交,如果相交就到这个子节点寻找是否有更加近的近邻,有的话就更新最近邻。
- 如果不相交直接返回父节点的父节点,在另一个子树继续搜索最近邻。当回溯到根节点时,算法结束,此时保存的最近邻节点就是最终的最近邻。
KD树预测
- 通过KD树搜索最近邻,得到第一个最近邻样本,将其置为已选。
- 在第二轮中,忽略置为已选的样本,重新选择最近邻。
- 循环k次,得到目标的K个最近邻,做出预测。
球树(BallTree)实现
KD树在处理不均匀分布的数据集时,效率并不高。
如果目标星向左偏移一点,那么虚线圆会如红线所示那样扩大,导致与左上方矩形的右下角相交,那么就需要检查这个左上方矩形。
球树的建立
- 先构建一个超球体,这个超球体是包含所有样本的最小球体。
- 从球中选择一个离球的中心最远的点,然后选择第二个点离第一个点最远,将球中所有的点分配到离这两个聚类中心最近的一个上,然后计算每个聚类的中心,以及聚类能够包含它所有数据点所需的最小半径。这样我们得到了两个子超球体。
- 对于这两个子超球体,递归执行得到了一个球树。
球树搜索最近邻
- 首先自上而下贯穿整棵树找出包含目标点所在的叶子,并在这个球里找出与目标点最邻近的点,这将确定出目标点距离它的最近邻点的一个上限值。
- 然后检查目标点到兄弟结点中心的距离是否超过兄弟结点的半径与当前的上限值之和:如果超过那么兄弟结点里不可能存在一个更近的点;否则的话,进一步检查位于兄弟结点下的子球。
限定半径最近邻算法
- 当某样本周边的样本非常的少,这导致该样本在寻找K个最近邻时,会把距离其实较远的其他样本考虑进来,而导致预测不准确。为此可以限定最近邻的一个最大距离,只在该距离范围内搜索所有的最近邻。
KNN算法小结
主要优点
- 既可以用来做分类也可以用来做回归
- 可用于非线性分类
- 训练时间复杂度比支持向量机之类的算法低
- 和朴素贝叶斯之类的算法比,对数据没有假设,准确度高,对异常点不敏感
- 对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合
- 适用于样本容量较大类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分
主要缺点
- 计算量大,尤其是特征数非常多的时候
- 样本不平衡时,对稀有类别的预测准确率低
- KD树,球树之类的模型建立需要大量的内存
- 预测时速度比起逻辑回归之类的算法慢