基础知识:
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树这一部分就实现了。