最近在学习《统计学习方法》(李航著)。在第三章K近邻法中,先一如既往地从统计学习的三要素(模型、策略、算法)介绍了k近邻法,接着讲述k近邻法的一个具体实现方法-kd树,包括kd树的构造和kd树的搜索。

但是,在kd树搜索部分,书中只给出了使用kd树进行最近邻搜索(NNS)的算法描述,而使用kd树进行k近邻搜索的算法描述被留作课后习题。

对于本书第三章课后习题中3.3使用kd树进行k近邻搜索的算法及实现,网上鲜有描述(可能是太简单了o_O)。

本文尝试对此题借助优先队列进行解答:

算法(用kd树的k近邻搜索)

•输入:已构造的kd树;目标点x;k值;

•输出:x的最近邻

•算法过程:构造优先队列L(最大优先队列,距离从小到大的顺序排队)

在树中找出包含目标点x的叶结点:从根结点递归访问kd树,若x当前维的坐标小于切分点的坐标,则移动到左子结点,否则移动到右子结点,直到子结点为叶结点

将此节点插入队列L,如果L长度大于k,则获取并删除队首元素

递归地向上回退,在每个结点进行以下操作

(a) 如果该结点保存的实例点比L队首更近,则将此节点插入队列L,如果L长度大于k,则获取并删除队首元素

(b) 检查该子结点的父结点的另一子结点对应的区域是否有比L队首更近的点。

具体地,检查另一子结点对应的区域是否与以“L队首结点”为球心、以目标点与“L队首结点”间的距离为半径的超球体相交

如果相交,可能在另一个子结点对应的区域内存在距离“L队首结点”更近的点,移动到另一个子结点.递归地进行k近邻搜索

如果不相交,向上回退

5. 当回退到根结点时,搜索结束,最后的L队列中的结点即为x的k近邻点

算法实现(python)

kd树结点表示为如下:

class KdNode(object):

def __init__(self):

self.element = None

self.split_dim = None

self.left = None

self.right = None

构建kd树

def construct_tree(X_train):

def construct(X_train, indices, depth):

split_dim = depth % X_train.shape[1]

cur_node = KdNode()

zipped_indices = list(zip(X_train[indices, split_dim], indices))

updated_array= median(zipped_indices)

