dbscan算法python实现_挑子学习笔记:DBSCAN算法的python实现

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)聚类算法,是一种基于高密度连通区域的、基于密度的聚类算法,能够将具有足够高密度的区域划分为簇(Cluster),并在具有噪声的数据中发现任意形状的簇。DBSCAN算法通过距离定义出一个密度函数,计算出每个样本附近的密度,从而根据每个样本附近的密度值来找出那些样本相对比较集中的区域,这些区域就是我们要找的簇。

1. DBSCAN算法的基本原理

其它聚类方法大都是基于对象之间的距离进行聚类,聚类结果是球状的簇。DBSCAN 算法利用簇的高密度连通性,寻找被低密度区域分离的高密度区域,可以发现任意形状的簇,其基本思想是:对于一个簇中的每个对象,在其给定半径的领域中包含的对象不能少于某一给定的最小数目。

DBSCAN算法中有两个重要参数:$\varepsilon$表示定义密度时的邻域半径,$M$ 表示定义核心点时的阈值。

考虑数据集合$X= \{x^{(1)}, x^{(2)},...,x^{(n)} \}$,引入以下概念与记号。

1. $\varepsilon$邻域

设$x \in X$,称

\begin{equation*}

N_{\varepsilon}(x) = \{ y \in X: d(y,x) \le \varepsilon \}

\end{equation*}

为$X$的$\varepsilon$邻域。显然,$x \in N_{\varepsilon}(x)$。

为了简单起见,节点$x^{(i)}$与其下标$i$一一对应,引入记号

\begin{equation*}

N_{\varepsilon}(i) = \{ j: d(y^{(j)},x^{(i)}) \le \varepsilon; \; y^{(j)},x^{(i)} \in X \}

\end{equation*}

2. 密度

设$x \in X$,称$\rho(x) = |N_{\varepsilon}(x)|$为$x$的密度。密度是一个整数,且依赖于半径$\varepsilon$。

3. 核心点

设$x \in X$,若$\rho(x) \ge M$,则称$x$为$X$的核心点。记由$X$中所有核心点构成的集合为$X_c$,并记$X_{nc}=X-X_c$表示$X$中所有非核心点构成的集合。

4. 边界点

若$x \in X_{nc}$,且$\exists y \in X$,满足$y \in N_{\varepsilon}(x) \bigcap X_c$,即$X$的非核心点$x$的$\varepsilon$邻域中存在核心点,则称$x$ 为$X$的边界点。记由$X$中所有边界点构成的集合为$X_{bd}$。

此外,边界点也可以这么定义,若$x \in X_{nc}$,且$x$落在某个核心点的$\varepsilon$邻域内,则称$x$为$X$的边界点。一个边界点可能同时落入一个或多个核心点的$\varepsilon$ 邻域内。

5. 噪声点

记$X_{noi} = X - (X_c \bigcup X_{bd})$,若$x \in X_{noi}$,则称$x$为噪音点。

至此,我们严格给出了核心点、边界点和噪音点的数学定义,且满足$X = X_c \bigcup X_{bd} \bigcup X_{noi}$.

图1:核心点、边界点和噪声点

直观地说,核心点对应稠密区域内部的点,边界点对应稠密区域边缘的点,而噪音点对应稀疏区域中的点。

数据集通过聚类形成的子集是簇。核心点位于簇的内部,它确定无误地属于某个特定的簇;噪音点是数据集中的干扰数据,它不属于任何一个簇;边界点是一类特殊的点,它位于一个或几个簇的边缘地带,可能属于一个簇,也可能属于另外一个簇,其归属并不明确。

6. 直接密度可达

设$x,y \in X$. 若满足$x \in X_c$,则称$y$是$x$从直接密度可达的。

7. 密度可达

设$p^{(1)}, p^{(2)},..., p^{(m)} \in X$,其中$m \ge 2$。若它们满足:$p^ {(i+1)}$ 是从$p^{(i)}$直接密度可达的,其中$i = 1,2,...,m-1$,则称$p^ {(m)}$ 是从$p^{(1)}$ 中密度可达的。

