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

【机器学习】密度聚类:从底层手写实现DBSCAN

【机器学习】Building-DBSCAN-from-Scratch

  • 概念
  • 代码
    • 数据导入
    • 实现DBSCAN
    • 使用样例及其可视化
  • 补充资料

概念

DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类方法)是一种基于密度的空间聚类算法。该算法将具有足够密度的区域划分为簇,并在具有噪声的空间数据库中发现任意形状的簇,它将簇定义为密度相连的点的最大集合。

该算法的核心概念是识别位于高密度区域的样本点,并将它们划分为簇。以图中的点A为例,我们观察到A点周围有较高的点密度。根据DBSCAN算法的特定参数——即邻域半径(Epsilon)和最小点数(MinPts)——我们可以确定一个点是否为核心点、边界点或离群点。

在这里插入图片描述

在此过程中,算法首先随机选择一个样本点(如A点)并围绕其绘制一个圆,其半径等于邻域半径。如果在这个圆内的样本点数量达到或超过MinPts的阈值,则该点被视为核心点,并且圆心会移动到圆内的另一个样本点,继续探索相邻区域。这个过程持续进行,直到没有更多的点可以加入到当前簇中。此时,圆内最后一个样本点被视为边界点,如B或C。而那些未能被纳入任何簇的点,如N,被视为离群点。

通过这种方式,DBSCAN算法有效地将样本空间中距离相近的点聚合在一起,形成不同的簇,同时识别并排除噪声或异常值。这种基于密度的聚类方法特别适合于处理具有复杂结构或不规则形状的数据集。

在这里插入图片描述

代码

数据导入

from sklearn.datasets import load_iris  # 导入数据集iris
import matplotlib.pyplot as plt  # 导入绘图库
import numpy as np  # 导入numpy库
# 加载Iris数据集
iris = load_iris()
X = iris.data  # 获得其特征向量,150*4

实现DBSCAN

在OurDBSCAN类中,我们首先通过初始化函数设置了邻域半径eps和最小样本数min_samples,这两个参数是确定簇的关键。在fit方法中,对输入数据集X的每个点进行遍历和分类处理。

算法开始时,所有点都标记为未分类。接着,对每个点,先检查其状态,如果已经分类则跳过,否则通过_find_neighbors方法找出该点的所有邻居。这一步骤涉及计算点与其他所有点之间的欧氏距离,判断是否在设定的邻域半径内。如果一个点的邻居数少于min_samples,则将其标记为噪声。

当一个点有足够多的邻居被确定为核心点后,算法会创建一个新的簇,并通过迭代地探索该点的邻居来扩展这个簇。在此过程中,每个新发现的点都会被检查是否也是核心点,如果是,它的邻居也会被加入到当前簇中。这种方式使得DBSCAN能够根据密度将数据集中的点聚合成多个簇,同时识别和剔除噪声点,有效应对具有不规则形状或包含噪声和异常值的数据集。

