dbscan java_DBSCAN算法的Java,C++,Python实现

article/2025/8/24 13:22:19

最近由于要实现‘基于网格的DBSCAN算法’,网上有没有找到现成的代码[如果您有代码,麻烦联系我],只好参考已有的DBSCAN算法的实现。先从网上随便找了几篇放这儿,之后对比研究。

DBSCAN简介:

1.简介

DBSCAN 算法是一种基于密度的空间聚类算法。该算法利用基于密度的聚类的概念,即要求聚类空间中的一定区域内所包含对象(点或其它空间对象)的数目不小于某一给定阀   值。DBSCAN 算法的显著优点是聚类速度快且能够有效处理噪声点和发现任意形状的空间聚类。但是由于它直接对整个数据库进行操作且进行聚类时使用了一个全局性的表征  密度的参数,因此也具有两个比较明显的弱点:

1. 当数据量增大时,要求较大的内存支持 I/0 消耗也很大;

2. 当空间聚类的密度不均匀、聚类间距离相差很大时,聚类质量较差。

2.DBSCAN算法的聚类过程

DBSCAN算法基于一个事实:一个聚类可以由其中的任何核心对象唯一确定。等价可以表述为: 任一满足核心对象条件的数据对象p,数据库D中所有从p密度可达的数据对象o  所组成的集合构成了一个完整的聚类C,且p属于C。

3.DBSCAN中的几个定义

密度可达是直接密度可达的传递闭包,非对称性关系;密度相连是对称性关系。DBSCA目的是找到密度相连对象的最大集合。

E领域:给定对象p半径为E内的区域称为该对象的E领域;

核心对象:p的E领域内样本数大于MinPts(算法输入值),则该对象p为核心对象;

直接密度可达:对于样本集合D,如果样本点q在p的E领域内,且p为核心对象,则p直接密度可达q;

密度可达:对于样本集合D,存在一串样本点p1,p2,p3,...pn,其中连续两个点直接密度可达,则 p=p1,q=qn,则p密度可达q;

密度相连:对于样本集合D中任意一点o,存在p到o密度可达,并且q到o密度可达,那么q从p密度相连;

