之前两篇随笔介绍了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

  完整代码在此处取

 import numpy as np
from numpy import array
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 readdata(filename):
data=open(filename).readlines()
x=[]
for line in data:
line=line.strip().split('\t')
x_i=[]
for num in line:
num=float(num)
x_i.append(num)
x.append(x_i)
x=array(x)
return x #求序列的中值
def median(x):
n=len(x)
x=list(x)
x_order=sorted(x)
return x_order[n//2],x.index(x_order[n//2]) #以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) #搜索树:输出目标点的近邻点
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 def dist(x1, x2): #欧式距离的计算
return ((np.array(x1) - np.array(x2)) ** 2).sum() ** 0.5 knears={}
k=int(input('请输入k的值'))
if k<2: print('k不能是1')
global pointlist
pointlist=[]
file=input('请输入数据文件地址')
data=readdata(file)
tree=buildtree(data)
tmp=input('请输入目标点')
tmp=tmp.split(',')
aim=[]
for num in tmp:
num=float(num)
aim.append(num)
aim=tuple(aim)
pointlist=traveltree(tree,aim)
for point in pointlist[-k:]:
print(point)

kdtree

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

  1. K近邻python

    有一个带标签的数据集X,标签为y.我们想通过这个数据集预测目标点x0的所属类别. K近邻算法是指在X的特征空间中,把x0放进去,然后找到距离x0最近的K个点.通过这K个点所属类别,一般根据少数服从多数 ...

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

    通过上文可知k近邻算法的基本原理,以及算法的具体流程,kd树的生成和搜索算法原理.本文实现了kd树的生成和搜索算法,通过对算法的具体实现,我们可以对算法原理有进一步的了解.具体代码可以在我的githu ...

  3. K近邻 Python实现 机器学习实战(Machine Learning in Action)

    算法原理 K近邻是机器学习中常见的分类方法之间,也是相对最简单的一种分类方法,属于监督学习范畴.其实K近邻并没有显式的学习过程,它的学习过程就是测试过程.K近邻思想很简单:先给你一个训练数据集D,包括 ...

  4. 机器学习_K近邻Python代码详解

    k近邻优点:精度高.对异常值不敏感.无数据输入假定:k近邻缺点:计算复杂度高.空间复杂度高 import numpy as npimport operatorfrom os import listdi ...

  5. CodeForces - 1093G:Multidimensional Queries (线段树求K维最远点距离)

    题意:给定N个K维的点,Q次操作,或者修改点的坐标:或者问[L,R]这些点中最远的点. 思路:因为最后一定可以表示维+/-(x1-x2)+/-(y1-y2)+/-(z1-z2)..... 所以我们可以 ...

  6. kNN(k近邻)算法代码实现

    目标:预测未知数据(或测试数据)X的分类y 批量kNN算法 1.输入一个待预测的X(一维或多维)给训练数据集,计算出训练集X_train中的每一个样本与其的距离 2.找到前k个距离该数据最近的样本-- ...

  7. k临近法的实现:kd树

    # coding:utf-8 import numpy as np import matplotlib.pyplot as plt T = [[2, 3], [5, 4], [9, 6], [4, 7 ...

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

    1.k近邻算法的思想 给定一个训练集,对于新的输入实例,在训练集中找到与该实例最近的k个实例,这k个实例中的多数属于某个类,就把该输入实例分为这个类. 因为要找到最近的k个实例,所以计算输入实例与训练 ...

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

    统计学习方法与Python实现(二)——k近邻法 iwehdio的博客园:https://www.cnblogs.com/iwehdio/ 1.定义 k近邻法假设给定一个训练数据集,其中的实例类别已定 ...

随机推荐

  1. Java中private、protected、public和default的区别-001

    public: 具有最大的访问权限,可以访问任何一个在classpath下的类.接口.异常等.它往往用于对外的情况,也就是对象或类对外的一种接口的形式. protected: 主要的作用就是用来保护子 ...

  2. linux之磁盘配额(quota)使用方法(转)

    1.什么是quota 简单的说就是限制用户对磁盘空间的使用量. 因为Linux是多用户多任务的操作系统,许多人共用磁盘空间,为了合理的分配磁盘空间,于是就有了quota的出现. 2.quota的用途  ...

  3. tomcat优化方案(转)

    1.内存设置(VM参数调优) (1).Windows环境下,是tomcat解压版(执行startup.bat启动tomcat) ,解决办法: 修改“%TOMCAT_HOME%\bin\catalina ...

  4. Apache, service httpd stop, Address already in use:

    service httpd stopStopping httpd:                                            [FAILED][root@testtest ...

  5. Vue中使用百度地图——设置地图标注

    知识点:创建Map实例,为指定的位置设置标注 参考博客:https://www.cnblogs.com/liuswi/p/3994757.html 1.效果图:初始化地图,设置指定经纬度为地图中心点坐 ...

  6. 01_MySQL DQL_基础查询

    DQL,Data Query Language,数据查询 # 基础查询/*语法:select 查询列表 from 表名: 特点:1.查询列表可以是:表中的字段,常量值.表达式.函数,也可以是多个组合2 ...

  7. Python基础笔记系列十:模块

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 模块 #1.类比于java中的jar包,模块能让你能够有逻辑地组织你的Py ...

  8. web项目整合Shiro框架

    1.修改pom.xml文件 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>s ...

  9. pwm计时器

    1 PWM timer定时器与(watchdog差不多)2 5个16位的定时器,独立的,其中,NO PIN 没有输出.16表示ffff,和ADC中10表示3FF一样.而寄存器都是32位.(以后6410 ...

  10. double int char long 等数据类型所占的字节数-----待整理