KNN-K近邻算法(K-Nearest Neighbors)

news2024/11/19 19:30:11

k近邻算法的特点

  • 思想极度简单
  • 应用数学知识少(近乎为零)
  • 效果好(缺点?)
  • 可以解释机器学习算法使用过程中的很多细节问题
  • 更完整的刻画机器学习应用的流程

k近邻算法

在这里插入图片描述

k近邻算法整体是这样的一个算法,我们已经知道的这些数据点其实是分布在一个特征空间中的,通常呢,我们使用一个二维的平面来演示。比如说现在这个例子就是一个肿瘤病人相关的数据,横轴代表一个特征,是发现了这个肿瘤病人他肿块的大小,而纵轴呢,是发现这个肿块的时间。对于每一个病人,他的肿块大小和发现这个肿瘤的时间就构成了在这个特征平面中的一个点。这些点中有恶性的肿瘤用蓝色表示,良性的肿瘤用红色表示,图中一共有八个数据点。
在这里插入图片描述

如果现在新来的一个病人,他在特征空间中对应的位置在这里,我们怎么判断这个新来的绿色点,它最有可能是良性肿瘤患者还是恶性肿瘤患者呢?K近邻算法就是这样的一个算法,首先我们必须取一个K值,假设K等于三。对于每一个新的数据点,K近邻算法做的事情就是在所有的这些点中寻找离这个新的点最近的三个点。然后这些最近的点以他们自己的label,自己的结果进行投票。在这个例子中,离这个新的点最近的三个点都是代表恶性肿瘤的蓝色的点,所以蓝色对红色是3:0。因此K近邻算法就说这个新的点有很高的概率,它其实也是一个蓝色的点,很有可能是一个恶性肿瘤的患者。

在这里插入图片描述

在这里插入图片描述

K近邻算法的本质是认为两个样本如果他们足够的相似的话,那么它就有更高的概率属于同一个类别。当然可能只看离它最近的那一个样本是不靠谱的,所以我们多看几个样本,一共看K个样本,看哪个类别最多,我们就认为这个新的样本最有可能属于哪个类别, 可以理解为少数服从多数。

在这里,我们描述两个样本是否相似,这个相似性是通过两个样本在特征空间中的距离来进行描述的。

我们再举一个例子, 比如现在又新来了一个病人
在这里插入图片描述

我们来看一下离它最近的三个点, 那么对于这个新来的点, 红色和蓝色的比率时候2:1, 所以红色胜出, 我们来看一下离它最近的三个点, 那么对于这个新来的点, 红色和蓝色的比率时候2:1, 所以红色胜出, 那么K近邻算法就告诉我们,对于这个新病人来说, 他更可能是一个良性肿瘤患者

k近邻算法首先可以解决的是我们之前介绍的监督学习分类的问题, 不过k近邻算法也可以解决回归问题, 后续我们将进行介绍

计算距离我们使用欧拉距离公式:

欧拉距离

( x ( a ) − x ( b ) ) 2 + ( y ( a ) − y ( b ) ) 2 ( x ( a ) − x ( b ) ) 2 + ( y ( a ) − y ( b ) ) 2 + ( z ( a ) − z ( b ) ) 2 ( X 1 ( a ) − X 1 ( b ) ) 2 + ( X 2 ( a ) − X 2 ( b ) ) 2 + … + ( X n ( a ) − X n ( b ) ) 2 \begin{array}{c}\sqrt{\left(x^{(a)}-x^{(b)}\right)^{2}+\left(y^{(a)}-y^{(b)}\right)^{2}} \\\sqrt{\left(x^{(a)}-x^{(b)}\right)^{2}+\left(y^{(a)}-y^{(b)}\right)^{2}+\left(z^{(a)}-z^{(b)}\right)^{2}} \\\sqrt{\left(X_{1}^{(a)}-X_{1}^{(b)}\right)^{2}+\left(X_{2}^{(a)}-X_{2}^{(b)}\right)^{2}+\ldots+\left(X_{n}^{(a)}-X_{n}^{(b)}\right)^{2}}\end{array} (x(a)x(b))2+(y(a)y(b))2 (x(a)x(b))2+(y(a)y(b))2+(z(a)z(b))2 (X1(a)X1(b))2+(X2(a)X2(b))2++(Xn(a)Xn(b))2
第二个公式是欧拉距离公式在立体几何中的拓展