7.1. 当$m = 2$时,密度可达即为直接密度可达。实际上,密度可达是直接密度可达的传递闭包。

7.2. 密度可达关系不具有对称性。若$p^{(m)}$是从$p^{(1)}$密度可达的,那么$p^ {(1)}$ 不一定是从$p^{(m)}$密度可达的。根据上述定义可知,$p^{(1)}, p^{(2)}, ..., p^{(m-1)}$必须为核心点,而$p^{(m)}$可以是核心点,也可以是边界点。当$p^ {(m)}$是边界点时,$p^{(1)}$一定不是从$p^{(m)}$密度可达的。

8. 密度相连

设$x,y,z \in X$,若$y$和$z$均是从$x$密度可达的,则称$y$和$z$是密度相连的。显然,密度相连具有对称性。

9. 簇(cluster)

非空集合$C \subset X$,如果$C$满足:对于$x,y \in X$

若$x \in C$,且$y$是从$x$密度可达的,则$y \in C$,

若$x \in C$,$y \in C$,则$x,y$是密度相连的。

则称$C$是$X$的一个簇。

DBSCAN 算法基于以下一个基本事实:对于任一核心点$x$,数据集$X$中所有从$x$ 密度可达的数据点可以构成一个完整的簇$C$,且$x \in C$。其核心思想描述如下:从某个选定的核心点出发,不断向密度可达的区域扩张,从而得到一个包含核心点和边界点的最大化区域,区域中任意两点密度相连。

2. DBSCAN算法的实现

《数据挖掘概念与技术》给出的算法伪代码如下:

考虑数据集合$X= \{x^{(1)}, x^{(2)},..., x^{(n)} \}$。DBSCAN算法的目标是将数据集合$X$分成$K$个簇及噪声点集合,其中$K$也是由算法得到,为此,引入簇的标记数组

\begin{equation*}

m_i =

\begin{cases}

j, & \text{若}x^{(i)}\text{属于第}j\text{个簇}; \\

-1, & \text{若}x^{(i)}\text{为噪声点}

\end{cases}

\end{equation*}

DBSCAN算法的目标就是生成标记数组$m_i, \; i=1,...,n$.

为了保证可以更有效地实现算法1中第3句随机选择一个unvisited对象$p$,设计了一个数据结构visitlist,其中包含两个列表visitedlist和unvisitedlist,分别用于存储已访问的点和未访问的点,每次从unvisitedlist 中取点可以保证每次取到的点都是未访问过的点,实现代码如下:

代码1:visitlist数据结构

1 #visitlist类用于记录访问列表

2 #unvisitedlist记录未访问过的点

3 #visitedlist记录已访问过的点

4 #unvisitednum记录访问过的点数量

5 classvisitlist:6 def _init_(self, count=0):7 self.unvisitedlist=[i for i inrange(count)]8 self.visitedlist=list()9 self.unvisitednum=count10

11 defvisit(self, pointId):12 self.visitedlist.append(pointId)13 self.unvisitedlist.remove(pointId)14 self.unvisitednum -= 1

DBSCAN算法实现代码如下:

代码2:DBSCAN算法实现

1 importnumpy as np2 importmatplotlib.pyplot as plt3 importmath4 importrandom5

6 defdist(a, b):7 #计算a,b两个元组的欧几里得距离

8 return math.sqrt(np.power(a-b, 2).sum())9

10 defmy_dbscanl(dataSet, eps, minPts):11 #numpy.ndarray的 shape属性表示矩阵的行数与列数

12 nPoints =dataSet.shape[0]13 #(1)标记所有对象为unvisited

14 #在这里用一个类vPoints进行买现

15 vPoints = visitlist(count=nPoints)16 #初始化簇标记列表C,簇标记为 k

17 k = -1

