聚类算法-DBSCAN-C++实现

程序流程图:

DBSCAN核心功能函数,计算每个point的eps范围内的point数量pts;

对于所有pts >Minpts的point,记为Core point;

对于所有的corepoint,将其eps范围内的core point下标添加到vector<int>::corepts中;

对于所有的corepoint,采用深度优先的方式遍历core point的所有cluster,使得相互连接的core point具有相同的cluster编号;

计算所有pts < Minpts且在Core point范围内的,记为Borderpoint;

将所有Borderpoint加入到任意一个关联的core point;

剩余的point的为Noise point,文件写写入时忽略;

将point信息写入clustering文件,程序结束。

/*
	DBSCAN Algorithm
	15S103182
	Ethan
*/
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <limits>
#include <cmath>
#include <stack>
using namespace std;
class point{
public:
	float x;
	float y;
	int cluster=0;
	int pointType=1;//1 noise 2 border 3 core
	int pts=0;//points in MinPts
	vector<int> corepts;
	int visited = 0;
	point (){}
	point (float a,float b,int c){
		x = a;
		y = b;
		cluster = c;
	}
};
float stringToFloat(string i){
	stringstream sf;
	float score=0;
	sf<<i;
	sf>>score;
	return score;
}
vector<point> openFile(const char* dataset){
	fstream file;
	file.open(dataset,ios::in);
	if(!file)
    {
        cout <<"Open File Failed!" <<endl;
        vector<point> a;
        return a;
    }
	vector<point> data;
	int i=1;
	while(!file.eof()){
		string temp;
		file>>temp;
		int split = temp.find(',',0);
		point p(stringToFloat(temp.substr(0,split)),stringToFloat(temp.substr(split+1,temp.length()-1)),i++);
		data.push_back(p);
	}
	file.close();
	cout<<"successful!"<<endl;
	return data;
}
float squareDistance(point a,point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void DBSCAN(vector<point> dataset,float Eps,int MinPts){
	int len = dataset.size();
	//calculate pts
	cout<<"calculate pts"<<endl;
	for(int i=0;i<len;i++){
		for(int j=i+1;j<len;j++){
			if(squareDistance(dataset[i],dataset[j])<Eps)
				dataset[i].pts++;
				dataset[j].pts++;
		}
	}
	//core point
	cout<<"core point "<<endl;
	vector<point> corePoint;
	for(int i=0;i<len;i++){
		if(dataset[i].pts>=MinPts) {
			dataset[i].pointType = 3;
			corePoint.push_back(dataset[i]);
		}
	}
	cout<<"joint core point"<<endl;
	//joint core point
	for(int i=0;i<corePoint.size();i++){
		for(int j=i+1;j<corePoint.size();j++){
			if(squareDistance(corePoint[i],corePoint[j])<Eps){
				corePoint[i].corepts.push_back(j);
				corePoint[j].corepts.push_back(i);
			}
		}
	}
	for(int i=0;i<corePoint.size();i++){
		stack<point*> ps;
		if(corePoint[i].visited == 1) continue;
		ps.push(&corePoint[i]);
		point *v;
		while(!ps.empty()){
			v = ps.top();
			v->visited = 1;
			ps.pop();
			for(int j=0;j<v->corepts.size();j++){
				if(corePoint[v->corepts[j]].visited==1) continue;
				corePoint[v->corepts[j]].cluster = corePoint[i].cluster;
				corePoint[v->corepts[j]].visited = 1;
				ps.push(&corePoint[v->corepts[j]]);
			}
		}
	}
	cout<<"border point,joint border point to core point"<<endl;
	//border point,joint border point to core point
	for(int i=0;i<len;i++){
		if(dataset[i].pointType==3) continue;
		for(int j=0;j<corePoint.size();j++){
			if(squareDistance(dataset[i],corePoint[j])<Eps) {
				dataset[i].pointType = 2;
				dataset[i].cluster = corePoint[j].cluster;
				break;
			}
		}
	}
	cout<<"output"<<endl;
	//output
	fstream clustering;
	clustering.open("clustering.txt",ios::out);
	for(int i=0;i<len;i++){
		if(dataset[i].pointType == 2)
			clustering<<dataset[i].x<<","<<dataset[i].y<<","<<dataset[i].cluster<<"\n";
	}
	for(int i=0;i<corePoint.size();i++){
			clustering<<corePoint[i].x<<","<<corePoint[i].y<<","<<corePoint[i].cluster<<"\n";
	}
	clustering.close();
}
int main(int argc, char** argv) {
	vector<point> dataset = openFile("dataset3.txt");
	DBSCAN(dataset,1.5,2);
	return 0;
}

数据文件格式:(x,y)

运行结果格式:(x,y,cluster)

图形化展现:

特殊形状:

桥梁:

变化密度:

总结:

DBSCAN算法能够很好处理不同形状与大小的数据,并且抗噪音数据。但对于变化的密度,DBSCAN算法具有局限性。在实现Core point连接时,遇到了一点小小的麻烦,很难将相互连接的core point的cluster编号统一,后来通过给每个core point增加一个数组用于记录相连core point的下标信息,并采用深度优先进行遍历的方式,不仅提高了计算速度,同时也保证了准确性。对于实验数据结果,如果不对其进行图形化展现,很难看出聚类的效果,采用WPF(C#)技术对数据点进行处理,对不同cluster编号的点,赋予不同的颜色,进行图形展现。

时间: 2024-10-07 05:06:30

聚类算法-DBSCAN-C++实现的相关文章

简单易学的机器学习算法——基于密度的聚类算法DBSCAN

一.基于密度的聚类算法的概述 最近在Science上的一篇基于密度的聚类算法<Clustering by fast search and find of density peaks>引起了大家的关注(在我的博文"论文中的机器学习算法--基于密度峰值的聚类算法"中也进行了中文的描述).于是我就想了解下基于密度的聚类算法,熟悉下基于密度的聚类算法与基于距离的聚类算法,如K-Means算法之间的区别. 基于密度的聚类算法主要的目标是寻找被低密度区域分离的高密度区域.与基于距离的聚

数据挖掘聚类算法--DBSCAN

数据集如下所示: 1,1,1 2,1.5,1 3,0.5,1 3,5,-1 7,0.75,-1 7,4,2 8,5,2 8,5.5,2 数据集有三个属性,分别是二维坐标中的x和y,第三个属性是所属的类,-1代表为孤立点,坐标系如下图所示: 源代码如下: package neugle.dbscan; import java.io.BufferedReader; import java.io.FileReader; import java.util.ArrayList; import java.ut

5.无监督学习-DBSCAN聚类算法及应用

DBSCAN方法及应用 1.DBSCAN密度聚类简介 DBSCAN 算法是一种基于密度的聚类算法: 1.聚类的时候不需要预先指定簇的个数 2.最终的簇的个数不确定DBSCAN算法将数据点分为三类: 1.核心点:在半径Eps内含有超过MinPts数目的点. 2.边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域内的点. 3.噪音点:既不是核心点也不是边界点的点. 如下图所示:图中黄色的点为边界点,因为在半径Eps内,它领域内的点不超过MinPts个,我们这里设置的MinPts为5

基于密度的聚类之Dbscan算法

一.算法概述 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一个比较有代表性的基于密度的聚类算法.与划分和层次聚类方法不同,它将簇定义为密度相连的点的最大集合,能够把具有足够高密度的区域划分为簇,并可在噪声的空间数据库中发现任意形状的聚类(笔者认为是因为他不是基于距离的,基于距离的发现的是球状簇). 该算法利用基于密度的聚类的概念,即要求聚类空间中的一定区域内所包含对象(点或其他空间对象)的数目不小于某一给

机器学习笔记(九)聚类算法及实践(K-Means,DBSCAN,DPEAK,Spectral_Clustering)

这一周学校的事情比较多所以拖了几天,这回我们来讲一讲聚类算法哈. 首先,我们知道,主要的机器学习方法分为监督学习和无监督学习.监督学习主要是指我们已经给出了数据和分类,基于这些我们训练我们的分类器以期达到比较好的分类效果,比如我们前面讲的Logistic回归啊,决策树啊,SVM啊都是监督学习模型.无监督学习就是指我们就只有数据,没有分类结果,然后根据数据进行建模能够给出哪些样本是属于一类的一个过程,通常我们就称之为聚类. 今天我主要介绍以下几种最常见的聚类算法,包括K-Means算法,基于密度的

基于密度聚类的DBSCAN算法

根据各行业特性,人们提出了多种聚类算法,简单分为:基于层次.划分.密度.图论.网格和模型的几大类. 其中,基于密度的聚类算法以DBSCAN最具有代表性. 假设有如下图的一组数据, 生成数据的R代码如下 x1 <- seq(0,pi,length.out=100) y1 <- sin(x1) + 0.1*rnorm(100) x2 <- 1.5+ seq(0,pi,length.out=100) y2 <- cos(x2) + 0.1*rnorm(100) data <- da

DBSCAN密度聚类算法

DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类方法)是一种很典型的密度聚类算法,和K-Means,BIRCH这些一般只适用于凸样本集的聚类相比,DBSCAN既可以适用于凸样本集,也可以适用于非凸样本集.下面我们就对DBSCAN算法的原理做一个总结. 1. 密度聚类原理 DBSCAN是一种基于密度的聚类算法,这类密度聚类算法一般假定类别可以通过样本分布的紧密程度决定.同一类别的样本,他们

聚类算法:K均值、凝聚层次聚类和DBSCAN

聚类分析就仅根据在数据中发现的描述对象及其关系的信息,将数据对象分组(簇).其目标是,组内的对象相互之间是相似的,而不同组中的对象是不同的.组内相似性越大,组间差别越大,聚类就越好. 先介绍下聚类的不同类型,通常有以下几种: (1)层次的与划分的:如果允许簇具有子簇,则我们得到一个层次聚类.层次聚类是嵌套簇的集族,组织成一棵树.划分聚类简单地将数据对象划分成不重叠的子集(簇),使得每个数据对象恰在一个子集中. (2)互斥的.重叠的与模糊的:互斥的指每个对象都指派到单个簇.重叠的或是模糊聚类用来反

DBScan聚类算法原理与实现整理

百度百科中的描述 算法描述: (1)检测数据库中尚未检查过的对象p,如果p为被处理(归为某个簇或者标记为噪声),则检查其邻域,若包含的对象数不小于minPts,建立新簇C,将其中的所有点加入候选集N: (2)对候选集N 中所有尚未被处理的对象q,检查其邻域,若至少包含minPts个对象,则将这些对象加入N:如果q 未归入任何一个簇,则将q 加入C: (3)重复步骤2),继续检查N 中未处理的对象,当前候选集N为空: (4)重复步骤1)~3),直到所有对象都归入了某个簇或标记为噪声. 伪代码: 输

【机器学习】DBSCAN Algorithms基于密度的聚类算法

一.算法思想: DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一个比较有代表性的基于密度的聚类算法.与划分和层次聚类方法不同,它将簇定义为密度相连的点的最大集合,能够把具有足够高密度的区域划分为簇,并可在噪声的空间数据库中发现任意形状的聚类. DBSCAN中的几个定义: Ε邻域:给定对象半径为Ε内的区域称为该对象的Ε邻域: 核心对象:如果给定对象Ε领域内的样本点数大于等于MinPts,则称该对象为核心对象: