机器学习算法手撕(一):KD树

import math
import matplotlib.pyplot as plt

class Node:
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

# 创建KDTree类
class KDTree:
    def __init__(self, k):
        self.k = k
    def create_tree(self,dataset,depth):
        if not dataset:
            return None
        mid_index=len(dataset)//2  # 中位数
        axis = depth%self.k  # 按照哪个坐标轴划分
        sorted_dataset = sorted(dataset,key=(lambda x : x[axis])) # 按照坐标轴划分
        mid_data = sorted_dataset[mid_index]#中位数数据值
        current_node = Node(mid_data)  # 创建当前节点
        left_data = sorted_dataset[:mid_index]  # 划分左节点数据
        right_data = sorted_dataset[mid_index+1:]  # 划分右节点数据
        current_node.left = self.create_tree(left_data,depth+1)  # 创建左子树
        current_node.right = self.create_tree(right_data,depth+1) # 创建右子树
        return current_node

    def search(self, tree, new_data):
        self.nearest_point = None  # 当前最邻近点
        self.nearest_val = None # 当前最邻近点与目标节点间距离

        def dfs(node,depth): # 深度优先搜索
            # 递归找叶子节点
            if not node:
                return None
            axis = depth % self.k
            if new_data[axis] < node.data[axis]:
                dfs(node.left,  depth+1)
            else:
                dfs(node.right, depth+1)

            # 比较距离,判断是否更新最近邻点
            dist = self.distance(new_data,node.data)
            if not self.nearest_val or dist<self.nearest_val:
                self.nearest_val = dist
                self.nearest_point = node.data

            # 判断是否遍历该节点另一边子树
            if abs(new_data[axis]-node.data[axis]) <= self.nearest_val:  # 计算父节点在其分割特征上的data距离目标点在该特征上的data的距离。若该距离小于 nearest_val,则进入另一个孩子节点,否则不进入
                if new_data[axis] < node.data[axis]:  # 之前若先遍历左子树,现在就要遍历右子树
                    dfs(node.right, depth+1)
                else:
                    dfs(node.left, depth+1)

        dfs(tree, 0)
        return self.nearest_point


    def distance(self,new_data, new_val):
        res = 0
        for i in range(self.k):
            res += (new_data[i]-new_val[i])**2
        return math.sqrt(res)