cur_node.element = updated_array[len(indices) // 2][1]

cur_node.split_dim = split_dim

if len(indices) > 1:

left_indices = list(map(lambda x: x[1], updated_array[:len(indices) // 2]))

cur_node.left = construct(X_train, left_indices, depth + 1)

if len(indices) > 2:

right_indices = list(map(lambda x: x[1], updated_array[len(indices) // 2 + 1:]))

cur_node.right = construct(X_train, right_indices, depth + 1)

return cur_node

return construct(X_train, np.arange(X_train.shape[0]), 0)

kd树搜索k近邻(KNN类的方法)

def search_kdt(self, tree, data, queue):

if tree is None:

return

if data[tree.split_dim] <= self.X_train[tree.element,tree.split_dim]:

self.search_kdt(tree.left, data, queue)

else:

self.search_kdt(tree.right, data, queue)

queue.put((distance(self.X_train[tree.element,:], data, p = self.p), tree.element))

if queue.size() > self.n:

queue.get()

# check another child

max_in_k = queue.first()

axis_distance = abs(data[tree.split_dim] - self.X_train[tree.element, tree.split_dim])

if max_in_k[0] > axis_distance:

if data[tree.split_dim] <= self.X_train[tree.element, tree.split_dim]:

self.search_kdt(tree.right, data, queue)

else:

self.search_kdt(tree.left, data, queue)

KNN模型如下(PriorityQueue为优先队列,篇幅有限,不列出具体实现)

'''KNN model with kdtree'''

class KNN:

def __init__(self, n_neighbors=3, p=2):

"""parameter: n_neighbors 临近点个数parameter: p 距离度量"""

self.n = n_neighbors

self.p = p

self.X_train = None

self.y_train = None

self.kdt_root = None

def fit(self, X, Y):

self.X_train = X

self.y_train = Y

self.kdt_root = construct_tree(self.X_train)

def predict(self, X):

if self.X_train is None or self.y_train is None:

print("Model has not been trained before prediction")

return None

ret = np.zeros((X.shape[0]))

# 取出top n个点

features_set = set(self.y_train)

Y_features = len(features_set)

for i in range(X.shape[0]):

queue = PriorityQueue(op=lambda x, y: x[0] > y[0])

self.search_kdt(self.kdt_root, X[i, :], queue)

# k个近邻多数表决

counter = {}

for each_feature in features_set:

counter[each_feature] = 0

for each_index in queue.data():

counter[self.y_train[each_index[1]]] += 1

ret[i] = max(counter, key=counter.get)

return ret

java knn kd树_KD树实现KNN相关推荐

  1. java knn kd树_KNN算法之KD树(K-dimension Tree)实现 K近邻查询

    KD树是一种分割k维数据空间的数据结构,主要应用于多维空间关键数据的搜索,如范围搜索和最近邻搜索. KD树使用了分治的思想,对比二叉搜索树(BST),KD树解决的是多维空间内的最近点(K近点)问题.( ...

  2. [Leedcode][JAVA][第820题][字典树][Set]

    [问题描述] 给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A.例如,如果这个列表是 ["time", "me", "be ...

  3. java二叉树是什么_树的基本概念以及java实现二叉树

    树具有的特点有: (1)每个结点有零个或多个子结点 (2)没有父节点的结点称为根节点 (3)每一个非根结点有且只有一个父节点 (4)除了根结点外,每个子结点可以分为多个不相交的子树. 树的基本术语有: ...

  4. java树_Java树

    树(tree)是一种抽象数据类型(ADT),用来模拟具有树状结构性质的数据集合.它是由n(n>0)个有限节点通过连接它们的边组成一个具有层次关系的集合.把它叫做"树"是因为它 ...

  5. java工具:字典树(单词查找树/Trie树)的实现以及使用

    项目地址 https://github.com/kylin-hunter/k-dic 文章目录 项目地址 前言 一.字典树 二.使用步骤 1 引入库 1.1 编译并发布到本地 1.2 gradle ( ...

  6. KNN算法(二) sklearn KNN实践

    上次介绍了KNN的基本原理,以及KNN的几个窍门,这次就来用sklearn实践一下KNN算法. 一.Skelarn KNN参数概述 要使用sklearnKNN算法进行分类,我们需要先了解sklearn ...

  7. Trie(前缀树/字典树)及其应用

    from:https://www.cnblogs.com/justinh/p/7716421.html Trie,又经常叫前缀树,字典树等等.它有很多变种,如后缀树,Radix Tree/Trie,P ...

  8. 数据结构 多路查找树 ---------B树和B+树的简单介绍

    参考链接:微信公众号 程序员小灰 https://mp.weixin.qq.com/s/rDCEFzoKHIjyHfI_bsz5Rw https://mp.weixin.qq.com/s/jRZMMO ...

  9. hdu 4836 The Query on the Tree(线段树or树状数组)

    The Query on the Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  10. 二叉树 红黑树 B树 B+树的优缺点

    前言 在MySQL中,无论是Innodb还是MyIsam,都使用了B+树作索引结构(这里不考虑hash等其他索引).本文将从最普通的二叉查找树开始,逐步说明各种树解决的问题以及面临的新问题,从而说明M ...

最新文章

  1. 漫谈我国主流人工智能软件基础设施
  2. JAVA enum实现简单状态机功能
  3. 浙江万里学院计算机专业宿舍,浙江万里学院宿舍条件,宿舍几人间环境好不好(图片)...
  4. 转载 oracle12c 切换字符集
  5. 在 SAP 电商云 Spartacus UI 里使用自定义配置控制 UI 调试的开关
  6. 服务器程序的Xamarin-Java.Interop体验(一)
  7. oracle 11g新特性之IPS Packing demonstration
  8. Google的21道面试问题
  9. c# json 汉字乱码_C# 读取Json内的数据,中文乱码,怎么解决
  10. 相机标定原理介绍(一)
  11. 好用的源码行数统计工具——cloc
  12. mysql测评作业指导书_测评作业指导书
  13. Mahony 互补滤波
  14. 河北农业大学林学可转计算机系吗,河北农业大学专业排名,招生专业目录(10篇)...
  15. python 开发个人日常操作笔记
  16. Linux文件名包含小括号处理
  17. Android10power有哪些功能,Android 功耗(10)---电流波形图(power monitor)
  18. 基于Matlab的车牌识别系统完整版课论文分享 快看
  19. X86/X64汇编语言基础
  20. C++之一些事一些情--写在前面

热门文章

  1. webRTC初探:如何实现音视频的录制
  2. STAMP:扩增子、宏基因组统计分析神器(中文帮助文档)
  3. 正宗eMule官方网站导航
  4. 大型体检系统源码,PEIS医院体检管理系统源码
  5. 前端表白Html+css+js,表白源码,520和七夕告白,雪花爱心记录
  6. Word 电子签名简单制作方法
  7. 搜索不到投屏设备怎么办_投屏,搜索不到电视设备解决方案
  8. ae中合成设置的快捷键_提升AE效率的20个快捷键
  9. 1. 测度论-概率空间的基本概念
  10. 图算法(十一):紧密中心度算法(Closeness Centrality)【适用场景:社交网络中关键节点发掘】【计算一个节点到所有其他可达节点的最短距离的倒数再累积归一化】【值越大,节点越靠近图中心】