class OurDBSCAN:def __init__(self, eps, min_samples):"""初始化DBSCAN对象。参数:eps (float): 邻域的半径。min_samples (int): 核心点的邻域中的最小样本数。"""self.eps = eps  # 邻域的半径self.min_samples = min_samples  # 核心点的最小样本数self.labels_ = None  # 簇标签def fit(self, X):"""将DBSCAN模型拟合到输入数据。参数:X (array-like): 输入数据。返回:None"""# 将所有点标记为-1(未分类)labels = -1 * np.ones(X.shape[0])  # -1表示未分类# 簇IDcluster_id = 0for i in range(X.shape[0]):  # 遍历所有点# 如果该点已被访问过,则跳过if labels[i] != -1:continue# 找到当前点的所有邻居neighbors = self._find_neighbors(i, X)# 如果邻居数小于min_samples,则标记为噪声并继续if len(neighbors) < self.min_samples:labels[i] = -2  # -2表示噪声continue# 否则,开始一个新的簇labels[i] = cluster_id# 找到当前簇的所有邻居seeds = set(neighbors)  # 邻居集合seeds.remove(i)  # 移除当前点while seeds:  # 只要种子集合不为空# 取出一个邻居current_point = seeds.pop()# 如果是噪声,则将其标记为当前簇if labels[current_point] == -2:labels[current_point] = cluster_id# 如果已经处理过,则跳过if labels[current_point] != -1:continue# 否则,将其标记为当前簇labels[current_point] = cluster_id# 找到当前点的所有邻居current_neighbors = self._find_neighbors(current_point, X)# 如果当前点是核心点,则将其邻居添加到种子集合中if len(current_neighbors) >= self.min_samples:seeds.update(current_neighbors)# 移动到下一个簇cluster_id += 1self.labels_ = labels  # 保存簇标签def _find_neighbors(self, point_idx, X):"""找到给定点的邻居。参数:point_idx (int): 点的索引。X (array-like): 输入数据。返回:neighbors (list): 邻居的索引。"""neighbors = []for i, point in enumerate(X):  # 遍历所有点if np.linalg.norm(X[point_idx] - point) <= self.eps:  # 计算距离neighbors.append(i)return neighbors

使用样例及其可视化

