kNN算法解析及应用【内附详细代码和数据集】

article/2025/9/7 3:32:55

首先,我们需要了解什么是“kNN”

kNN英文全称k Nearest Neighbor,即k近邻算法

  • 用途:分类问题
  • kNN的工作原理:事先有一个有标签的样本数据集,然后输入没有标签的新数据后,将新数据的每个特征和样本集里的数据对应特征进行比较,最后算法提取样本集中特征最相似(最近邻)数据的分类标签。一般而言,只取k个最相似数据中出现次数最多的分类作为新数据的分类。
  • 优点:精度高、对异常值不敏感、无数据输入假定。
  • 缺点:计算复杂度高、空间复杂度高。
  • 适用的数据范围:数值型和标称型。

一通文字理解下来后,下面给一个小例子

首先需要了解欧氏距离,很简单,就是平面上的两点之间的距离。

例:点A(x1, y1)与点B(x2, y2)之间的距离为 D=\sqrt{(x1 - x2)^{2} + (y1 - y2)^{2}}

样本数据集

样本编号XYlabel
11.01.1A
21.01.0A
300B
400.1B

测试数据

编号XYlabel
10.10.1待分类

从直观层面上就可以看出测试数据距离B类比较近,通过欧氏距离计算也是如此。下面给出kNN算法以及上面小例子的代码。

import numpy as np
import operator
import matplotlib.pyplot as pltdef kNN(inX, dataSet, labels, k):'''kNN算法:param inX: 需要分类的数据:param dataSet: 样本数据集:param labels: 样本数据的标签:param k: 需要取出的前k个:return: 最有可能的分类'''# 获取样本数据的个数dataSetSize = dataSet.shape[0]# np.tile函数将待分类的数据inX“广播”成和样本数据dataSet一样的形状# 获取待分类数据inX与样本数据集中的每个数据之间的差diffMat = np.tile(inX, (dataSetSize,1)) - dataSet# 平方sqDiffMat = diffMat**2# 按行累加sqDistances = sqDiffMat.sum(axis=1)# 开方,得出距离(欧氏距离)distances = sqDistances**0.5# 从小到大排序,得到的是数据的indexsortedDistIndicies = distances.argsort()classCount={}# 取出前k个距离最小的for i in range(k):voteIlabel = labels[sortedDistIndicies[i]]# 累计距离出现的次数,并做成字典classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1# 将字典按值的大小排序,大的在前sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)# 返回最有可能的预测值return sortedClassCount[0][0]def createDataSet():group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])labels = ['A','A','B','B']return group, labelsif __name__ == '__main__':group, labels = createDataSet()predict = kNN([0.1,0.1], group, labels, 3)print(predict) # 预测结果为B

接下来上实例,使用kNN算法改进约会网站的配对效果

数据集介绍:

总共10000条,包含三个特征(每年获得的飞行常客里程数,玩视频游戏所耗时间百分比,每周消费的冰淇淋公升数),而标签类型为(1代表“不喜欢的人”,2代表“魅力一般的人”,3代表“极具魅力的人”)

