当前位置: 首页 > news >正文

【机器学习】K近邻

2. K近邻

K近邻算法(KNN)的基本思想是通过计算待分类样本与训练集中所有样本之间的距离,选取距离最近的 K 个样本,根据这些样本的标签进行分类或回归。KNN 属于非参数学习算法,因为它不假设数据的分布形式,主要依赖距离度量来进行决策。

优点

  • 简单易懂:KNN算法非常直观,容易理解和实现。
  • 无假设:KNN算法对数据没有假设,适用于复杂分布的数据集。
  • 适用于多类分类问题:KNN能够处理多类分类问题,只需在投票过程中考虑不同的类别即可。

缺点

  • 计算复杂度高:对于大规模数据集,KNN算法的计算复杂度较高,需要计算每个测试样本与所有训练样本之间的距离,耗时较长。
  • 对数据的尺度和噪声敏感:KNN对数据的尺度敏感,通常需要对数据进行标准化或归一化处理。此外,KNN对噪声敏感,可能会受到

异常值的影响。

  • 需要大存储空间:由于需要存储整个训练集,KNN算法占用较大的内存空间。

2.1 基本模型

对于分类问题,KNN 模型可以表示为:

f ( x ) = argmax c ∑ i = 1 K 1 ( y i = c ) f(\mathbf{x}) = \underset{c}{\text{argmax}} \sum_{i=1}^K \mathbf{1}(y_i = c) f(x)=cargmaxi=1K1(yi=c)

其中:

  • x \mathbf{x} x 是待分类的输入样本。
  • y i y_i yi 是 K 个邻近样本的标签。
  • 1 ( ⋅ ) \mathbf{1}(\cdot) 1() 是指示函数,当条件为真时取值为 1,否则为 0。
  • c c c 是所有可能的类别。

对于回归问题,KNN 模型的预测可以通过 K 个邻近样本的标签值的平均来实现:

y ^ = 1 K ∑ i = 1 K y i \hat{y} = \frac{1}{K} \sum_{i=1}^K y_i y^=K1i=1Kyi

或使用加权平均:

y ^ = ∑ i = 1 K w i ⋅ y i ∑ i = 1 K w i \hat{y} = \frac{\sum_{i=1}^K w_i \cdot y_i}{\sum_{i=1}^K w_i} y^=i=1Kwii=1Kwiyi

其中 w i w_i wi 是样本 y i y_i yi 的权重,通常可以根据距离的倒数或其他方式定义。

2.2 距离度量

KNN 算法中,距离度量是核心部分,决定了如何选择邻近样本。常用的距离度量方法包括:

欧氏距离(Euclidean Distance):

欧氏距离是最常见的距离度量方法,适用于特征尺度相同的场景。对于两个样本 x i \mathbf{x}_i xi x j \mathbf{x}_j xj,欧氏距离定义为:

d ( x i , x j ) = ∑ k = 1 n ( x i k − x j k ) 2 d(\mathbf{x}_i, \mathbf{x}_j) = \sqrt{\sum_{k=1}^n (x_{ik} - x_{jk})^2} d(xi,xj)=k=1n(xikxjk)2

其中:

  • n n n是特征的维度数。
  • x i k x_{ik} xik x j k x_{jk} xjk分别是样本 x i \mathbf{x}_i xi x j \mathbf{x}_j xj 在第 k 个维度上的特征值。

曼哈顿距离(Manhattan Distance):

曼哈顿距离适用于高维空间且特征不相关的情况。曼哈顿距离定义为:

d ( x i , x j ) = ∑ k = 1 n ∣ x i k − x j k ∣ d(\mathbf{x}_i, \mathbf{x}_j) = \sum_{k=1}^n |x_{ik} - x_{jk}| d(xi,xj)=k=1nxikxjk

曼哈顿距离计算的是两个样本在各个维度上的绝对差值之和。

