本篇文章主要学习:
机器学习(八):DBSCAN算法(基础篇)
DBSCAN聚类算法原理及其实现
聚类算法之DBSCAN算法介绍及实现
1 DBSCAN介绍
1.1 基本概念
1.1.1 密度聚类
密度聚类也被称作“基于密度的聚类”(density-based clustering),此算法假设聚类结构能通过样本分布的紧密程度确定,通常情况下,密度聚类算法从样本密度的角度来考察样本之间的可连接性,并基于可连接样本不断扩展聚类以获取最终的聚类结果。
1.1.2 DBSAN算法
DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一个比较有代表性的基于密度的聚类算法。它基于一组**“邻域”**(neighborhood)参数来刻画样本分布的紧密程度,可以发现任何形状的聚类。
了解DBSCAN算法的原理,需要了解几个基本概念:
-
e邻域:给定对象半径为e内的区域称为该对象的e邻域。如图,P对象在半径e内构成的圆就是该对象的e邻域。
-
核心对象:如果给定对象e邻域内的样本点数大于等于MinPoints,则称该对象为核心对象;如图:设置MinPoints的点为2,那么在对象p的e领域内有4个点,大于MinPoints,那么p对象就是核心对象。
-
直接密度可达:给定一个对象集合D,如果样本点q在p的e邻域内,并且p为核心对象,那么对象q从对象p出发是直接密度可达。
-
密度可达:给定一个对象集合D,给定一串样本点p1,p2….pn, xi= p1并且xi为核心对象,xj= pn,xj不为核心对象,(即pn不为核心对象)。那么假如对象pi(可能为核心对象,也可能不为核心对象)从pi-1(核心对象)直接密度可达,那么对象xj从对象xi密度可达。
-
密度相连:存在样本集合D中的一点o,如果对象o(是核心对象)到对象p(不是核心对象)和对象q(不是核心对象)都是密度可达的,那么p和q密度相联。
1.2 基本原理/算法流程
- DBSCAN算法流程/基本原理
- 指定合适的e与Minpoints(e类似于半径,Minpoint是最小样本数,为了后续核心对象及其簇的确定)
- 计算所有的样本点,如果点p的e领域里有超过Minpoints个点,则创建一个以p为核心点的新簇(p是核心对象)。
- 反复寻找这些核心点直接密度可达(之后则是密度可达)的点,将其加入到相应的簇,对于核心点发生密度相连状况的簇,进行合并。
- 当没有新的点可以被添加到任何簇时,算法结束。
- 参数选择
DBSCAN算法需要用户输入2个参数:一个参数是半径(Eps),表示以给定点P为中心的圆形邻域的范围;另一个参数是以点P为中心的邻域内最少点的数量(MinPts)。如果满足:以点P为中心、半径为Eps的邻域内的点的个数不少于MinPts,则称点P为核心点。
DBSCAN聚类使用到一个k-距离的概念,k-距离是指:给定数据集P={p(i); i=0,1,…n},对于任意点P(i),计算点P(i)到集合D的子集S={p(1), p(2), …, p(i-1), p(i+1), …, p(n)}中所有点之间的距离,距离按照从小到大的顺序排序,假设排序后的距离集合为D={d(1), d(2), …, d(k-1), d(k), d(k+1), …,d(n)},则d(k)就被称为k-距离。也就是说,k-距离是点p(i)到所有点(除了p(i)点)之间距离第k近的距离。对待聚类集合中每个点p(i)都计算k-距离,最后得到所有点的k-距离集合E={e(1), e(2), …, e(n)}。
-
K距离:给定数据集P{p(1),p(2)…p(i)},计算p(i)到集合D的子集S中所有点的距离,按照从小到大的顺序排序,d(k)就被称为k距离。
-
半径e根据距离来设定:找突变点。即根据得到的所有点的k-距离集合E,对集合E进行升序排序后得到k-距离集合E’,需要拟合一条排序后的E’集合中k-距离的变化曲线图,然后绘出曲线,通过观察,将急剧发生变化的位置所对应的k-距离的值,确定为半径Eps的值。
-
MinPoints:称为点的密度,一般取值较小而多次尝试。
1.3 评价
- 优势
- 不需要指定K值(簇的个数)
- 可以处理复杂数据
- 劣势
- 当数据量较大时,要求较大的内存支持,而且I/O消耗也很大。
- 当空间聚类的密度不均匀时、聚类间距差相差较大时,聚类的效果质量就很差。
2 DBSCAN算法实现
2.1 DBSCAN API实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN # DBSCAN API
data = pd.read_csv("data.csv").values
plt.scatter(data[:,0],data[:,1])
plt.show()
model = DBSCAN(eps=1.5,min_samples=4) # 设半径为1.5 Minpoint为4
model.fit(data)
result = model.fit_predict(data)
result
# 可视化 不同颜色表示同簇的点
# 构建点的样式列表
mark = ['or','ob','og','oy','ok','om']
# 输出数据的 索引 以及 数据
for i,d in enumerate(data):
# print(i,d)
# 可视化
plt.plot(d[0],d[1],mark[result[i]])
plt.show()
2.2 比较DBSCAN和K-means的实现效果
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
x1,y1 = datasets.make_circles(n_samples=2000,factor=0.5,noise=0.05) # 构建数据集1
x2,y2 = datasets.make_blobs(n_samples=1000,centers=[[1.2,1.2]],cluster_std=[[0.1]]) # 构建数据集2
x = np.concatenate((x1,x2)) # 数据集1和2叠加
plt.scatter(x[:,0],x[:,1],marker='o')
plt.show()
"""
kmeans聚类:效果不好
"""
from sklearn.cluster import KMeans
y_pred = KMeans(n_clusters=3).fit_predict(x)
plt.scatter(x[:,0],x[:,1],c=y_pred)
plt.show()
"""
DBSCAN聚类:效果不错
"""
from sklearn.cluster import DBSCAN
y_pred = DBSCAN(eps=0.2,min_samples=50).fit_predict(x)
plt.scatter(x[:,0],x[:,1],c=y_pred)
plt.show()