《机器学习实战》学习笔记:K近邻算法入门及实战万字长文

在模式识别领域中,K-近邻算法(KNN算法)是一种用于分类和回归的非参数统计方法。

Github代码获取:

Python版本:Python3.x

运行平台:Windows

IDE:Sublimetext3

想入门的你还不快来上车。

一.简单k-近邻算法

本文将从k-邻近算法的思想开始讲起,使用python3一步一步编写代码进行实战训练。并且,我也提供了相应的数据集,对代码进行了详细的注释。除此之外,本文也对sklearn实现k-邻近算法的方法进行了讲解。

实战实例:电影类别分类、约会网站配对效果判定、手写数字识别。本文出现的所有代码和数据集,均可在我的github上下载,欢迎Follow、Star——

下载地址:

1.k-近邻法简介

k近邻法(k-nearestneighbor,k-NN)是1967年由CoverT和HartP提出的一种基本分类与回归方法。

它的工作原理是:存在一个样本数据集合,也称作为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系。

输入没有标签的新数据后,将新的数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。

最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

举个简单的例子,我们可以使用k-近邻算法分类一个电影是爱情片还是动作片。

表1.1就是我们已有的数据集合,也就是训练样本集。这个数据集有两个特征,即打斗镜头数和接吻镜头数。除此之外,我们也知道每个电影的所属类型,即分类标签。用肉眼粗略地观察,接吻镜头多的,是爱情片。打斗镜头多的,是动作片。

以我们多年的看片经验,这个分类还算合理。如果现在给我一部电影,你告诉我这个电影打斗镜头数和接吻镜头数。

不告诉我这个电影类型,我可以根据你给我的信息进行判断,这个电影是属于爱情片还是动作片。而k-近邻算法也可以像我们人一样做到这一点,不同的地方在于,我们的经验更”牛逼”,而k-邻近算法是靠已有的数据。

比如,你告诉我这个电影打斗镜头数为2,接吻镜头数为102,我的经验会告诉你这个是爱情片,k-近邻算法也会告诉你这个是爱情片。

但是k-近邻算法不会告诉你这些,因为在它的眼里,电影类型只有爱情片和动作片,它会提取样本集中特征最相似数据(最邻近)的分类标签,得到的结果可能是爱情片,也可能是动作片,但绝不会是”爱情动作片”。当然,这些取决于数据集的大小以及最近邻的判断标准等因素。

2.距离度量

我们已经知道k-近邻算法根据特征比较,然后提取样本集中特征最相似数据(最邻近)的分类标签。那么,如何进行比较呢?比如,我们还是以表1.1为例,怎么判断红色圆点标记的电影所属的类别呢?如图1.1所示。

我们可以从散点图大致推断,这个红色圆点标记的电影可能属于动作片,因为距离已知的那两个动作片的圆点更近。k-近邻算法用什么方法进行判断呢?

没错,就是距离度量。这个电影分类的例子有2个特征,也就是在2维实数向量空间,可以使用我们高中学过的两点距离公式计算距离,如图1.2所示。

(101,20)->动作片(108,5)的距离约为16.55

(101,20)->动作片(115,8)的距离约为18.44

(101,20)->爱情片(5,89)的距离约为118.22

(101,20)->爱情片(1,101)的距离约为128.69

通过计算可知,红色圆点标记的电影到动作片(108,5)的距离最近,为16.55。如果算法直接根据这个结果,判断该红色圆点标记的电影为动作片,这个算法就是最近邻算法,而非k-近邻算法。那么k-邻近算法是什么呢?k-近邻算法步骤如下:

计算已知类别数据集中的点与当前点之间的距离;

按照距离递增次序排序;

选取与当前点距离最小的k个点;

确定前k个点所在类别的出现频率;

返回前k个点所出现频率最高的类别作为当前点的预测分类。