18 C = [-1 for i inrange(nPoints)]19 while(vPoints.unvisitednum >0):20 #(3)随机上选择一个unvisited对象p

21 P =random.choice(vPoints.unvisitedlist)22 #(4)标记p为visited

23 vPoints.visit(p)24 #(5)if p的$\varepsilon$-邻域至少有MinPts个对象

25 #N是p的$\varepsilon$-邻域点列表

26 N = [i for i in range(nPoints) if dist(dataSet[i], dataSet[p])<=eps]27 if len(N) >=minPts:28 #(6)创建个新簇C,并把p添加到C

29 #这里的C是一个标记列表,直接对第p个结点进行赋植

30 k += 1

31 C[p]=k32 #(7)令N为p的ε-邻域中的对象的集合

33 #N是p的$\varepsilon$-邻域点集合

34 #(8) for N中的每个点p'

35 for p1 inN:36 #(9) if p'是unvisited

37 if p1 invPoints.unvisitedlist:38 #(10)标记p’为visited

39 vPoints.visit(p1)40 #(11) if p'的$\varepsilon$-邻域至少有MinPts个点,把这些点添加到N

41 #找出p'的$\varepsilon$-邻域点,并将这些点去重添加到N

42 M=[i for i in range(nPoints) ifdist(dataSet[i], \43 dataSet[p1]) <=eps]44 if len(M) >=minPts:45 for i inM:46 if i not inN:47 N.append(i)48 #(12) if p'还不是任何簇的成员,把P'添加到C

49 #C是标记列表,直接把p'分到对应的簇里即可

50 if C[p1] == -1:51 C[p1]=k52 #(15)else标记p为噪声

53 else:54 C[p]=-1

55

56 #(16)until没有标t己为unvisitedl内对象

57 return C

利用sklearn生成数据集,共2500条数据,并利用matplotlib画出散点图,代码如下:

代码3:生成数据集

1 importnumpy as np2 importmatplotlib.pyplot as plt3 from sklearn importdatasets4

5 X1, Y1 = datasets.make_circles(n_samples=2000, factor=0.6, noise=0.05,6 random_state=1)7 X2, Y2 = datasets.make_blobs(n_samples=500, n_features=2, centers=[[1.5,1.5]],8 cluster_std=[[0.1]], random_state=5)9

10 X =np.concatenate((X1, X2))11 plt.figure(figsize=(12, 9), dpi=80)12 plt.scatter(X[:,0], X[:,1], marker='.')13 plt.show()

图2:数据集散点图

设置参数Eps=0.1, MinPts=10,聚类结果如下图:

图3:聚类结果

3. 利用KD树进行优化

KD树(K-Dimensional Tree),是一种分割k维数据空间的数据结构,是二叉搜索树在多维条件下的推广。主要应用于多维空间关键数据的搜索。KD树的介绍见:https://www.jianshu.com/p/ffe52db3e12b,不赘述。

利用scipy实现KD树的构造和查询,对代码2的算法进行改进,代码如下:

代码4:DBSCAN算法的优化实现

1 importnumpy as np2 importmatplotlib.pyplot as plt3 importmath4 importrandom5 from scipy.spatial importKDTree6

7 def my-dbscan2(dataSet, eps, minPts):8 #numpy.ndarray的 shape属性表示矩阵的行数与列数

9 #行数即表小所有点的个数

10 nPoints =dataSet.shape[0]11 #(1) 标记所有对象为unvisited

12 #在这里用一个类vPoints进行实现

13 vPoints = visitlist(count=nPoints)14 #初始化簇标记列表C,簇标记为 k

15 k = -1

16 C = [-1 for i inrange(nPoints)]17 #构建KD-Tree,并生成所有距离<=eps的点集合

18 kd =KDTree(X)19 while(vPoints.unvisitednum>0):20 #(3) 随机选择一个unvisited对象p

21 p =random.choice(vPoints.unvisitedlist)22 #(4) 标t己p为visited

