DBSCAN是一种基于密度的聚类算法
- 首先,DBSCAN算法会以任何尚未访问过的任意起始数据点为核心点,并对该核心点进行扩充。这时我们给定一个半径/距离ε,任何和核心点的距离小于ε的点都是它的相邻点。
- 如果核心点附近有足够数量的点,则开始聚类,且选中的核心点会成为该聚类的第一个点。如果附近的点不够,那算法会把它标记为噪声(之后这个噪声可能会成为簇中的一部分)。在这两种情形下,选中的点都会被标记为“已访问”。
- 一旦聚类开始,核心点的相邻点,或者说以该点出发的所有密度相连的数据点(注意是密度相连)会被划分进同一聚类。然后我们再把这些新点作为核心点,向周围拓展ε,并把符合条件的点继续纳入这个聚类中。
- 重复步骤2和3,直到附近没有可以扩充的数据点为止,即簇的ε邻域内所有点都已被标记为“已访问”。
- 一旦我们完成了这个集群,算法又会开始检索未访问过的点,并发现更多的聚类和噪声。一旦数据检索完毕,每个点都被标记为属于一个聚类或是噪声。
与其他聚类算法相比,DBSCAN有一些很大的优势。首先,它不需要输入要划分的聚类个数。其次,即使数据点非常不同,它也会将它们纳入聚类中,DBSCAN能将异常值识别为噪声,这就意味着它可以在需要时输入过滤噪声的参数。第三,它对聚类的形状没有偏倚,可以找到任意大小和形状的簇。
DBSCAN的主要缺点是,当聚类的密度不同时,DBSCAN的性能会不如其他算法。这是因为当密度变化时,用于识别邻近点的距离阈值ε和核心点的设置会随着聚类发生变化。而这在高维数据中会特别明显,因为届时我们会很难估计ε。
# encoding=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
import matplotlib.pyplot as pltclass DBScan (object):#封装DBscan算法def __init__(self, p, l_stauts): self.point = pself.labels_stats = l_stautsself.db = DBSCAN(eps=0.2, min_samples=10).fit(self.point)def draw(self): coreSamplesMask = np.zeros_like(self.db.labels_, dtype=bool)coreSamplesMask[self.db.core_sample_indices_] = Truelabels = self.db.labels_nclusters = denoise(labels)# 输出模型评估参数,包括估计的集群数量、均匀度、完整性、V度量、# 调整后的兰德指数、调整后的互信息量、轮廓系数print('Estimated number of clusters: %d' % nclusters)print("Homogeneity: %0.3f" % metrics.homogeneity_score(self.labels_stats, labels))print("Completeness: %0.3f" % metrics.completeness_score(self.labels_stats, labels))print("V-measure: %0.3f" % metrics.v_measure_score(self.labels_stats, labels))print("Adjusted Rand Index: %0.3f"% metrics.adjusted_rand_score(self.labels_stats, labels))print("Adjusted Mutual Information: %0.3f"% metrics.adjusted_mutual_info_score(self.labels_stats, labels))print("Silhouette Coefficient: %0.3f"% metrics.silhouette_score(self.point, labels))# 绘制结果# 黑色被移除,并被标记为噪音。unique_labels = set(labels)colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))for k, col in zip(unique_labels, colors):if k == -1:# 黑色用于噪声col = 'k'classMemberMask = (labels == k)# 画出分类点集xy = self.point[classMemberMask & coreSamplesMask]plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col,markeredgecolor='k', markersize=6)# 画出噪声点集xy = self.point[classMemberMask & ~coreSamplesMask]plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col,markeredgecolor='k', markersize=3)# 加标题,显示分类数plt.title('Estimated number of clusters: %d' % nclusters)plt.show()def denoise (labels): # 标签中的簇数,忽略噪声(如果存在)clusters = len(set(labels)) - (1 if -1 in labels else 0)return clustersdef standar_scaler(points): p = StandardScaler().fit_transform(points)return pif __name__ == "__main__":#test class dbScancenters = [[1, 1], [-1, -1], [-1, 1], [1, -1]]point, labelsTrue = make_blobs(n_samples=2000, centers=centers, cluster_std=0.4,random_state=0)point = standar_scaler(point)db = DBScan(point, labelsTrue)db.draw()
sklearn.cluster.DBSCAN
class sklearn.cluster.DBSCAN(eps=0.5, *,min_samples=5, metric='euclidean', metric_params=None, algorithm='auto', leaf_size=30, p=None, n_jobs=None)
https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html