sklearn.DBSCAN解析

文章目录

  • sklearn版本
  • sklearn.DBSCAN使用实例
  • 实例1 Iris,鸢尾花数据集(UC Irvine Machine Learning Repository)
  • 实例2 RandomData,随机生成的月牙形数据(非凸数据集)
  • sklearn.DBSCAN解析
  • DBSCAN类
  • 构造函数__init__(),调用格式iris_dbscan = DBSCAN(eps = 0.3, min_samples = 5)
  • iris_dbscan.fit(X)
  • dbscan_inner(is_core, neighborhoods, labels)
  • iris_dbscan.fit_predict(X)
  • 参考

sklearn版本

  • scikit-learn 0.23.2

sklearn.DBSCAN使用实例

  • 实例1 Iris,鸢尾花数据集(UC Irvine Machine Learning Repository)

    Iris可以从sklearn包内部导入,常常用作分类的训练数据集。这里为了方便展示聚类效果(二维在平面图中效果明显),选取Iris的前两个维度作为聚类依据。上一篇文章(sklearn.KMeans解析)中,我们已经用KMeans做过这个实验,这里用DBSCAN来做。代码参见Iris_DBSCAN.py。左图为全部数据点,右图为DBSCAN聚类(eps = 0.3, min_samples = 5)结果,不同颜色代表不同簇。参数是经过调整的,以接近KMeans的结果,因为个人认为这个数据集聚类还是KMeans效果略好。
    sklearn.DBSCAN解析_第1张图片sklearn.DBSCAN解析_第2张图片

  • 实例2 RandomData,随机生成的月牙形数据(非凸数据集)

    这个例子体现出了DBSCAN在处理非凸数据集时的优势。代码参见RandomData_DBSCAN.py。最左图为随机生成的月牙形数据点。剩余两张图分别为KMeans聚类(n_cluseters=2)结果和DBSCAN聚类(eps = 0.1, min_samples = 10)结果。
    sklearn.DBSCAN解析_第3张图片sklearn.DBSCAN解析_第4张图片sklearn.DBSCAN解析_第5张图片

sklearn.DBSCAN解析