闵可夫斯基距离(Minkowski Distance):

闵可夫斯基距离是欧氏距离和曼哈顿距离的泛化形式,定义为:

d ( x i , x j ) = ( ∑ k = 1 n ∣ x i k − x j k ∣ p ) 1 / p d(\mathbf{x}_i, \mathbf{x}_j) = \left(\sum_{k=1}^n |x_{ik} - x_{jk}|^p\right)^{1/p} d(xi,xj)=(k=1nxikxjkp)1/p

其中:

  • p p p 是参数,决定距离度量的形式。
  • p = 2 p=2 p=2 时,闵可夫斯基距离即为欧氏距离;当 p = 1 p=1 p=1 时,即为曼哈顿距离。

2.3 决策规则

KNN 的决策规则基于多数投票或加权投票的原则:

分类问题:

  • 对于分类任务,KNN 会根据 K 个邻近样本中出现频率最高的类别来决定待分类样本的类别。若出现频率相同,则可以随机选择,或考虑引入距离的权重来打破平局。

回归问题:

  • 对于回归任务,KNN 会取 K 个邻近样本标签的平均值或加权平均值作为预测结果。加权时,权重 w i w_i wi 通常与样本 x i \mathbf{x}_i xi 和待分类样本 x \mathbf{x} x 之间的距离的倒数成正比:

w i = 1 d ( x i , x ) w_i = \frac{1}{d(\mathbf{x}_i, \mathbf{x})} wi=d(xi,x)1

2.4 K值选择

K 值是 KNN 算法中的重要参数,决定了选择多少个邻近样本参与投票。K 值的选择通常通过交叉验证来确定。一般来说:

  • 较小的 K 值:模型对训练数据的拟合度较高,但可能会受到噪声影响,导致过拟合。
  • 较大的 K 值:模型变得平滑,减少了过拟合的风险,但也可能导致欠拟合。

2.5 KD树(K-Dimensional Tree)

为了加速 KNN 的搜索过程,可以使用 KD 树进行优化。KD 树是一种对 k 维空间数据进行分割的树形数据结构,通过这种数据结构可以有效地减少搜索空间,从而提高查找效率。

KD树的构建过程:

  1. 选择分割维度:选择一个维度将数据按照该维度的中位数分割成两部分。选择的维度通常是通过计算当前节点数据在各维度的方差,选择方差最大的维度进行划分。
  2. 分割数据:在选定的分割维度上,以中位数为分割点,将数据集划分为两部分,分别作为左右子节点的数据。
  3. 递归构建:对每个子节点递归进行上述步骤,直到每个子节点的样本数达到预定阈值或所有样本在某一维度上的值都相同。
  4. 节点表示:每个节点存储一个样本点及其对应的分割维度。

KD树的搜索过程:

  1. 递归搜索叶节点:从根节点开始,比较目标点与当前节点在分割维度上的值,决定进入左子树还是右子树,直到到达叶节点。
  2. 回溯搜索:到达叶节点后,计算当前叶节点样本与目标点之间的距离,并更新当前最近邻居。如果当前节点的父节点到目标点的距离小于当前最近邻居的距离,则有可能在兄弟子树中找到更近的邻居,需要回溯检查。
  3. 剪枝操作:如果兄弟子树的区域与目标点之间的最小距离大于当前已知最近邻居的距离,则可以剪枝,即不需要搜索该子树。
  4. 返回最近邻居:最终返回 K 个最近邻居。

优缺点:

  • 优点:KD 树在低维空间中能显著减少 KNN 搜索的计算量,提高查询效率。对于静态数据集,KD 树是一种非常有效的加速工具。
  • 缺点:在高维空间中,KD 树的性能会下降,尤其是当维度数接近样本数时,KD 树的效率可能退化为线性搜索。此外,KD 树不适用于动态数据集,因为在插入或删除样本后需要重建树结构。

