当前位置: 首页 > 编程日记 > 正文

机器学习 KNN算法实践

作者 | 叶庭云

来源 | 修炼Python

头图 | 下载于视觉中国


KNN算法简介

KNN(K-Nearest Neighbor)最邻近分类算法是数据挖掘分类(classification)技术中常用算法之一,其指导思想是"近朱者赤,近墨者黑",即由你的邻居来推断出你的类别。

KNN最邻近分类算法的实现原理:为了判断未知样本的类别,以所有已知类别的样本作为参照,计算未知样本与所有已知样本的距离,从中选取与未知样本距离最近的 K 个已知样本,再根据少数服从多数的投票法则(majority-voting),将未知样本与 K 个最邻近样本中所属类别占比较多的归为一类。

KNN算法的核心思想:寻找最近的k个数据,来预测新数据的分类

KNN算法的关键:

  • 样本的所有特征都要做可比较的量化,若是样本特征中存在非数值的类型,必须采取手段将其量化为数值。例如样本特征中包含颜色,可通过将颜色转换为灰度值来实现距离计算。

  • 样本特征要做归一化处理,样本有多个参数,每一个参数都有自己的定义域和取值范围,他们对距离计算的影响不一样,如取值较大的影响力会盖过取值较小的参数。所以样本参数必须做一些 scale 处理,最简单的方式就是所有特征的数值都采取归一化处置。

  • 需要一个距离函数以计算两个样本之间的距离 通常使用的距离函数有:欧氏距离、曼哈顿距离、切比雪夫距离等,一般选欧氏距离作为距离度量,但是这是只适用于连续变量。在文本分类这种非连续变量情况下,汉明距离可以用来作为度量。通常情况下,如果运用一些特殊的算法来计算度量的话,K近邻分类精度可显著提高,如运用大边缘最近邻法或者近邻成分分析法。

以计算二维空间中的A(x1,y1)、B(x2,y2)两点之间的距离为例,常用的欧氏距离的计算方法如下图所示:

KNN算法的优点:

  • 简单,易于理解,易于实现,无需估计参数,无需训练;

  • 适合对稀有事件进行分类;

  • 特别适合于多分类问题(multi-modal,对象具有多个类别标签), KNN比 SVM 的表现要好。

KNN算法的缺点:

  • 只适合小数据集:正是因为这个算法太简单,每次预测新数据都需要使用全部的数据集,所以如果数据集太大,就会消耗非常长的时间,占用非常大的存储空间。

  • 数据不平衡效果不好:如果数据集中的数据不平衡,有的类别数据特别多,有的类别数据特别少,那么这种方法就会失效了,因为特别多的数据最后在投票的时候会更有竞争优势。

  • 需要做数据标准化:由于使用距离来进行计算,如果数据量纲不同,数值较大的字段影响就会变大,所以需要对数据进行标准化,比如都转换到 0-1 的区间。

  • 不适合特征维度太多的数据:由于我们只能处理小数据集,如果数据的维度太多,那么样本在每个维度上的分布就很少。比如我们只有三个样本,每个样本只有一个维度,这比每个样本有三个维度特征要明显很多。

关于 K 的选取:

  • K 值的选取会影响到模型的效果。当 K 越小的时候容易过拟合,因为结果的判断与某一个点强相关。而 K 越大的时候容易欠拟合,因为要考虑所有样本的情况,那就等于什么都不考虑。

  • 对于 K 的取值,一种显而易见的办法就是从 1 开始不断地尝试,查看准确率。随着 K 的增加,一般情况下准确率会先变大后变小,然后选取效果最好的那个 K 值就好了。当然,关于 K 最好使用奇数,因为偶数在投票的时候就困难了,如果两个类别的投票数量是一样的,那就没办法抉择了,只能随机选一个。

  • 所以选取一个合适的 K 值也是 KNN 算法在实现时候的一个难点,需要根据经验和效果去进行尝试。


鸢尾花数据分类


