您的位置:首页 > 编程语言 > Python开发

从零开始:用Python实现KNN算法

2016-06-15 17:46 393 查看

转载自http://www.58maisui.com/2016/06/15/a-197/?ref=myread

从零开始:用Python实现KNN算法

目录Python2016年6月15日

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之间(这个过程叫归一化)。你可以改进这个算法让它支持数据归一化。
可更换距离计算方法:其实有很多其他的距离计算方法,你甚至可以自己开发一个距离计算方法。实现一个替换的距离计算方法,比如曼哈顿距离,或者向量的点积。
你可以发掘更多扩展的逻辑。比如投票的时候不同距离的实例有不同的权重,或者你可以用一个树形结构来进行最近实例的搜索。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: