书中存在的一些疑问

  • 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. POJ-2239 Selecting Courses,三维邻接矩阵实现,钻数据空子。

    Selecting Courses Time Limit: 1000MS   Memory Limit: 65536K       Description It is well known that ...

  2. [OJ#40]后宫佳丽

    [OJ#40]后宫佳丽 试题描述 如果机房要关门了,或者有妹子在等你,你可以直接看最后一句话. Fyq 是一只饥渴的鸭子. Fyq 有一个充实的后宫,可惜他总是体力不支,为此他经常苦恼,总是想方设法让 ...

  3. [BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)

    传送门 题意 N个点M条边的有向图 每个点有点权 从某一个结点出发 问能获得的最大点权和 一个点的点权最多被计算一次 N<=500000 M<=500000 思路 先tarjan缩点,然后 ...

  4. Codeforces713D. Animals and Puzzle

    $n<=1000,m<=1000$,$n*m$的01矩阵,给$t<=1000000$个询问,每次问一个矩形中最大的1正方形的边长. 先想想不考虑“一个矩形中”的限制,那记$f(i,j ...

  5. 安装最新版本的zabbix

    1. 先安装php5.4 最新版本: yum安装php5.4或5.5 https://blog.csdn.net/MarkBoo/article/details/49424183 2. 然后参照官网或 ...

  6. Apache2 Web 服务器

    Apache2 Web 服务器的安装 sudo apt install apache2 -y 当安装Apache2包之后,Apache2相关的服务是启用的,并在重启后自动运行.在某些情况下如果你的Ap ...

  7. Unix - 文件里构成一个空洞的分析

    lseek函数显示地为一个打开文件设置偏移量,文件偏移量能够大于文件的当前长度,在这样的情况下.对该文件的下一次写将加长该文件.并在文件里构成一个空洞,这一点是同意的. 位于文件里但没有写过的字节都被 ...

  8. CentOS 6.4安装Ganglia

    samba 1.这里安装的是3.1.7版本,web前端是最新版本,安装前期环境(yum源用的是本地的) yum -y insatll php php-gd rrdtools apr-devel apr ...

  9. tf.image.resize_bilinear 图像缩放,双线性插值-图像中心对齐

    http://www.cnblogs.com/yssongest/p/5303151.html 双线性插值算法及需要注意事项 input = tf.placeholder(tf.float32, sh ...

  10. 【bzoj2654]】tree

    给白色边都加上一个值,二分这个值,使得选取的白边数量减少 #include<algorithm> #include<iostream> #include<cstdlib& ...