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

KNN算法及KDTree树

KNN

K-近邻(K-Nearest Neighbors, KNN)算法是一种基于实例的学习方法,它属于监督学习的范畴。KNN的核心思想是:如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。KNN算法既可以用于分类问题也可以用于回归问题。

基本原理

  1. **选择距离度量**:计算新样本与训练集中所有已知类别的样本之间的距离。
  2.  **确定邻居**:根据距离从小到大排序,选取最近的k个邻居。
  3.  **投票决策**:
    1. 对于分类任务,通常采用多数表决法,即选择这k个邻居中出现次数最多的类别作为预测结果。
    2. 对于回归任务,通常取这k个邻居的目标值的平均数或加权平均数作为预测结果。

公式推导

假设我们有两个n维向量\(X = (x_1, x_2, ..., x_n)\) 和 \(Y = (y_1, y_2, ..., y_n)\),它们之间的距离可以通过不同的度量方法来计算:

- **欧几里得距离** (Euclidean Distance):
  \[ d(X, Y) = \sqrt{\sum_{i=1}^{n}(x_i - y_i)^2} \]

- **曼哈顿距离** (Manhattan Distance):
  \[ d(X, Y) = \sum_{i=1}^{n}|x_i - y_i| \]

- **闵可夫斯基距离** (Minkowski Distance):
  \[ d(X, Y) = \left( \sum_{i=1}^{n} |x_i - y_i|^p \right)^{1/p} \]
  当\(p=1\)时,为曼哈顿距离;当\(p=2\)时,为欧几里得距离;当\(p \to \infty\)时,为切比雪夫距离。

- **切比雪夫距离** (Chebyshev Distance):
  \[ d(X, Y) = \max(|x_i - y_i|) \]

算法分析

- **优点**:
  - 简单易懂,易于实现。
  - 对异常值不敏感。
  - 不需要显式的训练阶段,因为训练阶段只是存储训练数据。
  - 可以处理多分类问题。

- **缺点**:
  - 计算成本高,特别是对于大规模的数据集。
  - 对参数k的选择非常敏感,不同k值可能导致不同的结果。
  - 必须进行特征缩放,否则某些特征可能会对距离产生不成比例的影响。
  - 没有明确的概率输出,无法直接提供概率估计。

KNN算法优化之KDTree

KD树通过递归地分割空间来组织数据点,这使得它可以有效地支持上述提到的各种操作。它能够快速确定哪些点与查询相关,哪些不相关,从而加速搜索过程。

K-Dimensional Tree,简称KD树,是一种用于组织多维空间中点的数据结构。它特别适合用来解决高维空间中的最近邻搜索和范围查询问题。KD树本质上是一种二叉树,其构建过程涉及到选择合适的维度进行分割,并将数据递归地分成两个子集。

关于机器学习更系统更形象的讲解请看本人的课程https://edu.csdn.net/course/detail/39309

KD树的构建


构建KD树的过程主要包括以下几个步骤:

  1. 确定分裂维度:通常从根节点开始,依次选择不同的维度来分割数据。一种常见的做法是按照维度循环选择(例如,在二维空间中,第一次按x轴分,第二次按y轴分,然后重复),或者根据当前数据在各个维度上的方差来选择,即选择方差最大的那个维度以获得更好的分割效果。
  2. 找到分裂点:选定分裂维度后,需要在这个维度上找到一个值作为分裂点,以便将数据分为左右两部分。常用的方法是选取该维度上的中位数,这样可以保证左右子树大小相对均衡。
  3. 递归分割:使用分裂点将数据分为两部分,左边的数据进入左子树,右边的数据进入右子树。然后对每个子集重复上述步骤,直到满足某个终止条件(如子集中数据点的数量小于预设阈值)。


KD树的操作
最近邻搜索

  • 从根节点开始,沿着树向下查找,选择离目标点更近的那一侧分支继续。
  • 当到达叶子节点时,记录当前距离最短的点。
  • 回溯到父节点,检查是否需要探索另一侧的子树(如果另一侧可能包含更近的邻居,则需要访问)。
  • 通过这种方式,逐步向上回溯并更新最近邻点,直至回到根节点。

范围查询

  • 类似于最近邻搜索,但是这次我们关注的是目标区域内所有点。
  • 同样从根节点开始,选择与查询区域相交的一侧或两侧分支进行深入。
  • 在叶子节点处收集符合条件的点。
  • 如果另一侧也可能包含满足条件的点,则同样需要进行探索。

KD树的优势与局限性
优势:

  • 对于静态数据集,KD树能够提供非常高效的最近邻和范围查询性能。
  • 结构简单,易于理解和实现。

局限性:

  • 当数据分布不均匀时,可能导致树的高度不平衡,从而影响查询效率。
  • 更新操作复杂度较高,对于动态变化的数据集,维护KD树的成本较大。
  • 随着维度增加,所谓的“维度灾难”会导致KD树性能下降,因为高维空间中点之间的距离变得难以区分。

Python示例 (使用scikit-learn库)


下面是一个使用scikit-learn库中的KDTree类来创建和使用KD树的例子:

from sklearn.neighbors import KDTree
import numpy as np# 创建一些随机二维点
data = np.random.rand(10, 2)  # 生成10个随机点,每个点有2个坐标# 构建KD树
kdtree = KDTree(data, leaf_size=2)# 查询最邻近的点
query_point = [0.5, 0.5]
distances, indices = kdtree.query([query_point], k=1)
print(f"Nearest point to {query_point} is at index {indices[0][0]}, distance: {distances[0][0]}")# 范围查询
radius = 0.2
indices_within_radius = kdtree.query_radius([query_point], r=radius)
print(f"Indices of points within radius {radius} of {query_point}: {indices_within_radius[0]}")


这段代码展示了如何用Python创建一个基于随机数据点的KD树,并执行最近邻搜索和范围查询。leaf_size参数控制了叶节点中存储的数据点数量,它会影响树的深度以及查询的速度。


http://www.mrgr.cn/news/51335.html

相关文章:

  • 数据分析分段折线图
  • 【C++常见错误】0xC0000005: 读取位置 0x00000000 时发生访问冲突
  • .Net的潘多拉魔盒开箱即用,你学废了吗?
  • 【面经】2024年软件测试面试题,精选100 道(附答案)
  • OpenGauss学习笔记
  • 【开源】Appium:自动化移动应用测试的强大工具
  • 10月报名 | 海克斯康Adams二次开发培训
  • 前端全栈混合之路Deno篇:Deno 2.0 的权限系统详解和多种权限配置权限声明方式 -一次性搞懂和学会用
  • vulhub复现记录
  • 面试记录一
  • 概率测试:用随机性来发现难以复现的问题
  • STM32 QSPI接口驱动GD/W25Qxx配置简要
  • 瞬时存取,无限可能:顺序表的独特魅力
  • 代码随想录训练营Day35 | 452. 用最少数量的箭引爆气球 | 435. 无重叠区间 | 763.划分字母区间
  • 富格林:竭力击退欺诈守卫出金
  • Integer中的getInteger()方法和parseInt()方法有什么区别?
  • 【数据分享】全国文化-限额以上文化批发和零售业企业情况(2017-2021年)
  • 域名邮箱免费注册指南:烽火域名邮箱优势?
  • Windows系统上根据端口号查找对应进程
  • 5大主流方案对比:MySQL千亿级数据线上平滑扩容实战