首页 > 编程语言 >机器学习——K近邻算法-kd(简化因数据过过多而造成的搜索复杂度大)

机器学习——K近邻算法-kd(简化因数据过过多而造成的搜索复杂度大)

时间:2023-11-25 19:22:55浏览次数:28  
标签:node kd 复杂度 sortDataSet 过过 depth data self axis

kd树是为了减少搜索最近邻点的时间复杂度,一般来说可以使用穷举法,但是太耗时,因此采用平衡二叉树的思想来解决这个问题

"""
This is the implementation of Knn(KdTree),
which is accessible in https://github.com/FlameCharmander/MachineLearning,
accomplished by FlameCharmander,
and my csdn blog is https://blog.csdn.net/tudaodiaozhale,
contact me via [email protected].
"""
import numpy as np
class Node:
    def __init__(self, data, lchild = None, rchild = None):
        self.data = data
        self.lchild = lchild
        self.rchild = rchild
 
class KdTree:
    def __init__(self):
        self.kdTree = None
 
    def create(self, dataSet, depth):   #创建kd树,返回根结点
        if (len(dataSet) > 0):
            m, n = np.shape(dataSet)    #求出样本行,列
            midIndex = int(m / 2) #中间数的索引位置
            axis = depth % n    #判断以哪个轴划分数据
            sortedDataSet = self.sort(dataSet, axis) #进行排序
            node = Node(sortedDataSet[midIndex]) #将节点数据域设置为中位数,具体参考下书本
            # print sortedDataSet[midIndex]
            leftDataSet = sortedDataSet[: midIndex] #将中位数的左边创建2改副本
            rightDataSet = sortedDataSet[midIndex+1 :]
            print(leftDataSet)
            print(rightDataSet)
            node.lchild = self.create(leftDataSet, depth+1) #将中位数左边样本传入来递归创建树
            node.rchild = self.create(rightDataSet, depth+1)
            return node
        else:
            return None
 
    def sort(self, dataSet, axis):  #采用冒泡排序,利用aixs作为轴进行划分
        sortDataSet = dataSet[:]    #由于不能破坏原样本,此处建立一个副本
        m, n = np.shape(sortDataSet)
        for i in range(m):
            for j in range(0, m - i - 1):
                if (sortDataSet[j][axis] > sortDataSet[j+1][axis]):
                    temp = sortDataSet[j]
                    sortDataSet[j] = sortDataSet[j+1]
                    sortDataSet[j+1] = temp
        print(sortDataSet)
        return sortDataSet
 
    def preOrder(self, node):
        if node != None:
            print("tttt->%s" % node.data)
            self.preOrder(node.lchild)
            self.preOrder(node.rchild)
 
    # def search(self, tree, x):
    #     node = tree
    #     depth = 0
    #     while (node != None):
    #         print node.data
    #         n = len(x)  #特征数
    #         axis = depth % n
    #         if x[axis] < node.data[axis]:
    #             node = node.lchild
    #         else:
    #             node = node.rchild
    #         depth += 1
    def search(self, tree, x):
        self.nearestPoint = None    #保存最近的点
        self.nearestValue = 0   #保存最近的值
        def travel(node, depth = 0):    #递归搜索
            if node != None:    #递归终止条件
                n = len(x)  #特征数
                axis = depth % n    #计算轴
                if x[axis] < node.data[axis]:   #如果数据小于结点,则往左结点找
                    travel(node.lchild, depth+1)
                else:
                    travel(node.rchild, depth+1)
 
                #以下是递归完毕后,往父结点方向回朔
                distNodeAndX = self.dist(x, node.data)  #目标和节点的距离判断
                if (self.nearestPoint == None): #确定当前点,更新最近的点和最近的值
                    self.nearestPoint = node.data
                    self.nearestValue = distNodeAndX
                elif (self.nearestValue > distNodeAndX):
                    self.nearestPoint = node.data
                    self.nearestValue = distNodeAndX
 
                print(node.data, depth, self.nearestValue, node.data[axis], x[axis])
                if (abs(x[axis] - node.data[axis]) <= self.nearestValue):  #确定是否需要去子节点的区域去找(圆的判断)
                    if x[axis] < node.data[axis]:
                        travel(node.rchild, depth+1)
                    else:
                        travel(node.lchild, depth + 1)
        travel(tree)
        return self.nearestPoint
 
    def dist(self, x1, x2): #欧式距离的计算
        return ((np.array(x1) - np.array(x2)) ** 2).sum() ** 0.5
 
