最近邻算法

最近邻算法

常见距离准则:算法

 

 

Jaccard类似度常使用的场景:数据中有较多的0和1的断定,此时适合使用Jaccard类似度。数据结构

简介

NearestNeighbors (最近邻)实现了 unsupervised nearest neighbors learning(无监督的最近邻学习)。 它为三种不一样的最近邻算法提供统一的接口:BallTree, KDTree, 还有基于 sklearn.metrics.pairwise 的 brute-force 算法。算法的选择可经过关键字 'algorithm' 来控制, 并必须是 ['auto', 'ball_tree', 'kd_tree', 'brute'] 其中的一个。当默认值设置为 'auto' 时,算法会尝试从训练数据中肯定最佳方法。ide

暴力计算

最简单的近邻搜索的实现涉及数据集中全部成对点之间距离的暴力计算: 对于 D 维度中的 N 个样原本说, 这个方法的复杂度是 O[D N^2]。 对于小数据样本,高效的暴力近邻搜索是很是有竞争力的。 然而,随着样本数 N 的增加,暴力方法很快变得不切实际了。性能

 

在 sklearn.neighbors 类中, 暴力近邻搜索经过关键字 algorithm = 'brute' 来指定,并经过 sklearn.metrics.pairwise 中的例程来进行计算。学习

K-D 树

为了解决效率低下的暴力计算方法,已经发明了大量的基于树的数据结构。总的来讲, 这些结构试图经过有效地编码样本的 aggregate distance (聚合距离) 信息来减小所需的距离计算量。 基本思想是,若 A 点距离 B 点很是远,B 点距离 C 点很是近, 可知 A 点与 C 点很遥远,不须要明确计算它们的距离。 经过这样的方式,近邻搜索的计算成本能够下降为 O[D N log(N)] 或更低。 这是对于暴力搜索在大样本数 N 中表现的显著改善。测试

 

利用这种聚合信息的早期方法是 KD tree 数据结构(* K-dimensional tree* 的简写), 它将二维 Quad-trees 和三维 Oct-trees 推广到任意数量的维度. KD 树是一个二叉树结构,它沿着数据轴递归地划分参数空间,将其划分为嵌入数据点的嵌套的各向异性区域。 KD 树的构造很是快:由于只需沿数据轴执行分区, 无需计算 D-dimensional 距离。 一旦构建完成, 查询点的最近邻距离计算复杂度仅为 O[log(N)] 。 虽然 KD 树的方法对于低维度 (D < 20) 近邻搜索很是快, 当 D 增加到很大时, 效率变低: 这就是所谓的 “维度灾难” 的一种体现。 在 scikit-learn 中, KD 树近邻搜索可使用关键字 algorithm = 'kd_tree' 来指定, 而且使用类 KDTree 来计算。编码

Ball 树

为了解决 KD 树在高维上效率低下的问题, ball 树 数据结构就被研发出来了. 其中 KD 树沿卡迪尔轴(即坐标轴)分割数据, ball 树在沿着一系列的 hyper-spheres 来分割数据. 经过这种方法构建的树要比 KD 树消耗更多的时间, 可是这种数据结构对于高结构化的数据是很是有效的, 即便在高维度上也是同样.idea

 

ball 树将数据递归地划分为由质心 C 和半径 r 定义的节点,spa

使得节点中的每一个点位于由 r 和 C 定义的 hyper-sphere 内. 经过使用 triangle inequality(三角不等式) 减小近邻搜索的候选点数:rest

|x+y| <= |x| + |y|

经过这种设置, 测试点和质心之间的单一距离计算足以肯定距节点内全部点的距离的下限和上限. 因为 ball 树节点的球形几何, 它在高维度上的性能超出 KD-tree, 尽管实际的性能高度依赖于训练数据的结构. 在 scikit-learn 中, 基于 ball 树的近邻搜索可使用关键字 algorithm = 'ball_tree' 来指定, 而且使用类 sklearn.neighbors.BallTree 来计算. 或者, 用户能够直接使用 BallTree 类.

使用

from sklearn.neighbors import NearestNeighbors

import numpy as np

X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])

 

# n_neighbors默认5,algorithm默认‘auto’

nbrs = NearestNeighbors(n_neighbors=3, algorithm='ball_tree').fit(X) 

 

# indices获得k个最近邻的索引,distances获得与k个最近邻的距离

distances, indices = nbrs.kneighbors(X)

indices

>>> array([[0, 1, 2],

       [1, 0, 2],

       [2, 1, 0],

       [3, 4, 5],

       [4, 3, 5],

       [5, 4, 3]], dtype=int64)

Distances

>>>  array([[ 0.        ,  1.        ,  2.23606798],

       [ 0.        ,  1.        ,  1.41421356],

       [ 0.        ,  1.41421356,  2.23606798],

       [ 0.        ,  1.        ,  2.23606798],

       [ 0.        ,  1.        ,  1.41421356],

       [ 0.        ,  1.41421356,  2.23606798]])

 

也能够直接使用:

from sklearn.neighbors import KDTree

import numpy as np

X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])

kdt = KDTree(X, leaf_size=30, metric='euclidean')

 

#获得k个最近邻的索引

kdt.query(X, k=2, return_distance=False)  

相关文章
相关标签/搜索