本节分析sklearn.DBSCAN中的主要函数。

  • DBSCAN类

    导入方法:from sklearn.cluster import DBSCAN
    描述: 构造一个DBSCAN聚类,其函数用于完成聚类。待初始化参数参见构造函数。
    待计算参数(计算完成后,聚类完成):
    self.core_samples_indices		#DBSCAN聚类核心对象在训练数据中的索引
    self.components_				#DBSCAN聚类核心对象
    self.labels_					#训练数据簇标签(训练后,每条数据所属簇)
    
  • 构造函数__init__(),调用格式iris_dbscan = DBSCAN(eps = 0.3, min_samples = 5)

    描述: DBSCAN类构造函数。调用格式中传入两个参数值,其他值取默认。
    主要代码(__init__):

    self.eps = eps						#邻域半径设为0.3
    self.min_samples = min_samples		#邻域样本数量阈值设为5
    self.metric = metric				#样本距离计算标准,取默认'euclidean'
    self.algorithm = algorithm			#样本距离计算算法,取默认'auto',根据self.metric
    									#选择算法,可能是'brute'或'ball_tree'
    
  • iris_dbscan.fit(X)

    描述: DBSCAN类训练函数。
    输入: X-训练数据。返回:self(DBSCAN对象)。
    主要代码:

    #构造计算样本最近邻的模型,传入邻域半径、距离计算标准、距离计算算法等参数
    neighbors_model = NearestNeighbors(radius=self.eps, 
    	algorithm=self.algorithm, metric=self.metric,)
    #传入X训练最近邻模型,若使用'ball_tree'计算距离,会构造ball_tree
    neighbors_model.fit(X)
    #传入X,求出X所有样本在X中邻域半径范围内所有邻居样本的索引,包括样本自己
    neighborhoods = neighbors_model.radius_neighbors(X,)
    #创建记录样本邻域半径范围邻居数量的数组n_neighbors,大小与X样本数量一致
    n_neighbors = np.array([len(neighbors) 
    	for neighbors in neighborhoods])
    #初始化X簇标签,所有样本簇标签暂为-1,-1表示噪音点
    labels = np.full(X.shape[0], -1,)
    #创建标记样本是否是核心对象的数组core_samples,大小与X样本数量一致。如果样本
    #邻域半径范围内邻居数量大于等于self.min_samples,对应项标记为1 
    core_samples = np.asarray(n_neighbors >= self.min_samples,)
    #根据core_samples和neighborhoods,完成DBSCAN聚类,更新labels
    dbscan_inner(core_samples, neighborhoods, labels)
    #得到训练数据X的簇标签
    self.labels_ = labels
    #根据core_samples计算核心对象索引,然后得到核心对象
    self.core_sample_indices_ = np.where(core_samples)[0]
    self.components_ = X[self.core_sample_indices_].copy()
    #返回
    return self
    
  • dbscan_inner(is_core, neighborhoods, labels)

    描述: DBSCAN聚类过程。根据核心对象标记is_core和邻域样本索引neighborhoods,完成聚类,更新簇标签labels
    主要代码:

    #簇号设置为0
    label_num = 0
    #找到剩余样本的第一个没有簇标签的核心对象,形成一个簇;循环结束后,所有簇形
    #成。没有被设置簇号的样本簇标签仍为-1,不属于任何一个簇,视为噪音点。
    for i in range(labels.shape[0]):
    	#如果样本已有簇标签或该样本不是核心对象,不能进入while循环。
        if labels[i] != -1 or not is_core[i]:
            continue
    	#剩余样本中第一个没有簇标签的核心对象首先进入下面的while循环,首先将其簇标签设置为
    	#当前簇号,然后将其邻域半径范围内的、没有簇标签的邻居样本压入栈中。从栈中弹出样本,
    	#继续while循环;若栈中无样本,跳出while。从栈中弹出的样本有两种:1.没有簇标签的核
    	#心对象,首先将其簇标签设置为当前簇号,然后将其邻域半径范围内的、没有簇标签的邻居
    	#样本压入栈中;2.没有簇标签的普通样本,将其簇标签设置为当前簇号。跳出while循环后,
    	#当前簇的所有样本都已经设置好簇号,当前簇形成。
        while True:
    		#没有簇标签
            if labels[i] == -1:
    			#设置簇号
                labels[i] = label_num
    			#是核心对象
                if is_core[i]:
                    neighb = neighborhoods[i]
    				#扩展邻居
                    for i in range(neighb.shape[0]):
                        v = neighb[i]
    					#如果该邻居没有簇标签,压入栈
                        if labels[v] == -1:
                            push(stack, v)
    		#如果栈空,跳出while循环
            if stack.size() == 0:
                break
    		#弹出栈顶样本,继续循环
            i = stack.back()
            stack.pop_back()
    	#簇号+1
        label_num += 1
    
  • iris_dbscan.fit_predict(X)

    描述: DBSCAN类训练、预测函数。导入训练数据X,完成训练后直接返回簇标签。
    返回: self.labels_
    主要代码:

    #调用self.fit(X)
    self.fit(X)
    #返回
    return self.labels_
    

参考

DBSCAN密度聚类算法
作者:刘建平Pinard
用scikit-learn学习DBSCAN聚类
作者:刘建平Pinard
K近邻法(KNN)原理小结
作者:刘建平Pinard
sklearn 源码分析系列:neighbors(2)
作者:Demon的黑与白

时间关系,文章中有很多东西一笔带过,逻辑可能有点小bug。但这部分代码我看得比较细,欢迎批评指正、交流讨论。
还有同系列文章哈哈哈:
sklearn.KMeans解析

你可能感兴趣的:(数据挖掘,数据挖掘,python,聚类算法,聚类)