当前位置:   article > 正文

人工智能——DBSCAN密度聚类(Python)_dbscan python

dbscan python

目录

1 概述

1.1 概念

1.2 DBSCAN数据点分类

2 DBSCAN算法流程 

2.1 DBSCAN算法流程:

2.2 举例

3 案例1(Python实现 )

3.1 案例

3.2 Python实现

3.3 结果 

3.4 拓展

4 案例2(Python实现)

4.1 代码

4.2 结果

5 案例3(Python原码实现)

5.1 代码 

5.2 结果 

5.3 数据 

6 参考


1 概述

上一次讲解了人工智能——K-Means聚类算法(Python),这节课分享密度聚类:

1.1 概念

密度聚类,即基于密度的聚类(density-based clustering),此类算法假设聚类结构能通过样本分布的紧密程度确定。前面所讲的都是把距离(欧式距离,闵科夫斯基距离,曼哈顿距离等)作为两个样本或者两个簇之间相似度的评价指标,因此导致了最终聚类结构大都是球状簇或者凸形集合,对任意形状的聚类簇比较吃力,同时对噪声数据不敏感,而基于密度的聚类算法可以发现任意形状的聚类,且对带有噪音点的数据起着重要的作用。

DBSCAN算法 是一种基于密度的聚类算法:
聚类的时候不需要预先指定簇的个数
最终的簇的个数不定

1.2 DBSCAN数据点分类

DBSCAN算法将数据点分为三类:
核心点:在半径Eps内含有超过MinPts数目的点
边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域内
噪音点:既不是核心点也不是边界点的点

DBSCAN算法流程 

2.1 DBSCAN算法流程:

1.将所有点标记为核心点、边界点或噪声点;
2.删除噪声点;
3.为距离在Eps之内的所有核心点之间赋予一条边;
4.每组连通的核心点形成一个簇;
5.将每个边界点指派到一个与之关联的核心点的簇中(哪一个核心点的半径范围之内)。

2.2 举例

有如下13个样本点,使用DBSCAN进行聚类:
(1)取Eps=3,MinPts=3,依据DBSACN对所有点进行聚类(曼哈顿距离)。
             

(2)• 对每个点计算其邻域Eps=3内的点的集合。

         • 集合内点的个数超过MinPts=3的点为核心点

         • 查看剩余点是否在核心点的邻域内,若在,则为边界点,否则为噪声点。
          

(3)将距离不超过Eps=3的点相互连接,构成一个簇,核心点邻域内的点也会被加入到这个簇中。 则下侧形成3个簇。

                

3 案例1(Python实现 )

3.1 案例

数据介绍:
现有大学校园网的日志数据,290条大学生的校园网使用情况数据,数据包
括用户ID,设备的MAC地址,IP地址,开始上网时间,停止上网时间,上
网时长,校园网套餐等。利用已有数据,分析学生上网的模式。
实验目的:
通过DBSCAN聚类,分析学生 上网时间 上网时长 的模式。
实验过程:
使用算法: DBSCAN聚类算法
实现过程:
数据实例:

3.2 Python实现

from sklearn.cluster import DBSCAN
DBSCAN主要参数
(1)eps: 两个样本被看作邻居节点的最大距离
(2)min_samples: 簇的样本数
(3)metric:距离计算方式
例:sklearn.cluster.DBSCAN(eps=0.5, min_samples=5, metric='euclidean')
  1. #*===================1. 建立工程,导入sklearn相关包===========================**
  2. import numpy as np
  3. import sklearn.cluster as skc
  4. from sklearn import metrics
  5. from sklearn.cluster import DBSCAN
  6. import matplotlib.pyplot as plt
  7. #*=================2. 读入数据并进行处理=====================================**
  8. mac2id = dict() #mac2id是一个字典:key是mac地址value是对应mac地址的上网时长以及开始上网时间
  9. onlinetimes = [] #value:对应mac地址的上网时长以及开始上网时间
  10. f = open('TestData.txt', encoding='utf-8')
  11. for line in f:
  12. mac = line.split(',')[2] #读取每条数据中的mac地址
  13. onlinetime = int(line.split(',')[6]) #上网时长
  14. starttime = int(line.split(',')[4].split(' ')[1].split(':')[0]) #开始上网时间
  15. if mac not in mac2id: #mac2id是一个字典:key是mac地址value是对应mac地址的上网时长以及开始上网时间
  16. mac2id[mac] = len(onlinetimes)
  17. onlinetimes.append((starttime, onlinetime))
  18. else:
  19. onlinetimes[mac2id[mac]] = [(starttime, onlinetime)]
  20. real_X = np.array(onlinetimes).reshape((-1, 2))
  21. X = real_X[:, 0:1]
  22. #*==============3上网时间聚类,创建DBSCAN算法实例,并进行训练,获得标签=============**
  23. db = skc.DBSCAN(eps=0.01, min_samples=20).fit(X) # 调 用 DBSCAN 方 法 进 行 训 练 ,labels为每个数据的簇标签
  24. labels = db.labels_
  25. #*=============4. 输出标签,查看结果===========================================**
  26. print('Labels:') #打印数据被记上的标签,计算标签为-1,即噪声数据的比例。
  27. print(labels)
  28. raito = len(labels[labels[:] == -1]) / len(labels)
  29. print('Noise raito:', format(raito, '.2%'))
  30. n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0) #计算簇的个数并打印,评价聚类效果
  31. print('Estimated number of clusters: %d' % n_clusters_)
  32. print("Silhouette Coefficient: %0.3f" % metrics.silhouette_score(X, labels))
  33. for i in range(n_clusters_): #打印各簇标号以及各簇内数据
  34. print('Cluster ', i, ':')
  35. print(list(X[labels == i].flatten()))
  36. #*==========5.画直方图,分析实验结果========================================**
  37. plt.hist(X, 24)
  38. plt.show()

