您的位置:首页 > 编程语言 > Python开发

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

2020-02-17 03:55 323 查看

密度聚类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
  • 点赞 1
  • 收藏
  • 分享
  • 文章举报
德鲁伊的治疗 发布了1 篇原创文章 · 获赞 1 · 访问量 44 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: