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.mzph.cn/news/899686.shtml

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

相关文章

【Feign】⭐️使用 openFeign 时传递 MultipartFile 类型的参数参考

💥💥✈️✈️欢迎阅读本文章❤️❤️💥💥 🏆本篇文章阅读大约耗时三分钟。 ⛳️motto:不积跬步、无以千里 📋📋📋本文目录如下:🎁🎁&a…

zk基础—1.一致性原理和算法二

大纲 1.分布式系统特点 2.分布式系统的理论 3.两阶段提交Two-Phase Commit(2PC) 4.三阶段提交Three-Phase Commit(3PC) 5.Paxos岛的故事来对应ZooKeeper 6.Paxos算法推导过程 7.Paxos协议的核心思想 8.ZAB算法简述 6.Paxos算法推导过程 (1)Paxos的概念 (2)问题描述 …

216. 组合总和 III 回溯

目录 问题描述 解决思路 关键点 代码实现 代码解析 1. 初始化结果和路径 2. 深度优先搜索(DFS) 3. 遍历候选数字 4. 递归与回溯 示例分析 复杂度与优化 回溯算法三部曲 1. 路径选择:记录当前路径 2. 递归探索:进入下…

从AI大模型到MCP中台:构建下一代智能服务的核心架构

从AI大模型到MCP中台:构建下一代智能服务的核心架构 引言:AI大模型带来的服务重构革命 在ChatGPT掀起全球AI热潮的今天,大模型展现出的惊人能力正在重塑整个软件服务架构。但鲜为人知的是,真正决定AI服务成败的不仅是模型本身&a…

美团小程序 mtgsig1.2 拼好饭案例 分析 mtgsig

声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 逆向分析 美团网页、小程序、app全是指…

【大模型基础_毛玉仁】5.5 模型编辑应用

目录 5.5 模型编辑应用5.5.1 精准模型更新5.5.2 保护被遗忘权5.5.3 提升模型安全 5.5 模型编辑应用 大语言模型面临更新成本高、隐私保护难、安全风险大等问题。模型编辑技术: 通过细粒度修改预训练模型,避免从头训练,降低更新成本&#xff…

揭秘:父子组件之间的传递

基础知识 组件与组件之间有三大方面的知识点: 子组件通过props defineProps({})接收父组件传递到参数和方法;子组件可以通过定义 emit 事件,向父组件发送事件;父组件调用子组件通过defineExpose 导出的方法…

微前端实现方案对比Qiankun VS npm组件

架构层面: 1、Qiankun是典型的微前端架构,侧重构建多个独立前端应用协同工作的架构,主应用负责自用用的加载、卸载和通信;子应用不限制,可以是VUE、React等; 2、Qiankun松耦合,各个自应用独立…

可编辑160页PPT | 营销流程和管理数字化转型规划

荐言分享:随着技术的发展和消费者行为的变化,传统营销方式已难以满足现代企业的需求。企业需要借助数字化手段,对营销流程进行全面梳理和优化,提升营销活动的精准度和效率。同时,通过数字化营销管理,企业可…

Ecovadis认证需要准备哪些材料?

Ecovadis认证,作为全球领先的企业社会责任(CSR)评估平台,其准备材料的过程不仅需要详尽无遗,更要体现出企业在环境、社会、劳工和伦理四大方面的卓越实践与持续改进的决心。 首先,环境管理方面&#xff0c…

程序化广告行业(45/89):RTB竞价后续流程、结算规则及相关要点解读

程序化广告行业(45/89):RTB竞价后续流程、结算规则及相关要点解读 大家好!一直以来,我都希望能和大家一起在程序化广告这个领域不断探索、共同成长,这也是我写这系列博客的初衷。之前我们了解了程序化广告…

权重参数矩阵

目录 1. 权重参数矩阵的定义与作用 2. 权重矩阵的初始化与训练 3. 权重矩阵的解读与分析 (1) 可视化权重分布 (2) 统计指标分析 4. 权重矩阵的常见问题与优化 (1) 过拟合与欠拟合 (2) 梯度问题 (3) 权重对称性问题 5. 实际应用示例 案例1:全连接网络中的…

文法 2025/3/3

文法的定义 一个文法G是一个四元组:G(,,S,P) :一个非空有限的终极符号集合。它的每个元素称为终极符号或终极符,一般用小写字母表示。终极符号是一个语言不可再分的基本符号。 :一个非空有限的非终极符号集合。它的每个元素称为…

字符串复习

344:反转字符串 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1: 输入:s ["…

【数据结构】算法效率的双刃剑:时间复杂度与空间复杂度

前言 在算法的世界里,效率是衡量算法优劣的关键标准。今天,就让我们深入探讨算法效率的两个核心维度:时间复杂度和空间复杂度,帮助你在算法设计的道路上更进一步。 一、算法效率:衡量算法好坏的关键 算法的效率主要…

Java基础-26-多态-认识多态

在Java编程中,多态(Polymorphism) 是面向对象编程的核心概念之一。通过多态,我们可以编写更加灵活、可扩展的代码。本文将详细介绍什么是多态、如何实现多态,并通过具体的例子来帮助你更好地理解这一重要概念。 一、什…

使用自定义的RTTI属性对对象进行流操作

由于历史原因,在借鉴某些特定出名的游戏引擎中,不知道当时的作者的意图和编写方式 特此做这篇文章。(本文出自游戏编程精粹4 中 使用自定义的RTTI属性对对象进行流操作 文章) 载入和 保存 关卡,并不是一件容易办到的事…

周总结aa

上周学习了Java中有关字符串的内容,与其有关的类和方法 学习了static表示静态的相关方法和类的使用。 学习了继承(extends) 多态(有继承关系,有父类引用指向子类对象) 有关包的知识,final关键字的使用,及有…

密码学基础——密码学相关概念

目录 1.1 密码系统(Cryptosystem) 1.2 密码编码学 1.3 密码分析学 1.4 基于算法保密 1.5 基于密钥保密 1.6密码系统的设计要求 1.7 单钥体制 1.8 双钥体制 密钥管理 1.1 密码系统(Cryptosystem) 也称为密码体制&#xff0…

初始JavaEE篇 —— Mybatis-plus 操作数据库

找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程程(ಥ_ಥ)-CSDN博客 所属专栏:JavaEE 目录 前言 Mybatis-plus 快速上手 Mybatis-plus 复杂操作 常用注解 TableName TableField TableId 打印日志 条件构造器 …