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

算法核心

KNN算法的核心思想是“近朱者赤,近墨者黑”。对于一个待分类或预测的样本点,它会查找训练集中与其距离最近的K个样本点(即“最近邻”)。然后根据这K个最近邻的标签信息来对当前样本进行分类或回归。 在分类任务中,通常是根据K个最近邻中出现次数最多的类别来确定待分类样本的类别;在回归任务中,则是根据K个最近邻的目标值的平均值来预测待预测样本的目标值。

 例如在图中:

如果我们以k=3画圆,因为在圆圈内ClassB出现的数量要比ClassA更多,因此我们可以把它归到ClassB

但如果我们以k=6画圆,因为在圆圈内ClassA出现的数量要比ClassB更多,因此我们可以把它归到ClassA

值得注意的是:这里的k是离我们观测点最近的第k个点,而非半径

距离选择

这里的距离可以采用不同的求法,常见的距离度量方式有:

• 欧氏距离:这是最常见的距离度量方式,它计算的是样本点在多维空间中的直线距离。对于两个样本点 x = (x_1, x_2, ..., x_n) 和 y = (y_1, y_2, ..., y_n) ,欧氏距离定义为 \sqrt{(x_1 - y_1)^2 + (x_2 - y_2)^2 + ... + (x_n - y_n)^2} 。• 曼哈顿距离:它计算的是样本点在坐标轴方向上的绝对距离之和,即 |x_1 - y_1| + |x_2 - y_2| + ... + |x_n - y_n| 。在某些场景下,比如在城市街区网格中计算两点之间的距离时,曼哈顿距离更符合实际情况。

• 明可夫斯基距离:它是一种更通用的距离度量,欧氏距离和曼哈顿距离都是它的特例。明可夫斯基距离的定义为

 当 p = 2 时,就是欧氏距离;当 p = 1 时,就是曼哈顿距离

 K值的选择

K值的选择对KNN算法的性能影响很大。 如果K值选得太小,算法会过于敏感,容易受到噪声数据的影响。例如,当K = 1时,一个噪声点可能会直接影响到分类或回归的结果。如果K值选得太大,算法又会过于“平滑”,可能会将不同类别的样本混合在一起。比如在一个复杂的分类问题中,如果K值过大,可能会导致不同类别之间的边界模糊。 通常,k值选择时一般选择的是比较小的值,像是3、5、7、9这样的个位单数

kd树优化算法

kd树(k-d tree,k维树)是用于优化KNN算法中最近邻搜索过程的一种数据结构。

kd树的作用

1. 加速最近邻搜索

• 在KNN算法中,最耗时的部分是计算待预测点与训练集中所有点之间的距离,以找到最近的K个邻居。当训练集规模很大时,这种暴力搜索方法效率非常低。

• kd树通过将训练数据组织成一种树形结构,能够快速定位到与目标点最近的区域,从而减少需要计算距离的点的数量,大大加快最近邻搜索的速度。

2. 空间划分

• kd树是一种二叉树结构,它通过递归地将数据空间划分为超矩形区域。在每次划分时,选择一个维度(通常是方差最大的维度)作为划分轴,将数据点按照该维度的中值分为两部分,分别存储在树的左子树和右子树中。通过这种方式,kd树将整个数据空间划分为多个小区域,每个区域对应树中的一个节点。

kd树的构建过程

1. 选择划分维度

• 在构建kd树时,需要选择一个维度作为划分轴。通常会选择方差最大的维度,因为方差大的维度意味着数据在这个方向上的分布更分散,划分效果更好。

2. 选择划分点

• 在选定的维度上,选择该维度的中值作为划分点。将小于中值的点分配到左子树,大于中值的点分配到右子树。

3. 递归划分

• 对左右子树重复上述过程,每次选择不同的维度进行划分,直到每个区域只包含一个数据点,或者满足其他停止条件。

kd树在KNN中的使用

1. 搜索最近邻

• 当需要找到某个目标点的最近邻时,kd树会从根节点开始,沿着树的结构向下搜索。根据目标点在当前划分维度上的值,决定是进入左子树还是右子树。通过这种方式,可以快速定位到目标点所在的区域。

