传送门

《统计学习方法》读书笔记——机器学习常用评价指标
《统计学习方法》读书笔记——感知机(原理+代码实现)
《统计学习方法》读书笔记——K近邻法(原理+代码实现)
《统计学习方法》读书笔记——朴素贝叶斯法(公式推导+代码实现)


K近邻法

  • 传送门
  • 一、K近邻法
  • 二、K近邻法模型
    • 2.1 距离度量
    • 2.2 K值的选择
    • 2.3 决策规则
  • 三、K近邻法的一种实现:kd树
    • 3.1 构造kd树
    • 3.2 搜索kd树
  • 四、代码实现
  • 参考

一、K近邻法

K近邻法((k-nearest neighbor),简称KNN,是一种基本的分类算法。其描述如下:
给定一个数据集与待分类样本xxx,分类时,在数据集中找出K个与xxx最近邻的样本。根据这K个样本的类别,通过多数表决等方式进行预测xxx的类别。

注:K近邻法没有显式的学习过程

二、K近邻法模型

k 近邻法使用的模型实际上对应于对特征空间的划分。K近邻法模型有三个基本要素:距离度量K值的选择分类决策规则
特征空间中,对每个训练样本xix_ixi​,距离该点比其他点更近的所有点组成一个区域,叫作单元( cell) 。每个训练实例点拥有一个单元,所有训练实例点的单元构成对特征空间的一个划分。

2.1 距离度量

使用LpL_pLp​距离可以对特征空间中的两个实例点的相近邻程度进行度量,LpL_pLp​的定义如下:
假设xix_ixi​、xjx_jxj​是nnn维度特征空间中的两个实例点,其中xi=(xi(1),xi(2),...,xi(n))Tx_i = (x_i^{(1)},x_i^{(2)},...,x_i^{(n)})^Txi​=(xi(1)​,xi(2)​,...,xi(n)​)T,xj=(xj(1),xj(2),...,xj(n))Tx_j = (x_j^{(1)},x_j^{(2)},...,x_j^{(n)})^Txj​=(xj(1)​,xj(2)​,...,xj(n)​)T,则
Lp(xi,xj)=(∑l=1n∣xi(l)−xj(l)∣p)1pL_p(x_i,x_j) = (\sum_{l=1}^{n}|x_i^{(l)} - x_j^{(l)}|^p )^{\frac{1}{p}} Lp​(xi​,xj​)=(l=1∑n​∣xi(l)​−xj(l)​∣p)p1​
在上式中,若p=2p=2p=2即为欧式距离,在K近邻法中常用欧式距离做相近邻程度的度量。

2.2 K值的选择

  • K值较小的时候,预测结果对近邻的样本数据非常敏感,易使模型发生过拟合
  • K值过大时,意味着整体的模型变得简单,易使模型发生欠拟合。若k=Nk = Nk=N,即K值为数据集的样本总数,则不管输入什么数据,得到的结果永远是数据集中数量最多的类别
  • 在应用中,K值一般取一个比较小的数值。通常采用交叉验证法来选取最优的K值。

2.3 决策规则

K近邻法中的分类决策规则往往是多数表决。即假设K=10,在选得10个近邻的样本后,哪个类别最多,数据结果就是那个类别!

三、K近邻法的一种实现:kd树

实现K近邻法时,主要考虑的问题是如何对训练数据进行快速K近邻搜索。最简单的实现时对数据集进行线性扫描,但过于耗时,其时间复杂度为O(n)\mathcal{O(n)}O(n)。因此可使用特殊的数据结构存储数据集,以便在搜索时快速找到最近邻样本。

3.1 构造kd树

构造kd树相当于不断用垂直于坐标轴的超平面将k维空间作划分。

kd树构造算法
输入:kkk维空间数据集T={x1,x2,...,xN}T = \{x_1,x_2,...,x_N\}T={x1​,x2​,...,xN​},其中xi=(xi(1),xi(2),...,xi(k))T,i=1,2,...,Nx_i = (x_i^{(1)},x_i^{(2)},...,x_i^{(k)})^T,i = 1,2,...,Nxi​=(xi(1)​,xi(2)​,...,xi(k)​)T,i=1,2,...,N;
输出:kd树
(1) 开始:构造根结点,根结点即为全部数据集对应的k维超矩形区域。
选择x(1)x^{(1)}x(1)为坐标轴,以数据集中所有样本的x(1)x^{(1)}x(1)坐标的中位数为切分点(即x1(1),x2(1),...,xN(1)x_1^{(1)},x_2^{(1)},...,x_N^{(1)}x1(1)​,x2(1)​,...,xN(1)​),将根结点对应的超矩形区域切分为两个子区域。切分由通过切分点并与坐标轴x(1)x^{(1)}x(1)垂直的超平面实现。
由根结点生成深度为1的左、右子结点:左子结点对应坐标x(1)x^{(1)}x(1)小于切分点的子区域,右子结点对应于坐标x(1)x^{(1)}x(1)大于切分点的子区域。
将落在切分超平面上的实例点保存在根结点。
(2) 重复:对深度为j的结点,选择x(l)x^{(l)}x(l)为切分的坐标轴,l=jmodk+1l=j \mod k+1l=jmodk+1,以该结点的区域中所有实例的x(l)x^{(l)}x(l)坐标的中位数为切分点,将该结点对应的超矩形区域切分为两个子区域。切分由通过切分点并与坐标轴x(l)x^{(l)}x(l)垂直的超平面实现。
由该结点生成深度为j+1j+1j+1的左、右子结点:左子结点对应坐标x(l)x^{(l)}x(l)小于切分点的子区域,右子结点对应坐标x(l)x^{(l)}x(l)大于切分点的子区域。
将落在切分超平面上的实例点保存在该结点。
(3) 直到两个子区域没有实例存在时停止。从而形成kd树的区域划分。

3.2 搜索kd树

kd树搜索算法
输入:己构造的kd树,目标点xxx;
输出:X 的最近邻。
(1) 在kd树中找出包含目标点x的叶结点:从根结点出发,递归地向下访问kd树。若目标点x当前维的坐标小于切分点的坐标,则移动到左子结点,否则移动到右子结点。直到子结点为叶结点为止。
(2) 以此叶结点为“当前最近点”。
(3) 递归地向上回退,在每个结点进行以下操作:
  (a) 如果该结点保存的实例点比当前最近点距离目标点更近,则以该实例点为“当前最近点”。
  (b)当前最近点一定存在于该结点一个子结点对应的区域。检查该子结点的父结点的另一子结点对应的区域是否有更近的点。具体地,检查另一子结点对应的区域是否与以目标点为球心、以目标点与“当前最近点”间的距离为半径的超球体相交。
如果相交,可能在另一个子结点对应的区域内存在距目标点更近的点,移动到另一个子结点。接着,递归地进行最近邻搜索;如果不相交,向上回退。
(4) 当回退到根结点时,搜索结束。最后的“当前最近点”即为x的最近邻点。

如果实例点是随机分布的,kd树搜索的平均计算复杂度是O(log⁡N)\mathcal{O}(\log N)O(logN)

四、代码实现

没有实现kd树的构造和搜索,对数据集的搜索只是线性扫描,所以搜索时间很长。

# coding=utf-8
import numpy as np
import time
def loadData(fileName):print('start to read data:' + fileName)dataArr = []labelArr = []fr = open(fileName, 'r')# 将文件按行读取for line in fr.readlines():# 对每一行数据按切割符','进行切割,返回字段列表curLine = line.strip().split(',')dataArr.append([int(num) for num in curLine[1:]])labelArr.append(int(curLine[0]))# 返回data和labelreturn dataArr, labelArrdef calcDist(x1, x2):# 计算欧式距离return np.sqrt(np.sum(np.square(x1 - x2)))def getClosest(trainDataArr, trainLabelArr, x, topK):''':param trainDataArr:训练集数据集:param trainLabelArr:训练集标签集:param x:要预测的样本x:param topK:选择参考最邻近样本的数目:return:预测的标记'''# x与训练集中样本的距离distList = [0] * len(trainLabelArr)# 遍历训练集中所有的样本点,计算与x的欧式距离for i in range(len(trainDataArr)):distList[i] = calcDist(trainDataArr[i], x)# 找出**欧式距离**最近的k个样本topKList = np.argsort(np.array(distList))[:topK]# "投票箱"labelList = [0] * 10# 对topK个索引进行遍历for index in topKList:labelList[int(trainLabelArr[index])] += 1# 返回“投票箱”中票数最多的labelreturn labelList.index(max(labelList))def model_test(trainData, trainLabel, testData, testLabel, topK):'''测试正确率:param trainData:训练集数据集:param trainLabel: 训练集标记:param testData: 测试集数据集:param testLabel: 测试集标记:param topK: 选择多少个邻近点参考:return: 正确率'''print('start test')trainDataArr = np.array(trainData)trainLabelArr = np.array(trainLabel).TtestDataArr = np.array(testData)testLabelArr = np.array(testLabel).T# 错误数量errorCnt = 0for i in range(100):print('test %d:%d' % (i, 100))# 获取测试数据x的最近邻y = getClosest(trainDataArr, trainLabelArr, x=testDataArr[i], topK=topK)if y != testLabelArr[i]:errorCnt += 1# 返回正确率return 1 - (errorCnt / 100)if __name__ == "__main__":start = time.time()# 获取训练集、测试集trainData, trainLabel = loadData('./mnist/mnist_train.csv')testData, testLabel = loadData('./mnist/mnist_test.csv')# 计算测试集正确率accur = model_test(trainData, trainLabel, testData, testLabel, 25)print('accur is:%d' % (accur * 100), '%')print('time span:', time.time() - start)

运行结果:

start to read data:./mnist/mnist_train.csv
start to read data:./mnist/mnist_test.csv
start test
test 0:100
test 1:100
test 2:100
....(笔者手动折叠)
test 99:100
accur is:98 %
time span: 92.45222759246826

参考

原理:《统计学习方法》
代码: https://github.com/Dod-o/Statistical-Learning-Method_Code

《统计学习方法》读书笔记——K近邻法(原理+代码实现)相关推荐

  1. 统计学习方法读书笔记(六)-逻辑斯蒂回归与最大熵模型(迭代尺度法(IIS))

    全部笔记的汇总贴:统计学习方法读书笔记汇总贴 逻辑斯谛回归 (logistic regression )是统计学习中的经典分类方法.最大熵是概率模型学习的一个准则,将其推广到分类问题得到最大熵模型(m ...

  2. 统计学习方法读书笔记(九)-EM算法及其推广

    全部笔记的汇总贴:统计学习方法读书笔记汇总贴 EM算法用于含有隐变量(hidden variable)的概率模型参数的极大似然估计,或极大后验概率估计.EM算法的每次迭代由两步组成:E步,求期望(ex ...

  3. 挖掘原理|k近邻法原理

    k近邻法原理 k近邻法(k-nearest neighbor)用于分类时,给定一个训练数据集,对于新输入的实例,计算得出与该实例距离最近的k个样本,由k个样本中的大多数决定出该实例属于哪一类. 假设数 ...

  4. 统计学习方法 读书笔记(五)

    读书笔记仅供个人学习使用 本文主要参考书籍为<统计学习方法>(李航)第二版 参考 Sunning_001的博客 决策树 决策树的定义 if-then 的理解 条件概率分布的理解 决策树学习 ...

  5. [转载] Python 统计学习方法——kdTree实现K近邻搜索

    参考链接: K最近邻居的Python实现 效果说明: Input:输入Num个Dim维点的坐标,Points.size=(Num,Dim),输入一个目标点坐标Target.查找最近邻点数量K.Outp ...

  6. 统计学习方法读书笔记15-逻辑斯蒂回归习题

    文章目录 1.课后习题 2.视频课后习题 1.课后习题 import numpy as np import time import matplotlib.pyplot as plt from mpl_ ...

  7. 《统计学习方法》 第九章 EM算法(原理+代码)

    EM算法 EM算法是含有隐变量的概率模型极大似然估计或极大后验概率估计的迭代算法 含有隐变量的概率模型的数据表示为 θ \theta θ 这里, Y Y Y是观测变量的数据, Z Z Z是隐变量的数据 ...

  8. 统计学习方法笔记(一)-k近邻算法原理及python实现

    k近邻法 k近邻算法 算法原理 距离度量 距离度量python实现 k近邻算法实现 案例地址 k近邻算法 kkk近邻法(kkk-NN)是一种基本分类和回归方法. 算法原理 输入:训练集 T={(x1, ...

  9. 机器学习理论《统计学习方法》学习笔记:第三章 k近邻法

    机器学习理论<统计学习方法>学习笔记:第三章 k近邻法 3 k近邻法 3.1 K近邻算法 3.2 K近邻模型 3.2.1 模型 3.2.2 距离度量 3.2.3 K值的选择 3.2.4 分 ...

最新文章

  1. 【OpenCV】正确创建用于保存YUV420P格式的cv::Mat
  2. 1.8M超轻量目标检测模型NanoDet,比YOLO跑得快
  3. altium designer 不自动清除回路 清除功能打开失效
  4. csgo准星设置代码_csgo控制台的这些神秘的指令你知道多少
  5. 迄今为止用到的Eclipse快捷键,最常用的--[欢迎补充]
  6. 烟花程序c语言,C语言烟花程序
  7. Android 最火高速开发框架AndroidAnnotations使用具体解释
  8. Linux服务器时间同步那些事
  9. 使用SQLyog创建MySQL数据库
  10. linux 安装核显驱动程序,在Ubuntu系统上安装英特尔核显驱动安装器的方法
  11. Asp.net 使用weboffice实现Word在线编辑
  12. 两个小故事告诉你静下来的力量
  13. 敌兵布阵(CDQ分治模板题)
  14. 手机远程唤醒 android,手机微信实现网络唤醒电脑(WOL),远程开机,WakeOnLan – 全栈笔记...
  15. RStudio的安装
  16. ResponseEntity总结
  17. H.266/VVC测试软件VTM
  18. PANDA pipeline的安装与使用-安装(1)
  19. vxWorks系统ps2键盘,tty设备,vga设备的联系
  20. HTC View 手柄操作简介

热门文章

  1. 二级菜单不同方法的实现
  2. Android IOS WebRTC 音视频开发总结(四一)-- QQ和webrtc打洞能力pk
  3. [转自360kr]如何才能进入Facebook工作?公司内部工程师告诉你
  4. 怎样对待一个延期的项目
  5. Web安全实践(6)web应用剖析之信息提炼
  6. 金笛邮件之邮件倒入专题
  7. [转]医生和强盗的区别
  8. EASYSIZE备份
  9. LightGBM大战XGBoost,谁将夺得桂冠?
  10. thinkphp整合Ueditor编辑器