23 vPoints.visit(p)24 #(5) if p 的$\varepsilon$-邻域至少有MinPts个对象

25 #N是p的$\varepsilon$-邻域点列表

26 N =kd.query_ball_point(dataSet[p], eps)27 if len(N) >=minPts:28 #(6) 创建个一个新簇C,并把p添加到C

29 #这里的C是一个标记列表,直接对第p个结点进行赋值

30 k += 1

31 C[p] =k32 #(7) 令N为p的$\varepsilon$-邻域中的对象的集合

33 #N是p的$\varepsilon$-邻域点集合

34 #(8) for N中的每个点p'

35 for p1 inN:36 #(9) if p'是unvisited

37 if p1 invPoints.unvisitedlist:38 #(10) 标记p'为visited

39 vPoints.visit(p1)40 #(11) if p'的$\varepsilon$-邻域至少有MinPts个点,把这些点添加到N

41 #找出p'的$\varepsilon$-邻域点,并将这些点去重新添加到N

42 M =kd.query_ball_point(dataSet[p1], eps)43 if len(M) >=minPts:44 for i inM:45 if i not inN:46 N.append(i)47 #(12) if p'还不是任何簇的成员,把p'添加到c

48 #C是标记列表,直接把p'分到对应的簇里即可

49 if C[p1] == -1

50 C[p1] =k51 #(15) else标记p为噪声

52 else:53 C[p1] = -1

54

55 #(16) until没有标记为unvisited的对象

56 return C

以代码3中生成的2500条数据作为测试,比较优化前后的算法性能

1 importtime2 start =time.time()3 C1 = my_dbscanl(X, 0.1, 10)4 end =time.time()5 print "`运行时间`:", end -start6 plt.scatter(X[:, 0], X[:, 1], c=C1, marker='.')7 plt.show()8 >>> `运行时间:`29.1249849796

图4:优化前算法结果

1 importtime2 start =time.time()3 C2 = my_dbscan2(X, 0.1, 10)4 end =time.time()5 print "运行时间:", end -start6 plt.scatter(X[:, 0], X[:, 1], c=C2, marker='.')7 plt.show()8 >>> 运行时间:4.72340583801

图5:优化后算法结果

可以看到优化后的算法运行时间从29.12s降到了4.72s,优化的效果非常明显。

4. 后记

上文仅仅是对DBSCAN算法的思想与实现进行了简略摘要,是学习算法的一个过程。算法的学习还比较粗劣和浅层,在实践应用中上述代码并不实用。如果需要使用DBSCAN的算法求解聚类问题,建议使用sklearn自带的DBSCAN函数。以代码3中生成数据为例:

1 #DBSCAN eps = 0.1, MinPts = 10

2 importtime3 from sklearn.cluster importDBSCAN4 start =time.time()5 C = DBSCAN(eps=0.1, min_pts=10).6 end =time.time()7 print "运行时间:", end -start8 plt.scatter(X[:, 0], X[:, 1], c=C, marker='.')9 plt.show()10 >>> 运行时间:0.0240921974182

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

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

相关文章

计算机怎么应用最小二乘法作图,最小二乘法应用

最小二乘法的数据处理一、引言在实际的工程或者实验中&#xff0c;误差处理和数据的统计是一项必备的过程&#xff0c;处理误差和数据统计的结果与否关系到这项工程最后的结果是否达到预计的要求&#xff0c;所测量数据的实际值和理论值是否接近&#xff0c;关系到工程最后质量…

latex 分行 表格标题过长_Latex 表格内文字过长自动换行 表格内单元格内容强制换行...

\usepackage{array}\begin{tabular}{m{5cm}}或者\begin{tabular}{p{0.9\columnwidth}}[LaTex]表格内单元格内容强制换行multirowmultirow 宏包提供了 \multirow 命令可以在表格中排版横跨两行以上的文本。命令的格式如下&#xff1a;\multirow{nrows}[bigstructs]{width}[fixup…