不过对于我们要处理的这个特征向量很有可能要比三维要高,那么此时我们使用这种XYZ一个一个的字母是不方便的所以在这里我们又添加了一个角标,X就是代表我们整个的数据, x n ( a ) {x_{n}}^{(a)} xn(a)就代表a样本的第n个维度, x n ( b ) {x_{n}}^{(b)} xn(b)就代表b样本的第n个维度, 那么这个式子其实就是在计算ab两个样本之间的距离, 这个计算方式就是A样本的每个维度的特征减去B样本中相应的每个维度的特征然后平方然后进行相加最后再开个根号, 在公式中我们假设我们的特征向量一共有N个维度, 也就是说一共有n个特征。这就是高维的欧拉距离公式的计算

但是这种公式看起来比较不方便, 所以通常我们使用连加的形式来进行表示
∑ i = 1 n ( X i ( a ) − X i ( b ) ) 2 \sqrt{\sum_{i=1}^{n}\left(X_{i}^{(a)}-X_{i}^{(b)}\right)^{2}} i=1n(Xi(a)Xi(b))2
它表示从i=1开始, 直到i=n结束, 每次都将A样本的第i个特征和B样本的第i个特征相减再平方, 最后所有的项加起来开个根号

接下来我们先采用最原始的方式实现一下KNN分类算法, 先大致的了解一下KNN算法的实现思路(以下代码均在jupyter 中实现)

在此之前我们先使用matplotlib库可视化一下数据集中的数据

import numpy as np
import matplotlib.pyplot as plt
raw_data_X = [[3.393533211, 2.331273381],
              [3.110073483, 1.781539638],
              [1.343808831, 3.368360954],
              [3.582294042, 4.679179110],
              [2.280362439, 2.866990263],
              [7.423436942, 4.696522875],
              [5.745051997, 3.533989803],
              [9.172168622, 2.511101045],
              [7.792783481, 3.424088941],
              [7.939820817, 0.791637231]
             ]

# 每一个样本的类别, 0代表良性肿瘤, 1代表恶性肿瘤
raw_data_y = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
# 将所有的数据都作为我们的训练集
# 在这里我们进行命名训练集, 也就是对应的是训练使用的这些样本的label
X_train = np.array(raw_data_X)
y_train = np.array(raw_data_y)
X_train
array([[3.39353321, 2.33127338],
       [3.11007348, 1.78153964],
       [1.34380883, 3.36836095],
       [3.58229404, 4.67917911],
       [2.28036244, 2.86699026],
       [7.42343694, 4.69652288],
       [5.745052  , 3.5339898 ],
       [9.17216862, 2.51110105],
       [7.79278348, 3.42408894],
       [7.93982082, 0.79163723]])
y_train
array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1])
# 进行可视化我们训练的样本
plt.scatter(X_train[y_train==0, 0], X_train[y_train==0, 1], color="g")
plt.scatter(X_train[y_train==1, 0], X_train[y_train==1, 1], color="r")
plt.show()

在这里插入图片描述

# 假设新输入一个数据
x = np.array([8.093607318, 3.365731514])
# 进行可视化我们训练的样本
plt.scatter(X_train[y_train==0, 0], X_train[y_train==0, 1], color="g")
plt.scatter(X_train[y_train==1, 0], X_train[y_train==1, 1], color="r")
plt.scatter(x[0], x[1], color="b")
plt.show()

在这里插入图片描述

KNN的过程

from math import sqrt
# 原始方法(笨方法)
# 该列表是用于存储它们之间的距离
distances =  []
for x_train in X_train:
    d = sqrt(np.sum((x_train - x)**2))# 让两个样本进行对应相减得到两点之间的距离
    distances.append(d)
distances
[4.812566907609877,
 5.229270827235305,
 6.749798999160064,
 4.6986266144110695,
 5.83460014556857,
 1.4900114024329525,
 2.354574897431513,
 1.3761132675144652,
 0.3064319992975,
 2.5786840957478887]
nearest = np.argsort(distance)
# 查看训练数据集中离新输入的患者最近的几个点
nearest
array([8, 7, 5, 6, 9, 3, 0, 1, 4, 2], dtype=int64)

在 k-最近邻(k-Nearest Neighbors,简称 k-NN)算法中,“k” 指的是一个超参数,表示用于确定新样本所属类别的邻居数量。具体来说,k-NN 算法通过以下步骤来进行分类:

  1. 计算未知样本与训练集中所有已知样本的距离。
  2. 选择距离最近的 “k” 个已知样本(最近的 k 个邻居)。
  3. 根据这 k 个邻居中所属类别的多数投票来确定未知样本的类别。换句话说,未知样本将被分类为与其距离最近的 k 个邻居中最常见的类别。

