DBSCAN聚类

star2017 1年前 ⋅ 796 阅读

DBSCAN聚类算法

基本概念:基于密度的带有噪声点的聚类算法(Desity-Based Spatial Clustering of Applications with Noise),简称DBSCAN,又叫密度聚类。

核心对象:若某个点得密度达到算法设定的阈值,则这个点称为核心对象(即r邻域内点的数量不小于minPts)

[公式] 邻域的距离阈值:设定的半径r

直接密度可达:若某点p在点q的r邻域内,且q是核心点,则p-q密度可达

密度可达:若有一个点的序列q0、q1、…qK,对任意qi-qi是直接密度可达的,则称从q0到qK密度可达,这实际上是直接密度可达的“传播”。

密度相连:若从某核心点p出发,点q和点k都是密度可达的,则称点q和点k使密度相连的

边界点:属于某一个类的非核心点,不能发展下线了

噪声点:不属于任何一个类簇的点,从任何一个核心点出发都是密度不可达的(所以DBSCAN聚类算法常用于异常值或者离群点得检测)

DBSCAN聚类算法的实现过程如下图:

DBSCAN聚类

对于奇葩的簇,K-Means是无法正常聚类的,而DBSCAN完全没有问题

DBSCAN聚类

优点:

1、与K-Means相比,不需要手动确定簇的个数K,但需要确定邻域r和密度阈值minPts

2、能发现任意形状的簇

3、能有效处理噪声点(邻域r和密度阈值minPts参数的设置可以影响噪声点)

缺点:

1、当数据量大时,处理速度慢,消耗大

2、当空间聚类的密度不均匀、聚类间距差相差很大时参数密度阈值minPts和邻域r参数选取困难

3、对于高维数据,容易产生“维数灾难”(聚类算法基于欧式距离的通病)

sklearn中的DBSCAN

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

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) 
# StandardScaler 标准化处理。且是针对每一个特征维度来做的,而不是针对样本。
# 调用密度聚类  DBSCAN
db = DBSCAN(eps=0.3, min_samples=10).fit(X)
# print(db.labels_)  # db.labels_为所有样本的聚类索引,没有聚类索引为-1
# print(db.core_sample_indices_) # 所有核心样本的索引

core_samples_mask = np.zeros_like(db.labels_, dtype=bool)  # 设置一个样本个数长度的全false向量
core_samples_mask[db.core_sample_indices_] = True #将核心样本部分设置为true
labels = db.labels_

n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
# 获取聚类个数。(聚类结果中-1表示没有聚类为离散点)

# 模型评估
print('估计的聚类个数为: %d' % n_clusters_)
print("同质性: %0.3f" % metrics.homogeneity_score(labels_true, labels))  # 每个群集只包含单个类的成员。
print("完整性: %0.3f" % metrics.completeness_score(labels_true, labels))  # 给定类的所有成员都分配给同一个群集。
print("V-measure: %0.3f" % metrics.v_measure_score(labels_true, labels))  # 同质性和完整性的调和平均
print("调整兰德指数: %0.3f" % metrics.adjusted_rand_score(labels_true, labels))
print("调整互信息: %0.3f" % metrics.adjusted_mutual_info_score(labels_true, labels))
print("轮廓系数: %0.3f" % metrics.silhouette_score(X, labels))

估计的聚类个数为: 3
同质性: 0.953
完整性: 0.883
V-measure: 0.917
调整兰德指数: 0.952
调整互信息: 0.883
轮廓系数: 0.626

# Plot result
import matplotlib.pyplot as plt
import seaborn as sns 
%matplotlib inline
sns.set(font='SimHei',style='ticks')

unique_labels = set(labels)
colors = [plt.cm.Spectral(each) for each in np.linspace(0, 1, len(unique_labels))]

plt.figure(figsize=(10,6))
for k, col in zip(unique_labels, colors):
    if k == -1:  # 聚类结果为-1的样本为离散点
        # 使用黑色绘制离散点
        col = [0, 0, 0, 1]

    class_member_mask = (labels == k)  # 将所有属于该聚类的样本位置置为true

    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_)
sns.despine()
DBSCAN聚类

 

本文来自zhihu,观点不代表一起大数据-技术文章心得立场,如若转载,请注明出处:https://zhuanlan.zhihu.com/p/54833132

更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: