Python 实现 KNN(K-近邻)算法
Python 实现 KNN(K-近邻)算法
一、概述
KNN(K-最近邻)算法是相对比较简单的机器学习算法之一,它主要用于对事物进行分类。用比较官方的话来说就是:给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例, 这K个实例的多数属于某个类,就把该输入实例分类到这个类中。为了更好地理解,通过一个简单的例子说明。
我们有一组自拟的关于电影中镜头的数据:
那么问题来了,如果有一部电影 X,它的打戏为 3,吻戏为 2。那么这部电影应该属于哪一类?
我们把所有数据通过图表显示出来(圆点代表的是自拟的数据,也称训练集;三角形代表的是 X 电影的数据,称为测试数据):
计算测试数据到训练数据之间的距离,假设 k 为 3,那么我们就找到距离中最小的三个点,假如 3 个点中有 2 个属于动作片,1 个属于爱情片,那么把该电影 X 分类为动作片。这种通过计算距离总结 k 个最邻近的类,按照”少数服从多数“原则分类的算法就为 KNN(K-近邻)算法。
二、算法介绍
还是以上面的数据为例,打戏数为 x,吻戏数为 y,通过欧式距离公式计算测试数据到训练数据的距离,我上中学那会儿不知道这个叫做欧式距离公式,一直用”两点间的距离公式“来称呼这个公式: 。但是现实中的很多数据都是多维的,即使如此,也还是按照这个思路进行计算,比如如果是三维的话,就在根号里面再加上 z 轴差的平方,即 ,以此类推。
知道了这个计算公式,就可以计算各个距离了。我们以到最上面的点的距离为例:,那么从上到下的距离分别是:,,,。现在我们把 k 定为 3,那么距离最近的就是后面三个数了,在这三个数中,有两个属于动作片,因此,电影 X 就分类为动作片。
三、算法实现
知道了原理,那就可以用代码实现了,这里就不再赘述了,直接上带注释的 Python 代码:
''' trainData - 训练集 testData - 测试集 labels - 分类 ''' def knn(trainData, testData, labels, k): # 计算训练样本的行数 rowSize = trainData.shape[0] # 计算训练样本和测试样本的差值 diff = np.tile(testData, (rowSize, 1)) - trainData # 计算差值的平方和 sqrDiff = diff ** 2 sqrDiffSum = sqrDiff.sum(axis=1) # 计算距离 distances = sqrDiffSum ** 0.5 # 对所得的距离从低到高进行排序 sortDistance = distances.argsort() count = {} for i in range(k): vote = labels[sortDistance[i]] count[vote] = count.get(vote, 0) + 1 # 对类别出现的频数从高到低进行排序 sortCount = sorted(count.items(), key=operator.itemgetter(1), reverse=True) # 返回出现频数最高的类别 return sortCount[0][0]
ps:np.tile(testData, (rowSize, 1)) 是将 testData 这个数据扩展为 rowSize 列,这样能避免运算错误;
sorted(count.items(), key=operator.itemgetter(1), reverse=True) 排序函数,里面的参数 key=operator.itemgetter(1), reverse=True 表示按照 count 这个字典的值(value)从高到低排序,如果把 1 换成 0,则是按字典的键(key)从高到低排序。把 True 换成 False 则是从低到高排序。
四、测试与总结
用 Python 实现了算法之后,我们用上面的数据进行测试,看一下结果是否和我们预测的一样为动作片:
trainData = np.array([[5, 1], [4, 0], [1, 3], [0, 4]]) labels = ['动作片', '动作片', '爱情片', '爱情片'] testData = [3, 2] X = knn(trainData, testData, labels, 3) print(X)
执行这段代码后输出的结果为:动作片 。和预测的一样。当然通过这个算法分类的正确率不可能为 100%,可以通过增加修改数据测试,如果有大量多维的数据就更好了。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
sql注入问题
java.sql.PreparedStatement(SQL预处理) 防止SQL注入 只要你的sql参数是用户提供过来的都需要使用sql预处理 设置参数的时候需要选择对应数据类型进行设置,要不然处理类型的时候会有问题 setObject 此方法有一个好处就是,你可以给它任何类型,自己进行类型判断,识别你的类型进行设置 sql防注入代码举例: import java.sql.*; import java.util.Arrays; import java.util.Scanner; public class T4 { public static void main(String[] args) throws SQLException { java.util.Scanner input = new Scanner(System.in); System.ou...
- 下一篇
企业级 SpringBoot 教程 (二)Spring Boot配置文件详解
springboot采纳了建立生产就绪Spring应用程序的观点。 Spring Boot优先于配置的惯例,旨在让您尽快启动和运行。在一般情况下,我们不需要做太多的配置就能够让spring boot正常运行。在一些特殊的情况下,我们需要做修改一些配置,或者需要有自己的配置属性。完整项目的源码来源技术支持一七九一七四三三八零哦~~ 一、自定义属性 当我们创建一个springboot项目的时候,系统默认会为我们在src/main/java/resources目录下创建一个application.properties。个人习惯,我会将application.properties改为application.yml文件,两种文件格式都支持。 在application.yml自定义一组属性: my: name: forezp age: 12 如果你需要读取配置文件的值只需要加@Value(“${属性名}”): @RestController public class MiyaController { @Value("${my.name}") private String name; @Value(...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS8编译安装MySQL8.0.19
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS关闭SELinux安全模块
- Red5直播服务器,属于Java语言的直播服务器