# 使用手动实现的 DBSCAN,不使用 NearestNeighbors
manual_dbscan_nn = OurDBSCAN(eps=0.5, min_samples=5)
manual_dbscan_nn.fit(X)
# 创建一个图形和子图
fig, axs = plt.subplots(2, 3, figsize=(15, 10))# 组合特征以创建散点图
feature_combinations = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
feature_names = iris.feature_namesfor i, (fi, fj) in enumerate(feature_combinations):ax = axs[i//3, i % 3]ax.scatter(X[:, fi], X[:, fj], c=manual_dbscan_nn.labels_, cmap='viridis',marker='o', edgecolor='k', s=50)ax.set_xlabel(feature_names[fi])ax.set_ylabel(feature_names[fj])ax.set_title(f'DBSCAN Clustering with {feature_names[fi]} vs {feature_names[fj]}')plt.tight_layout()
plt.show()

在这里插入图片描述
在IRIS数据集中,每个样本都有四个特征:花萼长度(sepal length)、花萼宽度(sepal width)、花瓣长度(petal length)和花瓣宽度(petal width),所有的这些特征都以厘米为单位进行测量。在第一行的图表中,我们可以看到花萼长度与花萼宽度、花瓣长度和花瓣宽度的聚类关系。在第二行,展示的是花萼宽度与花瓣长度、花瓣宽度的聚类效果,以及花瓣长度与花瓣宽度的聚类情况。

通过DBSCAN算法的密度聚类特性,我们可以看到在密度较高的区域形成了聚类簇,而在密度较低的区域,点则被标记为噪声点或者位于不同簇的边界。

补充资料

一个有趣的DBSCAN可视化网站:
https://www.naftaliharris.com/blog/visualizing-dbscan-clustering/

相关文章:

【机器学习】密度聚类:从底层手写实现DBSCAN

【机器学习】Building-DBSCAN-from-Scratch 概念代码数据导入实现DBSCAN使用样例及其可视化 补充资料 概念 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff0c;具有噪声的基于密度的聚类方法&#xff09;是一种基于密度的空间聚类算…...

2023-12-20 二叉搜索树的最近公共祖先和二叉搜索树中的插入操作和删除二叉搜索树中的节点

235. 二叉搜索树的最近公共祖先 思想&#xff1a;和二叉树的公共最近祖先节点的思路基本一致的&#xff01;就是不用从下往上遍历处理&#xff01;可以利用的二叉搜索树的特点从上往下处理了&#xff01;而且最近公共节点肯定是第一个出现在【q&#xff0c;p】这个区间的内的&…...

pytorch文本分类(三)模型框架(DNNtextCNN)

pytorch文本分类&#xff08;三&#xff09;模型框架&#xff08;DNN&textCNN&#xff09; 原任务链接 目录 pytorch文本分类&#xff08;三&#xff09;模型框架&#xff08;DNN&textCNN&#xff09;1. 背景知识深度学习 2. DNN2.1 从感知器到神经网络2.2 DNN的基本…...

<长篇文章!!>数据结构与算法的重要知识点与概要总结 ( •̀ ω •́ )✧✧临近考试和查漏补缺的小伙伴看这一篇就都懂啦~

目录 一、数据结构概论二、算法概论三、线性表四、栈五、队列六、串七、多维数组与矩阵八、广义表九、树与二叉树十、图 一、数据结构概论 1、数据元素和数据项 数据由数据元素组成&#xff0c;即数据元素是数据的基本单位&#xff0c;而数据元素又由若干个数据项组成&#xf…...

【安全】audispd调研

audispd调研 1 问题背景 在Linux中&#xff0c;当某个进程调用audit_set_pid将自己的pid保存到内核的audit模块后&#xff0c;如果有日志生成&#xff0c;kaudit内核线程就会通过netlink通信机制将审计日志发送给audit_pid&#xff0c;因此&#xff0c;只能有一个进程占用aud…...

WINDOWS(WIN11)通过IP添加网络打印机

点击添加设备 点击手动添加 使用IP地址或主机名添加打印机 选择TCP/IP设备&#xff0c;输入打印机地址 如果有正确驱动就安装&#xff0c;没有就取消。 通过手动设置添加本地打印机或网络打印机 使用现有的端口 根据打印机IP&#xff0c;选择标准端口。 成功&#xff01; 到…...

华为数通试题

选择题 华为数通推出的面向企业的云计算平台是&#xff1f; A) FusionSphere B) CloudEngine C) Agile Controller D) eSight 下面哪个不是华为数通的核心交换机系列&#xff1f; A) S12700 B) S5700 C) S9300 D) CloudEngine 华为数通的企业级路由器系列包括哪个&#xff1f…...

Labview Vision 机器视觉使用,从下载程序安装应用,到实战找硬币并输出值

1.前言 大家好,今天我要和机器人一起配合来打算 做机器视觉 用Labview 和 Vision 联动实现机器的视觉 2.下载软件-软件的安装 我们除了基础款的labview软件 还要安装视觉四件套 1.Labview 编程平台&#xff08;我是 2023 q3&#xff09; 2. NI - IMAQdx &#xff08;驱动软…...

【delphi11】delphi基础探索【三、基础组件和事件】

目录 基础组件 1. TButton&#xff08;按钮&#xff09; 2. TLabel&#xff08;标签&#xff09; 3. TEdit&#xff08;编辑框&#xff09; 4. TMemo&#xff08;多行编辑框&#xff09; 5. TComboBox&#xff08;组合框&#xff09; 6. TCheckBox&#xff08;复选框&…...

react hooks浅谈

一.useEffect useEffect是hooks中的生命周期函数 1.只要页面更新就触发回调&#xff1a; useEffect(() > { // 执行逻辑 }) 2.只运行一次&#xff08;组件挂载和卸载时执行&#xff09;&#xff0c;第二个参数传空数组[]&#xff1a; useEffect(() > { // },[]) 3. 条件…...

stable diffusion webui之lora调用

1.触发词底模lora效果最好&#xff08;分数不一定要取到1&#xff0c;0.8也行&#xff09;&#xff1b; 2.引用时一定要使用<lora:>&#xff0c;例如<lora:C4D_geometry_bg_v2.5:0.8>&#xff1b; "prompt": "(masterpiece:1.3), (best quality:1.…...

FormData文件上传多文件上传

一、简介 ​ 通常情况下&#xff0c;前端在使用post请求提交数据的时候&#xff0c;请求都是采用application/json 或 application/x-www-form-urlencoded编码类型&#xff0c;分别是借助JSON字符串来传递参数或者keyvalue格式字符串&#xff08;多参数通过&进行连接&#…...

八股文打卡day4——计算机网络(4)

TCP和UDP的概念、特点、区别和对应的使用场景&#xff1f; 我的回答&#xff1a; 概念&#xff1a; TCP是传输控制协议&#xff0c;是面向连接、可靠的、基于字节流的传输层通信协议。 UDP是用户数据报协议&#xff0c;是无连接、不可靠的&#xff0c;基于数据报的传输层通信…...

TensorFlow(2):Windows安装TensorFlow

1 安装python环境 这一步请自行安装&#xff0c;这边不做介绍。 2 安装anaconda 下载路径&#xff1a;Index of /&#xff0c;用户自行选择自己的需要的版本。 3 环境配置 3.1 anaconda环境配置 找到设置&#xff0c;点击系统->系统信息->高级系统设置->环境变量…...

一文解决idea导入源码控制台爆红问题

文章目录 唠嗑部分背景说明idea查看maven配置 言归正传安装mavenidea配置maven 结语及资料获取 唠嗑部分 背景说明 很多新手伙伴们在导入项目源码时&#xff0c;都会遇到大片依赖爆红&#xff0c;项目跑不起来&#xff0c;小白也是把自己电脑重新配置了一番&#xff0c;复现了…...

排序算法——快排

快速排序算法最早是由图灵奖获得者Tony Hoare设计出来的,他在形式化方法理论以 及ALGOL.60编程语言的发明中都有卓越的贡献,是20世纪最伟大的计算机科学家之—。 而这快速排序算法只是他众多贡献中的—个小发明而已。 快速排序&#xff08;Quick Sort&#xff09;的基本算法思…...

第二节TypeScript 基础语法

1、typescript程序由以下几个部分组成&#xff1a; 模块函数变量语句和表达式注释 2、开始第一个typescript程序 创建一个typescript程序&#xff0c;使之输出“hello typescript”&#xff1a; 代码&#xff1a; var message:string "hello typescript" cons…...

Go、Python、Java、JavaScript等语言的求余(取模)计算

余数符号规则&#xff1a; Go&#xff08;%&#xff09;&#xff1a; 余数与被除数符号一致 Java&#xff08;%&#xff09;&#xff1a; 余数与被除数符号一致 JavaScript&#xff08;%&#xff09;&#xff1a; 余数与被除数符号一致 Python&#xff08;%&#xff09;…...

scrapy快加构造并发送请求

scrapy数据建模与请求 学习目标&#xff1a; 应用 在scrapy项目中进行建模应用 构造Request对象&#xff0c;并发送请求应用 利用meta参数在不同的解析函数中传递数据 1. 数据建模 通常在做项目的过程中&#xff0c;在items.py中进行数据建模 1.1 为什么建模 定义item即提前…...

【C++】谈谈深拷贝与浅拷贝

目录 一、浅拷贝 1.定义 2.示例 3.问题 二、深拷贝 1.定义 2.示例 3.优点 三、考虑场景 浅拷贝的考虑 1.性能要求 2.简单地数据结构 3.资源管理 深拷贝的考虑 1.动态内存分配 2.复杂数据结构 3.资源管理 总结 一、浅拷贝 1.定义 浅拷贝是指对对象进行复制时…...

手把手调参:在TMS320F28034上实现永磁电机的高功率因数控制(附代码思路)

手把手调参&#xff1a;在TMS320F28034上实现永磁电机的高功率因数控制&#xff08;附代码思路&#xff09; 当你在调试一台采用薄膜电容的永磁电机驱动器时&#xff0c;是否遇到过这样的困境&#xff1a;明明按照教科书设计了PWM波形&#xff0c;但实测功率因数始终卡在0.92上…...

手把手教你用MP2144搭建超低功耗单键开关机电路(含单片机代码)

超低功耗单键开关机电路设计与实现指南 在电池供电的嵌入式设备中&#xff0c;电源管理往往是决定产品续航能力的关键因素。想象一下&#xff0c;当你精心设计的智能手表因为待机功耗过高而需要频繁充电&#xff0c;或者户外传感器因为电源管理不当而提前耗尽电量——这些场景凸…...

OpCore-Simplify:让黑苹果配置从复杂到简单的智能化革命

OpCore-Simplify&#xff1a;让黑苹果配置从复杂到简单的智能化革命 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 你是否曾为黑苹果&#xff08;Hac…...

别再只用交叉熵了!深入对比YOLOv8中Focal Loss与CIoU Loss的改进效果与适用场景

深入解析YOLOv8损失函数优化&#xff1a;Focal Loss与CIoU Loss的实战对比与场景适配 当你在深夜调试YOLOv8模型时&#xff0c;是否遇到过这样的困境&#xff1a;明明增加了训练数据&#xff0c;小目标检测的准确率却始终上不去&#xff1f;或是发现模型对密集排列的物体总是漏…...

WuliArt Qwen-Image Turbo新手必看:Web界面操作,一键保存高清图片

WuliArt Qwen-Image Turbo新手必看&#xff1a;Web界面操作&#xff0c;一键保存高清图片 1. 快速认识这个AI绘图神器 如果你正在寻找一个能在自己电脑上快速生成高质量图片的AI工具&#xff0c;WuliArt Qwen-Image Turbo绝对值得一试。这个工具最大的特点就是"快"…...

MacBook Pro本地部署OpenClaw:百川2-13B量化模型7×24小时运行方案

MacBook Pro本地部署OpenClaw&#xff1a;百川2-13B量化模型724小时运行方案 1. 为什么选择MacBook Pro部署OpenClaw&#xff1f; 去年冬天&#xff0c;当我第一次尝试在MacBook Pro上部署量化版百川2-13B模型时&#xff0c;身边的朋友都觉得我疯了。"M1芯片能跑得动13B…...

颈腰椎病引发 “耳后疼痛”:耳根刺痛,可能是颈椎在 “捣乱”

很多人出现耳后持续性刺痛或按压痛&#xff0c;会误以为是中耳炎、腮腺炎&#xff0c;实则部分耳后疼痛与颈椎病变相关。颈椎病变压迫枕大神经&#xff08;从颈椎延伸至耳后&#xff09;&#xff0c;会导致神经分布区域疼痛&#xff1b;同时颈椎肌肉痉挛、僵硬&#xff0c;牵拉…...

FastAPI 2.0流式响应源码深度拆解,从Starlette 1.12到Pydantic v2.6兼容层的5处隐式await丢失点(生产环境已验证)

第一章&#xff1a;FastAPI 2.0流式响应架构演进与问题定位全景FastAPI 2.0 对流式响应&#xff08;StreamingResponse&#xff09;进行了底层重构&#xff0c;核心变化在于将 ASGI 生命周期与异步生成器的生命周期解耦&#xff0c;并引入更严格的流控契约。此前版本中常见的内…...

滞回比较器设计实战:从理论到参数优化

1. 滞回比较器基础&#xff1a;从门铃到航天器的抗噪神器 第一次接触滞回比较器是在大学电子设计课上&#xff0c;当时教授用一个生动的例子开场&#xff1a;"想象你家的门铃——如果它对任何风吹草动都响个不停&#xff0c;你会疯掉&#xff1b;但如果连用力敲门都没反应…...

OpenClaw技能开发入门:为nanobot镜像编写第一个插件

OpenClaw技能开发入门&#xff1a;为nanobot镜像编写第一个插件 1. 为什么需要自定义技能 当我第一次接触OpenClaw时&#xff0c;最让我惊喜的是它能够像人类一样操作电脑完成各种任务。但很快我发现&#xff0c;内置的基础技能并不能完全满足我的个性化需求。比如我需要定期…...