当前位置:   article > 正文

【聚类】一种自适应Eps和Minpts的DBSCAN方法(python实现)_自适应dbscan

自适应dbscan

一、算法来源

1、DBSCAN算法原型

       这个算法原型非常简单,有很多博主都有写,大家自己去看看就好了,也不用花太多时间,顶多十分钟就能了解个大概。

2、自适应Eps和Minpts参数

       由于该算法对Eps和Minpts参数十分敏感,所以如何确定这两个参数对于DBSCAN来说是很重要的一步,这篇博文是基于李文杰老师的论文《自适应确定DBSCAN算法参数的算法研究》,通过这篇论文,输入数据集即可大致确定这两个参数,从而可以直接在DBSCAN中应用。

二、大致思想

        参考论文中提出的,根据数据集提取出Eps候选项(按从小到大排列),然后再提取出Minpts候选项,随后用这些候选项尝试使用DBSCAN算法进行聚类,如果连续的候选项聚类的类别数目相同,那么选择Eps相对较大的那个最为最终参数输入到DBSCAN算法中去。

        论文中认为如果连续3个Eps候选项聚类的类别数目相同,那么可以认为数据集在这些参数下逐渐收敛,但是我觉得具体最好看图像是否收敛,所以我就简单的在程序里将聚类数目打印出来,读者可以自行选择聚利时使用的Eps和Minpts参数。

三、程序介绍

0、头文件import

  1. import math
  2. import copy
  3. import numpy as np
  4. from sklearn.cluster import DBSCAN

1、首先定义聚类的“距离”,这里将欧式距离作为聚类距离

  1. def dist(a,b):
  2. """
  3. :param a: 样本点
  4. :param b: 样本点
  5. :return: 两个样本点之间的欧式距离
  6. """
  7. return math.sqrt(math.pow(a[0]-b[0],2) + math.pow(a[1]-b[1],2))

2、根据论文求解Eps和Minpts候选项列表

  1. def returnDk(matrix,k):
  2. """
  3. :param matrix: 距离矩阵
  4. :param k: 第k最近
  5. :return: 第k最近距离集合
  6. """
  7. Dk = []
  8. for i in range(len(matrix)):
  9. Dk.append(matrix[i][k])
  10. return Dk
  11. def returnDkAverage(Dk):
  12. """
  13. :param Dk: k-最近距离集合
  14. :return: Dk的平均值
  15. """
  16. sum = 0
  17. for i in range(len(Dk)):
  18. sum = sum + Dk[i]
  19. return sum/len(Dk)
  20. def CalculateDistMatrix(dataset):
  21. """
  22. :param dataset: 数据集
  23. :return: 距离矩阵
  24. """
  25. DistMatrix = [[0 for j in range(len(dataset))] for i in range(len(dataset))]
  26. for i in range(len(dataset)):
  27. for j in range(len(dataset)):
  28. DistMatrix[i][j] = dist(dataset[i], dataset[j])
  29. return DistMatrix
  30. def returnEpsCandidate(dataSet):
  31. """
  32. :param dataSet: 数据集
  33. :return: eps候选集合
  34. """
  35. DistMatrix = CalculateDistMatrix(dataSet)
  36. tmp_matrix = copy.deepcopy(DistMatrix)
  37. for i in range(len(tmp_matrix)):
  38. tmp_matrix[i].sort()
  39. EpsCandidate = []
  40. for k in range(1,len(dataSet)):
  41. Dk = returnDk(tmp_matrix,k)
  42. DkAverage = returnDkAverage(Dk)
  43. EpsCandidate.append(DkAverage)
  44. return EpsCandidate
  45. def returnMinptsCandidate(DistMatrix,EpsCandidate):
  46. """
  47. :param DistMatrix: 距离矩阵
  48. :param EpsCandidate: Eps候选列表
  49. :return: Minpts候选列表
  50. """
  51. MinptsCandidate = []
  52. for k in range(len(EpsCandidate)):
  53. tmp_eps = EpsCandidate[k]
  54. tmp_count = 0
  55. for i in range(len(DistMatrix)):
  56. for j in range(len(DistMatrix[i])):
  57. if DistMatrix[i][j] <= tmp_eps:
  58. tmp_count = tmp_count + 1
  59. MinptsCandidate.append(tmp_count/len(dataSet))
  60. return MinptsCandidate