因此,k-NN 算法中的 “k” 控制了决策过程中邻居的数量,它是一个重要的超参数,需要根据具体问题的特点来选择。选择不同的 “k” 值可能会导致不同的分类结果,因此通常需要进行交叉验证等方法来确定最佳的 “k” 值。较小的 “k” 值可能会导致模型对噪声敏感,而较大的 “k” 值可能会导致模型过于平滑。因此,在实际应用中,需要根据数据集的特点和问题的需求来选择合适的 “k” 值。

# k 指的是要查找的最近样本的数量
k=6
# 查找最近的点相应的y坐标
topk_y = [y_train[i] for i in nearest[:k]]
topk_y
[1, 1, 1, 1, 1, 0]

接下来我们看下collections中的Counter方法
collections 模块是 Python 标准库中的一个模块,它提供了一些额外的数据类型和数据结构,用于扩展内置数据类型(如列表、元组、字典等)的功能。Countercollections 模块中的一个类,用于创建计数器对象,用于计算可迭代对象中元素的出现次数。

以下是关于 Counter 类的一些详细信息和用法示例:

  1. 创建计数器对象:可以使用 Counter() 构造函数来创建一个计数器对象。计数器对象可以接受一个可迭代对象作为参数,例如列表、字符串、元组等。

    from collections import Counter
    
    # 创建计数器对象
    my_list = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
    counter = Counter(my_list)
    
    print(counter)
    

    输出:

    Counter({4: 4, 3: 3, 2: 2, 1: 1})
    

    上面的计数器对象表示在 my_list 中,元素 4 出现了 4 次,元素 3 出现了 3 次,以此类推。

  2. 元素计数:可以使用计数器对象的键(元素)来查询元素出现的次数。

    print(counter[3])  # 查询元素 3 出现的次数
    

    输出:

    3
    
  3. 元素计数的方法:计数器对象还提供了一些方法来获取元素的计数。

    print(counter.get(2))        # 获取元素 2 出现的次数
    print(counter.keys())        # 获取所有不重复的元素
    print(counter.values())      # 获取所有元素的计数值
    print(counter.most_common()) # 获取按计数值降序排列的元素列表
    
  4. 更新计数器:可以使用计数器对象的 update() 方法来更新计数器的内容。

    counter.update([3, 4, 5])  # 更新计数器,增加元素 5 的计数
    

    更新后的计数器会反映新的计数值。

Counter 类在数据分析、文本处理和统计分析等领域非常有用,它可以帮助你快速统计和分析数据中元素的出现频率。

from collections import Counter

# 我们可以把这个统计的过程理解成投票vote的过程
Counter(topk_y)  # 它会自动统计距离这个新输入样本最近的7个样本中不同类别所占的个数, 返回值是个字典类型的数据
Counter({1: 5, 0: 1})
votes = Counter(topk_y)
votes.most_common(1)[0][0]  # 括弧中的数字代表票数最多的几个元素, 返回值是一个元素为元组的列表
1
predict_y = votes.most_common(1)[0][0]  # 这就是整个预测出来的值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1035560.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务注册发现_Eureka概述

Spring Cloud Eureka 是Netflix 开发的注册发现组件,本身是一个基于 REST 的服务。提供注册与发现,同时还提供了负载均衡、故障转移等能力。 Eureka3个角色 服务中心服务提供者服务消费者。 注意: Eureka Server:服务器端。它提…

【Linux】系统编程线程读写者模式(C++)

目录 一、读写锁 二、读写锁接口 【2.1】设置读写优先 【2.2】初始化 【2.3】销毁 【2.4】加读锁 【2.5】加写锁 【2.6】解锁 三、读写锁实例 一、读写锁 在编写多线程的时候,有一种情况是十分常见的。那就是,有些公共数据修改的机会比较少。相…

接口自动化测试之Mock

【软件测试面试突击班】如何逼自己一周刷完软件测试八股文教程,刷完面试就稳了,你也可以当高薪软件测试工程师(自动化测试) 1.Mock实现原理和实现机制 在某些时候,后端在开发接口的时候,处理逻辑非常复杂&a…

基于Java+SpringBoot+Vue+Uniapp奶茶在线下单小程序设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言用户微信小程序端的主要功能有:管理员的主要功能有:具体实现截图详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考论文参考源码获取 前言 💗博主介绍:✌…

Linux 用户 用户组管理

用户 Linux系统是一个多用户多任务的分时操作系统,任何要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统。每个用户账号都拥有一个唯一的用户名和各自的口令。用户在登录时键入正确的用户名和口令后&a…

ubuntu22.04编译DPDK19.08.2注意事项

下载:http://fast.dpdk.org/rel/dpdk-19.08.2.tar.xz 解压:tar -xvf dpdk-19.08.2.tar.xz (1)设置环境变量和编译 cd dpdk-stable-19.08.2 export RTE_SDKpwd export RTE_TARTGETx86_64-native-linuxapp-gcc make config Tx86…