2. 回溯查找

• 单纯沿着树向下搜索可能无法找到真正的最近邻,因为可能存在其他区域的点距离目标点更近。因此,在搜索到叶子节点后,需要进行回溯。在回溯过程中,检查每个节点的划分超平面与目标点的距离,如果这个距离小于当前已知的最近距离,就需要检查另一侧子树,以确保找到真正的最近邻。

示例场景

假设我们有一个二维空间中的数据点集合,目标是找到某个目标点\(P\)的最近邻点。我们将通过以下步骤来展示如何利用空间划分和距离关系来优化搜索过程。

1.数据点和目标点

假设我们有以下数据点:

• \(A(1,1)\)

• \(B(2,2)\)

• \(C(10,10)\)

• \(D(11,11)\)

• \(E(12,12)\)

目标点\(P\)的坐标为\((0,0)\)。

2.构建空间划分结构(如kd树)

为了优化搜索过程,我们首先构建一个kd树。假设我们按照以下步骤构建kd树:

1. 选择第一个维度(x轴)作为划分轴,找到中值点\(B(2,2)\)。

2. 将数据点分为两部分:

• 左子树:\(A(1,1)\)

• 右子树:\(C(10,10)\),\(D(11,11)\),\(E(12,12)\)

3. 对右子树,选择第二个维度(y轴)作为划分轴,找到中值点\(D(11,11)\)。

4. 继续划分,直到每个区域只包含一个点。

构建的kd树如下:

        B(2, 2)/ \A(1, 1) D(11, 11)/ \C(10, 10) E(12, 12)

3.利用距离关系跳过某些点

现在,我们从目标点\(P(0,0)\)开始搜索其最近邻点。

第一步:从根节点开始

• 从根节点\(B(2,2)\)开始,计算\(P\)与\(B\)的距离:

 第二步:选择子树

• 由于\(P\)的 x 坐标小于\(B\)的 x 坐标,我们进入左子树,到达点\(A(1,1)\)。

• 计算\(P\)与\(A\)的距离:

 • 目前,\(A\)是最近邻点,最近距离为\(\sqrt{2}\)。

第三步:回溯并跳过某些点

• 回溯到根节点\(B\)。检查右子树是否可能包含更近的点。

• 计算目标点\(P\)到右子树划分超平面(x=2)的距离:

 • 由于\(2>\sqrt{2}\),这意味着右子树中任何点到\(P\)的距离都不会小于当前的最近距离\(\sqrt{2}\)。因此,我们可以跳过右子树中的所有点(\(C\),\(D\),\(E\)),而不需要进一步计算它们与\(P\)的距离。

4.优化后的搜索过程

通过上述步骤,我们利用了空间划分(kd树)和距离关系(跳过距离远的点)来优化搜索过程。最终,我们确定\(A(1,1)\)是目标点\(P(0,0)\)的最近邻点,而无需计算\(P\)与右子树中所有点的距离。

5.复杂度分析

• 暴力搜索:计算目标点与所有点的距离,复杂度为\(O(DN)\)。

• 优化后的搜索:通过kd树的空间划分和跳过无关区域,复杂度降低到\(O(DN\log N)\)。这是因为:

• 构建kd树的复杂度为\(O(N\log N)\)。

• 搜索过程通过递归和回溯,每次只需要检查部分点,而不是所有点。

应用实例

以下是一个使用Python和`scikit-learn`库实现的KNN算法对鸢尾花(Iris)数据集进行分类的完整代码示例。鸢尾花数据集是机器学习中常用的入门数据集,包含150个样本,每个样本有4个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度),分为3个类别。
 

# 导入必要的库
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score# 加载鸢尾花数据集
iris = load_iris()
X = iris.data  # 特征数据
y = iris.target  # 标签数据# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 数据标准化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)# 创建KNN分类器
k = 3  # 选择K值
knn = KNeighborsClassifier(n_neighbors=k)# 训练模型
knn.fit(X_train, y_train)# 进行预测
y_pred = knn.predict(X_test)# 评估模型
print("混淆矩阵:")
print(confusion_matrix(y_test, y_pred))
print("\n分类报告:")
print(classification_report(y_test, y_pred))
print("\n准确率:")
print(accuracy_score(y_test, y_pred))# 输出测试集的真实标签和预测标签
print("\n测试集的真实标签:", y_test)
print("测试集的预测标签:", y_pred)