以经典的鸢尾花数据分类为例,熟悉 KNN 算法基本原理。使用 sklearn 自带的鸢尾花数据集,这个数据集里面有 150 条数据,共有 3 个类别,即 Setosa 鸢尾花、Versicolour 鸢尾花和 Virginica 鸢尾花,每个类别有 50 条数据,每条数据有 4 个维度,分别记录了鸢尾花的花萼长度、花萼宽度、花瓣长度和花瓣宽度。

导入需要的依赖库

from sklearn import datasets   # sklearn自带的数据集
from sklearn.neighbors import KNeighborsClassifier   # sklearn模块的KNN类
import numpy as np    # 矩阵运算库numpy# 设置随机种子,不设置的话默认是按系统时间作为参数
# 设置后可以保证我们每次产生的随机数是一样的,便于测试
np.random.seed(6)

加载数据

iris = datasets.load_iris()
iris_x = iris.data      # 数据部分
iris_y = iris.target    # 类别部分
print(iris_x)
print(iris_y)

结果如下:这个数据集里面有 150 条数据,共有 3 个类别,即 Setosa 鸢尾花、Versicolour 鸢尾花和 Virginica 鸢尾花,每个类别有 50 条数据,每条数据有 4 个维度,分别记录了鸢尾花的花萼长度、花萼宽度、花瓣长度和花瓣宽度。

KNN预测分类

# permutation 接收一个数作为参数(这里为数据集长度150) 产生一个0-149乱序一维数组
randomarr= np.random.permutation(len(iris_x))
# 随机从150条数据中选125条作为训练集,25条作为测试集
iris_x_train = iris_x[randomarr[:-25]] # 训练集数据
iris_y_train = iris_y[randomarr[:-25]] # 训练集标签
iris_x_test = iris_x[randomarr[-25:]]  # 测试集数据
iris_y_test = iris_y[randomarr[-25:]]  # 测试集标签
# 定义一个KNN分类器对象
knn = KNeighborsClassifier()
# 调用该对象的训练方法,主要接收两个参数:训练数据集及其类别标签
knn.fit(iris_x_train, iris_y_train)
# 调用预测方法,主要接收一个参数:测试数据集
iris_y_predict = knn.predict(iris_x_test)
# 计算各测试样本预测的概率值 这里我们没有用概率值,但是在实际工作中可能会参考概率值来进行最后结果的筛选,而不是直接使用给出的预测标签
probility = knn.predict_proba(iris_x_test)
# 计算与最后一个测试样本距离最近的5个点,返回的是这些样本的距离和序号组成的数组
neighborpoint = knn.kneighbors([iris_x_test[-1]], 5)
print(neighborpoint)
print('------------------------------------------------------------------')
# 调用该对象的打分方法,计算出准确率
score = knn.score(iris_x_test, iris_y_test, sample_weight=None)
# 输出测试的结果
print('iris_y_predict = ')
print(iris_y_predict)
print('------------------------------------------------------------------')
# 输出原始测试数据集的正确标签,以方便对比
print('iris_y_test = ')
print(iris_y_test)
print('------------------------------------------------------------------')
# 输出准确率计算结果
print('Accuracy:', score)

结果如下:

经过上面的一个动手尝试,我们成功地实践了 KNN 算法,并使用它对鸢尾花数据进行了分类计算,预测准确率在 90% 以上。

手写KNN算法实现思路

为了加深对 KNN 算法的理解,我们手动实现,而不用 sklearn 模块的 KNN 类。

要自己动手用 Python 实现 KNN 算法,主要有以下三个步骤:

  • 算距离:给定待分类样本,计算它与已分类样本中的每个样本的距离;

  • 找邻居:圈定与待分类样本距离最近的 K 个已分类样本,作为待分类样本的近邻;

  • 做分类:根据这 K 个近邻中的大部分样本所属的类别来决定待分类样本该属于哪个分类;


预测城市空气质量

数据来源:http://www.tianqihoubao.com/aqi/chengdu-201901.html

以预测城市空气质量为例,对已获取的几个城市 2019 年的空气质量数据进行处理,划分测试集、训练集。

读取数据集

def read_dataset(filename1, filename2, trainingSet, testSet):with open(filename1, 'r') as csvfile:lines = csv.reader(csvfile)  # 读取所有的行dataset1 = list(lines)       # 转化成列表for x in range(len(dataset1)):  # 每一行数据for y in range(8):dataset1[x][y] = float(dataset1[x][y])   # 8个参数转换为浮点数testSet.append(dataset1[x])    # 生成测试集with open(filename2, 'r') as csvfile:lines = csv.reader(csvfile)  # 读取所有的行dataset2 = list(lines)       # 转化成列表for x in range(len(dataset2)):   # 每一行数据for y in range(8):dataset2[x][y] = float(dataset2[x][y])  # 8个参数转换为浮点数trainingSet.append(dataset2[x])  # 生成训练集

计算欧氏距离

def calculateDistance(testdata, traindata, length):  # 计算距离distance = 0  # length表示维度 数据共有几维for x in range(length):distance += pow((int(testdata[x]) - int(traindata[x])), 2)return round(math.sqrt(distance), 3)    # 保留3位小数

找 K 个相邻最近的邻居

def getNeighbors(self, trainingSet, test_instance, k):  # 返回最近的k个边距distances = []length = len(test_instance)# 对训练集的每一个数计算其到测试集的实际距离for x in range(len(trainingSet)):dist = self.calculateDistance(test_instance, trainingSet[x], length)print('训练集:{} --- 距离:{}'.format(trainingSet[x], dist))distances.append((trainingSet[x], dist))distances.sort(key=operator.itemgetter(1))  # 按距离从小到大排列# print(distances)neighbors = []# 排序完成后取距离最小的前k个for x in range(k):neighbors.append(distances[x][0])print(neighbors)return neighbors

计算比例最大的分类

def getResponse(neighbors):   # 根据少数服从多数,决定归类到哪一类class_votes = {}for x in range(len(neighbors)):response = neighbors[x][-1]  # 统计每一个分类的多少  空气质量的数字标识if response in class_votes:class_votes[response] += 1else:class_votes[response] = 1print(class_votes.items())sortedVotes = sorted(class_votes.items(), key=operator.itemgetter(1), reverse=True)  # 按分类大小排序  降序return sortedVotes[0][0]    # 分类最大的  少数服从多数   为预测结果

预测准确率计算

def getAccuracy(test_set, predictions):correct = 0for x in range(len(test_set)):# predictions预测的与testset实际的比对  计算预测的准确率if test_set[x][-1] == predictions[x]:correct += 1else:# 查看错误预测print(test_set[x], predictions[x])print('有{}个预测正确,共有{}个测试数据'.format(correct, len(test_set)))return (correct / (len(test_set))) * 100.0

run函数调用

def run(self):training_set = []    # 训练集test_set = []        # 测试集self.read_dataset('./train_4/test.txt', './train_4/train.txt', training_set, test_set)  # 数据划分print('Train set: ' + str(len(training_set)))print('Test set: ' + str(len(test_set)))# generate predictionspredictions = []k = 7  # 取最近的7个数据for x in range(len(test_set)):  # 对所有的测试集进行测试neighbors = self.getNeighbors(training_set, test_set[x], k)  # 找到8个最近的邻居result = self.getResponse(neighbors)  # 找这7个邻居归类到哪一类predictions.append(result)accuracy = self.getAccuracy(test_set, predictions)print('预测准确度为:  {:.2f}%'.format(accuracy))   # 保留2位小数

运行效果如下:

测试集上预测准确率在 95% 以上。可以通过增加训练集城市空气质量数据量,调节找邻居的数量k,提高预测准确率。

福 利

CSDN给大家发压岁钱啦!

2月4日到2月11日每天上午11点

