DBSCAN具有噪声的基于密度的聚类方法

 

  1. 简介
    1. 聚类:将原始数据分类 ( 数据集 -> 聚类算法 -> 数据分组 )
    2. 目的:希望将数据根据特征的密度找相似性,分为指定或者若干数据组
  2. 使用场景:
    1. 简单的如将同颜色的球分类,或将一个班的成绩分类为文科科目好的学生和理科科目好的学生
    2. 复杂的,图像特征识别等
  3. 概念解释:
    1. 主要有两个参数进行调节dist,minpoints。dist指点与点之间的距离,表示你想把密度多大的点聚合在一起。minpoints指符合上述密度的点至少有多少个。图片来源((五十)通俗易懂理解——DBSCAN聚类算法 - 知乎 (zhihu.com)
    2.  

       密度可达:除N点外都可达,密度直通:ABC

    3. 特点
      1.   本算法是无监督学习
      2.   

         

         

  4. 代码实现和解释:
    1. 算法代码
      #-*- coding:utf-8 -*-
      import math
      import numpy as np
      import pylab as pl
       #数据集:每三个是一组分别是西瓜的编号,密度,含糖量
      data = """
      1,0.697,0.46,2,0.774,0.376,3,0.634,0.264,4,0.608,0.318,5,0.556,0.215,
      6,0.403,0.237,7,0.481,0.149,8,0.437,0.211,9,0.666,0.091,10,0.243,0.267,
      11,0.245,0.057,12,0.343,0.099,13,0.639,0.161,14,0.657,0.198,15,0.36,0.37,
      16,0.593,0.042,17,0.719,0.103,18,0.359,0.188,19,0.339,0.241,20,0.282,0.257,
      21,0.748,0.232,22,0.714,0.346,23,0.483,0.312,24,0.478,0.437,25,0.525,0.369,
      26,0.751,0.489,27,0.532,0.472,28,0.473,0.376,29,0.725,0.445,30,0.446,0.459"""
      #数据处理 dataset是30个样本(密度,含糖量)的列表
      a = data.split(',')
      dataset = [(float(a[i]), float(a[i+1])) for i in range(1, len(a)-1, 3)]
      #计算欧几里得距离,a,b分别为两个元组
      def dist(a, b):
        return math.sqrt(math.pow(a[0]-b[0], 2)+math.pow(a[1]-b[1], 2))
      #算法模型
      def DBSCAN(D, e, Minpts):
        #初始化核心对象集合T,聚类个数k,聚类集合C, 未访问集合P,
        T = set(); k = 0; C = []; P = set(D)
        for d in D:
          if len([ i for i in D if dist(d, i) <= e]) >= Minpts:
            T.add(d)
        #开始聚类
        while len(T):
          P_old = P
          o = list(T)[np.random.randint(0, len(T))]
          P = P - set(o)
          Q = []; Q.append(o)
          while len(Q):
            q = Q[0]
            Nq = [i for i in D if dist(q, i) <= e]
            if len(Nq) >= Minpts:
              S = P & set(Nq)
              Q += (list(S))
              P = P - S
            Q.remove(q)
          k += 1
          Ck = list(P_old - P)
          T = T - set(Ck)
          C.append(Ck)
        return C
      #画图
      def draw(C):
        colValue = ['r', 'y', 'g', 'b', 'c', 'k', 'm']
        for i in range(len(C)):
          coo_X = []  #x坐标列表
          coo_Y = []  #y坐标列表
          for j in range(len(C[i])):
            coo_X.append(C[i][j][0])
            coo_Y.append(C[i][j][1])
          pl.scatter(coo_X, coo_Y, marker='x', color=colValue[i%len(colValue)], label=i)
        pl.legend(loc='upper right')
        pl.show()
      C = DBSCAN(dataset, 0.11, 5)
      draw(C)
      

        

       

       

       

    2. 流程图载自(DBSCAN算法原理 - cheney-pro - 博客园 (cnblogs.com)
      1.   

         

         

    3. 调用函数代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
%matplotlib inline

#生成数据
X=np.empty((100,2))
X[:,0]=np.random.uniform(0.,100.,size=100)
X[:,1]=0.75*X[:,0]+3+np.random.normal(0,10,size=100)
plt.scatter(X[:,0],X[:,1])
plt.show()
df=pd.DataFrame(X,columns=['feature1','feature2'])
df.plot.scatter('feature1','feature2')
print(df)

#调用DBSCAN接口完成聚类
from sklearn.cluster import dbscan
# eps为邻域半径,min_samples为最少点数目
core_samples,cluster_ids = dbscan(X, eps = 10, min_samples=3) 
df = pd.DataFrame(np.c_[X,cluster_ids],columns = ['feature1','feature2','cluster_id'])
df.plot.scatter('feature1','feature2', s = 100,
    c = list(df['cluster_id']),cmap = 'rainbow',colorbar = False,
    alpha = 0.6,title = 'DBSCAN cluster result')

 

 

posted @ 2022-10-12 09:42  困到很想醒  阅读(122)  评论(0编辑  收藏  举报