书中存在的一些疑问

  • kd树的实现过程中,为何选择的切分坐标轴要不断变换?公式如:x(l)=j(modk)+1。有什么好处呢?优点在哪?还有的实现是通过选取方差最大的维度作为划分坐标轴,有何区别?

    • 第一种方法网上也没具体的解释,我不是很清楚其原因(可能要去论文上找原因)。
    • 不过第二种方法的话,方差越大,说明这个维度数据的相似性就越差,就越容易通过选取中点的方式将数据集分开,kd树的效率就越高,试想如果你挑了一个维度其中数据全为一样,那么kd树的建立过程就无法将使用挑选中位数的方法来达到,而且后面的kd树的搜索效率就和线性的没什么大的区别。
  • kd树实现加速查找的最近邻方法是:某个维度的中位数作为切分点,父节点与子节点的关系为其为其下面所有节点的在某个维度的中位数。

代码实现过程中的一些难点

  • kd树的实现也就是二叉树的实现过程。
  • kd树的搜索过程。二叉树的搜索还不是很清楚(枯辽)

具体代码实现:

import matplotlib.pyplot as plt
import numpy as np def ls(p):
# 返回左子节点
return p << 1 def rs(p):
# 返回右子节点
return p << 1 | 1 def build_kd_tree(data_x, tree, p, dim):
"""
建立二叉树的过程
:param data: 建立二叉树所需要的数据
:param tree: 存二叉树的数组
:param p: 所在的节点
:param dim: 现在所在的维度
:return: None
"""
# 根据dim对数据进行排序并取其中位数
# data[data[:,i].argsort()],根据第i维对数据进行排序
if len(data_x) == 1:
tree[p] = data_x
return
if len(data_x) == 0:
return
length = len(data_x[0]) - 1
data_x = data_x[data_x[:, dim].argsort()]
mid = len(data_x) >> 1
tree[p] = data_x[mid]
build_kd_tree(data_x[:mid, :], tree, ls(p), ((dim + 1) % length))
build_kd_tree(data_x[mid + 1:, :], tree, rs(p), ((dim + 1) % length))
return def find_leaf_node(data, tree):
# 从根节点出发,循环向下访问kd树,返回其叶子节点
p, dim, length = 1, 0, len(tree[1]) - 1
if tree[p, dim].sum() <= 0.0:
return 1
while True:
if data[dim] > tree[p, dim]:
if tree[rs(p), dim].sum() <= 0.0:
return p
p = rs(p)
else:
if tree[ls(p), dim].sum() <= 0.0:
return p
p = ls(p)
dim = (dim + 1) % length
return 1 def distance(a, b, p=1):
# 我只对数据进行p方运算,不进行开方运算
sum = 0
if p == 1:
c = a - b
else:
c = a - b
c=c.__pow__(p)
c=c.__abs__()
sum=c.sum()
return sum def find_label(data,tree,nowp,mer):
if tree[nowp].sum()<=0.0:
return
len_of_mer=len(mer)
len_of_data=len(data)
mer=mer[mer[:,0].argsort()]
dis=distance(data,tree[nowp,:-1])
if dis<=mer[0,0]:
for i in range(1,len_of_mer-2):
mer[i]=mer[i+1]
mer[0]=[dis,tree[nowp,-1]]
find_label(data,tree,ls(nowp),mer)
find_label(data,tree,rs(nowp),mer)
for i in range(1,len_of_mer):
if dis>mer[len_of_mer-i,0]:
if i!=1:
mer[len_of_mer-1]=[dis,tree[nowp,-1]]
find_label(data, tree, nowp >> 1, mer)
return def k_NN(data, tree, p, k):
label = np.zeros((len(data), 1))
for i in range(len(data)):
# 先找到其对应的叶子节点
#直接默认p=1吧,p对这个影响不是很大吧,主要是k的影响
pointer = find_leaf_node(data[i], tree)
mer=np.zeros((k,2))
for j in range(k):
mer[j,0]=9999999
find_label(data[i],tree,pointer,mer)
# d=np.argmax(np.bincount(int(mer[:,1])))
# label[i]=d
return label if __name__ == '__main__':
# train_x, train_y = np.load("data//train_x.npy"), np.load("data//train_y.npy")
# test_x, test_y = np.load("data//test_x.npy"), np.load("data//test_y.npy") # kd树的建立过程,即为二叉树的建立过程,只需要将二叉树对位置的划分变成对某个维度的排序再取其中位数位置的作为划分中点即可
# 下面为验证数据集,可以看到完美符合
train_x = np.array(((2, 3), (5, 4), (9, 6), (4, 7), (8, 1), (7, 2)))
train_y = np.array((4, 2, 3, 5, 6, 1))
# 为了防止操作过于繁琐,将标签直接加到数据的最后一列
test_x=np.array(((1,2),(3,4)))
data = np.insert(train_x, len(train_x[0]), train_y, axis=1)
tree = np.zeros(((len(train_x) << 2) + 10, len(data[0])))
build_kd_tree(data, tree, 1, 0)
p, k = 1, 4
test_label = k_NN(test_x, tree, p, k)
print(test_label)

第三章 K近邻法(k-nearest neighbor)的更多相关文章

  1. K近邻法(K-Nearest Neighbor,KNN)

    KNN是一种基本分类与回归方法,本篇只总结分类问题中的KNN. 输入:样本的特征向量,对应于特征空间中的点 输出:样本的类别,可取多类 算法思想:给定一个样本类别已知的训练数据集,对于新样本,根据其K ...

  2. 学习笔记——k近邻法

    对新的输入实例,在训练数据集中找到与该实例最邻近的\(k\)个实例,这\(k\)个实例的多数属于某个类,就把该输入实例分给这个类. \(k\) 近邻法(\(k\)-nearest neighbor, ...

  3. k近邻法(kNN)

    <统计学习方法>(第二版)第3章 3 分类问题中的k近邻法 k近邻法不具有显式的学习过程. 3.1 算法(k近邻法) 根据给定的距离度量,在训练集\(T\)中找出与\(x\)最邻近的\(k ...

  4. 《统计学习方法(李航)》讲义 第03章 k近邻法

    k 近邻法(k-nearest neighbor,k-NN) 是一种基本分类与回归方法.本书只讨论分类问题中的k近邻法.k近邻法的输入为实例的特征向量,对应于特征空间的点;输出为实例的类别,可以取多类 ...

  5. 统计学习方法(三)——K近邻法

    /*先把标题给写了.这样就能经常提醒自己*/ 1. k近邻算法 k临近算法的过程,即对一个新的样本,找到特征空间中与其最近的k个样本,这k个样本多数属于某个类,就把这个新的样本也归为这个类. 算法  ...

  6. 《统计学习方法》笔记三 k近邻法

    本系列笔记内容参考来源为李航<统计学习方法> k近邻是一种基本分类与回归方法,书中只讨论分类情况.输入为实例的特征向量,输出为实例的类别.k值的选择.距离度量及分类决策规则是k近邻法的三个 ...

  7. 统计学习三:1.k近邻法

    全文引用自<统计学习方法>(李航) K近邻算法(k-nearest neighbor, KNN) 是一种非常简单直观的基本分类和回归方法,于1968年由Cover和Hart提出.在本文中, ...

  8. 机器学习PR:k近邻法分类

    k近邻法是一种基本分类与回归方法.本章只讨论k近邻分类,回归方法将在随后专题中进行. 它可以进行多类分类,分类时根据在样本集合中其k个最近邻点的类别,通过多数表决等方式进行预测,因此不具有显式的学习过 ...

  9. k近邻法(二)

    上一篇文章讲了k近邻法,以及使用kd树构造数据结构,使得提高最近邻点搜索效率,但是这在数据点N 远大于 2^n 时可以有效的降低算法复杂度,n为数据点的维度,否则,由于需要向上回溯比较距离,使得实际效 ...

  10. K近邻法(KNN)原理小结

    K近邻法(k-nearst neighbors,KNN)是一种很基本的机器学习方法了,在我们平常的生活中也会不自主的应用.比如,我们判断一个人的人品,只需要观察他来往最密切的几个人的人品好坏就可以得出 ...

随机推荐

  1. 动态规划之最长公共子序列(LCS)

             在字符串S中按照其先后顺序依次取出若干个字符,并讲它们排列成一个新的字符串,这个字符串就被称为原字符串的子串          有两个字符串S1和S2,求一个最长公共子串,即求字符串 ...

  2. Uvalive - 3026 Period (kmp求字符串的最小循环节+最大重复次数)

    参考:http://www.cnblogs.com/jackge/archive/2013/01/05/2846006.html 总结一下,如果对于next数组中的 i, 符合 i % ( i - n ...

  3. hunnu - 11545 小明的烦恼——找路径 (最大流)

    http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11545 只是要求不经过相同的边,那么每次找出一条增广路T-- ...

  4. DOM节点是啥玩意?

    在 HTML DOM 中,所有事物都是节点.DOM 是被视为节点树的 HTML. DOM 节点 根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点: 整个文档是一个文档节点 ...

  5. NOIP 2010 乌龟棋

    P1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行 NN 个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第 NN 格是终点, ...

  6. 在 IIS 中承载 WCF 服务

    本主题概述了创建 Internet 信息服务 (IIS) 中承载的 Windows Communication Foundation (WCF) 服务所需的基本步骤. 本主题假设您熟悉 IIS 且了解 ...

  7. laravel event

    事件监听 方法一: web.php Event::listen('eloquent.created: App\post',function(){ dump('A post was created'); ...

  8. Unix时间戳(Unix timestamp)转换

    http://tool.chinaz.com/Tools/unixtime.aspx 如何在不同编程语言中获取现在的Unix时间戳(Unix timestamp)? Java time JavaScr ...

  9. 【python】一些好的学习网址

    http://www.cnblogs.com/BeginMan/p/3179302.html http://www.cnblogs.com/huxi/category/251137.html http ...

  10. Java这样学,Offer随便拿,学习方法和面试经验分享

    Java这样学,Offer随便拿,学习方法和面试经验分享 学习中:https://mp.weixin.qq.com/s/iSutLzqCiPMWwm_Rm_2oPw