价值198元的芒果TV年卡,价值99元的CSDN月卡现金红包,CSDN电子书月卡等奖品大放送!百分百中奖

电脑端点击链接参与:

https://t.csdnimg.cn/gAkN

更多精彩推荐
☞Python 分析热卖年货,今年春节大家都在送啥?☞爬了20W+条猫咪交易数据,它不愧是人类团宠☞英超引入 AI 球探,寻找下一个足球巨星
☞三年投 1000 亿,达摩院何以仗剑走天涯?☞2021年浅谈多任务学习
点分享点收藏点点赞点在看

相关文章:

【生活随想】实习结束以及开始校园招聘

我发现很多时候我处理事情的思维是局限的!就拿前几天辞职的事情来说吧,我原打算直接向公司辞职,但后来听同学说“还是先试着向公司请假比较好”,不用细想也是,如果公司同意我请假,我还能给自己留一条后路&a…

《21世纪机器人》一一第1章 他用自己的思想打造机器人

第1章 他用自己的思想打造机器人 我在前面说过,这本书的结尾是吉米站在后台,准备闪亮登场,这是他的首次亮相。当我把吉米的这张照片发给我太太时,她很快回复:“这真的是用你的思想打造出的机器人!&#xff…

牛年快乐~新一年从甜蜜的烘焙里学AI

作者 | 神经小兮来源 | HyperAI超神经头图 | 下载于视觉中国经过数千年的积累,人类已经开发出了各色美味,但我们的味蕾却永远不知满足。谷歌一位 AI 开发者,为了探索新的可能,用 AI 来开发新的甜点食谱。AI 在菜谱开发这一领域&am…

Datalist控件,Repeater控件如何分页?

Asp.net提供了三个功能强大的列表控件:DataGrid、DataList和Repeater控件,但其中只有DataGrid控件提供分页功能。相对DataGrid,DataList和Repeater控件具有更高的样式自定义性,所以很多时候我们喜欢使用DataList或Repeater控件来显…

java List集合中contains方法总是返回false

ArrayList的contains方法 java 今天在用ArrayList类的caontains方法是遇到了问题,我写了一个存放User类的ArrayList 但在调用list.contains(user)时总是返回false。 去看了下ArrayList的源码,源码如下: Java代码 public boolean contains…

营销自动化的4大预测分析错误

预测分析是数字营销的新领域。许多专家已经讨论了将预测分析与营销自动化工具(如HubSpot和Marketo)合并的好处。 将预测分析整合到用户的营销自动化策略中可能非常有益,但也很难执行。以下是可能会阻止其实施的一些常见的错误: 1.…

Prolog学习:数独和八皇后问题

上一篇简单介绍了下Prolog的一些基本概念,今天我们来利用这些基本概念解决两个问题:数独和八皇后问题。 数独 数独是一个很经典的游戏: 玩家需要根据nn盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列…

每年节省170万美元的文档预览费用,借助机器学习的DropBox有多强​?

【CSDN 编者按】Dropbox 借助机器学习的预测功能,每年能为公司节省了一百多七十多万美元的基础架构成本。非常了不起的成就。本文,一起来看一看 Dropbox 采用机器学习的经过,以及分析一下其中的利弊。译者 | 弯月 责编 | 张文出品 | CSDN&a…

asp.net 对xml文件的读写,添加,修改,删除操作

asp.net 对xml文件的读写,添加,修改,删除操作 下面有代码调试正确 using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using…

阿里重金投数梦工场 布局PaaS动了谁的奶酪

就目前云计算市场来看,巨头的争夺表面上还在IaaS激战,但实际上他们对PaaS也在默默布局。6月8日,PaaS相关服务商数梦工场宣布完成光大实业资本、阿里巴巴等公司共同投资的7.5亿元A轮融资。值得注意的是,阿里巴巴是几位投资方中唯一…

ASP.net中太长的数据缩略显示