比如,现在我这个k值取3,那么在电影例子中,按距离依次排序的三个点分别是动作片(108,5)、动作片(115,8)、爱情片(5,89)。在这三个点中,动作片出现的频率为三分之二,爱情片出现的频率为三分之一,所以该红色圆点标记的电影为动作片。

这个判别过程就是k-近邻算法。

3.Python3代码实现

我们已经知道了k-近邻算法的原理,那么接下来就是使用Python3实现该算法,依然以电影分类为例。

(1)准备数据集

对于表1.1中的数据,我们可以使用numpy直接创建,代码如下:

运行结果,如图1.3所示:

(2)k-近邻算法

根据两点距离公式,计算距离,选择距离最小的前k个点,并返回分类结果。

运行结果,如图1.4所示:

可以看到,分类结果根据我们的”经验”,是正确的,尽管这种分类比较耗时,用时1.4s。

到这里,也许有人早已经发现,电影例子中的特征是2维的,这样的距离度量可以用两点距离公式计算,但是如果是更高维的呢?

对,没错。我们可以用欧氏距离(也称欧几里德度量),如图1.5所示。我们高中所学的两点距离公式就是欧氏距离在二维空间上的公式,也就是欧氏距离的n的值为2的情况。

看到这里,有人可能会问:“分类器何种情况下会出错?”或者“答案是否总是正确的?”答案是否定的,分类器并不会得到百分百正确的结果,我们可以使用多种方法检测分类器的正确率。此外分类器的性能也会受到多种因素的影响,如分类器设置和数据集等。

不同的算法在不同数据集上的表现可能完全不同。为了测试分类器的效果,我们可以使用已知答案的数据,当然答案不能告诉分类器,检验分类器给出的结果是否符合预期结果。

通过大量的测试数据,我们可以得到分类器的错误率-分类器给出错误结果的次数除以测试执行的总数。

错误率是常用的评估方法,主要用于评估分类器在某个数据集上的执行效果。完美分类器的错误率为0,最差分类器的错误率是1.0。

同时,我们也不难发现,k-近邻算法没有进行数据的训练,直接使用未知的数据与已知的数据进行比较,得到结果。因此,可以说k-邻近算法不具有显式的学习过程。

二.k-近邻算法实战之约会网站配对效果判定

上一小结学习了简单的k-近邻算法的实现方法,但是这并不是完整的k-近邻算法流程,k-近邻算法的一般流程:

已经了解了k-近邻算法的一般流程,下面开始进入实战内容。

1.实战背景

海伦女士一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的任选,但她并不是喜欢每一个人。经过一番总结,她发现自己交往过的人可以进行如下分类:

datingTestSet.txt数据下载:

海伦收集的样本数据主要包含以下3种特征:

每年获得的飞行常客里程数

每周消费的冰淇淋公升数

这里不得不吐槽一句,海伦是个小吃货啊,冰淇淋公斤数都影响自己择偶标准。打开txt文本文件,数据格式如图2.1所示。

2.准备数据:数据解析

在将上述特征数据输入到分类器前,必须将待处理的数据的格式改变为分类器可以接收的格式。分类器接收的数据是什么格式的?

从上小结已经知道,要将数据分类两部分,即特征矩阵和对应的分类标签向量。在kNN_test02.py文件中创建名为file2matrix的函数,以此来处理输入格式问题。将datingTestSet.txt放到与kNN_test02.py相同目录下,编写代码如下:

运行上述代码,得到的数据解析结果如图2.2所示。

可以看到,我们已经顺利导入数据,并对数据进行解析,格式化为分类器需要的数据格式。接着我们需要了解数据的真正含义。可以通过友好、直观的图形化的方式观察数据。

3.分析数据:数据可视化

在kNN_test02.py文件中编写名为showdatas的函数,用来将数据可视化。编写代码如下:

运行上述代码,可以看到可视化结果如图2.3所示。

为什么这么说呢?每年获得的飞行常客里程数表明,海伦喜欢能享受飞行常客奖励计划的男人,但是不能经常坐飞机,疲于奔波,满世界飞。

4.准备数据:数据归一化

