简介
K-D Tree, K-Dimensional Tree, 对高维的点作空间划分的一种二叉树.
传统的文本搜索是这样的:
一个doc 有若干个field, 分词后添加到倒排索引中, 然后按照 tf-idf 等思想计算match(query,doc), 然后取得分最高的top-k.
那么对于高维的点或向量
v=(x1,...,xd)
, 即给出一个集合
S={v|v∈Rd}
, 怎么做指定点
v
在集合
最朴素的思想, 就是暴力遍历, 作
O(n)
时间复杂度的操作.
但问题变复杂时, 如:
- 集合非常大, 百万级
- 维度d很大, 两三百维
- 数据类型为float, 计算两元素间距离 distance(a,b) 的代价较大
此时, 为了提升搜索效率, 就需要建索引, 就用到了K-D Tree.
1. 建树
像回归决策树一样, 不断地找划分点, 递归地得到树.
这里的划分点就是(split_dimension,split_value ).
便于说明, 用ndarray类型的变量A表示数据集, A.shape=(n,m)
流程见下:
- 对当前集合S,求出方差最大的那一维
split_dimension=argmaxdvariance(A[:,d])
- 在上步找到维度d之后, 求出该维度分量的中位数:
split_value=median(A[:,d]) - 确定(split_dimension,split_value )之后, 对集合作划分, 得到子集 S1,S2 , 分别做左右子树. 再递归地重复上述步骤, 直至对整个数据集划分完毕.
2. 搜索
代码
疑问
以 欧氏距离 做度量, 搜索K-近邻 很直观, 那 余弦距离呢?
参考
- wikipedia, k-d tree
- How to use a KdTree to search
- scipy,KDTree_example
- 一篇 cnblog,KNN算法与Kd树