问题&#xff1a;用<%# DataBinder.Eval(Container.DataItem,"NewsID"&#xff09;%>显示数据的&#xff0c;如果标题太长了怎么规定字数&#xff0c;多余的用"..."代替解决方法&#xff1a; 1.使用后台代码解决&#xff1a; cs文件代码&#xff1a;…

再见 for 循环!pandas 提速 315 倍~

for是所有编程语言的基础语法&#xff0c;初学者为了快速实现功能&#xff0c;依懒性较强。但如果从运算时间性能上考虑可能不是特别好的选择。本次东哥介绍几个常见的提速方法&#xff0c;一个比一个快&#xff0c;了解pandas本质&#xff0c;才能知道如何提速。下面是一个例子…

UVa 374 - Big Mod

题目大意&#xff1a;计算R BP mod M&#xff0c;根据模运算的性质计算。 正常计算会超时&#xff0c;可以用分治的思想降低时间复杂度。不过如果遇到00&#xff0c;结果...话说00的结果是1吗&#xff1f;忘了都... 1 #include <cstdio>2 3 int powMod(int base, int ex…

微软在慕尼黑设立欧洲首个物联网实验室

北京时间3月30日晚间消息&#xff0c;微软今日在慕尼黑设立了其在欧洲的首个物联网实验室。在此之前&#xff0c;微软已经在雷德蒙(Redmond)总部和中国深圳设立了物联网实验室。 慕尼黑是德国许多知名大企业的故乡&#xff0c;如宝马和西门子等。在此之前&#xff0c;思科和IBM…

linux的strace命令

linux的strace命令 strace 命令是一种强大的工具&#xff0c;它能够显示所有由用户空间程序发出的系统调用。 strace 显示这些调用的参数并返回符号形式的值。strace 从内核接收信息&#xff0c;而且不需要以任何特殊的方式来构建内核。 下面记录几个常用 option . …

明年,我要用 AI 给全村写对联

作者 | 神经小兮来源 | HyperAI超神经春节已经过完&#xff0c;你是否还沉浸在年味里&#xff1f;到腊月二十九、三十&#xff0c;家家户户贴上了 红红的春联&#xff0c;春节就正式拉开了序幕。春联也称为「对联」、「门对」、「楹联」&#xff0c;是汉语所独有的一种艺术形式…

C++实现int与string之间的相互转换

2019独角兽企业重金招聘Python工程师标准>>> c 利用stringstream实现int与string类型的相互转换&#xff0c;记录在此&#xff0c;以备后用 #include<iostream> #include<sstream> #include<string>using namespace std;string add_int(const st…

逆变器的技术创新 让光伏电站更具发展前景

曾几何时&#xff0c;光伏发电因为光照强度和温度的变化&#xff0c;逆变器输出功率波动大&#xff0c;对电网产生冲击&#xff0c;而被称为垃圾电而受到限制。随着技术的进步&#xff0c;光伏逆变器完善了多种保护功能&#xff0c;增加了低&#xff08;零&#xff09;电压穿越…

8个免费实用的C++GUI库

C标准中并没有包含GUI&#xff0c;这也使得C开发图形化界面需要依赖于第三方的库。实际上&#xff0c;图形界面恰恰是C的强项&#xff0c;小到平常使用的各类桌面软件&#xff0c;大到魔兽世界这样的游戏&#xff0c;都是C擅长的地方。C之所以能做到这一点&#xff0c;原因在于…

.Net2.0 使用ConfigurationManager读写配置文件

.net1.1中如果需要灵活的操作和读写配置文件并不是十分方便&#xff0c;一般都会在项目中封装一个配置文件管理类来进行读写操作。而在.net2.0中使用ConfigurationManager 和WebConfigurationManager 类可以很好的管理配置文件&#xff0c;ConfigurationManager类在System.Conf…

举个例子,如何用GCN图卷积神经网络实现摔倒监测?