表2.1给出了四组样本,如果想要计算样本3和样本4之间的距离,可以使用欧拉公式计算。

计算方法如图2.4所示。

而产生这种现象的唯一原因,仅仅是因为飞行常客里程数远大于其他特征值。但海伦认为这三种特征是同等重要的,因此作为三个等权重的特征之一,飞行常客里程数并不应该如此严重地影响到计算结果。

在处理这种不同取值范围的特征值时,我们通常采用的方法是将数值归一化,如将取值范围处理为0到1或者-1到1之间。下面的公式可以将任意取值范围的特征值转化为0到1区间内的值:

其中min和max分别是数据集中的最小特征值和最大特征值。虽然改变数值取值范围增加了分类器的复杂度,但为了得到准确结果,我们必须这样做。在kNN_test02.py文件中编写名为autoNorm的函数,用该函数自动将数据归一化。代码如下:

运行上述代码,得到结果如图2.4所示。

从图2.4的运行结果可以看到,我们已经顺利将数据归一化了,并且求出了数据的取值范围和数据的最小值,这两个值是在分类的时候需要用到的,直接先求解出来,也算是对数据预处理了。

5.测试算法:验证分类器

机器学习算法一个很重要的工作就是评估算法的正确率,通常我们只提供已有数据的90%作为训练样本来训练分类器,而使用其余的10%数据去测试分类器,检测分类器的正确率。

需要注意的是,10%的测试数据应该是随机选择的,由于海伦提供的数据并没有按照特定目的来排序,所以我么你可以随意选择10%数据而不影响其随机性。

运行上述代码,得到结果如图2.5所示。

从图2.5验证分类器结果中可以看出,错误率是3%,这是一个想当不错的结果。我们可以改变函数datingClassTest内变量hoRatio和分类器k的值,检测错误率是否随着变量值的变化而增加。依赖于分类算法、数据集和程序设置,分类器的输出结果可能有很大的不同。

6.使用算法:构建完整可用系统

我们可以给海伦一个小段程序,通过该程序海伦会在约会网站上找到某个人并输入他的信息。程序会给出她对男方喜欢程度的预测值。

在cmd中,运行程序,并输入数据(12,44000,0.5),预测结果是”你可能有些喜欢这个人”,也就是这个人魅力一般。一共有三个档次:讨厌、有些喜欢、非常喜欢,对应着不喜欢的人、魅力一般的人、极具魅力的人。结果如图2.6所示。

三、k-近邻算法实战之sklearn手写数字识别1.实战背景

对于需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小:宽高是32像素x32像素。尽管采用本文格式存储图像不能有效地利用内存空间,但是为了方便理解,我们将图片转换为文本格式,数字的文本格式如图3.1所示。

与此同时,这些文本格式存储的数字的文件命名也很有特点,格式为:数字的值_该数字的样本序号,如图3.2所示。

对于这样已经整理好的文本,我们可以直接使用Python处理,进行数字预测。数据集分为训练集和测试集,使用上小结的方法,自己设计k-近邻算法分类器,可以实现分类。数据集和实现

代码下载地址:

这里不再讲解自己用Python写的k-邻域分类器的方法,因为这不是本小节的重点。接下来,我们将使用强大的第三方Python科学计算库Sklearn构建手写数字系统。

2.sklearn简介

使用sklearn可以很方便地让我们实现一个机器学习算法。一个复杂度算法的实现,使用sklearn可能只需要调用几行API即可。所以学习sklearn,可以有效减少我们特定任务的实现周期。

3.sklearn安装

在安装sklearn之前,需要安装两个库,即numpy+mkl和scipy。不要使用pip3直接进行安装,因为pip3默安装的是numpy,而不是numpy+mkl。

找到对应python版本的numpy+mkl和scipy,下载安装即可,如图3.3和图3.4所示。

4.sklearn实现k-近邻算法简介

官网英文文档:

sklearn.neighbors模块实现了k-近邻算法,内容如图3.5所示。

