KD-Tree二叉树检索学习笔记和Python实现

KD-Tree应用于中低量的维度数据,是检索二叉树,可以很快速的完成检索,但是对于大量的维度数据,速度慢就不能用,此时用的是LSH。

算法的步骤:

这里假定多维度向量组成的shape是[rows,cols],每行是一个向量,由于是检索,所以有多行向量,rows行就组成这个矩阵,接着构建二叉树

矩阵有行维度,也有列维度,找划分节点就需要找能将行尽可能划分开的节点,这里按列计算并寻找方差最大的列 H,对列H找出其中的中位数M,这样中位数M所在的行就是根节点,这行也是分割面

根据根节点划分,列H中的数,大于M的所在行分到根节点的右侧,小于M的所在行分到左侧

对于左右两侧,分别循环上面划分节点的步骤,直到划分以后只有一行向量

 KD-Tree举例:

有5个向量用来检索
x1=[9,10],x2=[12,16],x3=[16,19],x4=[19,6],x5=[19,10]
shape=[2,2],方差为:[15.6 , 21.76],var2>var1,第二列的中位数是10
令x1是划分节点,x4,x5在左侧,x2、x3在右侧,
                                                    x1
                                 x4、x5                   x3、x2
由于第二列用来划分过一次,接着用第一列划分,x4和x5的中位数是19,x2和x3的中位数是14
                                                      x1
                               x5       x4                    x2   x3

检索过程可以根据根节点的记录信息即划分的维度是第几维H,用第H维的数据对比,然后不断寻找直到找到结点。

Python实现:

import numpy as np
np.random.seed(99999)
v=np.random.randint(19,size=(10,2));print(v)
def KDTree(matrix):
    if len(matrix)==2:
        return {tuple(matrix[0]),tuple(matrix[1])}
    if len(matrix)==1:
        return {tuple(matrix[0])}
    if len(matrix)==0:
        return {}
    matrix=np.array(matrix)
    vars=list(matrix.var(0))              #按列计算矩阵的方差
    ind=vars.index(max(vars))       #找出方差最大所在列的列号
    m=list(matrix[:,ind])
    m.sort()
    middle=m[len(m)//2]    #找到该列的中位数
    lm=[]
    rm=[]
    for i in range(matrix.shape[0]):  #遍历所有行然后分配到左右子树
        if matrix[i,ind]==middle:
            continue
        if matrix[i,ind]<middle:
            lm.append(list(matrix[i,:]))
        else:
            rm.append(list(matrix[i,:]))
    kdtree={(ind,middle):{}}         #ind记录检索时的列号,middle是比对的值
    kdtree[(ind,middle)]=[KDTree(lm),KDTree(rm)]      #递归生成左右子树
    return kdtree
print(KDTree(v))

生成的结果:
[[11 16]
 [12 14]
 [15 12]
 [17 11]
 [17  3]
 [15 14]
 [ 6 16]
 [16  0]
 [12 18]
 [16 16]]
{(1, 14): [{(1, 11): [{(16, 0), (17, 3)}, {(15, 12)}]}, {(0, 12): [{(11, 16), (6, 16)}, {(16, 16)}]}]}

猜你喜欢

转载自blog.csdn.net/shiheyingzhe/article/details/81814575