dataSet = [[2, 3],
           [5, 4],
           [9, 6],
           [4, 7],
           [8, 1],
           [7, 2]]
x = [3, 4.5]
kdtree = KdTree()
tree = kdtree.create(dataSet, 0)
kdtree.preOrder(tree)
print(kdtree.search(tree, x))

 

标签:node,kd,复杂度,sortDataSet,过过,depth,data,self,axis
From: https://www.cnblogs.com/copyjames/p/17855924.html

相关文章

  • linux 中 mkdir -p选项
     mkdir-p选项保证在创建目录的时没有上一级目录情况下自动创建001、不加-p选项(base)[root@pc1test]#ls(base)[root@pc1test]#mkdirtest01/test02##不加-p,创建两级目录,失败mkdir:cannotcreatedirectory‘test01/test02’:Nosuchfileordirector......
  • Markdown入门教程
    在这个网络时代,每个人多少都得掌握一些互联网编辑语言,今天我就从0开始,带着大家入门一个比较简单的编辑语言——MarkdownMarkdown是一种轻量级标记语言,排版语法简洁,让人们更多地关注内容本身而非排版。它使用易读易写的纯文本格式编写文档,可与HTML混编,可导出HTML、PDF以及本身......
  • 时间复杂度与空间复杂度
    时间复杂度:主要衡量的是一个算法的运行速度。空间复杂度:主要衡量一个算法所需要的额外空间。在计算机发展的早期,计算机的存储容量很小,所以对空间复杂度很是在乎。但是随着计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法......
  • kde桌面不同分辨率的显示器设置不同缩放
    kde桌面不同分辨率的显示器设置不同缩放xrandr命令可以查看当前使用的显示器名称#!/bin/bash#你可以在kde设置里先把你的主显器分辨率缩放比例设置好。在运行下面的命令。并不会影响你设置里的分辨率。简单的讲下面的命令会按你设置里真是生成的分辨率去计算#设置eDP-1显示器......
  • 如何使用markdown写毕业论文
    step1:pandoc:https://github.com/jgm/pandoc/releasesstep2:pandoc-crossref:https://github.com/lierdakil/pandoc-crossref/releasesstep3:pip3installgit+https://github.com/pandocker/pandoc-docx-pagebreak-py......
  • 玩转开源 | 搭建 Hugo 管理 Markdown 文档
    在工作、学习中,不可避免会要写一些文档;又或者想搭建个简单网站,记录和分享您的生活经验或知识;撰写这些文档中使用markdown是一个非常不错的选择,让我们更加聚焦在文档表达的内容上。实际上笔者的文档基本都是在Sublime中用markdown格式撰写的。在先前文章《Markdown的那些......
  • Markdown学习
    Markdown学习1.标题语法:#+空格一级标题(#+空格),二级标题(##+空格)以此类推2.字体语法:字体前后加**是字体加粗如:Hello,World!语法:字体前后加*是字体斜体如:Hello,World!语法:字体前后加***是字体加粗斜体如:Hello,World!语法:字体前后加~~是废弃如:Hello,World3.引用语......
  • pycharm 中 markdown 数学公式无法显示怎么办
    pycharm自带的markdown确实一大堆问题,公式显示不出来,插件主页里一堆差评。如果确实要在python里用markdown,并且要在markdown里用公式的话,建议去下载一个MarkdownEditor插件。 ......
  • markdown小技巧
    一些markdown快捷键1-6级标题代码方法#+空格+内容---》几个#号就是几级标题快捷键ctrl+字母键上面的数字键12---6(有序列表)ctrl+shift+[(无序列表)ctrl+shift+]-+空格快速插入代码英文模式下的三个```language比如```python使用快......
  • MarkDown学习
    标题三级标题四级标题字体Hello,World!Hello,World!Hello,World!Hello,World!引用勇敢的人先享受世界分割线图片超链接点击跳转到博客列表ABCABC表格姓名性别生日张三男2000-1-1代码public......