kd树 求k近邻 python 代码

   之前两篇随笔介绍了kd树的原理,并用python实现了kd树的构建和搜索,具体可以参考

  kd树的原理

  python kd树 搜索 代码

  kd树常与knn算法联系在一起,knn算法通常要搜索k近邻,而不仅仅是最近邻,下面的代码将利用kd树搜索目标点的k个近邻。

  首先还是创建一个类,用于保存结点的值,左右子树,以及用于划分左右子树的切分轴

class decisionnode:
    def __init__(self,value=None,col=None,rb=None,lb=None):
        self.value=value
        self.col=col
        self.rb=rb
        self.lb=lb

  切分点为坐标轴上的中值,下面代码求得一个序列的中值

def median(x):
    n=len(x)
    x=list(x)
    x_order=sorted(x)
    return x_order[n//2],x.index(x_order[n//2])

  然后按照左子树大于切分点,右子树小于切分点的规则构造kd树,其中data是输入的数据

#以j列的中值划分数据,左小右大,j=节点深度%列数
def buildtree(x,j=0):
    rb=[]
    lb=[]
    m,n=x.shape
    if m==0: return None
    edge,row=median(x[:,j].copy())
    for i in range(m):
        if x[i][j]>edge:
            rb.append(i)
        if x[i][j]<edge:
            lb.append(i)
    rb_x=x[rb,:]
    lb_x=x[lb,:]
    rightBranch=buildtree(rb_x,(j+1)%n)
    leftBranch=buildtree(lb_x,(j+1)%n)
    return decisionnode(x[row,:],j,rightBranch,leftBranch)

  接下来就是搜索树得到k近邻的过程,与搜索最近邻的过程大致相同,需要创建一个字典knears,用于存储k近邻的点以及与目标点的距离(欧氏距离)

  搜索的过程为:

  (1)第一步还是遍历树,找到目标点所属区域对应的叶节点

  (2)从叶结点依次向上回退,按照寻找最近邻点的方法回退到父节点,并判断其另一个子节点对区域内是否可能存在k近邻点,具体的,在每个结点上进行以下操作:

    (a)如果字典中的成员个数不足k个,将该结点加入字典

    (b)如果字典中的成员不少于k个,判断该结点与目标结点之间的距离是否不大于字典中各结点所对应距离的的最大值,如果不大于,便将其加入到字典中

    (c)对于父节点来说,如果目标点与其切分轴之间的距离不大于字典中各结点所对应距离的的最大值,便需要访问该父节点的另一个子节点

  (3)每当字典中增加新成员,就按距离值对字典进行降序排序,将得到的列表赋值给poinelist,pointlist[0][1]便是字典中各结点所对应距离的最大值

  (4)当回退到根节点并完成对其操作时,pointlist中后k个结点就是目标点的k近邻

  代码如下:

#搜索树:输出目标点的近邻点
def traveltree(node,aim):
    global pointlist  #存储排序后的k近邻点和对应距离
    if node==None: return
    col=node.col
    if aim[col]>node.value[col]:
        traveltree(node.rb,aim)
    if aim[col]<node.value[col]:
        traveltree(node.lb,aim)
    dis=dist(node.value,aim)
    if len(knears)<k:
        knears.setdefault(tuple(node.value.tolist()),dis)#列表不能作为字典的键
        pointlist=sorted(knears.items(),key=lambda item: item[1],reverse=True)
    elif dis<=pointlist[0][1]:
        knears.setdefault(tuple(node.value.tolist()),dis)
        pointlist=sorted(knears.items(),key=lambda item: item[1],reverse=True)
    if node.rb!=None or node.lb!=None:
        if abs(aim[node.col] - node.value[node.col]) < pointlist[0][1]:
            if aim[node.col]<node.value[node.col]:
                traveltree(node.rb,aim)
            if aim[node.col]>node.value[node.col]:
                traveltree(node.lb,aim)
    return pointlist

  完整代码在此处取

 1 import numpy as np
 2 from numpy import array
 3 class decisionnode:
 4     def __init__(self,value=None,col=None,rb=None,lb=None):
 5         self.value=value
 6         self.col=col
 7         self.rb=rb
 8         self.lb=lb
 9
10 #读取数据并将数据转换为矩阵形式
11 def readdata(filename):
12     data=open(filename).readlines()
13     x=[]
14     for line in data:
15         line=line.strip().split(‘\t‘)
16         x_i=[]
17         for num in line:
18             num=float(num)
19             x_i.append(num)
20         x.append(x_i)
21     x=array(x)
22     return x
23
24 #求序列的中值
25 def median(x):
26     n=len(x)
27     x=list(x)
28     x_order=sorted(x)
29     return x_order[n//2],x.index(x_order[n//2])
30
31 #以j列的中值划分数据,左小右大,j=节点深度%列数
32 def buildtree(x,j=0):
33     rb=[]
34     lb=[]
35     m,n=x.shape
36     if m==0: return None
37     edge,row=median(x[:,j].copy())
38     for i in range(m):
39         if x[i][j]>edge:
40             rb.append(i)
41         if x[i][j]<edge:
42             lb.append(i)
43     rb_x=x[rb,:]
44     lb_x=x[lb,:]
45     rightBranch=buildtree(rb_x,(j+1)%n)
46     leftBranch=buildtree(lb_x,(j+1)%n)
47     return decisionnode(x[row,:],j,rightBranch,leftBranch)
48
49 #搜索树:输出目标点的近邻点
50 def traveltree(node,aim):
51     global pointlist  #存储排序后的k近邻点和对应距离
52     if node==None: return
53     col=node.col
54     if aim[col]>node.value[col]:
55         traveltree(node.rb,aim)
56     if aim[col]<node.value[col]:
57         traveltree(node.lb,aim)
58     dis=dist(node.value,aim)
59     if len(knears)<k:
60         knears.setdefault(tuple(node.value.tolist()),dis)#列表不能作为字典的键
61         pointlist=sorted(knears.items(),key=lambda item: item[1],reverse=True)
62     elif dis<=pointlist[0][1]:
63         knears.setdefault(tuple(node.value.tolist()),dis)
64         pointlist=sorted(knears.items(),key=lambda item: item[1],reverse=True)
65     if node.rb!=None or node.lb!=None:
66         if abs(aim[node.col] - node.value[node.col]) < pointlist[0][1]:
67             if aim[node.col]<node.value[node.col]:
68                 traveltree(node.rb,aim)
69             if aim[node.col]>node.value[node.col]:
70                 traveltree(node.lb,aim)
71     return pointlist
72
73 def dist(x1, x2): #欧式距离的计算
74     return ((np.array(x1) - np.array(x2)) ** 2).sum() ** 0.5
75
76 knears={}
77 k=int(input(‘请输入k的值‘))
78 if k<2: print(‘k不能是1‘)
79 global pointlist
80 pointlist=[]
81 file=input(‘请输入数据文件地址‘)
82 data=readdata(file)
83 tree=buildtree(data)
84 tmp=input(‘请输入目标点‘)
85 tmp=tmp.split(‘,‘)
86 aim=[]
87 for num in tmp:
88     num=float(num)
89     aim.append(num)
90 aim=tuple(aim)
91 pointlist=traveltree(tree,aim)
92 for point in pointlist[-k:]:
93     print(point)

kdtree

原文地址:https://www.cnblogs.com/bambipai/p/8443182.html

时间: 2024-07-31 03:44:52

kd树 求k近邻 python 代码的相关文章

统计学习三:2.K近邻法代码实现(以最近邻法为例)

通过上文可知感知机模型的基本原理,以及算法的具体流程.本文实现了感知机模型算法的原始形式,通过对算法的具体实现,我们可以对算法有进一步的了解.具体代码可以在我的github上查看. 代码 #!/usr/bin/python3 # -*- coding:utf-8 -*- import sys import numpy as np class Kdtree(object): ''' 类名: Kdtree 用于存储kd树的数据 成员: __value: 训练数据,保存数据点的坐标 __type: 保

【黎明传数==&gt;机器学习速成宝典】模型篇05——朴素贝叶斯【Naive Bayes】(附python代码)

目录 先验概率与后验概率 什么是朴素贝叶斯 模型的三个基本要素 构造kd树 kd树的最近邻搜索 kd树的k近邻搜索 Python代码(sklearn库) 先验概率与后验概率 什么K近邻算法(k-Nearest Neighbor,kNN) 引例 有一个训练集包含100个实例,属性是皮肤颜色(黑.白.黄),标记是地区(亚洲.非洲.北美洲人).在训练集中有30个非洲人(28个黑人),有50个亚洲人(1个黑人),有20个北美洲人(5个黑人).请训练一个贝叶斯模型. 当一个训练集外的黑人来报道,我们该如何

k近邻法的C++实现:kd树

1.k近邻算法的思想 给定一个训练集,对于新的输入实例,在训练集中找到与该实例最近的k个实例,这k个实例中的多数属于某个类,就把该输入实例分为这个类. 因为要找到最近的k个实例,所以计算输入实例与训练集中实例之间的距离是关键! k近邻算法最简单的方法是线性扫描,这时要计算输入实例与每一个训练实例的距离,当训练集很大时,非常耗时,这种方法不可行,为了提高k近邻的搜索效率,常常考虑使用特殊的存储结构存储训练数据,以减少计算距离的次数,具体方法很多,这里介绍实现经典的kd树方法. 2.构造kd树 kd

统计学习方法与Python实现(二)——k近邻法

统计学习方法与Python实现(二)——k近邻法 iwehdio的博客园:https://www.cnblogs.com/iwehdio/ 1.定义 k近邻法假设给定一个训练数据集,其中的实例类别已定.分类时,对新的实例,根据其k个最近邻的训练实例的类别,通过多数表决的方式进行预测.k近邻法不具有显式的学习过程,而实际上是利用训练数据集对特征空间进行划分,并作为其分类的模型.k近邻法的三个基本要素是 k值的选择.距离度量和分类决策规则. k近邻法的模型是将特征空间划分成一些称为单元的子空间,并且

3.K近邻法

1. k 近邻算法k近邻法(k-nearest neighbor, k-NN) 是一种基本分类与回归方法.  k近邻法的输入为实例的特征向量, 对应于特征空间的点: 输出为实例的类别, 可以取多类. k近邻法假设给定一个训练数据集, 其中的实例类别已定. 分类时, 对新的实例, 根据其k个最近邻的训练实例的类别, 通过多数表决等方式进行预测.因此, k近邻法不具有显式的学习过程. k近邻法实际上利用训练数据集对特征向量空间进行划分, 并作为其分类的“模型”. k值的选择. 距离度量及分类决策规则

《统计学习方法》第三章,k 近邻法

? k 近邻法来分类,用到了 kd 树的建立和搜索 ● 代码 1 import numpy as np 2 import matplotlib.pyplot as plt 3 from mpl_toolkits.mplot3d import Axes3D 4 from mpl_toolkits.mplot3d.art3d import Poly3DCollection 5 from matplotlib.patches import Rectangle 6 import operator 7 i

K近邻法(KNN)原理小结

K近邻法(k-nearst neighbors,KNN)是一种很基本的机器学习方法了,在我们平常的生活中也会不自主的应用.比如,我们判断一个人的人品,只需要观察他来往最密切的几个人的人品好坏就可以得出了.这里就运用了KNN的思想.KNN方法既可以做分类,也可以做回归,这点和决策树算法相同. KNN做回归和分类的主要区别在于最后做预测时候的决策方式不同.KNN做分类预测时,一般是选择多数表决法,即训练集里和预测的样本特征最近的K个样本,预测为里面有最多类别数的类别.而KNN做回归时,一般是选择平均

k近邻算法(k-nearest neighbor,k-NN)

kNN是一种基本分类与回归方法.k-NN的输入为实例的特征向量,对应于特征空间中的点:输出为实例的类别,可以取多类.k近邻实际上利用训练数据集对特征向量空间进行划分,并作为其分类的"模型".k值的选择.距离度量及分类决策规则是k近邻的三个基本要素. 算法 输入:训练数据集T={(x1,y1),(x2,y2),--..,(xN,yN)} 输出:实例x所属的类y (1)根据给定的距离度量,在训练集T中找到与x最邻近的k个点,涵盖这k个点的x的邻域记作Nk(x) (2)在Nk(x)中根据分类

【黎明传数==&gt;机器学习速成宝典】模型篇04——k近邻法【kNN】(附python代码)

目录 什么是k近邻算法 模型的三个基本要素 构造kd树 搜索kd树 Python代码(sklearn库) 什么K近邻算法(k-Nearest Neighbor,kNN) 引例 假设有数据集,其中前6部是训练集(有属性值和标记),我们根据训练集训练一个KNN模型,预测最后一部影片的电影类型. 首先,将训练集中的所有样例画入坐标系,也将待测样例画入 然后计算待测分类的电影与所有已知分类的电影的欧式距离 接着,将这些电影按照距离升序排序,取前k个电影,假设k=3,那么我们得到的电影依次是<He's N