部分数据展示如下:(需要下载数据集的见文末

40920	8.326976	0.953952	3
14488	7.153469	1.673904	2
26052	1.441871	0.805124	1
75136	13.147394	0.428964	1

样本数据集展示:

 下面先给出作图代码,其他可以自主更换坐标轴以更好的分类:

def show():n = 1000  # number of points to createxcord1 = [];ycord1 = []xcord2 = [];ycord2 = []xcord3 = [];ycord3 = []markers = []colors = []fw = open('datingTestSet2.txt', 'w')for i in range(n):[r0, r1] = np.random.standard_normal(2)myClass = np.random.uniform(0, 1)if (myClass <= 0.16):fFlyer = np.random.uniform(22000, 60000)tats = 3 + 1.6 * r1markers.append(20)colors.append(2.1)classLabel = 1  # 'didntLike'xcord1.append(fFlyer);ycord1.append(tats)elif ((myClass > 0.16) and (myClass <= 0.33)):fFlyer = 6000 * r0 + 70000tats = 10 + 3 * r1 + 2 * r0markers.append(20)colors.append(1.1)classLabel = 1  # 'didntLike'if (tats < 0): tats = 0if (fFlyer < 0): fFlyer = 0xcord1.append(fFlyer);ycord1.append(tats)elif ((myClass > 0.33) and (myClass <= 0.66)):fFlyer = 5000 * r0 + 10000tats = 3 + 2.8 * r1markers.append(30)colors.append(1.1)classLabel = 2  # 'smallDoses'if (tats < 0): tats = 0if (fFlyer < 0): fFlyer = 0xcord2.append(fFlyer);ycord2.append(tats)else:fFlyer = 10000 * r0 + 35000tats = 10 + 2.0 * r1markers.append(50)colors.append(0.1)classLabel = 3  # 'largeDoses'if (tats < 0): tats = 0if (fFlyer < 0): fFlyer = 0xcord3.append(fFlyer);ycord3.append(tats)fw.close()fig = plt.figure()ax = fig.add_subplot(111)# ax.scatter(xcord,ycord, c=colors, s=markers)type1 = ax.scatter(xcord1, ycord1, s=20, c='red')type2 = ax.scatter(xcord2, ycord2, s=30, c='green')type3 = ax.scatter(xcord3, ycord3, s=50, c='blue')plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签ax.legend([type1, type2, type3], ["不喜欢", "魅力一般", "极具魅力"], loc=2)ax.axis([-5000, 100000, -2, 25])plt.xlabel('每年获取的飞行常客里程数')plt.ylabel('玩游戏所耗时间百分比')plt.show()

图像展示如下:

下面给出实例测试代码:

# 使用kNN算法改进约会网站的配对效果
import numpy as np
import pandas as pd
import operator
import matplotlib.pyplot as pltdef file_Matrix(filename):'''将源数据规整为所需要的数据形状:param filename: 源数据:return: returnMat:规整好的数据;classLabelVector:数据类标签'''data = pd.read_csv(filename, sep='\t').as_matrix()returnMat = data[:,0:3]classLabelVector = data[:,-1]return returnMat, classLabelVectordef autoNorm(dataSet):'''数据归一化:param dataSet::return:'''# 每列的最小值minVals = dataSet.min(0)# 每列的最大值maxVals = dataSet.max(0)ranges = maxVals - minVals# normDataSet = np.zeros(np.shape(dataSet))m = dataSet.shape[0]# np.tile(minVals,(m,1))的意思是将一行数据广播成m行normDataSet = (dataSet - np.tile(minVals, (m,1))) / np.tile(ranges, (m,1))# print(normDataSet)return normDataSet, ranges, minValsdef kNN(inX, dataSet, labels, k):'''kNN算法:param inX: 需要分类的数据:param dataSet: 样本数据集:param labels: 样本数据的标签:param k: 需要取出的前k个:return: 最有可能的分类'''# 获取样本数据的个数dataSetSize = dataSet.shape[0]# np.tile函数将待分类的数据inX“广播”成和样本数据dataSet一样的形状# 获取待分类数据inX与样本数据集中的每个数据之间的差diffMat = np.tile(inX, (dataSetSize,1)) - dataSet# 平方sqDiffMat = diffMat**2# 按行累加sqDistances = sqDiffMat.sum(axis=1)# 开方,得出距离(欧氏距离)distances = sqDistances**0.5# 从小到大排序,得到的是数据的indexsortedDistIndicies = distances.argsort()classCount={}# 取出前k个距离最小的for i in range(k):voteIlabel = labels[sortedDistIndicies[i]]# 累计距离出现的次数,并做成字典classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1# 将字典按值的大小排序,大的在前sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)# 返回最有可能的预测值return sortedClassCount[0][0]def datingClassTest():hoRatio = 0.10      #hold out 10%datingDataMat,datingLabels = file_Matrix('datingTestSet2.txt')       #load data setfrom filenormMat, ranges, minVals = autoNorm(datingDataMat)# print(normMat)m = normMat.shape[0]numTestVecs = int(m * hoRatio)errorCount = 0.0for i in range(numTestVecs):classifierResult = kNN(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],4)print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]))if (classifierResult != datingLabels[i]): errorCount += 1.0print("测试集个数为%d ,分类错误的个数为%d"%(numTestVecs, errorCount))print("the total error rate is: %f" % (errorCount/float(numTestVecs)))print("accuracy: %f" % ((1-errorCount/float(numTestVecs))*100))if __name__ == '__main__':datingClassTest()

 测试结果如下:

the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
... ...
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
测试集个数为99 ,分类错误的个数为4
the total error rate is: 0.040404
accuracy: 95.959596

测试的结果是错误率为4.04%,可以接受。不过还可以自主调节hoRatio和变量k的值,以便让错误率降低。

数据集下载:(百度网盘)

链接:https://pan.baidu.com/s/1UErV8D4Hrw557tjj9fyjlQ 
提取码:o80d 


参考文献:《Machine Learning in Action》


http://chatgpt.dhexx.cn/article/htBiNQts.shtml

相关文章

KNN算法介绍及代码实现

k-近邻法简介 k近邻法(k-nearest neighbor, k-NN)是1967年由Cover T和Hart P提出的一种基本分类与回归方法。它的工作原理是&#xff1a;存在一个样本数据集合&#xff0c;也称作为训练样本集&#xff0c;并且样本集中每个数据都存在标签&#xff0c;即我们知道样本集中每一个数…

机器学习——KNN及代码实现

KNN KNN即k-nearest neighbor(k近邻法)&#xff0c;多应用于分类问题。 k近邻法的输入为实例的特征向量&#xff0c;对应于特征空间中的点。输出为实例的类别。 K近邻法原理 给定一个训练数据集&#xff0c;对新的输入数据&#xff0c;在训练数据集中找到与该实例最邻近的k个…

KNN算法及其改进

KNN算法优缺点 优点 (1) 精度高 (2) 对异常值不敏感&#xff1a;某个异常值对整个结果不造成影响&#xff1b; (3) 无数据输入假定&#xff1a;无数据的独立性等假设&#xff1b;缺点 (1) 计算复杂度高&#xff1a;因为要计算的点需要与所有点计算距离&#xff0c;所以复杂度很…

机器学习算法-KNN代码实现

机器学习算法-KNN代码实现 一、KNN算法初步理解二、代码实现1.数据集处理2.创建model3.可视化 总结 一、KNN算法初步理解 统计学习方法书上的解释&#xff1a;给定一个训练数据集&#xff0c;对于新的输入实例&#xff0c;在训练数据集中找到与该实例最邻近的k个实例&#xff…

【数据挖掘基础】——KNN算法+sklearn代码实现(6)

🤵‍♂️ 个人主页:@Lingxw_w的个人主页 ✍🏻作者简介:计算机科学与技术研究生在读 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+ 目录 介绍算法的例子 KNN算法原理

KNN的优化算法1:距离加权

参考文章&#xff1a;https://www.cnblogs.com/bigmonkey/p/7387943.html 对参考文章中最后一部分说的有问题的地方进行了修改。 权值加权&#xff1a;为每个点的距离增加一个权重&#xff0c;使得距离近的点可以得到更大的权重&#xff0c;在此描述如何加权。 反函数 该方法最…

机器学习之深入理解K-means、与KNN算法区别及其代码实现

K-means方法是一种非监督学习的算法&#xff0c;它解决的是聚类问题。 1、算法简介&#xff1a;K-means方法是聚类中的经典算法&#xff0c;数据挖掘十大经典算法之一&#xff1b;算法接受参数k,然后将事先输入的n个数据对象划分为k个聚类以便使得所获得的聚类满足聚类中的对象…

KNN算法代码实现

原理&#xff1a; KNN 算法也叫K近邻算法。假设给定一个训练数据集&#xff0c;其中的实例类别已定。它是通过找到一个数据集中与目标数据最近的K个邻居&#xff0c;然后通过多数表决等方式来预测目标数据的分类结果进行预测。 三要素&#xff1a; 距离度量、K值、分类决策规…

KNN中的优化算法KD-tree

我们知道KNN是基于距离的一个简单分类算法&#xff0c;熟悉KNN的都知道&#xff0c;我们要不断计算两个样本点之间的距离&#xff0c;但是&#xff0c;试想一下&#xff0c;如果数据量特别大的时候&#xff0c;我们要每个都计算一下&#xff0c;那样计算量是非常大的&#xff0…

KNN算法代码

一、K近邻算法 KNN是一种监督学习类别的算法&#xff0c;全称&#xff08;K-NearestNeighbor&#xff09;直译为K个最近的邻居&#xff0c;是一种聚类算法。该算法认为我们在判断一个物体的类别可以根据与他非常相似的K个物体的类别&#xff08;这K个物体的类别是已知的&#x…

KNN数据缺失值填充(附源码和数据)不调用包

KNN估计 数据缺失值填充—KNN估计一、基本思想二、步骤1.导入数据2.查看空缺值3.取出要分析的数据4.计算平均值5.计算标准差6.规范化7.计算欧几里得距离8.最优解9.画图 总结 数据缺失值填充—KNN估计 运行环境 python3.6 jupyter notebook 一、基本思想 先将数据标准化&…

数据挖掘——KNN算法的实现

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;练习时长两年半的java博主 &#x1f4d6;个人主页&#xff1a;君临๑ &#x1f381; ps&#xff1a;点赞是免费的&#xff0c;却可以让写博客的作者开心好几天&#x1f60e; 文章目录 一、k-最近邻分类算法介绍 二、k-NN的特…

KNN算法调优

1.所用方法: 交叉验证与网格搜索 交叉验证(为了让被评估的模型更加精确可信): 所有训练集数据分成N等分&#xff0c;几等分就是几折交叉验证 网格搜索:调参数 K-近邻:超参数K 2.API: sklearn.model_selection.GridSearchCV&#xff1a; CV即cross validation…

计算机编程—必备基础知识点

目录&#xff1a; 1. 编程语言1.1 编程1.2 计算机语言1.3 编程语言1.4 翻译器1.5 编程语言和标记语言区别 2. 计算机基础2.1 计算机组成2.2 数据存储2.3 数据存储单位2.4 程序运行 1. 编程语言 1.1 编程 编程&#xff1a;就是让计算机为解决某个问题而使用某种程序设计语言编…

计算机概论--计算机基础知识快速入门

0.前言1.计算机&#xff1a;辅助人脑的好工具 1.1计算机硬件的五大单元1.2CPU的种类1.3接口设备1.4运作流程 2.个人计算机架构与接口设备 2.1CPU2.2内存2.3显卡2.4硬盘与存储设备2.5主板 3.软件程序执行 3.1机器程序与编译程序3.2操作系统 3.2.1操作系统内核3.2.2系统调用 3.3小…

0基础如何开始学习计算机知识?

一、计算机的基本操作 计算机中只有文件和文件夹 计算机中&#xff0c;只有两样东西&#xff0c;文件和文件夹。 文件夹&#xff1a;本身不存储数据内容。文件夹是用来组织和管理文件的。 文件&#xff1a; 所有的txt文本文档&#xff0c;音乐&#xff0c;视频&#xff0c;图…

【电脑讲解】电脑知识入门大全,超详细电脑基础知识讲解

这是一个新坑&#xff0c;希望大家喜欢 电脑的基础知识大全&#xff0c;你确定都知道? 一、软件系统 软件系统包括&#xff1a;操作系统、应用软件等。应用软件中电脑行业的管理软件&#xff0c;IT电脑行业的发展必备利器&#xff0c;电脑行业的erp软件。 二、硬件系统 硬件系…

计算机知识01:计算机基础知识入门

1. 计算机运行流程 如果不是很了解电脑运行流程的话&#xff0c;我们可以类比一下&#xff0c;假设电脑是一个人体&#xff0c;那么每个元件对应到哪个地方呢&#xff1f;可以这样思考&#xff1a; CPU脑袋&#xff1a;每个人会做的事情都不一样&#xff08;微指令集的差异&a…

IP地址(IP Address)

IP Address在网络中&#xff0c;通信节点都需要一个IP地址 以点分十进制表示&#xff0c;有32位二进制构成&#xff08;大约43亿&#xff09; 分为两个部分&#xff1a;网络位和主机位 网络位&#xff1a;代表IP地址所属的网段 主机位&#xff1a;代表网点上的某个节点 由子…

IP地址构成 ,以及如何求“网络地址“以及“广播地址“

IP地址&#xff08;英语&#xff1a;IP Address, 全称&#xff1a;Internet Protocol Address&#xff09;又称互联网协议地址。当设备连接网络&#xff0c;设备将被分配一个IP地址&#xff0c;用作标识。通过IP地址&#xff0c;设备间可以互相通讯&#xff0c;如果没有IP地址&…