首先确保你在动手写代码之前已经了解什么是聚类分析。
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 # 在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