if __name__ == '__main__':
    data_set = [[3,3],[5,4],[5,6],[2,7],[9,1],[2,5],[3,2],[2,0]
    new_data = [2,9]
    k = len(data_set[0])
    kd_tree = KDTree(k)
    our_tree = kd_tree.create_tree(data_set,0)
    predict = kd_tree.search(our_tree,new_data)
    print(f"Nearest Point of {new_data} is {predict}")
    plt.scatter([x[0] for x in data_set],[x[1] for x in data_set],c='purple',label='train_data')
    plt.scatter(new_data[0],new_data[1],c='red',label='target_data')
    plt.plot([predict[0], new_data[0]], [predict[1],new_data[1]], c='green',label='Nearest Point',linestyle='--')
    plt.legend()
    plt.show()

  • Node类用于表示KD树的节点。
  • data保存当前节点的数据点。
  • leftright分别指向左子树和右子树。
  • KDTree类用于创建和操作KD树。
  • k表示数据点的维度。
  • create_tree方法用于递归地创建KD树。
  • dataset是要构建树的数据集。
  • depth表示当前节点的深度,用于确定划分的轴。
  • 根据深度计算轴并排序数据集,选择中位数作为当前节点的数据点。
  • 递归地创建左子树和右子树。

  

  • search方法用于在KD树中查找离new_data最近的点。
  • self.nearest_pointself.nearest_val用于保存当前找到的最近点及其距离。
  • 定义深度优先搜索dfs函数,递归地搜索树,更新最近点和距离。
  • 检查是否需要遍历另一边的子树。
  • 主程序创建数据集data_set和要查找的点new_data
  • 初始化KDTree实例并创建KD树。
  • 使用search方法查找最近点并打印结果。
  • 使用matplotlib绘制数据点和最近邻点的连线。

参考文献Kd Tree算法详解_kd-tree-CSDN博客

Python手撸机器学习系列(十一):KNN之kd树实现_knn原理及python代码实现建立kd树-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/648174.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【DAOS】daos client和dfuse 是什么?

目录 什么是daos client dfuse 是什么 dfuse 和 FUSE 之间的关系 什么是daos client &#xff08;参加&#xff1a;DAOS: A Scale-Out High Performance Storage Stack for Storage Class Memory | SpringerLink&#xff09; DAOS Client是一个与应用程序集成的库。 从堆栈…

堆(建堆算法,堆排序)

目录 一.什么是堆&#xff1f; 1.堆 2.堆的储存 二.堆结构的创建 1.头文件的声明&#xff1a; 2.向上调整 3.向下调整 4.源码&#xff1a; 三.建堆算法 1.向上建堆法 2.向下建堆法 四.堆排序 五.在文件中Top出最小的K个数 一.什么是堆&#xff1f; 1.堆 堆就…

【docker】仓库harbor的部署

harbor介绍 Harbor 是一个用于存储和管理 Docker 镜像的开源仓库。它提供了一系列的功能&#xff0c;比如用户管理、访问控制、镜像管理、日志审计和安全扫描等。Harbor 可以作为私有仓库来使用&#xff0c;也可以与公有仓库&#xff08;如 Docker Hub&#xff09;集成使用。 …

03.tomcat环境搭建

上传软件包 JDK #man bash #PATH 存放命令的路径 ## ls #加入环境变量&#xff0c;注意&#xff1a;EOF的单引号的意思就是追加到文件中的内容带有变量的不做解析&#xff0c;否则会被解析 cat >>/etc/profile <<EOF export JAVA_HOME/application/jdk export PAT…

华为OD机试 - 寻找最富裕的小家庭(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

Python 开心消消乐

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

M00238-固定翼无人机集群飞行仿真平台MATLAB完整代码含效果

一个小型无人机集群仿真演示平台&#xff0c;使用matlab和simulink搭建。 给出的例子是5架的&#xff0c;当然如果你愿意花时间&#xff0c;也可以把它扩展到10架&#xff0c;20架甚至更多。 输入&#xff1a;5架飞机的规划路径 输出&#xff1a;每架无人机每个时刻的13个状态量…

【模拟面试问答】深入解析力扣164题:最大间距(桶排序与排序方法详解)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

【C++】从零开始构建红黑树

送给大家一句话&#xff1a; 日子没劲&#xff0c;就过得特别慢&#xff0c;但凡有那么一点劲&#xff0c;就哗哗的跟瀑布似的拦不住。 – 巫哲 《撒野》 &#x1f30b;&#x1f30b;&#x1f30b;&#x1f30b;&#x1f30b;&#x1f30b;&#x1f30b;&#x1f30b; ⛰️⛰️…

指针(6)

1. sizeof和strlen的对比 1.1 sizeof 在学习操作符的时候&#xff0c;我们学习了 sizeof &#xff0c; sizeof 计算变量所占内存内存空间大小的&#xff0c;单位是字节&#xff0c;如果操作数是类型的话&#xff0c;计算的是使⽤类型创建的变量所占内存空间的大小。 sizeof 只…

leetcode:计数质数

class Solution { public:// 如果 x 是质数&#xff0c;那么大于 x 的 x 的倍数 2x,3x… 一定不是质数int countPrimes(int n) {vector<int> isPrime(n, 1);int ans 0;for (int i 2; i < n; i) {if (isPrime[i]) {ans 1;if ((long long)i * i < n) {for (int j …

Linux内核重置root密码

Ubuntu 首先重新启动Ubuntu系统&#xff0c;然后快速按下shift键&#xff0c;以调出grub启动菜单在这里我们选择第二个&#xff08;Ubuntu高级选项&#xff09;&#xff0c;选中后按下Enter键 选择最高的Linux内核版本所对应的recovery mode模式&#xff0c;按e键编辑启动项 在…

C语言 | Leetcode C语言题解之第113题路径总和II

题目&#xff1a; 题解&#xff1a; int** ret; int retSize; int* retColSize;int* path; int pathSize;typedef struct {struct TreeNode* key;struct TreeNode* val;UT_hash_handle hh; } hashTable;hashTable* parent;void insertHashTable(struct TreeNode* x, struct Tr…

数据结构——链表——模板类实现双向链表——先完成再完美——持续更

链表&#xff1a;概念&#xff0c;实现&#xff0c;《数据结构》这里实现是基于模板的 C语言基础&#xff0c;指针&#xff0c;引用。模板。《CPrimer》有些进阶用法放在语言学习的目录 LeetCode应用&#xff0c;会更新在LeetCode150&#xff0c;目前这个系列先暂停&#xff0c…

【PB案例学习笔记】-09滚动条使用

写在前面 这是PB案例学习笔记系列文章的第8篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gitee…

云界洞见——基于移动云云数据库MySQL应用实践

目录 简介1 新手入门1.1 创建MySQL实例1.2 公网连接MySQL实例 2 操作指南2.1 创建数据库2.2 数据备份设置2.3 日志管理2.4 监控告警2.5 代码审计 3 应用场景4 总结 如今&#xff0c;大型企业如金融企业和银行等&#xff0c;在下一代的微服务架构转型要求下&#xff0c;需要基础…

C++ prime 第五版 第14章 重载运算与类型转换

一、基本概念 重载的运算符是具有特殊名字的函数&#xff1a;它们的名字由关键字operator和其后要定义的运算符号共同组成。和其他函数一样&#xff0c;重载的运算符也包含返回类型、参数列表以及函数体。 我们不能为内置类型的运算对象重定义运算符。对于一个运算符函数来说&…

【Week-R1】RNN实现心脏病预测,基于tensorflow框架

文章目录 一、什么是RNN&#xff1f;二、准备环境和数据2.1 导入数据 三、构建模型四、训练和预测五、其他&#xff08;1&#xff09;sklearn模块导入报错&#xff1a;ModuleNotFoundError: No module named sklearn&#xff08;2&#xff09;优化器改为SGD&#xff0c;accurac…

MySQL--备份恢复

目录 一、备份恢复的工作职责 1.备份的时间周期 2.备份的方式 3.恢复方案 4.检查备份 5.定期恢复演练 6.故障恢复策略 7.迁移升级 二、逻辑备份工具--mysqldump 1.介绍 2.使用场景 3.mysqldump命令的参数介绍 1&#xff09;全备&#xff1a; 2&#xff09;单库或…

四轮麦轮平衡车四个轮子安放位置要求,以及编码器测速注意事项(强调,否则无法正常平移)——基于STM32F103ZET6

轮子推荐ABBA&#xff0c;当然BAAB也可以 如图安放&#xff1a; 这两种安防位置可以实现平移效果 若要实现平移则需要先实现PID控制平衡&#xff0c;这里用到520编码电机&#xff0c;相较于370电机他的动力更足&#xff0c;在调节PID时能节约不少时间而且更加容易。 需要注意…