k近邻法及其实现

基础知识:

1、k近邻法的学习模型

k近邻法是基本且简单的分类与回归的方法,基本做法是:对给定的训练实例点和输入实例点,首先确定输入实例点的k个最近邻实例点,然后利用这k个训练实例点的类的多数来预测输入实例点的类,k近邻模型对应于基于训练数据集对特征空间的一种划分。在k近邻法中,当训练集、距离度量、k值及分类决策规则确定后,其结果唯一确定。

具体算法如下:

     

 

2、k近邻法的三要素

距离度量、k值的选择和分类决策规则。常用的距离度量是欧氏距离及更一般的Lp距离。k值小的时候,k近邻模型更复杂;k值打的时候,k近邻模型更简单。k值的选择反映了对近似误差与估计误差之间的权衡,通常由交叉验证选择最优的k。常用的分类决策策略是多数表决,对应于经验风险最小化。

3、k近邻法的实现

k近邻法实现的关键在于如何快速找到k个最近邻点。kd树是一种便于在k维空间中的数据进行快速检索的数据结构,是一种二叉树,表示对k维空间的一种划分,其每个节点对应于k维空间划分中的一个超矩形区域,从而可以省去对大部分数据点的搜索,从而减少搜索的计算量。

搭建kd树的过程与二叉树的过程差不多,都是一个递归的过程.

 

kd树的构建以及搜索代码实现:

T = [[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]]
 
# 定义节点类
class node:
    def __init__(self, point):
        self.left = None
        self.right = None
        self.point = point
        self.parent = None
        pass
 
    def set_left(self, left):
        if left == None: pass
        left.parent = self
        self.left = left
 
    def set_right(self, right):
        if right == None: pass
        right.parent = self
        self.right = right
 
 # 计算中位数
def median(lst):
    m = len(lst) / 2
    return lst[int(m)], int(m)
 
# 构建kd树
def build_kdtree(data, d):
    # 按照元组里面第d个元素进行排序  ,lambda隐函数固定写法,可不变  
    data = sorted(data, key=lambda x: x[d])
    p, m = median(data)
    tree = node(p)
 
    del data[m]
    
    # 递归搭建二叉树,不断在0和1之间循环排序
    if m > 0: tree.set_left(build_kdtree(data[:m], not d))
    if len(data) > 1: tree.set_right(build_kdtree(data[m:], not d))
    return tree
 
# 欧氏距离
def distance(a, b):
    print (a, b)
    return ((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) ** 0.5
 
# 搜索kd树
def search_kdtree(tree, d, target):
    best = [tree.point, 100000.0] # tree.point即为根节点,10000.0即为预设的很大的初始距离值
    if target[d] < tree.point[d]:
        if tree.left != None:
            return search_kdtree(tree.left, not d, target)
    else:
        if tree.right != None:
            return search_kdtree(tree.right, not d, target)
            
    # 不断更新最优值,也就是最小距离
    def update_best(t, best):
        if t == None: return
        t = t.point
        d = distance(t, target)
        if d < best[1]:
            best[1] = d
            best[0] = t
 
    # 从最底端子节点开始不断向上优化
    while (tree.parent != None):
        # 对比左子树和右子树与最优值,从而不断优化        
        update_best(tree.parent.left, best)
        update_best(tree.parent.right, best)
        tree = tree.parent
    return best[0]
 
 
kd_tree = build_kdtree(T, 0)
#print (kd_tree.point)
print (search_kdtree(kd_tree, 0, [9, 4]))

输出结果:

前三行是kd树搜索的具体步骤,可以看到距离在不断地被优化,最终找到了一个最优的与测试点[9,4]最近的点[9,6],至此kd树这一部分就实现了。

转载于:https://www.cnblogs.com/RiTianBigBrother/p/5846708.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值