统计机器学习【3】- K近邻法(三)Ball Tree

在计算机科学中,球树(ball tree)是一种空间划分数据结构,用于组织在多维空间中的点。球数之所有得到此名,是因为它将数据点划分为一组嵌套的超球体。这种类型的数据结构特征使其在很多方面都有用,特别是在最近邻搜索。

一般的在特征向量维度小于20的时候是可以用KD-Tree的,但是更高维度的时候建议使用Ball-Tree,这种算法的效率更高

非正式描述

球树是二叉树,其中每个结点定义一个d维的超球面,或称为球, 其中包含被搜索的点的子集。树的每个内部结点将数据点划分为两个不相交的集合,这两个集合与不同的球相关联。当球本身可能相交时,每个点根据它到球心的距离被分配到其中一个球中。树中每个叶结点定义了一个球并枚举该球内的所有数据点。

树里的每个结点定义了一个能包含这个子树所有数据点的最小球。这就产生一个有用的性质,对于给定的测试点 t t ,到树中球B中任意一点的距离大于或等于从 t t 到该球的距离。

D B ( t ) = { m a x ( t B . p i v o t B . r a d i u s , D B . p a r e n t ) , i f B R o o t m a x ( t B . p i v o t B . r a d i u s , 0 ) , i f B = R o o t D^B(t) = \left \{ \begin{aligned} max(|t - B.pivot| - B.radius, D^{B.parent}), && if B \neq Root \\ max(|t - B.pivot| - B.radius, 0), && if B = Root\\ \end{aligned} \right.
D B ( t ) D^{B}(t) 表示球B的任一点到某点 t t 的最小距离。

构造球树(ball tree)

最简单的构造就是“k-d构造算法”,类比构造k-d树的过程。这是一种离线算法,也就是说,一种同时对整个数据集进行操作的算法。树是通过递归地将数据点分割成两个集合而自顶向下构建的,分割线是沿着单一维度的增大方向排列,用该维度上所有点的中值对集合进行划分。要找到每个内部节点的划分,要在该结点包含的样本数量上花费线性时间,从而得到时间复杂度为 O ( n l o g n ) O(n logn) ,n是数据点的个数。

伪代码:

function construct_ball_tree is
	input: D, 数据点的数组
	output:B,构造好的ball tree的根节点

	if 只有一个数据点 then
		创建一个叶子结点B包含这一单一的点
		return B
	else:
		让c为最宽的维度
		让p为这个维度的中心点,
		让L, R设为左集合和右集合
		创建带有两个孩子的B:
			B.pivot := P
			B.child1 := contruct_balltree(L),
			B.child2 := contruct_balltree(R),
			让B.radius 为p到孩子的最大距离
		return B
	end if
end function

最近邻搜索

球树最近邻算法以深度优先的顺序检查结点,从根节点开始。在搜索过程中,算法维护一个max-first优先队列(通常用堆实现),记作Q,表示到目前为止遇到的k个最近的点。在每个结点B上,它可能执行三个操作之一,然后最终返回一个更新版本的优先队列:
(1)如果测试点 t t 到当前结点B的距离大于Q中最远的店,则忽略B,返回Q;
(2)如果B是一个叶结点,则扫面B中枚举的每个结点,然后更新队列,然后返回;
(3)如果B是一个内部节点,递归调用B的两个子结点算法,搜先搜索中心更靠近 t t 的子结点。在每次调用后更新队列,然后返回。

伪代码:

   function knn_search is
       input: 
           t, the target point for the query
           k, the number of nearest neighbors of t to search for
           Q, max-first priority queue containing at most k points
           B, a node, or ball, in the tree
       output: 
           Q, containing the k nearest neighbors from within B
       if distance(t, B.pivot) - B.radius ≥ distance(t, Q.first) then
           return Q unchanged
       else if B is a leaf node then
           for each point p in B do
               if distance(t, p) < distance(t, Q.first) then
                   add p to Q
                   if size(Q) > k then
                       remove the furthest neighbor from Q
                   end if
               end if
           repeat
       else
           let child1 be the child node closest to t
           let child2 be the child node furthest from t
           knn_search(t, k, Q, child1)
           knn_search(t, k, Q, child2)
       end if
   end function[2]

参考资料:
【1】Ball tree

猜你喜欢

转载自blog.csdn.net/weixin_43763859/article/details/106364605