我们使用sklearn.neighbors.KNeighborsClassifier就可以是实现上小结,我们实现的k-近邻算法。KNeighborsClassifier函数一共有8个参数,如图3.6所示。

△图3.6KNeighborsClassifier

KNneighborsClassifier参数说明:

n_neighbors:默认为5,就是k-NN的k的值,选取最近的k个点。

weights:默认是uniform,参数可以是uniform、distance,也可以是用户自己定义的函数。uniform是均等的权重,就说所有的邻近点的权重都是相等的。distance是不均等的权重,距离近的点比距离远的点的影响大。用户自定义的函数,接收距离的数组,返回一组维数相同的权重。

algorithm:快速k近邻搜索算法,默认参数为auto,可以理解为算法自己决定合适的搜索算法。除此之外,用户也可以自己指定搜索算法ball_tree、kd_tree、brute方法进行搜索,brute是蛮力搜索,也就是线性扫描,当训练集很大时,计算非常耗时。

kd_tree,构造kd树存储数据以便对其进行快速检索的树形数据结构,kd树也就是数据结构中的二叉树。以中值切分构造的树,每个结点是一个超矩形,在维数小于20时效率高。

balltree是为了克服kd树高纬失效而发明的,其构造过程是以质心C和半径r分割样本空间,每个节点是一个超球体。

leaf_size:默认是30,这个是构造的kd树和ball树的大小。这个值的设置会影响树构建的速度和搜索速度,同样也影响着存储树所需的内存大小。需要根据问题的性质选择最优的大小。

metric:用于距离度量,默认度量是minkowski,也就是p=2的欧氏距离(欧几里德度量)。

p:距离度量公式。在上小结,我们使用欧氏距离公式进行距离度量。除此之外,还有其他的度量方法,例如曼哈顿距离。这个参数默认为2,也就是默认使用欧式距离公式进行距离度量。也可以设置为1,使用曼哈顿距离公式进行距离度量。

metric_params:距离公式的其他关键参数,这个可以不管,使用默认的None即可。

n_jobs:并行处理设置。默认为1,临近点搜索并行工作数。如果为-1,那么CPU的所有cores都用于并行工作。

KNeighborsClassifier提供了以一些方法供我们使用,如图3.7所示。

由于篇幅原因,每个函数的怎么用,就不具体讲解了。官方手册已经讲解的很详细了,各位可以查看这个手册进行学习,我们直接讲手写数字识别系统的实现。

5.sklearn小试牛刀

我们知道数字图片是32x32的二进制图像,为了方便计算,我们可以将32x32的二进制图像转换为1x1024的向量。

对于sklearn的KNeighborsClassifier输入可以是矩阵,不用一定转换为向量,不过为了跟自己写的k-近邻算法分类器对应上,这里也做了向量化处理。然后构建kNN分类器,利用分类器做预测。创建kNN_test04.py文件,编写代码如下:

运行上述代码,得到如图3.8所示的结果。

四、总结1.kNN算法的优缺点

简单好用,容易理解,精度高,理论成熟,既可以用来做分类也可以用来做回归;

可用于数值型数据和离散型数据;

对异常值不敏感

计算复杂性高;空间复杂性高;

样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少);

一般数值很大的时候不用这个,计算量太大。但是单个样本又不能太少,否则容易发生误分。

最大的缺点是无法给出数据的内在含义。

2.其他

关于algorithm参数kd_tree的原理,可以查看《统计学方法李航》书中的讲解;

关于距离度量的方法还有切比雪夫距离、马氏距离、巴氏距离等;

如有问题,请留言。如有错误,还望指正,谢谢!

五.参考说明

本文中提到的电影类别分类、约会网站配对效果判定、手写数字识别实例和数据集,均来自于《机器学习实战》的第二章k-近邻算法。

本文的理论部分,参考自《统计学习方法李航》的第三章k近邻法以及《机器学习实战》的第二章k-邻近算法。