3、求解出聚类类别数列表

  1. def returnClusterNumberList(dataset,EpsCandidate,MinptsCandidate):
  2. """
  3. :param dataset: 数据集
  4. :param EpsCandidate: Eps候选列表
  5. :param MinptsCandidate: Minpts候选列表
  6. :return: 聚类数量列表
  7. """
  8. np_dataset = np.array(dataset) #将dataset转换成numpy_array的形式
  9. ClusterNumberList = []
  10. for i in range(len(EpsCandidate)):
  11. clustering = DBSCAN(eps= EpsCandidate[i],min_samples= MinptsCandidate[i]).fit(np_dataset)
  12. num_clustering = max(clustering.labels_)
  13. ClusterNumberList.append(num_clustering)
  14. return ClusterNumberList

 四、程序(完全版)

  1. import math
  2. import copy
  3. import numpy as np
  4. from sklearn.cluster import DBSCAN
  5. def loadDataSet(fileName, splitChar='\t'):
  6. """
  7. 输入:文件名
  8. 输出:数据集
  9. 描述:从文件读入数据集
  10. """
  11. dataSet = []
  12. with open(fileName) as fr:
  13. for line in fr.readlines():
  14. curline = line.strip().split(splitChar)
  15. fltline = list(map(float, curline))
  16. dataSet.append(fltline)
  17. return dataSet
  18. def dist(a,b):
  19. """
  20. :param a: 样本点
  21. :param b: 样本点
  22. :return: 两个样本点之间的欧式距离
  23. """
  24. return math.sqrt(math.pow(a[0]-b[0],2) + math.pow(a[1]-b[1],2))
  25. def returnDk(matrix,k):
  26. """
  27. :param matrix: 距离矩阵
  28. :param k: 第k最近
  29. :return: 第k最近距离集合
  30. """
  31. Dk = []
  32. for i in range(len(matrix)):
  33. Dk.append(matrix[i][k])
  34. return Dk
  35. def returnDkAverage(Dk):
  36. """
  37. :param Dk: k-最近距离集合
  38. :return: Dk的平均值
  39. """
  40. sum = 0
  41. for i in range(len(Dk)):
  42. sum = sum + Dk[i]
  43. return sum/len(Dk)
  44. def CalculateDistMatrix(dataset):
  45. """
  46. :param dataset: 数据集
  47. :return: 距离矩阵
  48. """
  49. DistMatrix = [[0 for j in range(len(dataset))] for i in range(len(dataset))]
  50. for i in range(len(dataset)):
  51. for j in range(len(dataset)):
  52. DistMatrix[i][j] = dist(dataset[i], dataset[j])
  53. return DistMatrix
  54. def returnEpsCandidate(dataSet):
  55. """
  56. :param dataSet: 数据集
  57. :return: eps候选集合
  58. """
  59. DistMatrix = CalculateDistMatrix(dataSet)
  60. tmp_matrix = copy.deepcopy(DistMatrix)
  61. for i in range(len(tmp_matrix)):
  62. tmp_matrix[i].sort()
  63. EpsCandidate = []
  64. for k in range(1,len(dataSet)):
  65. Dk = returnDk(tmp_matrix,k)
  66. DkAverage = returnDkAverage(Dk)
  67. EpsCandidate.append(DkAverage)
  68. return EpsCandidate
  69. def returnMinptsCandidate(DistMatrix,EpsCandidate):
  70. """
  71. :param DistMatrix: 距离矩阵
  72. :param EpsCandidate: Eps候选列表
  73. :return: Minpts候选列表
  74. """
  75. MinptsCandidate = []
  76. for k in range(len(EpsCandidate)):
  77. tmp_eps = EpsCandidate[k]
  78. tmp_count = 0
  79. for i in range(len(DistMatrix)):
  80. for j in range(len(DistMatrix[i])):
  81. if DistMatrix[i][j] <= tmp_eps:
  82. tmp_count = tmp_count + 1
  83. MinptsCandidate.append(tmp_count/len(dataSet))
  84. return MinptsCandidate
  85. def returnClusterNumberList(dataset,EpsCandidate,MinptsCandidate):
  86. """
  87. :param dataset: 数据集
  88. :param EpsCandidate: Eps候选列表
  89. :param MinptsCandidate: Minpts候选列表
  90. :return: 聚类数量列表
  91. """
  92. np_dataset = np.array(dataset) #将dataset转换成numpy_array的形式
  93. ClusterNumberList = []
  94. for i in range(len(EpsCandidate)):
  95. clustering = DBSCAN(eps= EpsCandidate[i],min_samples= MinptsCandidate[i]).fit(np_dataset)
  96. num_clustering = max(clustering.labels_)
  97. ClusterNumberList.append(num_clustering)
  98. return ClusterNumberList
  99. if __name__ == '__main__':
  100. dataSet = loadDataSet('788points.txt', splitChar=',')
  101. EpsCandidate = returnEpsCandidate(dataSet)
  102. DistMatrix = CalculateDistMatrix(dataSet)
  103. MinptsCandidate = returnMinptsCandidate(DistMatrix,EpsCandidate)
  104. ClusterNumberList = returnClusterNumberList(dataSet,EpsCandidate,MinptsCandidate)
  105. print(EpsCandidate)
  106. print(MinptsCandidate)
  107. print('cluster number list is')
  108. print(ClusterNumberList)

五、相关文件

我会将txt文件和程序放在以下位置:

https://download.csdn.net/download/liyihao17/11125093

https://download.csdn.net/download/liyihao17/11125098

另外我也在github上放了

https://github.com/liyihao17/KANN-DBSCAN

需要的读者可以自行下载,相关论文读者可以自行去知网搜索下载

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

闽ICP备14008679号