书中存在的一些疑问

  • 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. ajax一个很好的加载效果

    推荐一个常用的jquery加载效果插件: 要引入这个插件的css和js: <link href="<%=path %>/css/showLoading.css" ...

  2. [luoguP1578] 奶牛浴场(DP)

    传送门 O(s2)算法 详见论文 王知昆--浅谈用极大化思想解决最大子矩形问题 我就复制你能把我怎么样QAQ #include <cstdio> #include <iostream ...

  3. hdu 5073 推公式相邻质心转换

    #include<stdio.h> #include<stdlib.h> #include<string.h> #define N 51000 int cmp(co ...

  4. SpringBoot入门系列~Spring-Data-JPA自动建表

    1.pom.xml引入Spring-Data-Jpa和mysql依赖 <!-- Spring-data-jpa依赖 --> <dependency> <groupId&g ...

  5. 原 linux添加虚拟ip(手动vip和keepalived方式)

    https://blog.csdn.net/dear_snowing/article/details/68066544 https://www.cnblogs.com/liuyisai/p/59906 ...

  6. STL算法设计理念 - 函数对象和函数对象当參数和返回值

    函数对象: 重载函数调用操作符的类.其对象常称为函数对象(function object),即它们是行为类似函数的对象. 一个类对象,表现出一个函数的特征,就是通过"对象名+(參数列表)&q ...

  7. CSS3实现各种格子纹理效果

    <!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/h ...

  8. Excel数据字典转换为PDM(且显示表名、字段相应的中文描写叙述)

    在工作中遇到了一个问题就是把Excel数据字典转换为PDM. 可是转换完毕了全是英文,原来对表名.字段名的中文描写叙述就没有了. 且对于这个问题在powerdesigner15.2以后能够直接完毕.可 ...

  9. 安装eclipse中html/jsp/xml editor插件以及改动html页面的字体

    近期在做android项目,用到了jquery mobile 框架以及phonegap,所以就会涉及一些html文件,可是html文件打开的方式是Text Editor ,而且打开之后一些html代码 ...

  10. UTF-8 的中文檔案名上傳問題

    在上传文件后,一般都会用 move_uploaded_file() 进行文件移动改名.但是 move_uploaded_file() 并不支持 UTF-8 编码,如果含有,那么函数就会执行失败,但是这 ...