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

通过上文可知感知机模型的基本原理,以及算法的具体流程。本文实现了感知机模型算法的原始形式,通过对算法的具体实现,我们可以对算法有进一步的了解。具体代码可以在我的github上查看。

代码

#!/usr/bin/python3
# -*- coding:utf-8 -*-

import sys
import numpy as np

class Kdtree(object):
    ‘‘‘
    类名: Kdtree
    用于存储kd树的数据
    成员:
    __value: 训练数据,保存数据点的坐标
     __type: 保存点对应的类型
      __dim: 保存当前kd树节点的切分平面维度
       left: 左子树
      right: 右子树
    ‘‘‘
    def __init__(self, node = None, node_type = -1, dim = 0, left = None, right = None):
        self.__value = node
        self.__type  = node_type
        self.__dim   = dim
        self.left    = left
        self.right   = right

    @property
    def type(self):
        return self.__type

    @property
    def value(self):
        return self.__value

    @property
    def dim(self):
        return self.__dim

    def distance(self, node):
        ‘‘‘
        计算当前节点与传入节点之间的距离
        参数:
        node: 需要计算距离的节点
        ‘‘‘
        if node == None:
            return sys.maxsize

        dis = 0
        for i in range(len(self.__value)):
            dis = dis + (self.__value[i] - node.__value[i]) ** 2
        return dis

    def build_tree(self, nodes, dim = 0):
        ‘‘‘
        利用训练数据建立一棵kd树
        参数: nodes: 训练数据集
                dim: 树的切分平面维度
        return: a kd-tree
        ‘‘‘
        if len(nodes) == 0:
            return None
        elif len(nodes) == 1:
            self.__dim  = dim
            self.__value = nodes[0][:-1]
            self.__type  = nodes[0][-1]
            return self

        #将数据集按照第dim维度的值的大小进行排序
        sortNodes = sorted(nodes, key = lambda x:x[dim], reverse = False)

        #排序后,中间的点为当前节点值
        midNode      = sortNodes[len(sortNodes) // 2]
        self.__value = midNode[:-1]
        self.__type  = midNode[-1]
        self.__dim   = dim

        leftNodes  = list(filter(lambda x: x[dim] < midNode[dim], sortNodes[:len(sortNodes) // 2]))
        rightNodes = list(filter(lambda x: x[dim] >= midNode[dim], sortNodes[len(sortNodes) // 2 + 1:]))
        nextDim    = (dim + 1) % (len(midNode) - 1)

        self.left  = Kdtree().build_tree(leftNodes, nextDim)
        self.right = Kdtree().build_tree(rightNodes, nextDim)

        return self

    def find_type(self, fnode):
        ‘‘‘
        在kd树内查找传入点的最近邻点和对应的类型
        参数: fnode: 需要判断类型的点
        return: fnode的最近邻点和其类型
        ‘‘‘
        if fnode == None:
            return self, -1

        fNode = Kdtree(fnode)

        #首先搜索整棵树到达叶子节点
        path = []
        currentNode = self
        while currentNode != None:
            path.append(currentNode)

            dim   = currentNode.__dim
            if fNode.value[dim] < currentNode.value[dim]:
                currentNode = currentNode.left
            else:
                currentNode = currentNode.right

        #path的最后一个节点即为叶子节点
        nearestNode = path[-1]
        nearestDist = fNode.distance(nearestNode)
        path = path[:-1]

        #向上进行回溯
        while path != None and len(path) > 0:
            currentNode = path[-1]
            path = path[:-1]
            dim  = currentNode.__dim

            #判断当前点是否比最近点更近
            if fNode.distance(currentNode) < nearestDist:
                nearestNode = currentNode
                nearestDist = fNode.distance(currentNode)

            #当前最近点一定存在于当前点的一棵子树上,那么找到它的兄弟子树的节点
            brotherNode = currentNode.left
            if fNode.value[dim] < currentNode.value[dim]:
                brotherNode = currentNode.right

            if brotherNode == None:
                continue

            #若兄弟子树的节点对应的区域与以fnode为圆心,以nearestDist为半径的圆相交,则进入兄弟子树,进行递归查找
            bdim = brotherNode.__dim
            if np.abs(fnode[bdim] - brotherNode.__value[bdim]) < nearestDist:
                cNode, _ = brotherNode.find_type(fnode)
                if fNode.distance(cNode) < nearestDist:
                    nearestDist = fNode.distance(cNode)
                    nearestNode = cNode

        return nearestNode, nearestNode.type

if __name__ == "__main__":

   #训练数据集
   trainArray = [[1.0, 1.0, ‘a‘], [1.1, 1.1, ‘a‘], [1.5, 1.5, ‘a‘],            [5.0, 5.0, ‘b‘], [5.2, 5.2, ‘b‘], [5.5, 5.5, ‘b‘],            [3.0, 2.5, ‘c‘], [3.1, 2.8, ‘c‘], [3.2, 2.4, ‘c‘]]

   kdtree = Kdtree().build_tree(trainArray)

   #test1
   testNode = [1.6, 1.5]
   _, testType = kdtree.find_type(testNode)
   print("the type of ", testNode, "is ", testType)

   #test2
   testNode = [3.5, 2.7]
   _, testType = kdtree.find_type(testNode)
   print("the type of ", testNode, "is ", testType)

   #test3
   testNode = [4.3, 5.1]
   _, testType = kdtree.find_type(testNode)
   print("the type of ", testNode, "is ", testType)

测试结果

通过测试结果可知,kd树可以有效地对输入数据进行类型的识别。

讨论

虽然通过测试结果正确,但代码依然存在许多需要改进的地方,如kd树的选择,可以通过改进为红黑平衡树,来提高搜索速度。以及对于树的每层切分平面的维度选择,可以选择各维度中方差最大的维度,这样在此维度下的点分布更加分散,使后续的查找难度更小等等。

原文地址:https://www.cnblogs.com/zhiyuxuan/p/9636069.html

时间: 2024-07-30 13:36:29

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

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): sel

《统计学习方法》:第三章 K 近邻算法

k -- NN k--NN 是一种基本分类和回归方法.对新实例进行分类时,通过已经训练的数据求出 k 个最近实例,通过多数表决进行分类.故 k 邻近算法具有不显式的学习过程. 三个基本要素:k 值选择,距离度量,分类决策规则. 1. k 近邻算法 原理:给定一个训练集,对于新输入的实例,在训练集中找到与其相似的 k 个实例,这 k 个实例的多数属于某一类,就将该实例归属到这一类. 输入:训练数据集 \(T = \{(x_1,y_1),(x_2,y_2),...,(x_3,y_3)\}\) 其中,

李航统计学习方法——算法2——k近邻法

一.K近邻算法 k近邻法(k-nearest neighbor,k-NN)是一种基本分类与回归方法,输入实例的特征向量,输出实例的类别,其中类别可取多类 二.k近邻模型 2.1 距离度量 距离定义: (1)当p=1,称为曼哈顿距离 (2)当p=2,称为欧式距离 (3)当p取无穷大时,它是各个坐标距离的最大值 max|xi-xj| 注意:p值的选择会影响分类结果,例如二维空间的三个点 x1=(1,1),x2=(5,1), x3=(4,4) 由于x1和x2只有第二维上不同,不管p值如何变化,Lp始终

统计学习三要素

原文链接:https://www.mlpod.com/mlbase/23.html 三要素:方法=模型+策略+算法. 1.1 模型 在监督学习过程中,模型就是所要学习的条件概率分布或决策函数.假设空间用$\mathcal{F}$表示,假设空间可以定义为$$\mathcal{F} = \left\{ {f|Y = {f_\theta }\left( X \right),\theta \in {\mathbb{R}^n}} \right\}$$或$$\mathcal{F} = \left\{ {P|

【学习笔记】K近邻归类算法

# -*- coding:utf-8 -*- __author__ = 'Ghostviper' """ K近邻归类算法 """ from numpy import * import operator def createDataset():     group = array([         [1.0, 1.1],         [1.0, 1.0],         [0, 0],         [0, 0.1]     ])    

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

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

机器学习 —— 基础整理(三):非参数方法——Parzen窗估计、k近邻估计;k近邻分类器

本文简述了以下内容: (一)非参数方法 (二)Parzen窗估计 (三)k近邻估计 (四)k近邻算法(k-nearest neighbor,kNN) (一)非参数方法(Non-parametric method) 对于生成模型来说,重要的地方在于类条件概率密度 $p(\textbf x|\omega_i)$ 的估计.上一篇介绍的参数方法,假定其是一个固定的分布密度形式,然后估计这个显式表达的函数中未知的参数.但这里存在两个问题:首先,假定的形式可能是不准确的,实际数据并不符合这个假设:其次,经典

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

近邻法(-nearest neighbor, -NN)是一种基本的分类方法. 近邻法假设给定一个数据集,其中的样例类别已定.分类时,对新的样例,根据这个新样例的个最近邻的训练样例的类别,通过多数表决等方式进行预测. 因此,近邻法不具有显式的学习过程.值的选择.距离度量及分类决策规则是近邻法的三个基本要素. 近邻法于1968年由Cover和Hart提出. 给定训练集并且训练集,一共个样本,个维度,用表示数据集中的第个样本,用表示标记(类别)向量,代表第个样本的标记. 我们这时候要预测一个测试样例的

机器学习算法系列(1):K近邻

一.K近邻算法 K近邻算法简单.直观.首先给出一张图,根据这张图来理解最近邻分类器. 根据上图所示,有两类不同的样本数据,分别用蓝色的小正方形和红色的小三角形表示,而图正中间的那个绿色的圆所标示的数据则是待分类的数据.也就是说,现在,我们不知道中间那个绿色的数据是从属于哪一类(蓝色小正方形或者红色小三角形),下面,我们就要解决这个问题:给这个绿色的圆分类. 我们常说,物以类聚,人以群分,判别一个人是一个什么样的人,常常可以从他身边的朋友入手,所谓观其友,而识其人.我们不是要判别上图中那个绿色的圆