9月份计算机应用基础统考,2018年9月计算机应用基础统考题库-网考计算机应用基础真题1...

一、单选题1.第一台电子计算机是1946年在美国研制成功的&#xff0c;该机的英文缩写名是______。A.ENIACB.EDVACC.EDSACD.MARK答案&#xff1a;A知识点&#xff1a;理论基础\计算机的基本概念\计算机的发展\计算机的诞生2.计算机的通用性使其可以求解不同的算术和逻辑问题&…

java word 转换 图片_怎样把手机上的图片转换成word?

在当今这个快速发展的时代&#xff0c;人手一部手机是件很正常的事&#xff0c;小编的手机上往往会存有许多喜欢的文字图片&#xff0c;可是那么多的图片又会占用很多手机的空间&#xff0c;这样就有些不好了。庆幸的是最近小编学习到一个可以将手机上的图片转化成文字的技巧&a…

uic计算机科学与技术,北京师范大学-香港浸会大学联合国际学院UIC理工科技学部高招网...

马真真计算机科学与技术专业,现于美国南加州大学攻读硕士学位想想当初报考UIC的时候是冲着网上一个学长说的“如果你想要学习&#xff0c;那么来UIC绝对不会后悔”&#xff0c;现在毕业了&#xff0c;发现&#xff0c;确实如此。四年&#xff0c;学习了方方面面的知识&#xff…

应付账款账龄分析模板_6万字长文剖析宁德时代(三):财务分析

本文为《6万字长文剖析宁德时代》的第三篇。本文来自微信公众号&#xff1a; 凯昇资本(ID&#xff1a;gh_9c57a4031683)&#xff0c;头图来自&#xff1a;视觉中国在《6万字长文剖析宁德时代(一)&#xff1a;核心技术》和《6万字长文剖析宁德时代(二)&#xff1a;市场分析》中我…

阜阳市乡镇企业中专学校计算机教师高翱简介,2017年中南林业科技大学博士研究生奖助学金...

类似问题答案2020年中南林业科技大学博士研究生奖助学金奖助学金 为提高研究生待遇水平&#xff0c;保障研究生安心学习、潜心研究&#xff0c;我校统筹财政投入、科研经费、学费收入等各种资源&#xff0c;设立研究生国家奖学金、学业奖学金、单项奖学金等多种奖学金&#xff…

开发db文件_Swoole高效跟传统的web开发有什么区别?life

一、swoole的运行模式Swoole高效跟传统的web开发有什么区别&#xff0c;除了传统的LAMP/LNMP同步开发模式&#xff0c;swoole的异步开发模式是怎么样的。我的官方群点击此处。获取更多的swoole学习资料以及视频源码笔记。程序猿的生活&#xff1a;面试12家公司&#xff0c;收获…

计算机设备操作与讲解,计算机组成与操作系统简介

计算机的五大组成部分控制器、运算器、存储器、输入设备、输出设备控制器&#xff1a;是计算机的指挥系统&#xff0c;负责控制计算机其他硬件的工作运算器&#xff1a;负责数学运算与逻辑运算控制器运算器CPU》人的大脑存储器内存优点&#xff1a;存取速度快缺点&#xff1a;断…

360网络修复工具_Win10网络图标不见了解决方法

经常有网友反馈&#xff0c;电脑桌面右下角的网络图标不见了&#xff0c;有时候想要对网络进行相关设置&#xff0c;而找不到入口。下面以最新的系统为例&#xff0c;谈谈Win10网络图标不见了的原因与解决办法。Win10网络图标不见了怎么办&#xff1f;如果仅仅是桌面右下角找不…

计算机课中初中一年级学生特点分析,初中信息技术说课稿:计算机的组成

初中信息技术说课稿《计算机的组成》首先非常感谢我们学校我这个机会&#xff0c;今天能和全镇的信息技术权威坐到一起&#xff0c;我感到无比的荣幸。下面我将从以下8个方面来阐述我的这节课&#xff0c;不当之处&#xff0c;还请各位专家多多批评指正。一、教材分析计算机是初…