点击左下角“阅读原文”处,可以进入作者的知乎专栏,可以查看高清完整版代码

THE END
1.算法算法基础入门(进入算法的世界)算法入门【算法】算法基础入门(进入算法的世界) 本文介绍了算法的基础概念,包括分治法、递归法、贪心法、动态规划法、迭代法、枚举法和回溯法,通过实例演示了这些算法在编程中的应用,强调算法思维的重要性。 摘要由CSDN通过智能技术生成 目录 引言 正文 算法的定义https://blog.csdn.net/2301_79784865/article/details/135107433
2.2021年计算机数据结构与算法[1]知识点第一章:数据结构与算法 1.1 算法 算法:是指解题方案的准确而完整的描述。 算法不等于程序,也不等计算机方法,程序的编制不可能优于算法的设计。 算法的基本特征:是一组严谨地定义运算顺序的规则,每一个规则都是有效的,是明确的,此顺序将在有限的次数下终止。特征包括: https://xue.baidu.com/okam/pages/strategy-tp/index?strategyId=137041646971828&source=natural
3.《Python编程入门与算法进阶》(中国电子学会)简介书评Python青少年等级考试程序软件开发教程编程入门,py基础能力训练,电子学会青少年编程考试指定用书,让孩子们轻松学习Python! 作者:中国电子学会出版社:人民邮电出版社出版时间:2022年04月 手机专享价 ¥ 当当价降价通知 ¥99.00 定价 ¥99.00 配送至 北京市东城区 http://product.dangdang.com/29382153.html
4.图形化编程入门与算法进阶.pptx读书笔记图形化编程入门与算法进阶01思维导图精彩摘录目录分析内容摘要阅读感受作者简介目录0305020406思维导图算法入门编程读者进阶编程图形算法通过深入掌握探索可以理解实践能力各种帮助入门本书关键字分析思维导图内容摘要内容摘要《图形化编程入门与算法进阶》是一本引领读者从零基础开始,逐步深入探索图形化编程与算法的书籍https://m.renrendoc.com/paper/305663231.html
5.算法入门基础知识算法效率的度量方法 事后统计方法 这种方法主要是通过设计好的测试程序和数据, 利用计算机计时器对不同算方法编制的程序运行时间进行比较,从而确定算法效率的高低 缺陷: 必须一句算法事先编制好程序 时间的比较依赖计算机及硬件和软件等环境因素,有时会掩盖算法本身的优劣 https://www.jianshu.com/p/2283d8f93a18
6.算法设计与分析基础(第3版)[AnanyLevitin著]中文pdf扫描版[20MB算法设计与分析基础(第3版)在讲述算法设计技术时采用了新的分类方法,在讨论分析方法时条分缕析,形成了连贯有序、耳目一新的风格。为便于学生掌握,本书涵盖算法入门课程的全部内容,更注重对概念(而非形式)的理解。书中通过一些流行的谜题来激发学生的兴趣,帮助他们加强和提高解决算法问题的能力。每章小结、习题提示和https://www.jb51.net/books/582016.html
7.终于学完国内算法第一人10年经验总结的数据结构与算法详解文档数据结构主要研究数据的逻辑结构和存储结构,以及对数据的各种操作,是深入学习算法设计与分析、操作系统、编译原理、软件工程等的重要基础。随着计算机应用领域的不断扩展,非数值计算问题已成为计算机应用领域处理的主要问题之一,简单的数据结构已经不能满足需要,无论是系统软件设计还是应用软件设计,均涉及复杂的数据结构处理https://zhuanlan.zhihu.com/p/507739650
8.程序员应该知道的十个基础算法腾讯云开发者社区程序员应该知道的十个基础算法 作为一名程序员,掌握各种算法可以帮助我们解决各种复杂的问题,提高代码的效率和性能,同时也是面试中常被考察的重要内容之一。无论是开发新的软件应用、优化现有的算法逻辑还是解决各类计算问题,算法都是不可或缺的工具。因此,程序员必须掌握一系列常用的算法,以确保能够高效地编写出稳定、https://cloud.tencent.com/developer/article/2352039
9.ACM算法竞赛入门——算法竞赛赛制题目形式常见评测状态xcx:学完C++基础语法之后,已经迫不及待的打比赛了,算法竞赛到底是什么? shy:别着急,今天我们来好好讲一讲算法竞赛赛制,题目形式和评测状态。 一、算法竞赛赛制 1. ACM赛制 ACM只有正确和错误两种结果,即使部分测试点通过仍显示答案错误。ACM赛制必须通过所有的测试点才算通过,虽然可以看到程序的运行结果,但无法了解https://m.nowcoder.com/discuss/596748280822808576
10.算法刷题的基础(一)——必会的算法基础知识Daisir算法刷题的基础(一)——必会的算法基础知识 一、应对算法刷题网站的输入要求 1.不知道输入什么时候结束怎么办? 比如: PAT 1002:读入一个正整数n,计算其各位数字之和,用汉语拼音写出和的每一位数字。 你根本不知道输入的正整数有多长,你该怎么办?https://www.cnblogs.com/dokidai/p/15243293.html
11.科学网—如何高效入门数据科学?《如何用Python做情感分析?》这篇文章,分别从英文和中文两个案例,分别采用不同的软件包,针对性地解决应用需求。 你只需要几行代码,就能让Python告诉你情感的取向。是不是很厉害? 有了情感分析做基础,你可以尝试增加维度,对更大体量的数据做分析。 增加时间维度,就可以持续分析变化的舆情。 https://wap.sciencenet.cn/blog-377709-1113955.html
12.课程:《算法竞赛宝典》语言及算法入门(公开课程)六级题库 七级题库 八级题库 九级题库 十级题库 培训课程 语言与算法入门 基础算法艺术 基础数据结构 数学与程序设计 普及组初赛指导 提高组初赛指导 普及组复赛指导 提高组复赛指导页面路径 首页 / ? 课程 / ? 信息学奥赛培训课程 / ? 语言及算法入门 《算法竞赛宝典》语言及算法入门(公开课程)主题http://razxhoi.21cnjy.net/course/view.php?id=8
13.Dotcpp编程(C语言网)编程入门学习训练题库C语言网(Dotcpp编程),老牌的编程入门学习平台,不仅仅提供C语言、C++、Java、Python、编译器(编程软件)等技术的教程资源和工具,还提供包括计算机二级、蓝桥杯真题在内的编程题库,让初学者学练同步,真正学会编程!https://www.dotcpp.com/
14.算法入门:从零开始学习算法的简单教程本文介绍了算法入门的基础知识,包括算法的基本概念、重要性及其应用领域。文章详细解释了如何描述和分析算法,并列举了常见的算法类型及其应用场景,适合希望从零开始学习算法的读者。 算法入门:从零开始学习算法的简单教程 算法基础概念介绍 什么是算法 算法是一组定义明确的指令,用于解决特定问题或完成特定任务。算法可https://www.imooc.com/article/357937
15.九章算法21周掌握初阶算法到高阶算法面试题,适合不同基础,不同专业的系统性面试算法课程,123课时和600+练习题,层次递 进的破解面试算法。 视频+互动 面向对象设计OOD 2025版 10个应用实例+9高频面试真题+7个设计案例,活用5C解题法让你轻松应对各种面试难题 视频+互动 https://www.jiuzhang.com/
16.清华大学出版社图书详情本书是算法竞赛的入门和进阶教材,包括算法思路、模板代码、知识体系、赛事相关等内容。本书把竞赛常用的知识点和竞赛题结合起来,讲解清晰、透彻,帮助初学者建立自信心,快速从实际问题入手,模仿经典代码解决问题,进入中级学习阶段。全书分为12章,覆盖了目前算法竞赛中的主要内容,包括算法竞赛概述、算法复杂度、STL和基本http://www.tup.tsinghua.edu.cn/booksCenter/book_08163901.html