密度聚类DBSCAN算法代码超详细注释(python版)

密度聚类DBSCAN算法代码超详细注释(python版)

个人对DBSCAN代码的理解

声明:我也不知道这个源代码是谁写的,看了之后自己手动做了注释,如果有侵权,本人会立刻删除。

不足的地方欢迎大家的指正,
先放一张聚类的效果图

代码如下(个人理解)

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
# 核心思想是贪心,k每加1,都会把这一个簇的全部子集都取出来完,才会进行下一个簇+1
def distance(x,y):
    return np.sqrt(np.sum( (x - y) **2 ))

def dbscan(dataset, minPts, eps): # 每个点都有这三个参数
    """

    :param dataset:  数据集
    :param minPts:   半径内的最小点数
    :param eps:      半径
    :return:     返回的是样本的簇的集合
    """
    n,m = dataset.shape #获取数据集的尺寸,其实只用到了n
    """
    注意:,注意这里传入的数据X是ndarray,因为有shape函数,所以这里的dataset也是ndarray格式
    """

    clusters = np.full(n,-1) #  顶一个容器去存储样本的分类,将整个数据的样本集初始化为样本数为n,值为-1的列表
    # 注意:这里初始化类一个cluster的ndarray的容器,用来存放样本分类结果
    #print(clusters)
    k = -1 #将类簇的个数初始化为-1
    for i in range(n): #注意 range(n)是全部的数据集,这里就是遍历数据集
        if clusters[i] != -1: #如果取出来的第i个样本的值不等于-1,则说明已经被聚类分到了某一个类簇
            """
            这里操作的都是clusters这个一维的数组,cluster是ndarray
            """

            continue  #终止当前循环,还是下一个循环
        # 获取邻域内的所有样本点,遍历整个数据集,然后进行对比,这里获得的时dataset的下标
        subdataset = [j for j in range(n) if distance(dataset[j], dataset[i]) <= eps]
        """
        这是个生成式,“生成式”主流的就是list,list中存的时是dataset的下标
        这里用的是dataset,用下标取出dataset中对应的样本的值,算出距离,并且将满足条件的dataset放在
        subdataset中,subdataset是一个list
        """
        #这里生成的是一个列表
        # 注意这一句是生成模型,生成一个list,这里i是外层i,j是整个数据集进行遍历,算出的距离和截断值对比
        # 因为这里用的是for循环,拍成一排的,按照顺序从前到后来,第一个样本点处理过后,在这次循环中就不会再遇到了
        if len(subdataset) < minPts:  #这里是那子集的长度和,半径内最小的样本数进行比较,下雨就终止本次循环开始下一次
            continue
            # 注意到此位置处理的都是,未处被理的点,标记为边界点,或者噪声点(这里并未进行分类)设置别的class
            # 或者将上面的full 写成full((n,2)-1),,不同的类标记不同的情况
        # 建立新簇/上面的if已经排除了,不能满足半径eps内的点个数少于minPts这种情况,所以进入到这里的点都是满足条件的
        k += 1  # 在建了k之后,会把k中的所有点都取完的
        # 这里是把子集(subdataset)内的所有点都标记为k,相当于是给样本赋值
        """
        此处的i还是循环开始时的那个i,相当于是簇的起始点
        """
        clusters[i] = k  #相当于给样本list中对应的第i个样本的属于类簇赋值为k
        """
        这里cluster时ndarray数组,不是list
        """
        # 这里处理的是已经处理过点
        for j in subdataset: #获取到满足要求的子集也就是subdataset
            print(subdataset) # 这里的subdataset是符合条件的元素的下标,
            clusters[j] = k
            """
            子集的所有点都等于k,用list的下标寻址,取出元素赋值为k,也就是聚类的结果
            """
            # 这里怎么再确认,找到的点是被处理过的,因为所有的点都被初始化赋值为了负1(-1),
            # 只要再进入循环的点大于-1,就是已经被处理过的点,注意外围的第一个for循环,只要不等于-1,就不会进入到这个循环中。
            if j>i: # j是在子集中遍历, i是在完整的数据中遍历, j大于i说明j还是没有被处理的
                # 这个是对新的for循环的判断,也是拍成一行进行逐个的来判断,也就是subdataset的数据集中的样本中遍历
                # 这里的新子集subdataset中的数据j到全部的数据集(range(n))中去寻找,然后生成一个新的核心点列表
                sub = [item for item in range(n) if distance(dataset[j],dataset[item])<=eps]
                """
                注意这里的j来自上面的j
                注意这里的dataset[i]是dbscan传进来的参数,传进来的是ndarray类型的数组,所以这里也是ndarray的数组
                """
                #这里sub时一个列表的生成式,意思是遍历数据集中全部的点命名为item,如果j(也就是子集中的点)到item的距离小于半径
                #就把满足这个条件的item点生成一个listsub
                for t in sub: #遍历sub列表
                    if t not in subdataset: # 如果sub列表中的点,不在子集中,则追加上来。
                        subdataset.append(t)
                        """
                        list 才有append
                        这一个append的灵魂在于,append之后,需要经历的是for循环,早晚会再遍历到这个append的值,
                        遍历到之时就会有clusters[j] = k  这一句作为赋值,保证是在类簇K中。
                        """
    print(clusters)
    return clusters
  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值