手写算法-python代码实现DBSCAN
原理解析
上篇文章我们优化了Kmeans聚类算法,最后留下一个问题:
Kmeans只适合处理凸样本集,不适合处理非凸样本集,这个问题,怎么解决?
链接: 手写算法-python代码实现Kmeans++以及优化
生成演示数据集:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_circles,make_blobs,make_moons
#演示数据集
x2,y2 = make_moons(n_samples=500,noise = 0.1,random_state=2020)
plt.scatter(x2[:,0],x2[:,1],marker='o')
plt.show()
从图像上看,这个数据集,我们适合聚类成2个类别,下面我们用sklearn里面的Kmeans算法来演示一下:
from sklearn.cluster import KMeans
Kmeans = KMeans(n_clusters=2)
y_preds = Kmeans.fit_predict(x2)
plt.scatter(x2[:,0],x2[:,1],c=y_preds,marker='o')
plt.show()
然后聚类结果是这样,对于这种非凸样本集,该怎么处理呢?
我们一般用DBSCAN聚类算法。
DBSCAN(Density-Based Spatial Clustering of Applications with Noise),
直译就是:具有噪声的基于密度的聚类方法,2个特点:
1、可以找出噪声数据;
2、基于密度的聚类算法(Kmeans是基于划分);
原理解析:
下面引用刘建平博士的一段话:
DBSCAN是基于一组邻域来描述样本集的紧密程度的,参数(ϵ, MinPts)用来描述邻域的样本分布紧密程度。其中,ϵ描述了某一样本的邻域距离阈值,MinPts描述了某一样本的距离为ϵ的邻域中样本个数的阈值。
假设我的样本集是D=(x1,x2,…,xm),则DBSCAN具体的密度描述定义如下:
1) ϵ-邻域:对于xj∈D,其ϵ-邻域包含样本集D中与xj的距离不大于ϵ的子样本集,即Nϵ(xj)={xi∈D|distance(xi,xj)≤ϵ},
这个子样本集的个数记为|Nϵ(xj)|2) 核心对象:对于任一样本xj∈D,如果其ϵ-邻域对应的Nϵ(xj)至少包含MinPts个样本,即如果|Nϵ(xj)|≥MinPts,则xj是核心对象。
3)密度直达