从零开始:用Python实现KNN算法 knn python代码
bigegpt 2024-09-25 14:37 3 浏览
Python部落(python.freelycode.com)组织翻译,欢迎转发,禁止转载
k-Nearest Neighbors算法(简称KNN算法)的逻辑很简单,它易于理解和实现,是你可以使用的有力工具。
通过学习这个教程,你将能够用Python从0开始实现一个KNN算法。这个实现主要用来处理分类问题,我们将使用鸢尾花分类问题来演示这个例子。
这个教程的学习要求是你能够使用Python编码,并且对实现一个KNN算法感兴趣。
什么是k-Nearest Neighbors?
KNN的模型是整个训练数据集。当我们需要预测一个新实例的某个属性A时,KNN算法会搜索训练数据集找到K个最相似的实例。这些相似实例的A属性会被总结归纳,作为新实例A属性的预测。
如何判断实例之间的相似程度,这需要具体看数据的类型。对于实数数据,我们可以使用欧式距离。对于分类或者二进制数据,我们可以使用汉明距离。
对于回归问题,可以使用预测值的平均值。对于分类问题,可以返回最普遍的一类。
KNN算法是如何工作的?
KNN算法属于基于实例的、竞争学习与懒惰学习算法。
基于实例的算法是算法模型使用数据实例(或者说数据行),并依据这些实例做出预测的算法。KNN算法是基于实例算法中的一个极端例子,因为所有的训练数据都成了算法模型的一部分。
它是一个竞争学习逻辑,因为它内部使用模型元素(数据实例)之间的竞争来作出预测。数据实例之间的相似性计算导致每一个数据实例都竞争去“赢”,或者说竞争去和需要预测的元素相似,再或者说竞争为预测结果做贡献。
说它是懒惰学习算法是因为一直到需要进行预测操作了,它才会建立一个预测模型,它总是最后需要出结果的时候才开始干活。
它的优势是只有跟需要预测元素相似的数据实例才会其作用,可以称之为一个局部模型。劣势是计算成本很高,因为它在一个很大的训练集上重复做着相似的搜索。
最后,KNN很有用,因为它不对数据做任何的假设,同时使用一致的规则在任意两个数据实例之间计算距离。也因为如此,它被称作非参数,或者非线性算法,因为它没有假设一个模型函数。
使用测量来分类花朵
本教程使用的练习问题是分类鸢尾花。
已有的数据集由对3个不同品种的鸢尾花的150组观察数据组成。对于这些花有4个测量维度:萼片长度、萼片宽度、花瓣长度、花瓣宽度,所有的数值都以厘米为单位。需要预测的属性是品种,品种的可能值有:清风藤、云芝、锦葵。
我们有一个标准数据集,在这个数据集中品种是已知的。我们可以把这个数据集切分成训练数据集和测试数据集,然后用测试结果来评估算法的准确程度。在这个问题上,好的分类算法应该有大于90%的正确率,通常都会达到96%甚至更高。
你可以从https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data免费下载这个数据集,在资源那一段有更多的说明。
如何用Python实现KNN
这个教程把实现步骤分为如下6布。
处理数据:从CSV中读取数据,并把它们分割成训练数据集和测试数据集。
相似度:计算两个数据实例之间的距离。
临近:确定最相近的N个实例。
结果:从这些实力中生成预测结果。
准确度:总结预测的准确度。
主程序:把这些串起来
1、处理数据
我们要做的第一件事是加载我们的数据文件。数据文件是CSV格式的,并且没有标题行和备注。我们可以使用open方法打开文件,并用csv模块读取数据:
接下来我们要把数据集切分成用来做预测的训练数据集和用来评估准确度的测试数据集。
首先,我们要把加载进来的特征数据从字符串转换成整数。然后我们随机地切分训练数据集和测试数据集。训练数据集数据量/测试数据集数据量的比值取67/33是一个常用的惯例。
把这些逻辑放在一起,我们得到下面这个函数loadDataset:
把鸢尾花的CSV数据文件下载到本地文件夹,我们就可以测试一下我们的函数了,测试代码如下:
2、相似度
为了作出预测,我们需要计算两个数据实例之间的相似度。有了计算相似度的函数,我们后面才能获取最相似的N个实例来做出预测。
因为有关花的四个测量维度的数据都是数字形式的,并且具有相同的单位。我们可以直接使用欧式距离来测量。欧式距离就是两列数中对应数做差的平方和,之后再开方。(类似于二维平面的距离公式,扩展到多维)。
另外,我们要确定哪些维度参与计算。在这个问题里,我们只需要包含测量好的4个维度,这4个维度放在数组的前几个位置。限制维度的一个办法就是增加一个参数,告诉函数前几个维度需要处理,忽略后面的维度。
把这些逻辑放在一起,得到计算欧式距离的函数:
我们可以用一些假数据来测试这个函数,像这样:
3、邻近元素
现在我们有了相似度计算的方法,我们可以获取跟需要预测数据最接近的N个数据实例了。
最直接的方法就是计算待预测数据到所有数据实例的距离,取其中距离最小的N个。
这个逻辑可以由下面函数表示:
我们可以像下面这样测试这个函数
4、结果
接下来的任务就是基于最近的几个实例来得到预测结果了。
我们可以让这些近邻元素来对预测属性投票,得票最多的选项作为预测结果。
下面这个函数实现了投票的逻辑,它假设需预测的属性放在数据实例(数组)的最后。
我们可以用一些测试数据测试一下:
如果投票结果是平局,这个函数还是返回了一个预测结果。不过你可以有你自己的处理方式,比如平局时返回None,或者平局时随机选择一个结果。
5、准确度
做预测的部分已经都写完了,接下来是评估这个算法的准确度。
一个简单的评估方法是,计算在测试数据集中算法正确预测的比例,这个比例叫分类准确度。
下面这个函数可以计算分类准确度。
我们可以用下面这个例子来测试它:
6、主程序
好了,我们已经有了这个算法需要的所有函数,剩的就是把它们串起来了。
下面是完整的代码:
运行这个程序,你就会看到每个预测数据和实际数据的对比。在程序的最后,你能看到这个预测模型的准确度。在这个例子中,准确度略高于98%。
有关扩展的想法
这一部分我们讲讲一些对本教程给出的Python代码的做扩展的想法。
回归:你可以调整代码,让这个算法能够处理一些回归问题(预测一个实数属性)。比如总结近邻实例的时候,采用预测属性的平均值或者中值。
归一化:当不同属性之间单位不同时,某些属性在决定距离时可能会获得很大的权重。对于这类问题,你可能需要在计算之前把各个属性的值都缩放到0-1之间(这个过程叫归一化)。你可以改进这个算法让它支持数据归一化。
可更换距离计算方法:其实有很多其他的距离计算方法,你甚至可以自己开发一个距离计算方法。实现一个替换的距离计算方法,比如曼哈顿距离,或者向量的点积。
你可以发掘更多扩展的逻辑。比如投票的时候不同距离的实例有不同的权重,或者你可以用一个树形结构来进行最近实例的搜索。
了解野狗,请点击阅读原文。
相关推荐
- C#.NET Autofac 详解(c# autoit)
-
简介Autofac是一个成熟的、功能丰富的.NET依赖注入(DI)容器。相比于内置容器,它额外提供:模块化注册、装饰器(Decorator)、拦截器(Interceptor)、强o的属性/方法注...
- webapi 全流程(webapi怎么部署)
-
C#中的WebAPIMinimalApi没有控制器,普通api有控制器,MinimalApi是直达型,精简了很多中间代码,广泛适用于微服务架构MinimalApi一切都在组控制台应用程序类【Progr...
- .NET外挂系列:3. 了解 harmony 中灵活的纯手工注入方式
-
一:背景1.讲故事上一篇我们讲到了注解特性,harmony在内部提供了20个HarmonyPatch重载方法尽可能的让大家满足业务开发,那时候我也说了,特性虽然简单粗暴,但只能解决95%...
- C# 使用SemanticKernel调用本地大模型deepseek
-
一、先使用ollama部署好deepseek大模型。具体部署请看前面的头条使用ollama进行本地化部署deepseek大模型二、创建一个空的控制台dotnetnewconsole//添加依赖...
- C#.NET 中间件详解(.net core中间件use和run)
-
简介中间件(Middleware)是ASP.NETCore的核心组件,用于处理HTTP请求和响应的管道机制。它是基于管道模型的轻量级、模块化设计,允许开发者在请求处理过程中插入自定义逻辑。...
- IoC 自动注入:让依赖注册不再重复劳动
-
在ASP.NETCore中,IoC(控制反转)功能通过依赖注入(DI)实现。ASP.NETCore有一个内置的依赖注入容器,可以自动完成依赖注入。我们可以结合反射、特性或程序集扫描来实现自动...
- C#.NET 依赖注入详解(c#依赖注入的三种方式)
-
简介在C#.NET中,依赖注入(DependencyInjection,简称DI)是一种设计模式,用于实现控制反转(InversionofControl,IoC),以降低代码耦合、提高可...
- C#从零开始实现一个特性的自动注入功能
-
在现代软件开发中,依赖注入(DependencyInjection,DI)是实现松耦合、模块化和可测试代码的一个重要实践。C#提供了优秀的DI容器,如ASP.NETCore中自带的Micr...
- C#.NET 仓储模式详解(c#仓库货物管理系统)
-
简介仓储模式(RepositoryPattern)是一种数据访问抽象模式,它在领域模型和数据访问层之间创建了一个隔离层,使得领域模型无需直接与数据访问逻辑交互。仓储模式的核心思想是将数据访问逻辑封装...
- C#.NET 泛型详解(c# 泛型 滥用)
-
简介泛型(Generics)是指在类型或方法定义时使用类型参数,以实现类型安全、可重用和高性能的数据结构与算法为什么需要泛型类型安全防止“装箱/拆箱”带来的性能损耗,并在编译时检测类型错误。可重用同一...
- 数据分析-相关性分析(相关性 分析)
-
相关性分析是一种统计方法,用于衡量两个或多个变量之间的关系强度和方向。它通过计算相关系数来量化变量间的线性关系,从而帮助理解变量之间的相互影响。相关性分析常用于数据探索和假设检验,是数据分析和统计建模...
- geom_smooth()函数-R语言ggplot2快速入门18
-
在每节,先运行以下这几行程序。library(ggplot2)library(ggpubr)library(ggtext)#用于个性化图表library(dplyr)#用于数据处理p...
- 规范申报易错要素解析(规范申报易错要素解析)
-
为什么要规范申报?规范申报是以满足海关监管、征税、统计等工作为目的,纳税义务人及其代理人依法向海关如实申报的行为,也是海关审接单环节依法监管的重要工作。企业申报的内容须符合《中华人民共和国海关进出口货...
- 「Eurora」海关编码归类 全球海关编码查询 关务服务
-
海关编码是什么? 海关编码即HS编码,为编码协调制度的简称。 其全称为《商品名称及编码协调制度的国际公约》(InternationalConventionforHarmonizedCo...
- 9月1日起,河南省税务部门对豆制品加工业试行新政7类豆制品均适用投入产出法
-
全媒体记者杨晓川报道9月2日,记者从税务部门获悉,为减轻纳税人税收负担,完善农产品增值税进项税额抵扣机制,根据相关规定,结合我省实际情况,经广泛调查研究和征求意见,从9月1日起,我省税务部门对豆制品...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- libcrypto.so (74)
- linux安装minio (74)
- ubuntuunzip (67)
- vscode使用技巧 (83)
- secure-file-priv (67)
- vue阻止冒泡 (67)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)