代码说明


1. 加载数据集

• 使用`load_iris()`函数加载鸢尾花数据集。

• 数据集包含150个样本,每个样本有4个特征,分为3个类别(0、1、2)。


2. 划分训练集和测试集

• 使用`train_test_split()`函数将数据集划分为训练集和测试集,其中测试集占30%。

• 设置`random_state`参数以确保结果的可重复性。


3. 数据标准化

• 使用`StandardScaler`对特征数据进行标准化处理,使每个特征的均值为0,标准差为1。这有助于提高KNN算法的性能。


4. 创建KNN分类器

• 使用`KNeighborsClassifier`创建KNN分类器,设置`n_neighbors=k`,其中`k`是最近邻的数量。


5. 训练模型

• 使用`fit()`方法训练模型。


6. 进行预测

• 使用`predict()`方法对测试集进行预测。


7. 评估模型

• 使用`confusion_matrix`、`classification_report`和`accuracy_score`评估模型的性能。

• 输出混淆矩阵、分类报告和准确率。

 注意事项

1. K值的选择

• K值的选择对KNN算法的性能有很大影响。可以通过交叉验证等方法来选择最优的K值。

2. 数据标准化

• 对于KNN算法,数据标准化是非常重要的,因为KNN依赖于距离计算,而不同特征的量纲可能不同。

3. 数据集划分

• 数据集的划分方式可能会影响模型的性能,可以通过多次划分或使用交叉验证来评估模型的稳定性。

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Appium中元素定位之一个元素定位API

应用场景 想要对按钮进行点击,想要对输入框进行输入,想要获取文本框的内容,定位元素是自动化操作必须要使用的方法。只有获取元素之后,才能对这个元素进行操作。 在 Java 中使用 Appium 定位元素时,可以通过多种方式…

Dify 服务器部署指南

1. 系统要求 在开始部署之前,请确保你的服务器满足以下要求: 操作系统:Linux(推荐使用 Ubuntu 20.04 或更高版本)内存:至少 4GB RAM存储:至少 20GB 可用空间网络:稳定的互联网连接…

Sa-Token

简介 Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。 官方文档 常见功能 登录认证 本框架 用户提交 name password 参数,调用登…

ADZS-ICE-2000和AD-ICE2000仿真器在线升级固件

作者的话 近期发现有些兄弟的ICE-2000仿真器链接DSP报错,然后test第四步不通过,我就拿我的仿真器也试了一下,发现ADI悄咪咪的在线升级仿真器固件,有些兄弟不会操作,就会导致仿真器升级失败,连不上目标板&a…

C++概述

1 什么是面向对象】 概念上来说:就是以对象(具体的变量)为导向的编程思路 专注于:一个对象具体能实现哪些过程(哪些功能) 面向对象 n * 面向过程 结论:面向对象需要做的事情 1:我们要想清楚,我们现在需要编写一个…

Java 大视界 -- 基于 Java 的大数据隐私计算在医疗影像数据共享中的实践探索(158)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…

数字化如何赋能食品抽检全流程升级,助力食品安全监管现代化

食品安全是关乎民众健康和社会稳定的重要问题。食品抽检作为保障食品安全的核心监管手段,通过对食品生产、加工、销售等环节的随机抽样检测,及时发现潜在的食品安全问题,防止不合格产品流入市场,同时为政府监管、企业自查和消费者…

HBase入门教程

HBase入门教程 HBase是一个开源的、分布式的、版本化的非关系型数据库,是Apache Hadoop生态系统的重要组成部分。本文将全面介绍HBase的基础知识,帮助你快速入门。 文章目录 HBase入门教程1. HBase简介1.1 什么是HBase?1.2 HBase核心特点 2.…

vscode连接服务器失败问题解决

文章目录 问题描述原因分析解决方法彻底删除VS Code重新安装较老的版本 问题描述 vscode链接服务器时提示了下面问题: 原因分析 这是说明VScode版本太高了。 https://code.visualstudio.com/docs/remote/faq#_can-i-run-vs-code-server-on-older-linux-distribu…

