基于kd树的KNN算法的实现

本文介绍了作者基于kd树实现KNN算法的过程,用于自动识别数字。算法简单直观,通过构建和搜索kd树提高效率。程序运行效果良好,识别近千个数字错误率约为1%。
摘要由CSDN通过智能技术生成

记得大三初期,刚从大连理工大学回来,眼巴巴的望着同学各自都有着落了,就我一副“初出茅庐,不谙世事”的样子,于是不得不觍着脸厚着皮去找老师,恳求他让我去海洋所实习。他给我的第一份差事便是将几个G的图片里的数字输入到excel,我整整输了一个国庆节假日。当时就在到处询问,有没有那种算法可以让自动识别图片里的数字,存入到excel中去,想来,那时的自己也是够拼的。
如今这个自动识别数字的算法算是写出来了吧, 我至少可以这样自我安慰到。
KNN算法的理论算的上是最简单最直观的一种了,比起前几次的支持向量机、贝叶斯、逻辑斯特回归那是简单太多了,都不用推导半个公式。这周的核心都是在完成k-近邻中kd树的构建和搜索,几乎都是自己完成的,也没有经过周密的测试,只是调试调通了。
我想,它的用例定不止于此,但这个用例说出去可谓是最唬人的了。
识别下面的“图片”为数字2 0 8

原理就不多讲了,感兴趣的网上都有,理论很简单,只是构建和搜索kd树可能会有些麻烦,而kd树只是为了让它运行的更快,其实用最简单粗暴的方法计算目标点与每个训练集点的距离也未尝不可。

程序运行的效果还行,识别近千个数字只错了10个,错误率1%左右。效果如下,为了好看,我就仅截图出识别几个数字的效果:

下面为实现的程序,注释写的很明白,训练数据在网上也不难找到:

KnnHelper.py

import numpy as np
'''
Created on 2017年7月17日

@author: fujianfei
'''

class KDNode(object):
    '''
    定义KD节点:
    point:节点里面的样本点,指的就是一个样本点
    split:分割纬度(即用哪个纬度的数据进行切分,比如4维数据,split=3,则表示按照第4列的数据进行切分空间)
    left:节点的左子节点
    right:节点的右子节点
    '''


    def __init__(self, point=None, split=None, left=None, right=None):
        '''
        Constructor
        '''
        self.point = point
        self.split = split
        self.left = left
        self.right = right


class KDTree(object):
    '''
    定义:
    KDNode:kd-tree的节点
    dimensions:数据的纬度
    right:节点的右子节点
    left:节点的左子节点
    curr_axis:当前需要切分的纬度
    next_axis:下一次需要切分的纬度
    '''


    def __init__(self, data=None):
        '''
        Constructor
        '''        
        def createNode(split=None, data_set=None):
            '''
            创建KD节点
            输入值:split:分割纬度 data_set:需要分割的样本点集合
            返回值:KDNode:KD节点
            '''
            if  len(data_set) == 0:    # 数据集为空,作为递归的停止条件
                return None
            #找到split维的中位数median,先对数据进行排序,按照split维的数据大小排序
            data_set = list(data_set)
            data_set.sort(key=lambda x: x[split])#对data_set进行排序,lambda是隐函数,具体用法请百度。排序方式为按照split维的数据大小排序
            data_set = np.array(data_set)
            median = len(data_set) // 2#//为python的整数除法,找到中间点的位置median,按照这个位置进行空间切分
            #返回KD节点
            #输入的变量分别是:
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值