(数据科学学习手札15)DBSCAN密度聚类法原理简介&Python与R的实现
DBSCAN算法是一种很典型的密度聚类法,它与K-means等只能对凸样本集进行聚类的算法不同,它也可以处理非凸集。
关于DBSCAN算法的原理,笔者觉得下面这篇写的甚是清楚练达,推荐大家阅读:
https://www.cnblogs.com/pinard/p/6208966.html
DBSCAN的主要优点有:
1) 可以对任意形状的稠密数据集进行聚类,相对的,K-Means之类的聚类算法一般只适用于凸数据集。
2) 可以在聚类的同时发现异常点,对数据集中的异常点不敏感。
3) 聚类结果没有偏倚,相对的,K-Means之类的聚类算法初始值对聚类结果有很大影响。
DBSCAN的主要缺点有:
1)如果样本集的密度不均匀、聚类间距差相差很大时,聚类质量较差,这时用DBSCAN聚类一般不适合。
2) 如果样本集较大时,聚类收敛时间较长,此时可以对搜索最近邻时建立的KD树或者球树进行规模限制来改进。
3) 调参相对于传统的K-Means之类的聚类算法稍复杂,主要需要对距离阈值ϵ,邻域样本数阈值MinPts联合调参,不同的参数组合对最后的聚类效果有较大影响。
R中的fpc包中封装了dbscan(data,eps,MinPts),其中data为待聚类的数据集,eps为距离阈值ϵ,MinPts为样本数阈值,这三个是必须设置的参数,无缺省项。
一、三种聚类算法在非凸样本集上的性能表现
下面我们以正弦函数为材料构造非凸样本集,分别使用DBSCAN、K-means、K-medoids算法进行聚类,并绘制最终的聚类效果图:
library(fpc)
library(cluster) #构造非凸样本集
x1 <- seq(0,pi,0.01)
y1 <- sin(x1)+0.06*rnorm(length(x1))
y2 <- sin(x1)+0.06*rnorm(length(x1))+0.6
plot(x1,y1,ylim=c(0,2.0))
points(x1,y2)
c1 <- c(x1,x1)
c2 <- c(y1,y2)
data1 <- as.matrix(cbind(c1,c2))
构造的样本集如下:
接着我们依次使用上述三种聚类算法:
#分别绘制三种聚类算法的聚类效果图
par(mfrow=c(1,3))
#DBSCAN聚类法
db <- dbscan(data1,eps=0.2,MinPts = 5)
db$cluster
plot(data1,col=db$cluster)
title('DBSCAN Cluster')
#K-means聚类法
km <- kmeans(data1,centers=2)
km$cluster
plot(data1,col=km$cluster)
title('K-means Cluster')
#K-medoids聚类法
pm <- pam(data1,k=2)
pm$clustering
plot(data1,col=pm$clustering)
title('K-medoids Cluster')
具体的聚类效果如下:
可以看出,在对非凸样本集的聚类上,DBSCAN效果非常好,而另外两种专门处理凸集的聚类算法就遇到了麻烦。
二、DBSCAN算法在常规凸样本集上的表现
上面我们研究了DBSCAN算法在非凸样本集上的表现,比K-means和K-medoids明显优秀很多,下面我们构造一个10维的凸样本集,具体的代码和聚类结果如下:
> library(fpc)
> library(Rtsne)
>
> #创建待聚类数据集
> data1 <- matrix(rnorm(10000,0,0.6),nrow=1000)
> data2 <- matrix(rnorm(10000,1,0.6),nrow=1000)
>
> data <- rbind(data1,data2)
>
> #对原高维数据集进行降维
> tsne <- Rtsne(data)
>
> par(mfrow=c(4,4))
> for(i in 1:16){
+ #进行DBSCAN聚类
+ db <- dbscan(data,eps=1.1+i*0.025,MinPts = 25)
+ #绘制聚类效果图
+ plot(tsne$Y[,1],tsne$Y[,2],col=db$cluster)
+ title(paste('eps=',as.character(1.1+i*0.025),sep=''))
+ print(paste('eps=',as.character(1.1+i*0.025)))
+ print(table(db$cluster))
+ }
[1] "eps= 1.125" 0
2000
[1] "eps= 1.15" 0 1 2
1950 26 24
[1] "eps= 1.175" 0 1 2
1920 59 21
[1] "eps= 1.2" 0 1 2
1834 120 46
[1] "eps= 1.225" 0 1 2
1682 177 141
[1] "eps= 1.25" 0 1 2
1515 250 235
[1] "eps= 1.275" 0 1 2
1305 344 351
[1] "eps= 1.3" 0 1 2
1163 425 412
[1] "eps= 1.325" 0 1 2
989 521 490
[1] "eps= 1.35" 0 1 2
854 596 550
[1] "eps= 1.375" 0 1 2
707 670 623
[1] "eps= 1.4" 0 1 2
572 732 696
[1] "eps= 1.425" 0 1 2
500 766 734
[1] "eps= 1.45" 0 1
420 1580
[1] "eps= 1.475" 0 1
355 1645
[1] "eps= 1.5" 0 1
285 1715
可以看出,DBSCAN虽然性能优越,但是涉及到有些麻烦的调参数的过程,需要进行很多次的试探,没有K-means和K-medoids来的方便快捷。
Python
在Python中,DBSCAN算法集成在sklearn.cluster中,我们利用datasets构造两个非凸集和一个凸集,效果如下:
from sklearn import datasets
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import style
from sklearn.cluster import KMeans,DBSCAN style.use('ggplot')
'''构造样本集'''
X1, y1=datasets.make_circles(n_samples=5000, factor=.6,noise=.05)
X2, y2 = datasets.make_blobs(n_samples=1000, n_features=2, centers=[[1.2,1.2]], cluster_std=[[.1]],random_state=9) X = np.concatenate((X1, X2))
plt.scatter(X[:, 0], X[:, 1], marker='*')
plt.title('Samples')
分别使用K-means和DBSCAN对上述样本集进行聚类,效果如下:
'''利用K-means'''
km = KMeans(n_clusters=3).fit_predict(X)
col = [(['red','green','blue','yellow','grey','purple'])[i] for i in km] plt.figure(figsize=(16,8))
plt.subplot(121)
plt.scatter(X[:, 0], X[:, 1], marker='*',c=col)
plt.title('K-means') '''利用DBSCAN'''
db = DBSCAN(eps = 0.12, min_samples = 19).fit_predict(X)
col = [(['red','green','blue','yellow'])[i] for i in db]
plt.subplot(122)
plt.scatter(X[:, 0], X[:, 1], marker='*',c=col)
plt.title('DBSCAN')
对DBSCAN中的参数eps(超球体半径)进行试探:
'''对eps进行试探性调整'''
plt.figure(figsize=(15,15))
for i in range(9):
db = DBSCAN(eps = 0.05+i*0.04, min_samples = 19).fit_predict(X)
col = [(['red','green','blue','yellow','purple','aliceblue','antiquewhite','black','blueviolet','cyan','darkgray'])[i] for i in db]
plt.subplot(331+i)
plt.scatter(X[:, 0], X[:, 1], marker='*',c=col)
plt.title('eps={}'.format(str(round(0.05+i*0.04,2))))
对DBSCAN中的参数MinPts(核心点内最少样本个数)进行试探:
'''对MinPts进行试探性调整'''
plt.figure(figsize=(15,15))
for i in range(9):
db = DBSCAN(eps = 0.12, min_samples = 10+i*4).fit_predict(X)
col = [(['red','green','blue','yellow','purple','aliceblue','antiquewhite','black','blueviolet','cyan','darkgray'])[i] for i in db]
plt.subplot(331+i)
plt.scatter(X[:, 0], X[:, 1], marker='*',c=col)
plt.title('MinPts={}'.format(str(round(10+i*4))))
可见参数的设置对聚类效果的影响非常显著。
以上就是DBSCAN的简单介绍,若发现错误望指出。
(数据科学学习手札15)DBSCAN密度聚类法原理简介&Python与R的实现的更多相关文章
- (数据科学学习手札13)K-medoids聚类算法原理简介&Python与R的实现
前几篇我们较为详细地介绍了K-means聚类法的实现方法和具体实战,这种方法虽然快速高效,是大规模数据聚类分析中首选的方法,但是它也有一些短板,比如在数据集中有脏数据时,由于其对每一个类的准则函数为平 ...
- (数据科学学习手札16)K-modes聚类法的简介&Python与R的实现
我们之前经常提起的K-means算法虽然比较经典,但其有不少的局限,为了改变K-means对异常值的敏感情况,我们介绍了K-medoids算法,而为了解决K-means只能处理数值型数据的情况,本篇便 ...
- (数据科学学习手札17)线性判别分析的原理简介&Python与R实现
之前数篇博客我们比较了几种具有代表性的聚类算法,但现实工作中,最多的问题是分类与定性预测,即通过基于已标注类型的数据的各显著特征值,通过大量样本训练出的模型,来对新出现的样本进行分类,这也是机器学习中 ...
- (数据科学学习手札14)Mean-Shift聚类法简单介绍及Python实现
不管之前介绍的K-means还是K-medoids聚类,都得事先确定聚类簇的个数,而且肘部法则也并不是万能的,总会遇到难以抉择的情况,而本篇将要介绍的Mean-Shift聚类法就可以自动确定k的个数, ...
- (数据科学学习手札11)K-means聚类法的原理简介&Python与R实现
kmeans法(K均值法)是麦奎因提出的,这种算法的基本思想是将每一个样本分配给最靠近中心(均值)的类中,具体的算法至少包括以下三个步骤: 1.将所有的样品分成k个初始类: 2.通过欧氏距离将某个样品 ...
- (数据科学学习手札08)系统聚类法的Python源码实现(与Python,R自带方法进行比较)
聚类分析是数据挖掘方法中应用非常广泛的一项,而聚类分析根据其大体方法的不同又分为系统聚类和快速聚类,其中系统聚类的优点是可以很直观的得到聚类数不同时具体类中包括了哪些样本,而Python和R中都有直接 ...
- (数据科学学习手札10)系统聚类实战(基于R)
上一篇我们较为系统地介绍了Python与R在系统聚类上的方法和不同,明白人都能看出来用R进行系统聚类比Python要方便不少,但是光介绍方法是没用的,要经过实战来强化学习的过程,本文就基于R对2016 ...
- (数据科学学习手札12)K-means聚类实战(基于R)
上一篇我们详细介绍了普通的K-means聚类法在Python和R中各自的实现方法,本篇便以实际工作中遇到的数据集为例进行实战说明. 数据说明: 本次实战样本数据集来自浪潮集团提供的美团的商家信息,因涉 ...
- (数据科学学习手札09)系统聚类算法Python与R的比较
上一篇笔者以自己编写代码的方式实现了重心法下的系统聚类(又称层次聚类)算法,通过与Scipy和R中各自自带的系统聚类方法进行比较,显然这些权威的快捷方法更为高效,那么本篇就系统地介绍一下Python与 ...
随机推荐
- Windows漏洞利用技术概述
Windows漏洞利用技术总结 1. 前言 本文是我对漏洞利用技术的学习总结,也是自己践行QAD (Questions.Answer.Discussions)的一次实践.本文通过阅读几位大牛的文章.演 ...
- Orchard core 中文文档翻译系列
本系列翻译顺序完全参照 官方顺序 原文地址:https://orchardcore.readthedocs.io/en/latest/ Orchard Core 中文文档翻译(一)关于Orchard ...
- 20165322 学习基础及C语言基础调查
学习基础和C语言基础调查 一.技能学习经验 有什么技能比90%的人更好? 说来惭愧,我并不认为自己有什么技能能超过90%的人.我从小喜爱水彩画和推理解谜,在自己一些闲余时间的练习与学习下,应该可以超过 ...
- 关于TOCTTOU攻击的简介
前言 最近看到了一些以 at 结尾的Linux系统调用,在维基百科上面说这可以防御一些特定的TOCTTOU攻击,而在TOCTTOU对应页面中并没有中文版的介绍,而且百度的结果也比较少,于是决定抽空写一 ...
- jsp的4个作用域区别( pageScope、requestScope、sessionScope、applicationScope)
简单描述 page里的变量没法从index.jsp传递到test.jsp.只要页面跳转了,它们就不见了. request里的变量可以跨越forward前后的两页.但是只要刷新页面,它们就重新计算了. ...
- Android学习笔记_65_登录功能本身没有任何特别
对于登录功能本身没有任何特别,使用httpclient向服务器post用户名密码即可.但是为了保持登录的状态(在各个Activity之间切换时要让网站知道用户一直是处于登录的状态)就需要进行cooki ...
- MYSQL添加外键关联
SELECT * from stu st,course co,score sc where st.sid = sc.sid and sc.cid = co.cid 如果我们要给 sid 做一个约束,即 ...
- o'Reill的SVG精髓(第二版)学习笔记——第二章
在网页中使用SVG 将SVG作为图像: SVG是一种图像格式,因此可以使用与其他图像类型相同的方式包含在HTML页面中,具体可以采用两种方法:将图像包含在HTML标记的<img>元素内(当 ...
- html+css让网页自动适应手机屏幕
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scal ...
- 分布式id生成
2016年08月09日 14:15:21 yuanyuanispeak 阅读数:318 编辑 一.需求缘起 几乎所有的业务系统,都有生成一个记录标识的需求,例如: (1)消息标识:message-id ...