算法伪代码

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 DBSCAN(SetOfPoints, Eps, MinPts){2 ClusterId=nextId(NOISE)3 for(i=0;i

13 ExpandCluster(SetOfPoints,Point, ClId, Eps, MinPts){14 seeds=SetOfPoints.regionQuery(Point, Eps)15 if(seeds.size()0){22 currentP=seeds.first()23 result=SetOfPoints.regionQuery(currentP, Eps)24 if(result.size()>=MinPts){25 for(i=0;i

View Code

JAVA实现:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packageorisun;2

3 importjava.io.File;4 importjava.util.ArrayList;5 importjava.util.Vector;6 importjava.util.Iterator;7

8 public classDBScan {9

10 double Eps=3; //区域半径

11 int MinPts=4; //密度12

13 //由于自己到自己的距离是0,所以自己也是自己的neighbor

14 public Vector getNeighbors(DataObject p,ArrayListobjects){15 Vector neighbors=new Vector();16 Iterator iter=objects.iterator();17 while(iter.hasNext()){18 DataObject q=iter.next();19 double[] arr1=p.getVector();20 double[] arr2=q.getVector();21 int len=arr1.length;22

23 if(Global.calEditDist(arr1,arr2,len)<=Eps){ //使用编辑距离24 //if(Global.calEuraDist(arr1, arr2, len)<=Eps){//使用欧氏距离25 //if(Global.calCityBlockDist(arr1, arr2, len)<=Eps){//使用街区距离26 //if(Global.calSinDist(arr1, arr2, len)<=Eps){//使用向量夹角的正弦

27 neighbors.add(q);28 }29 }30 returnneighbors;31 }32

33 public int dbscan(ArrayListobjects){34 int clusterID=0;35 boolean AllVisited=false;36 while(!AllVisited){37 Iterator iter=objects.iterator();38 while(iter.hasNext()){39 DataObject p=iter.next();40 if(p.isVisited())41 continue;42 AllVisited=false;43 p.setVisited(true); //设为visited后就已经确定了它是核心点还是边界点

44 Vector neighbors=getNeighbors(p,objects);45 if(neighbors.size()

48 }else{49 if(p.getCid()<=0){50 clusterID++;51 expandCluster(p,neighbors,clusterID,objects);52 }else{53 int iid=p.getCid();54 expandCluster(p,neighbors,iid,objects);55 }56 }57 AllVisited=true;58 }59 }60 returnclusterID;61 }62

63 private void expandCluster(DataObject p, Vectorneighbors,64 int clusterID,ArrayListobjects) {65 p.setCid(clusterID);66 Iterator iter=neighbors.iterator();67 while(iter.hasNext()){68 DataObject q=iter.next();69 if(!q.isVisited()){70 q.setVisited(true);71 Vector qneighbors=getNeighbors(q,objects);72 if(qneighbors.size()>=MinPts){73 Iterator it=qneighbors.iterator();74 while(it.hasNext()){75 DataObject no=it.next();76 if(no.getCid()<=0)77 no.setCid(clusterID);78 }79 }80 }81 if(q.getCid()<=0){ //q不是任何簇的成员

82 q.setCid(clusterID);83 }84 }85 }86

87 public static voidmain(String[] args){88 DataSource datasource=newDataSource();89 //Eps=3,MinPts=4

90 datasource.readMatrix(new File("/home/orisun/test/dot.mat"));91 datasource.readRLabel(new File("/home/orisun/test/dot.rlabel"));92 //Eps=2.5,MinPts=493 //datasource.readMatrix(new File("/home/orisun/text.normalized.mat"));94 //datasource.readRLabel(new File("/home/orisun/text.rlabel"));

95 DBScan ds=newDBScan();96 int clunum=ds.dbscan(datasource.objects);97 datasource.printResult(datasource.objects,clunum);98 }99 }

View Code

C++实现:

数据结构

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include

2

3 using namespacestd;4

5 const int DIME_NUM=2; //数据维度为2,全局常量6

7 //数据点类型

8 classDataPoint9 {10 private:11 unsigned long dpID; //数据点ID

12 double dimension[DIME_NUM]; //维度数据

13 long clusterId; //所属聚类ID

14 bool isKey; //是否核心对象

15 bool visited; //是否已访问

16 vector arrivalPoints; //领域数据点id列表

17 public:18 DataPoint(); //默认构造函数

19 DataPoint(unsigned long dpID,double* dimension , bool isKey); //构造函数

20

21 unsigned long GetDpId(); //GetDpId方法

22 void SetDpId(unsigned long dpID); //SetDpId方法

23 double* GetDimension(); //GetDimension方法

24 void SetDimension(double* dimension); //SetDimension方法

25 bool IsKey(); //GetIsKey方法

26 void SetKey(bool isKey); //SetKey方法

27 bool isVisited(); //GetIsVisited方法

28 void SetVisited(bool visited); //SetIsVisited方法

29 long GetClusterId(); //GetClusterId方法

30 void SetClusterId(long classId); //SetClusterId方法

31 vector& GetArrivalPoints(); //GetArrivalPoints方法

32 };

View Code

实现

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include "DataPoint.h"

2

3 //默认构造函数

4 DataPoint::DataPoint()5 {6 }7

8 //构造函数

9 DataPoint::DataPoint(unsigned long dpID,double* dimension , boolisKey):isKey(isKey),dpID(dpID)10 {11 //传递每维的维度数据

12 for(int i=0; idimension[i]=dimension[i];15 }16 }17

18 //设置维度数据

19 void DataPoint::SetDimension(double*dimension)20 {21 for(int i=0; idimension[i]=dimension[i];24 }25 }26

27 //获取维度数据

28 double*DataPoint::GetDimension()29 {30 return this->dimension;31 }32

33 //获取是否为核心对象

34 boolDataPoint::IsKey()35 {36 return this->isKey;37 }38

39 //设置核心对象标志

40 void DataPoint::SetKey(boolisKey)41 {42 this->isKey =isKey;43 }44

45 //获取DpId方法

46 unsigned longDataPoint::GetDpId()47 {48 return this->dpID;49 }50

51 //设置DpId方法

52 void DataPoint::SetDpId(unsigned longdpID)53 {54 this->dpID =dpID;55 }56

57 //GetIsVisited方法

58 boolDataPoint::isVisited()59 {60 return this->visited;61 }62

63

64 //SetIsVisited方法

65 void DataPoint::SetVisited( boolvisited )66 {67 this->visited =visited;68 }69

70 //GetClusterId方法

71 longDataPoint::GetClusterId()72 {73 return this->clusterId;74 }75

76 //GetClusterId方法

77 void DataPoint::SetClusterId( longclusterId )78 {79 this->clusterId =clusterId;80 }81

82 //GetArrivalPoints方法

83 vector&DataPoint::GetArrivalPoints()84 {85 returnarrivalPoints;86 }

View Code

PYTHON实现:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 from matplotlib.pyplot import *

2 fromcollections import defaultdict3 import random4

5 #function to calculate distance6 def dist(p1, p2):7 return ((p1[0]-p2[0])**2+ (p1[1]-p2[1])**2)**(0.5)8

9 #randomly generate around 100cartesian coordinates10 all_points=[]11

12 for i in range(100):13 randCoord = [random.randint(1,50), random.randint(1,50)]14 if not randCoord inall_points:15 all_points.append(randCoord)16

17

18 #take radius = 8 and min. points = 8

19 E = 8

20 minPts = 8

21

22 #find outthe core points23 other_points =[]24 core_points=[]25 plotted_points=[]26 for point inall_points:27 point.append(0) # assign initial level 0

28 total = 0

29 for otherPoint inall_points:30 distance =dist(otherPoint,point)31 if distance<=E:32 total+=1

33

34 if total >minPts:35 core_points.append(point)36 plotted_points.append(point)37 else:38 other_points.append(point)39

40 #find border points41 border_points=[]42 for core incore_points:43 for other inother_points:44 if dist(core,other)<=E:45 border_points.append(other)46 plotted_points.append(other)47

48

49 #implement the algorithm50 cluster_label=0

51

52 for point incore_points:53 if point[2]==0:54 cluster_label+=1

55 point[2]=cluster_label56

57 for point2 inplotted_points:58 distance =dist(point2,point)59 if point2[2] ==0 and distance<=E:60 print point, point261 point2[2] =point[2]62

63

64 #after the points are asssigned correnponding labels, we group them65 cluster_list =defaultdict(lambda: [[],[]])66 for point inplotted_points:67 cluster_list[point[2]][0].append(point[0])68 cluster_list[point[2]][1].append(point[1])69

70 markers = ['+','*','.','d','^','v','>','

72 #plotting the clusters73 i=0

74 print cluster_list75 for value incluster_list:76 cluster=cluster_list[value]77 plot(cluster[0], cluster[1],markers[i])78 i = i%10+1

79

80 #plot the noise points aswell81 noise_points=[]82 for point inall_points:83 if not point in core_points and not point inborder_points:84 noise_points.append(point)85 noisex=[]86 noisey=[]87 for point innoise_points:88 noisex.append(point[0])89 noisey.append(point[1])90 plot(noisex, noisey, "x")91

92 title(str(len(cluster_list))+"clusters created with E ="+str(E)+"Min Points="+str(minPts)+"total points="+str(len(all_points))+"noise Points ="+str(len(noise_points)))93 axis((0,60,0,60))94 show()

View Code

参考:http://www.cnblogs.com/zhangchaoyang/articles/2182748.html

http://www.cnblogs.com/lovell-liu/archive/2011/11/08/2241542.html

http://blog.sudipk.com.np/2013/02/implementation-of-dbscan-algorithm-for.html

http://caoyaqiang.diandian.com/post/2012-09-26/40039517485


http://chatgpt.dhexx.cn/article/cEcAD9Ug.shtml

相关文章

DBSCAN聚类

1.原理DBSCAN密度聚类算法https://www.cnblogs.com/pinard/p/6208966.html详解DBSCAN聚类 - 知乎使用DBSCAN标识为员工分组 基于密度的噪声应用空间聚类(DBSCAN)是一种无监督的ML聚类算法。无监督的意思是它不使用预先标记的目标来聚类数据点。聚类是指试图将相似的数据点分组到…

dbscan算法python实现_Python实现DBScan

Python实现DBScan 运行环境 Pyhton3 numpy(科学计算包) matplotlib(画图所需&#xff0c;不画图可不必) 计算过程 st>start: 开始 e>end: 结束 op1>operation: 读入数据 cond>condition: 是否还有未分类数据 op2>operation: 找一未分类点扩散 op3>operation:…

DBSCAN 算法

DBSCAN 算法 DBSCAN的由来 DBSCAN它将簇定义为密度相连的点组成的最大集合&#xff0c;能够把具有足够高密度的区域划分为簇&#xff0c;并可在噪声的空间数据库中发现任意形状的聚类 在k-means中 , 每个点有且只有一个簇 , 且必须属于一个簇 , 但是在DBSCAN中 , 点最多属于…

DBSCAN算法

本文简单介绍DBSCAN算法的原理及实现。 DBSCAN算法原理 基本概念 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;是一种基于密度的空间聚类算法。该算法将具有足够密度的区域划分为簇&#xff0c;并在具有噪声的空间数据库中发…

DBSCAN点云聚类

1、DBSCAN算法原理 DBSCAN是一种基于密度的聚类方法&#xff0c;其将点分为核心点与非核心点&#xff0c;后续采用类似区域增长方式进行处理。下图为DBSCAN聚类结果&#xff0c;可见其可以对任意类别的数据进行聚类&#xff0c;无需定义类别数量。 DBSCAN聚类说明 DBSCAN聚类过…

DBSCAN

DBSCAN 算法将具有足够高密度的区域划分为簇&#xff0c;并可 以发现任何形状的聚类 DBSCAN算法概念 &#x1d6c6;邻域&#xff1a;给定对象半径&#x1d700;内的区域称为该对象的&#x1d700;邻域。核心对象&#xff1a;如果给定 &#x1d700; 邻域内的样本点数大于等于M…

密度聚类之DBSCAN算法原理

DBSCAN(Density-Based Spatial Clustering of Applications with Noise&#xff0c;具有噪声的基于密度的聚类方法)是一种很典型的密度聚类算法&#xff0c;和K-Means&#xff0c;BIRCH这些一般只适用于凸样本集的聚类相比&#xff0c;DBSCAN既可以适用于凸样本集&#xff0c;也…

总结:机器学习之DBSCAN

一、基本思想 DBSCAN是一种基于密度的聚类算法&#xff0c;这类密度聚类算法一般假定类别可以通过样本分布的紧密程度决定。同一类别的样本&#xff0c;他们之间的紧密相连的&#xff0c;也就是说&#xff0c;在该类别任意样本周围不远处一定有同类别的样本存在。 通过将紧密…

聚类算法也可以异常检测?DBSCAN算法详解。

一、算法概述 DBSCAN是一个出现得比较早&#xff08;1996年&#xff09;&#xff0c;比较有代表性的基于密度的聚类算法&#xff0c;虽然这个算法本身是密度聚类算法&#xff0c;但同样可以用作异常检测&#xff0c;其思想就是找到样本空间中处在低密度的异常样本&#xff0c;本…

DBSCAN详解

一、基本概念 DBSCAN的基本概念可以用1&#xff0c;2&#xff0c;3&#xff0c;4来总结。 1个核心思想&#xff1a;基于密度 直观效果上看&#xff0c;DBSCAN算法可以找到样本点的全部密集区域&#xff0c;并把这些密集区域当做一个一个的聚类簇。 2个算法参数&#xff1a;邻…

【机器学习】DBSCAN聚类算法

DBSCAN聚类算法 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff0c;具有噪声的基于密度的聚类方法&#xff09;是一种基于密度的空间聚类算法。 1.基本概念 核心对象:若某个点的密度达到算法设定的阈值则其为核心点。(即r的 ϵ \e…

30款APP源码打包 Java Android安卓App源码 30款打包下载

[30款APP源码打包 Java Android安卓App源码 30款打包下载](访问密码: 168168)(https://474b.com/file/29013429-461457489)

【Android】Android源码下载

学而不思则罔&#xff0c;思而不学则殆 【Android】Android源码下载 一.环境准备虚拟机Ubuntu系统 二.Android源码下载Ubuntu下载1.repo下载2.修改源代码镜像地址3.初始化仓库4.指定版本5.同步源码树 Windows下载1.repo下载2.修改源代码镜像地址3.初始化仓库4.指定版本5.同步源…

下载Android源码流程(完整版)

要在Linux环境下操作&#xff0c;要在Linux环境下操作&#xff0c;要在Linux环境下操作~~ 不要想在Windows环境下操作&#xff0c;因为会有各种问题。Windows环境的童鞋又不想装双系统的可以跟着下面的操作&#xff0c;Linux的童鞋可以直接跳过看。Mac的童鞋就略过~~~ &#x…

Android系统源码下载

1&#xff0c;ubuntu电脑 2&#xff0c;下载 repo 工具: mkdir ~/bin PATH~/bin:$PATH curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo chmod ax ~/bin/repo3&#xff0c; 建立工作目录: mkdir WORKING_DIRECTORY cd WORKING_DIRECTORY4&am…

Android系统源码_下载编译——从下载系统源码到编译系统镜像

前言 近期因工作原因&#xff0c;需要频繁编译、调试Android源码 &#xff0c;特别是修改framework层的源码&#xff0c;经过不懈努力&#xff0c;终于可以正常调试了。 这里进行一些总结和分享。 参考文章&#xff1a;清华镜像之Android 镜像使用帮助、Android系统源码编译 …

下载并编译Android源码

下载编译源码 系统架构&#xff1a; Linux&#xff1a;Linux内核和驱动模块&#xff08;USB Camera 蓝牙等&#xff09; Libraries&#xff1a;提供动态库&#xff0c;Android运行时库、Dalvik虚拟机等&#xff0c;大部分是C 和C写的&#xff0c;可以看成是native层 Framewo…

一、安卓系统源码下载

前言&#xff1a;为了研究安卓系统&#xff0c;我们需要下载安卓源码&#xff0c;本篇博文参考安卓官网https://source.android.com &#xff0c;对安卓系统各个版本源码的下载做出了详细解释。 一、环境要求概览 在下载编译安卓系统源码前&#xff0c;我们必须对各个版本安卓…

从github下载最新Android源码

今年5月底开始&#xff0c;谷歌彻底被墙&#xff0c;所有谷歌的网站都不能访问了&#xff0c;这次包括了android.org&#xff0c;googlesource.com&#xff0c;code.google.com。Android官方的资源不能访问&#xff0c;想下载Android代码当然是困难重重了。 本文就为大家解决这…

Android源码下载编译(TI)

0 前言 通过《Android源码下载 & 编译&#xff08;高通&#xff09;》的方法下载的源码是包含有kernel目录的&#xff08;也就是包含Linux内核&#xff09;&#xff0c;然而&#xff0c;通过其它方法下载的源码可能并不包含kernel目录&#xff08;也就是不包含Linux内核&am…