【机器学习】密度聚类:从底层手写实现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/

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

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

相关文章

新手做抖店应该怎么做?应该注意些什么?踩坑避雷!

我是电商珠珠 新手做抖店&#xff0c;对于办理营业执照、选类目确定品&#xff0c;或是找达人这些&#xff0c;往往会在这上面吃很多亏。 我做抖店也已经三年了&#xff0c;关于抖店的玩法和规则这块也非常熟悉&#xff0c;这就来给大家讲讲我所踩的那些坑。 第一个&#xf…

自动化边坡监测设备是什么?

随着科技的不断进步&#xff0c;我们的生活和环境也在不断地发生变化。然而&#xff0c;自然灾害仍然是我们无法完全避免的风险。其中&#xff0c;边坡滑坡就是一种常见的自然灾害。为了保护人民的生命财产安全&#xff0c;科学家们研发出了自动化边坡监测设备。 WX-WY1 自动化…

亚信安慧AntDB数据库引领中文信息处理标准化创新

近期&#xff0c;亚信科技旗下的AntDB数据库再获殊荣&#xff0c;成功通过GB 18030-2022《信息技术中文编码字符集》最高实现级别&#xff08;级别3&#xff09;的检测认证&#xff0c;成为首批达到该认证标准的数据库产品之一。这一认证不仅是对AntDB数据库卓越技术实力的肯定…

算法02哈希法

算法01之哈希法 1.哈希法理论基础1.1哈希表&#xff08;1&#xff09;哈希表&#xff08;2&#xff09;哈希函数&#xff08;3&#xff09;哈希碰撞 1.2哈希法基本思想1.3哈希法适用场景与最常用的哈希结构 2.LeetCode242&#xff1a;有效的字母异位词&#xff08;1&#xff09…

《每天一分钟学习C语言·三》

1、 scanf的返回值由后面的参数决定scanf(“%d%d”,& a, &b); 如果a和b都被成功读入&#xff0c;那么scanf的返回值就是2如果只有a被成功读入&#xff0c;返回值为1如果a和b都未被成功读入&#xff0c;返回值为0 如果遇到错误或遇到end of file&#xff0c;返回值为EOF…

另一种理解伦敦金支撑阻力位的方法

支撑阻力位一向被认为是做伦敦金交易不可或缺的分析工具&#xff0c;但很多人对它的原理并不清楚&#xff0c;甚至不太服气&#xff0c;觉得凭什么一根平平无奇的水平位&#xff0c;能带来所谓的“大作用”呢&#xff1f;下面我们不妨从另外一个角度来看一下伦敦金市场中的支撑…

23、Web攻防——Python考点CTF与CMS-SSTI模板注入PYC反编译

文章目录 一、PYC文件二、SSTI 一、PYC文件 pyc文件&#xff1a;python文件编译后生成的字节码文件&#xff08;byte code&#xff09;&#xff0c;pyc文件经过python解释器最终会生成机器码运行。因此pyc文件是可以跨平台部署的&#xff0c;类似java的.class文件&#xff0c;…

金蝶EAS打印凭证,数据量多点的就会出错

金蝶EAS打印凭证&#xff0c;数据量多点的就会出错&#xff0c;约过100页&#xff0c;提示数据源有问题 经咨询工程师需修改java虚拟机内存。 打开eas客户端目录&#xff0c;运行set-url.bat 看到原来java虚拟机只配置了512M内存&#xff0c;把虚拟机内存修改为4096&#xff0…

如何解决苹果应用商城审核拒绝的Guideline 2.1 - Information Needed问题

当你的应用程序在苹果应用商城审核过程中被拒绝时&#xff0c;苹果会向您发送一封邮件&#xff0c;其中提供了关于拒绝原因的详细信息。本文将指导您如何正确处理Guideline 2.1 - Information Needed问题&#xff0c;并提供解决方案&#xff0c;以确保您的应用程序能够通过审核…

ansible的脚本—playbook剧本

一、playbook 1、简介 Playbook 剧本是由一个或多个play组成的列表。 play的主要功能在于将预定义的一组主机&#xff0c;装扮成事先通过ansible中的task定义好的角色。 Task实际是调用ansible的一个module&#xff0c;将多个play组织在一个playbook中&#xff0c;即可以让它…

系列十一(面试)、如何查看JVM的参数?

一、查看JVM的参数 1.1、概述 上篇文章介绍了JVM的参数类型&#xff0c;通过jinfo可以查看JVM的默认参数&#xff0c;本章介绍另外一种查看JVM参数的方式。 1.2、 分类 JVM中提供了三种方式查看JVM的参数信息&#xff0c;这三种方式又分为两类&#xff0c;即&#xff1a;查看默…

安防监控EasyCVR平台如何通过api接口设置实时流的sei数据实现画框等操作?

国标GB28181视频监控系统EasyCVR平台采用了开放式的网络结构&#xff0c;支持高清视频的接入和传输、分发&#xff0c;能提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力&#xff0…

(PC+WAP)装修设计公司网站模板 家装公司网站源码下载

(PCWAP)装修设计公司网站模板 家装公司网站源码下载 PbootCMS内核开发的网站模板&#xff0c;该模板适用于装修设计、家装公司类等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b; PCWAP&#xff0c;同一个后台&#xff0c…

贪吃蛇(一)

ncurses的使用 这是是用于改善用户交互的一个库&#xff0c;做到即时响应。 它的基本使用&#xff0c;涉及到两个函数initscr、endwin&#xff0c;涉及到键盘输入的交互&#xff0c;就需要使用到keypad函数。 基本用法 #include"curses.h" int main() {int key;in…

ubuntu推送本地仓库到coding

本教程提供在ubuntu系统下推送本地仓库到coding的指令&#xff0c;用于查阅 一、主要步骤有&#xff1a; 0.初始化仓库 git init 1.添加远程仓库 git remote add origin https://coding.git #修改自己仓库链接 &#xff08;命名仓库别名为origin&#xff09; 2.提交代码…

Ansible:模块2

1&#xff0c;command模块 一般用于执行linux的命令&#xff0c;不支持管道符和重定向。 2&#xff0c;shell模块 相当于command的升级版&#xff0c;也可以执行linux命令&#xff0c;支持管道符和重定向 3&#xff0c;cron 模块 在远程主机生成定时任务 分 时 日 月 周 m…

多级缓存:亿级流量的缓存方案

文章目录 一.多级缓存的引入二.JVM进程缓存三.Lua语法入门四.多级缓存1.OpenResty2.查询Tomcat3.Redis缓存预热4.查询Redis缓存5.Nginx本地缓存6.缓存同步 一.多级缓存的引入 传统缓存的问题 传统的缓存策略一般是请求到达Tomcat后&#xff0c;先查询Redis&#xff0c;如果未…

存储:windows 10 硬盘盒 新盘 SSD分区

1.准备好绿联2.5英寸 2.准备好 SSD 磁盘 3.接入硬盘和盒子 4.win10 电脑 win x 然后选择磁盘管理 &#xff08;磁盘管理 K&#xff09; 5.它会提示需要初始化的一个新的磁盘&#xff0c;确定初始化 6.添加卷 7.命名盘符 8.检测是否识别到盘符 9.end

【学习笔记】部署yolov8到安卓手机

一、环境配置和源码安装 首先你需要配置好pytorch环境&#xff0c;本文不再详细阐述&#xff0c;若未配置好环境&#xff0c;可以参考我的另一篇博客&#xff1a;https://blog.csdn.net/liujiahao123987/article/details/128743017 yolov8的安装可参考&#xff1a;https://blog…