DBSCAN算法简述:
为什么出现DBSCAN算法?

  当大家一说起聚类算法时候,最先想到的估计就是K-MeansMean-Shift算法了。但是,K-Means和Mean-Shift算法是通过距离聚类的方式来进行判别,需要设定类别参数,同时聚类的结果都是球状的簇。如果是非球状的分布结构,那么K-Means算法效果并不好。非球状结构的分布如下:



密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习


  像上述这样的分布结构,如果使用K-Means算法的话,聚类效果将会很差。那么这个时候DBSCAN算法就横空出世来解决这些问题。

  简单点说基于密度的聚类算法(Density-Based Spatial Clustering of Applications with Noise,DBSCAN)是一种基于密度的空间策略来进行聚类。通过初始化邻域半径密度聚类 PYTHON练习 密度聚类算法应用_dbscan_02与最小点集个数密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_03设定,来进行条件判断(核心点、边界点、噪音点等)迭代进行聚类。

DBSCAN算法原理:

  1 首先初始化DBSCAN算法的两个参数:邻域半径与最小点集个数的参数设定;

  2 选择一个初始点,判断是否是核心点,对于每一个核心点:选择一个未处理过的核心点,通过密度可达的原理对样本进行聚类生成簇。

  3 迭代重复以上的步骤直达所有的核心点都处理结束。

推荐一个DBSCAN算法动态显示聚类过程网站:传送门

解释关于DBSCAN算法相关名词定义:



密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_04

Figure 1 核心点与边界点相关解释

密度聚类 PYTHON练习 密度聚类算法应用_sklearn_05邻域与密度聚类 PYTHON练习 密度聚类算法应用_聚类算法_06

密度聚类 PYTHON练习 密度聚类算法应用_dbscan_02代表判断该点是不是核心点的密度半径,密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_08为在判断该点为中心,半径为密度聚类 PYTHON练习 密度聚类算法应用_dbscan_02的点集个数判断指标。

核心点:

密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_10同时密度聚类 PYTHON练习 密度聚类算法应用_dbscan_11时候,那么以上图红色的小方块为例:以它为圆心,半径为3的圆区域发现它的点数(密度聚类 PYTHON练习 密度聚类算法应用_dbscan_12)大于3,即红色小方块为核心点

边界点:

  我们发现红色如果以红色小方块邻域的三个蓝色圆心,继续以它们为中心,半径为3的区域内并没有超过三个点,但是它们在红色小方块为核心点的区域内,那么它们属于边界点

噪音点:

  噪音点就是既不是核心点也不是边界点的第三种情况。

下面在解释密度直达、密度可达、密度相连的相关定义,首先看下示意图2如下:



密度聚类 PYTHON练习 密度聚类算法应用_聚类算法_13

Figure 2 密度直达 密度可达 密度相连示意图 图片来自于知乎作者:传送门

密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14为边缘点,密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15为核心点,密度聚类 PYTHON练习 密度聚类算法应用_dbscan_16为噪音点。

密度直达:

密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14是由样本点密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15对于参数密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_19密度直达,满足条件为密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15是核心点同时密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14点在以密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15为核心点的圆区域内。显示示意图(b)

密度可达:

密度聚类 PYTHON练习 密度聚类算法应用_聚类算法_23(其中密度聚类 PYTHON练习 密度聚类算法应用_聚类_24, 密度聚类 PYTHON练习 密度聚类算法应用_dbscan_25)使得密度聚类 PYTHON练习 密度聚类算法应用_聚类_26可由样本点密度聚类 PYTHON练习 密度聚类算法应用_sklearn_27密度直达,那么样本点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14可由样本点密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15密度可达。示意图(c)

密度相连:

密度聚类 PYTHON练习 密度聚类算法应用_dbscan_30对于样本点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14是密度可达的,同时样本点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_30对于样本点密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15也是密度可达的,那么我们称作样本点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14与样本点密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15是密度相连的。示意图(d)

概念解释小结:

  密度直达:核心点密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15邻域内存在边缘点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14,那么我们称作样本点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14是由样本点密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15密度直达的。(密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15是相邻的);

  密度可达:样本点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14是由一系列核心点传递到核心点密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15的,那么我们称作样本点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14是由样本点密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15密度可达。(密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15具有传递性);

  密度相连:就是存在样本点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_30对样本点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14密度可达,同时又对样本点密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15密度可达,那么样本点密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14与样本点密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15密度相连。(某一个中间点到密度聚类 PYTHON练习 密度聚类算法应用_dbscan_14密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_15密度可达单方向传递性);

DBSCAN算法优缺点:

优点:

  较其它聚类策略,例如K-Means只能适用于凸数据集,DBSCAN算法可以对任意形状的稠密数据集有效的聚类。

  DBSCAN聚类对异常点抗干扰性强,即对受孤立的点影响很小,即对数据集中的异常点不明感。

缺点:

  如果样本集的密度不均匀,聚类间距相差很大时,聚类质量较差,所以不适合使用DBSCAN算法。

  针对大数据样本集,聚类收敛时间较长(目前改进是通过KD树快速搜索或者对球树规模限制).

密度聚类 PYTHON练习 密度聚类算法应用_dbscan_02,邻域样本数阈值密度聚类 PYTHON练习 密度聚类算法应用_密度聚类 PYTHON练习_03,这两个参数设置都会对聚类效果影响很大。参数建议根据数据量和具体应用场景进行调节与设定。

DBSCAN算法Python代码实践:
# -*- coding:utf-8 -*-
import numpy as np

from sklearn.cluster import DBSCAN
from sklearn import metrics
from sklearn.datasets.samples_generator import make_blobs
from sklearn.preprocessing import StandardScaler

# Generate sample data
centers = [[1, 1], [-1, -1], [1, -1]]
X, labels_true = make_blobs(n_samples=750, centers=centers,
                            cluster_std=0.4, random_state=0)

X = StandardScaler().fit_transform(X)

# Compute DBSCAN Algorithm
db = DBSCAN(eps=0.3, min_samples=10).fit(X)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
labels = db.labels_

# Number of clusters in labels, ignoring noise if present
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
n_noise_ = list(labels).count(-1)

print('Estimanted number of cluster: %d' % n_clusters_)
print('Estimated number of noise points: %d' % n_noise_)
print('Homogeneity: %0.3f' % metrics.homogeneity_score(labels_true, labels))
print('Completeness: %0.3f' % metrics.completeness_score(labels_true, labels))
print('V-measure: 0.3f' % metrics.v_measure_score(labels_true, labels))
print('Adjusted Rand Index: 0.3f'
      % metrics.adjusted_rand_score(labels_true, labels))

print('Adjusted Mutual Information: %0.3f'
      % metrics.adjusted_mutual_info_score(labels_true, labels))

print('Silhouette Coefficient: %0.3f' % metrics.silhouette_score(X, labels))

# plot result
import matplotlib.pyplot as plt

# Black removed and is used for noise instead
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
          for each in np.linspace(0, 1, len(unique_labels))]

for k, col in zip(unique_labels, colors):
    if k == -1:
        # Black used for noise
        col = [0, 0, 0, 1]

    class_member_mask = (labels == k)

    xy = X[class_member_mask & core_samples_mask]

    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=14)

    xy = X[class_member_mask & ~core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=6)

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()
聚类实验结果



密度聚类 PYTHON练习 密度聚类算法应用_dbscan_57