3.3 结果 

  

转换直方图分析
观察:上网时间大多聚集在22:00和23:00

3.4 拓展

数据分布 vs 聚类:

 3-1. 上网时间聚类,创建DBSCAN算法实例,并进行训练,获得标签(上面已经分析过了)

3-2. 上网时长聚类,创建DBSCAN算法实例,并进行训练,获得标签:

 结果:

          

Label表示样本的类别,-1表示DBSCAN划分为噪声。
(1)按照上网时长DBSCAN聚了5类,右图所示,显示了每个聚类的样本数量、聚
类的均值、标准差。
(2)时长聚类效果不如时间的聚类效果明显。

4 案例2(Python实现)

4.1 代码

from sklearn.datasets import make_blobs:聚类数据生成器

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from sklearn import datasets
  4. from sklearn.cluster import DBSCAN
  5. #matplotlib inline
  6. X1, y1=datasets.make_circles(n_samples=5000, factor=.6,
  7. noise=.05)
  8. X2, y2 = datasets.make_blobs(n_samples=1000, n_features=2, centers=[[1.2,1.2]], cluster_std=[[.1]],
  9. random_state=9)
  10. X = np.concatenate((X1, X2)) #矩阵合并
  11. #展示样本数据分布
  12. plt.scatter(X[:, 0], X[:, 1], marker='o')
  13. plt.show()
  14. #eps和min_samples 需要进行调参
  15. y_pred = DBSCAN(eps = 0.1, min_samples = 10).fit_predict(X)
  16. #分类结果
  17. plt.scatter(X[:, 0], X[:, 1], c=y_pred)
  18. plt.show()

4.2 结果

         

h2        

5 案例3(Python原码实现)

5.1 代码 

python中的zip()函数详解

python中的map函数

  1. #*============================导入相关库=====================================**
  2. import numpy as np
  3. import numpy.random as random
  4. from numpy.core.fromnumeric import * #查看矩阵或者数组的维数
  5. import matplotlib.pyplot as plt
  6. #*========================计算两个向量之间的欧式距离========================**
  7. def calDist(X1 , X2 ):
  8. sum = 0
  9. for x1 , x2 in zip(X1 , X2): #转换成浮点型
  10. sum += (x1 - x2) ** 2
  11. return sum ** 0.5
  12. #*==================获取一个点的ε-邻域(记录的是索引)=====================**
  13. def getNeibor(data , dataSet , e):
  14. res = []
  15. for i in range(shape(dataSet)[0]):
  16. if calDist(data , dataSet[i])<e:
  17. res.append(i)
  18. return res
  19. #*===================密度聚类算法=======================================**
  20. def DBSCAN(dataSet , e , minPts):
  21. coreObjs = {}#初始化核心对象集合
  22. C = {}
  23. n = shape(dataSet)[0]
  24. #找出所有核心对象,key是核心对象的indexvalue是ε-邻域中对象的index
  25. for i in range(n):
  26. neibor = getNeibor(dataSet[i] , dataSet , e)
  27. if len(neibor)>=minPts:
  28. coreObjs[i] = neibor
  29. oldCoreObjs = coreObjs.copy()
  30. k = 0#初始化聚类簇数
  31. notAccess = list(range(n))#初始化未访问样本集合(索引)
  32. while len(coreObjs)>0:
  33. OldNotAccess = []
  34. OldNotAccess.extend(notAccess)
  35. cores = coreObjs.keys()
  36. #随机选取一个核心对象
  37. randNum = random.randint(0,len(cores))
  38. cores=list(cores)
  39. core = cores[randNum]
  40. queue = []
  41. queue.append(core)
  42. notAccess.remove(core)
  43. while len(queue)>0:
  44. q = queue[0]
  45. del queue[0]
  46. if q in oldCoreObjs.keys() :
  47. delte = [val for val in oldCoreObjs[q] if val in notAccess]#Δ = N(q)∩Γ
  48. queue.extend(delte)#将Δ中的样本加入队列Q
  49. notAccess = [val for val in notAccess if val not in delte]#Γ = Γ\Δ
  50. k += 1
  51. C[k] = [val for val in OldNotAccess if val not in notAccess]
  52. for x in C[k]:
  53. if x in coreObjs.keys():
  54. del coreObjs[x]
  55. return C
  56. #*=====================预处理数据====================================**
  57. def loadDataSet(filename):
  58. dataSet = []
  59. fr = open(filename)
  60. for line in fr.readlines():
  61. curLine = line.strip().split(',')
  62. fltLine = map(float, curLine)
  63. dataSet.append(list(fltLine))
  64. return dataSet
  65. def draw(C , dataSet):
  66. color = ['r', 'y', 'g', 'b', 'c', 'k', 'm']
  67. for i in C.keys():
  68. X = []
  69. Y = []
  70. datas = C[i]
  71. for j in range(len(datas)):
  72. X.append(dataSet[datas[j]][0])
  73. Y.append(dataSet[datas[j]][1])
  74. plt.scatter(X, Y, marker='o', color=color[i % len(color)], label=i)
  75. plt.legend(loc='upper right')
  76. plt.show()
  77. #*============================主函数===============================**
  78. def main():
  79. dataSet = loadDataSet("密度聚类.csv")
  80. print(dataSet)
  81. C = DBSCAN(dataSet, 0.11, 5)
  82. draw(C, dataSet)
  83. if __name__ == '__main__':
  84. main()

5.2 结果 

        

5.3 数据 

6 参考


————————————————
密度聚类之DBSCAN及Python实现

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/667846
推荐阅读
相关标签
  

闽ICP备14008679号