K-D 树, 高维空间索引

简介

K-D Tree, K-Dimensional Tree, 对高维的点作空间划分的一种二叉树.

传统的文本搜索是这样的:
一个doc 有若干个field, 分词后添加到倒排索引中, 然后按照 tf-idf 等思想计算match(query,doc), 然后取得分最高的top-k.

那么对于高维的点或向量 v=(x1,...,xd) , 即给出一个集合 S={v|vRd} , 怎么做指定点 v 在集合 S 中的 k-近邻 搜索呢?
最朴素的思想, 就是暴力遍历, 作 O(n) 时间复杂度的操作.
但问题变复杂时, 如:

  1. 集合非常大, 百万级
  2. 维度d很大, 两三百维
  3. 数据类型为float, 计算两元素间距离 distance(a,b) 的代价较大

此时, 为了提升搜索效率, 就需要建索引, 就用到了K-D Tree.

1. 建树

像回归决策树一样, 不断地找划分点, 递归地得到树.
这里的划分点就是(split_dimension,split_value ).
便于说明, 用ndarray类型的变量A表示数据集, A.shape=(n,m)
流程见下:

  1. 对当前集合S,求出方差最大的那一维
    split_dimension=argmaxdvariance(A[:,d])
  2. 在上步找到维度d之后, 求出该维度分量的中位数:
    split_value=median(A[:,d])
  3. 确定(split_dimension,split_value )之后, 对集合作划分, 得到子集 S1,S2 , 分别做左右子树. 再递归地重复上述步骤, 直至对整个数据集划分完毕.

2. 搜索

代码

疑问

以 欧氏距离 做度量, 搜索K-近邻 很直观, 那 余弦距离呢?

参考

  1. wikipedia, k-d tree
  2. How to use a KdTree to search
  3. scipy,KDTree_example
  4. 一篇 cnblog,KNN算法与Kd树

你可能感兴趣的:(树)