Ae 效果:CC Simple Wire Removal

Keying/CC Simple Wire Removal Keying/CC Simple Wire Removal CC Simple Wire Removal (CC 简单线条移除)通过在两点之间创建一条指定宽度(厚度)的连线,然后将连线区域内的像素按指定方式进行填充,从而实…

R语言非线性方程数值分析生物降解、植物生长数据:多项式、渐近回归、米氏方程、逻辑曲线、Gompertz、Weibull曲线...

全文链接:https://tecdat.cn/?p33742 在选择最佳拟合实验数据的方程时,可能需要一些经验。当我们没有文献信息时该怎么办?我们建立模型的方法通常是经验主义的。也就是说,我们观察过程,绘制数据并注意到它们遵循一定的…

Qt使用opencv操作摄像头的例子

概述 这是一个Qt使用opencv lib操作摄像头的例子 详细 一、简介 这是一个Qt使用opencv lib操作摄像头的例子 二、代码实现过程 新建一个VideoCapture对象,然后通过这个对象读取Mat图像数据,再讲Mat数据转成QImage显示在QLabel上。 VideoCapture既支持…

PythonWeb服务器(HTTP协议)

一、HTTP协议与实现原理 HTTP(Hypertext Transfer Protocol,超文本传输协议)是一种用于在网络上传输超文本数据的协议。它是Web应用程序通信的基础,通过客户端和服务器之间的请求和响应来传输数据。在HTTP协议中连接客户与服务器的…

读写分离MySQL

利用Mycat控制后台数据库的读写分离和负载均衡 利用主从复制思想,实现读写分离,主库写,从库读 从库最好不要写,因为从库写入的数据不能同步到主库,只有主库写的数据才能同步到从库 balance属性值对应的含义(负载均衡) 一主一从读写分离的弊端 主节点Master宕机以后,业务系统…

DN-DETR(CVPR 2022)

DN-DETR(CVPR 2022) Accelerate DETR Training by Introducing Query DeNoising 匈牙利匹配不稳定导致了早期训练阶段的优化目标不一致 同一个图像,query在不同时期会对不同对象进行匹配 DN-DETR在真实的GT上添加噪声:xywh&am…

OpenGLES:多纹理贴图,文字水印

一.概述 上一篇博客讲解了OpenGLES怎么实现单纹理贴图 仅仅只绘制一张图片是不过瘾的 本篇博客讲解如何通过多纹理贴图实现图片和文本水印效果 在单纹理贴图基础上,多纹理贴图的区别主要有两点: 纹理的生成、绑定等由单个变成多个文本内容先转换为B…

深度学习实战基础案例——卷积神经网络(CNN)基于Xception的猫狗识别|第2例

文章目录 一、环境准备二、数据预处理三、构建模型四、实例化模型五、训练模型5.1 构建训练函数5.2 构建测试函数5.3 开始正式训练 六、可视化精度和损失七、个体预测 我的环境: pytorch:2.0python:3.8jupyternotebook 一、环境准备 impor…

jmeter——接口压测和性能监测实践

一、安装JMeter 1. 在客户端机器上安装JMeter压测工具,我这里安装的版本是apache-jmeter-5.2.1,由于JMeter是JAVA语言开发的,所以安装JMeter压测工具前先安装JDK,一般安装JDK1.8及以上即可。安装完成后,如果客户端机器…

【广州华锐互动】利用VR开展工业事故应急救援演练,确保救援行动的可靠性和有效性

在工业生产中,事故的突发性与不可预测性常常带来巨大的损失。传统的应急演练方式往往存在场地限制、成本高、效果难以衡量等问题。然而,随着虚拟现实(VR)技术的快速发展,VR工业事故应急救援演练应运而生,为…

基于PLE结合卡尔曼滤波的RSSI定位算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ............................................................... for Num_xb Num_xb2Num_…

Elasticsearch 部署学习

文章目录 Elasticsearch 部署学习1. 单节点部署 elasticsearch1.1 部署 jdk1.2 下载 elasticsearch1.3 上传文件并修改配置文件1.4 启动1.5 问题总结1.6 浏览器验证 2. 集群部署 elasticsearch3. 常用命令4. Elasticsearch kibana安装:one: 参考部署文档:two: 下载对应版本的安…

75、SpringBoot 整合 MyBatis------使用 Mapper 作为 Dao 组件

总结: 添加一个User类和Mapper接口, 在Mapper接口这个类上面添加Mapper注解,就可以和数据库进行映射了, 然后在mapper接口写方法和sql, 在测试类进行测试。 pom文件就添加个mybatis-spring-boot-starter 的组件&#x…