redis常用部署架构之redis分片集群。

redis 3.x版本后开始支持 作用: 1.提升数据读写速度 2..提升可用性 分片集群就是将业务服务器产生的数据储存在不同的机器上。 redis分片集群的架构 如上图所示,会将数据分散存储到不同的服务器上,相比于之前来说,redis要处…

Modbus主站EtherNet/IP转ModbusRTU/ASCII工业EIP网关串口服务器

型号 2路总线EIP网关 MS-A1-2021 4路总线EIP网关 MS-A1-2041 4路总线EIP网关(双网口) MS-A2-2041 8路总线EIP网关 MS-A1-2081 8路总线EIP网关(双网口) MS-A2-2081 EtherNet/IP 串口网关 EtherNet/IP 转 RS485 …

Centos7 安装 TDengine

Centos7 安装 TDengine 1、简介 官网: https://www.taosdata.com TDengine 是一款开源、高性能、云原生的时序数据库(Time Series Database, TSDB), 它专为物联网、车联网、工业互联网、金融、IT 运维等场景优化设计。同时它还带有内建的缓…

基于社交裂变的S2B2C电商模式创新研究——以“颜值PK+礼品卡+AI智能名片“融合生态为例

摘要 本文构建了融合开源AI技术、社交裂变机制与S2B2C商业模式的创新模型。通过开发具备AI智能名片功能的商城小程序,实现用户日均停留时长提升171%、社交转化效率提高2.8倍的实证效果。研究发现:基于GAN的虚拟形象生成技术可降低用户决策成本32%&…

王者荣耀服务器突然崩了

就在刚刚王者荣耀服务器突然崩了 #王者荣耀崩了#的话题毫无预兆地冲上热搜,许多玩家发现游戏登录界面反复弹出异常提示,匹配成功后卡在加载界面,甚至出现对局数据丢失的情况。根据官方公告,目前技术团队已在全力抢修服务器 #王者…

LabVIEW医疗设备备用电源实时监控系统

开发了一个基于LabVIEW的医疗设备备用电源实时监控系统。系统提高医疗设备备用电源的管理效能与使用安全,通过实时监测与数据分析,确保医疗设施在电力供应中断时的可靠运行。 ​ 项目背景 医院中的医疗设备对电源的连续供应有着极高的要求,…

04-SpringBoot3入门-配置文件(多环境配置)

1、简介 在 SpringBoot 中,不同的环境(如开发、测试、生产)可以编写对应的配置文件,例如数据库连接信息、日志级别、缓存配置等。在不同的环境中使用对应的配置文件。 2、配置环境 # 开发环境 zbj:user:username: root # 测试环…

C++链表详解:从基础概念到高级应用

C++链表详解:从基础概念到高级应用 链表是计算机科学中最基础也是最重要的数据结构之一,它在内存管理、算法实现和实际应用中扮演着关键角色。本文将详细介绍链表的概念、类型、C++实现以及实际应用场景,帮助读者全面理解这一重要的数据结构。 文章目录 C++链表详解:从基础…

了解图像质量评价指标PSNR

一、PSNR是什么 1.1 定义与数学公式 峰值信噪比(Peak Signal-to-Noise Ratio,PSNR)是数字图像处理领域最经典的客观质量评价指标之一。其核心思想是通过计算原始图像与失真图像之间的均方误差(MSE)来衡量失真程度&am…

NX二次开发刻字功能——布尔运算

刻字功能在经历、创建文本、拉伸功能以后就剩下布尔运算了。布尔运算的目的就是实现文本时凸还是凹。这部分内容很简单。 1、首先识别布尔运算的类型,我这里用到一个枚举类型的选项,凸就是布尔求和,凹就是布尔求差。 2、其放置位置为创建拉伸…

《C语言实现金字塔图案打印》

🚀个人主页:BabyZZの秘密日记 📖收入专栏:C语言练习题分享 🌍文章目入 程序代码程序功能程序分析外层循环内层循环输出结果 示例运行总结 在学习编程的过程中,打印图案是一个非常有趣的练习,它可…