c语言使用未初始化的内存怎么解决_C语言快速入门——数组与调试进阶

由ASCII码表的输出程序,我们可以认识到使用循环语句处理一组连续的数据有着巨大的优势。在更普遍的情况下,数据由一组离散的数值组成,如一组学生的考试成绩。对于这些数据的处理,有效的方式是使用循环。但前提是数据可以在循环中有序的访问。ASCII码表输出程序中,循环变量…

计算机七个计算原理,计算机组成原理计算题(7页)-原创力文档

计算题:【第三章】交叉方式的片选方法&#xff0c;交叉方式的地址分配&#xff0c;交叉存取度的概念&#xff0c;交叉存储器的带宽的计算多模块交叉存储器采用低位地址做偏选。模块存取一个字的存储周期为T &#xff0c;总线传送时间为 t &#xff0c;存储器的交叉模块数为m&am…

从全职高手开始的系统_动画全职高手第二季热血回归,腾讯视频的国漫IP全链路开发之道...

这个国庆档&#xff0c;国产动画在内容市场上的存在感比想象中更加有分量。电影市场上&#xff0c;动画IP电影《姜子牙》完成票房领跑&#xff0c;掀起观影热潮&#xff1b;动画番剧市场上&#xff0c;头部IP动画《全职高手》第二季时隔三年重磅回归——“这是在过年&#xff0…

计算机导论的试题,计算机导论试题

关于Word的功能&#xff0c;错误的说法是( 2 )。1.可自动保存文件&#xff0c;间隔时间由用户设定2.在查找和替换字符时&#xff0c;可区分大小写&#xff0c;但不能区分全角、半角 3.可编辑文本文件&#xff0c;但用DOS命令TYPE不能显示Word文档的内容 4.能以不同的比例显示文…

海南大学计算机调剂要求,海南大学2020年硕士研究生招生调剂的公告

医学教育网小编在海南大学的研究生院官网上查阅到了“海南大学2020年硕士研究生招生调剂的公告”&#xff0c;为帮助各位想要报考海南大学的考生了解&#xff0c;医学教育网小编整理通知内容如下&#xff1a;根据2020年全国硕士研究生招生考试考生进入复试的初试成绩基本要求(国…

api有哪些 javasocket_socket及socket java api

wiki上对于soket的定义1.起源&#xff1a;起源于https://tools.ietf.org/html/rfc1472.套接字主要是在Internet模型的传输层中使用的概念。路由器和交换机等网络设备一般不需要传输层的实现&#xff0c;因为它们一般在链路层(交换机)或互联网层(路由器)上运行。3.类型数据报套接…

xp 本地计算机策略组,Windows XP组策略应用

Windows XP组策略应用时间&#xff1a;2004/10/7 18:37:00作者&#xff1a;蓝点Windows XP组策略应用组策略是管理员为用户和计算机定义并控制程序、网络资源及操作系统行为的主要工具。通过使用组策略可以设置各种软件、计算机和用户策略。例如&#xff0c;可使用“组策略”从…

计算机上面mac怎么查看,怎么看电脑的mac地址

电脑上网之后&#xff0c;特别是组建了局域网之后&#xff0c;为了防止arp攻击等网络问题&#xff0c;可能会有在路由器上设置物理网卡绑定ip地址的设置。但是&#xff0c;怎么看电脑的mac地址呢?小编带来了具体的操作过程&#xff0c;下面大家跟着学习啦小编一起来学习一下吧…

echart移上去显示内容_echarts如何移动到柱状图上显示自己想显示的提示信息

首先把series里面的数据换成含有value的对象nameArr是显示x轴显示的名称&#xff0c;dataArr是series显示的数据let nameArr[],dataArr[];for(let i0;inameArr.push(data[i].name);data[i].valuedata[i].drp;dataArr.push(data[i]);}series: [{name: 雨强,type: bar,data: data…