聚类算法(二):DBSCAN算法

首先确保你在动手写代码之前已经了解什么是聚类分析。

DBSCAN算法----一种基于密度的聚类算法。DBSCAN算法是如何发现簇的呢?


1.首先,给定数据集D中的所有对象都被标记为unvisited

2.随机的选择一个未访问的对象p,标记为visited

3.检查p的e-邻域是否至少包含MinPts个点

4.如果不是则标记为噪声点,否则为p创建一个簇C,并且把p的e-邻域中的所有对象都放到候选集合N中

5.DBSCAN迭代的把N中不属于其它簇的对象添加到C中。在此过程中,对于N中标记为unvisited的对象p‘,DBSCAN把它标记为visited,并检查它的e-邻域对象。

6.如果p’的e-邻域至少有MinPts个对象,则p‘的e-邻域中的对象全部添加到N中

7.DBSCAN继续添加对象到C中,知道C不能再被扩充位置,至此N就空了。此时簇C被生成,于是被输出


源码(Python)

import random
import math
import copy

def DBSCAN(data, e, MinPts):
    visited = []  # 已访问的成员
    C = []   # 一个新的簇C
    cluster = []
    unvisited = copy.deepcopy(data)  # 对所有对象标记为unvisited
    while unvisited != []:  # 如果还有未被探索的点则继续循环
        mark = random.randint(0, len(unvisited)-1)
        p = unvisited[mark]  # 在unvisited中随机选择一个p点
        visited.append(p)  # 标记p点为visited
        unvisited.pop(mark)  #将p从unvisited中pop掉
        N = Naghbor(data, e, p)
        if len(N) >= MinPts:  # 如果邻域中至少有MinPts个对象的话
            C.append(p)  #将p添加到一个新的簇C中
            i = 0
            while i <= len(N)-1:
                pp = N[i]
                if pp in unvisited:  #如果pp未被探索
                    visited.append(pp)  #标记为visited
                    unvisited.pop(unvisited.index(pp))
                    NN = Naghbor(data, e, pp)
                    if len(NN) >= MinPts:  # pp的e邻域至少有MinPts个点
                        for j in range(len(NN)):
                            if NN[j] not in N:
                                N.append(NN[j])  #把这些邻域点都放进N中,记得去重复
                    #如果pp不在任何簇中,将pp添加到簇C中
                    #---------------------------#
                    flag = 0
                    for k in range(len(cluster)):
                        if pp not in cluster[k]:
                            flag += 1
                    if flag == len(cluster):  #如果pp不在任何簇集合中,将pp添加到簇C中
                        C.append(pp)
                    #---------------------------#
                    flag = 0  # flag归0
                    i += 1  # N的标志位+1
                else:
                    i += 1
            if len(C) > 1:
                cluster.append(C)  # 将C添加到簇集合中
            C = []
    return cluster


def Naghbor(data, e, p):  # 计算p点的e邻域点
    N = []
    len_data = len(data)
    for i in range(len_data):
        distance_p = Distance(p, data[i])
        if distance_p<=e and  distance_p!=0:  #待测点在e邻域之内,且不是自身
            N.append(data[i])
    return N

def Distance(point1, point2):  #计算两点欧氏距离
    if point1 == point2:
        return 0
    else:
        dis_x = point2[0] - point1[0]
        dis_y = point2[1] - point1[1]
        dis = math.sqrt(dis_x**2 + dis_y**2)
        return dis

这里面特别注意一点!

刚开始将所有data置为unvisited时,常人都会这样想:

unvisited = data

但是是不对的,应该改成:

unvisited = copy.deepcopy(data)

为什么要这么改呢?请看我下面这篇文章:

http://blog.csdn.net/chixujohnny/article/details/50340213


你可能感兴趣的:(聚类,聚类分析,DBSCAN)