书中存在的一些疑问

  • 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. [luoguP1868] 饥饿的奶牛(DP)

    传送门 先把所有区间按照左端点排序 f[i]表示区间0~i的最优解 #include <cstdio> #include <iostream> #include <alg ...

  2. Codeforces870F. Paths

    n<=10000000的图,满足:如果(i,j)>1就连一条边权1的无相变,问所有d(u,v) (u<=v)--u到v的最短路之和. 首先1和>n/2的质数都是孤立的点.然后两 ...

  3. Ubuntu12.04之SSH

    Ubuntu 12.04 关于SSH的知识 (1)安装完ubuntu系统12.04. (2)查看网络配置,输入命令ip addr后,显示有IP地址. (3)使用SSH终端工具Xshell连接系统,发现 ...

  4. csu - 1566: The Maze Makers (bfs)

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1566 题意还是蛮难懂的,至少对于我来说,需要认真读题. 输入矩阵的每一个数字换成2进制后,顺时针围 ...

  5. 博弈论入门题 kiki's game

    Problem Description Recently kiki has nothing to do. While she is bored, an idea appears in his mind ...

  6. Codeforces 651C Watchmen【模拟】

    题意: 求欧几里得距离与曼哈顿距离相等的组数. 分析: 化简后得到xi=xj||yi=yj,即为求x相等 + y相等 - x与y均相等. 代码: #include<iostream> #i ...

  7. 浅识MySQL

    MySQL常用语句 #操作数据库 ##创建数据库 CREATE DATABASE `dbName`; ##切换数据库 USE `dbName`; ##查看所有数据库 SHOW DATABASES; # ...

  8. Ubuntu 16.04下操作iptables的技巧(解决Failed to start iptables.service: Unit iptables.service not found.或者/etc/init.d/iptables: 没有那个文件或目录)

    /etc/init.d/iptables网上的解法应该都是基于CentOS 6去实践,而在CentOS 7中又被firewalld给取代,所以操作上的写法基本会改变,但是底层iptables则不会改变 ...

  9. JSP中HTTP状态码

    以下内容引用自http://wiki.jikexueyuan.com/project/jsp/http-status-codes.html: HTTP请求格式和HTTP响应消息的格式一样,都有以下结构 ...

  10. Lua迭代器

    在Lua中我们常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素.迭代器需要保留上一次成功调用的状态和下一次成功调用的状态,可以通过闭包提供的机制来实现这个任务(闭包中的外部局部变量可以用 ...