KNN 的时间复杂度较高,特别是在大规模数据集上,因为需要计算待分类样本与训练集中所有样本之间的距离。对于 N 个训练样本,每次分类的时间复杂度为 O ( N × D ) O(N \times D) O(N×D),其中 D 为特征维度。这使得 KNN 在大规模数据集或高维空间中不太适用。

2.6 代码实现

以下是KNN算法的简单实现:

import numpy as np
from collections import Counterdef knn_predict(X_train, y_train, X_test, k=3):predictions = []for x_test in X_test:# 计算测试样本与所有训练样本之间的距离distances = np.linalg.norm(X_train - x_test, axis=1)# 获取距离最近的 k 个样本的索引k_indices = np.argsort(distances)[:k]# 获取这些样本的标签k_nearest_labels = y_train[k_indices]# 投票选择出现频率最高的标签most_common = Counter(k_nearest_labels).most_common(1)predictions.append(most_common[0][0])return predictions

如果需要在大规模数据集上提高效率,可以使用 KD树 优化的版本。以下是构建 KD 树的伪代码:

class KDNode:def __init__(self, point, left=None, right=None):self.point = pointself.left = leftself.right = rightdef build_kdtree(points, depth=0):if not points:return Nonek = len(points[0])  # 维度axis = depth % k  # 选择分割维度points.sort(key=lambda x: x[axis])median = len(points) // 2  # 选择中位数# 递归构建 KD 树return KDNode(point=points[median],left=build_kdtree(points[:median], depth + 1),right=build_kdtree(points[median + 1:], depth + 1))

KNN算法是一种简单直观且有效的分类和回归方法,但其计算复杂度较高,特别是在高维空间和大规模数据集上。通过引入 KD树,可以在低维空间中显著提高KNN的效率。然而,在高维空间中,KD树的效果会减弱。因此,在实际应用中,需要根据数据集的具体特征选择合适的优化技术。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(五):Blender锥桶建模
  • C++语法知识点合集:11.模板
  • 锡林郭勒奶酪品牌呼和浩特市大召店盛大开业
  • Kafka【八】如何保证消息发送的可靠性、重复性、有序性
  • 什么是 TDengine?
  • 【机器学习】高斯网络的基本概念和应用领域
  • Python | Leetcode Python题解之第394题字符串解码
  • [数据集][目标检测]抽烟检测数据集VOC+YOLO格式22559张2类别
  • 外卖霸王餐对接接口为用户提供了哪些好处?
  • OpenVPN的测试主要包括安装客户端、配置连接、连接测试以及网络验证等步骤。以下是一个详细的测试流程:
  • 合宙LuatOS开发板Core_Air780EP使用说明
  • Android12上新增jar遇到的问题总结
  • 代码随想录Day39|322. 零钱兑换、279.完全平方数、139.单词拆分
  • Flask中的上下文(Context)
  • Mysql 主从复制、读写分离
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • .pyc 想到的一些问题
  • @angular/forms 源码解析之双向绑定
  • 2017-09-12 前端日报
  • canvas 高仿 Apple Watch 表盘
  • co模块的前端实现
  • GraphQL学习过程应该是这样的
  • HTML中设置input等文本框为不可操作
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 技术:超级实用的电脑小技巧
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 《天龙八部3D》Unity技术方案揭秘
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • 整理一些计算机基础知识!
  • ​ssh免密码登录设置及问题总结
  • # Redis 入门到精通(八)-- 服务器配置-redis.conf配置与高级数据类型
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #1015 : KMP算法
  • #if #elif #endif
  • #QT(QCharts绘制曲线)
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (Java)【深基9.例1】选举学生会
  • (Java数据结构)ArrayList
  • (pojstep1.3.1)1017(构造法模拟)
  • (pytorch进阶之路)扩散概率模型
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转载)OpenStack Hacker养成指南
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET 快速重构概要1
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .NET开发人员必知的八个网站