作者 | 李秋键责编 | 寇雪芹头图 | 下载于视觉中国引言近几年来深度学习的发展越来越火热&#xff0c;其中最为典型的就是半监督学习的新研究进展GCN。由Kipf和Welling提出的GCN被证明是一种有效的图半监督学习框架应用&#xff0c;如社会、医疗、商业和交通网络分析&#xff0…

数据中心节能大法 —— 尽在上海11月中国数据中心展

根据调研机构451Research的预测&#xff0c;全球数据中心托管市场2018年的市场规模将达到332亿美元。据悉&#xff0c;2015年我国数据中心节能改造规模已达30亿元左右&#xff0c;数据中心节能市场的空间是非常大的&#xff0c;在未来有望达到85亿元的市场空间。 根据调研机构4…

古怪的ConfigurationManager类

开始使用VS 2005&#xff0c;习惯性的使用ConfigurationSettings类来读取应用程序配置文件的信息时&#xff0c;却被编译器提示说&#xff1a;警告 1 “System.Configuration.ConfigurationSettings.AppSettings”已过时:“This method is obsolete, it has been replaced by …

最常用的css选择器及兼容性 +几个好用却不多见的 nth-child等

你也许已经掌握了id、class、后台选择器这些基本的css选择器。但这远远不是css的全部。下面向大家系统的解析css中30个最常用的选择器&#xff0c;包括我们最头痛的浏览器兼容性问题。掌握了它们&#xff0c;才能真正领略css的巨大灵活性。 1. * * { margin: 0; paddin…

对比四种爬虫定位元素方法,你更爱哪个?

作者 | 陈熹来源 | 早起Python头图 | 下载于视觉中国在使用Python本爬虫采集数据时&#xff0c;一个很重要的操作就是如何从请求到的网页中提取数据&#xff0c;而正确定位想要的数据又是第一步操作。本文将对比几种 Python 爬虫中比较常用的定位网页元素的方式供大家学习&…

2017年安全漏洞审查报告:安全补丁在不断增加,用户却不安装

软件漏洞难修复吗&#xff1f;年度FLexera漏洞审查报告显示&#xff0c;全部安全漏洞当中有81%已经拥有与之匹配的修复补丁&#xff0c;但多数常见软件项目的补丁安装率却相当低下。 作为一家面向应用程序开发商与企业客户的软件安全漏洞管理解决方案厂商&#xff0c;Flexera S…

Visual SourceSafe简明培训教程

名称Visual SourceSafe简明培训教程(Visual SourceSafe Training Short Course) 作者晨光&#xff08;Morning&#xff09; 简介对于采用Visual SourceSafe 6.0作为版本控制工具的项目及产品开发&#xff0c;本教程针对不同用户角色&#xff0c;提供有关该软件的若干使用指导…

水母智能联合蚂蚁森林、犀牛智造等,用AI助力非遗出圈,39万人开工得“福”

如今过年越来越有年味了&#xff0c;许多淡出已久的中国传统年俗&#xff0c;以更有趣、更年轻新潮、更科技的方式回到了大家身边。集五福、写福字、贴福字&#xff0c;挂福饰品&#xff0c;当然还有接“福袋”&#xff01;人工智能实现智能设计已经相当成熟&#xff0c;已有微…

绿色信托任重道远 应建立补偿机制?

作为绿色金融的分支之一&#xff0c;绿色信托面临的状况不如绿色信贷、绿色债券&#xff0c;整体规模尚小&#xff0c;且监管方面的鼓励措施未有明确&#xff0c;甚至连概念都尚未统一。 日前&#xff0c;北京大学法学院非营利组织法研究中心与中航信托联合发布《2016年绿色信托…

解读C#正则表达式

多少年来&#xff0c;许多的编程语言和工具都包含对正则表达式的支持&#xff0c;.NET基础类库中包含有一个名字空间和一系列可以充分发挥规则表达式威力的类&#xff0c;而且它们也都与未来的Perl 5中的规则表达式兼容。 此外&#xff0c;regexp类还能够完成一些其他的功能&am…