本人在此就不搬运书上关于密度聚类的理论知识了,仅仅实现密度聚类的模板代码和调用skelarn的密度聚类算法。
有人好奇,为什么有sklearn库了还要自己去实现呢?其实,库的代码是比自己写的高效且容易,但自己实现代码会对自己对算法的理解更上一层楼。

#调用科学计算包与绘图包
import numpy as np
import random
import matplotlib.pyplot as plt
# 获取数据
def loadDataSet(filename):
  dataSet=np.loadtxt(filename,dtype=np.float32,delimiter=',')
  return dataSet
#计算两个向量之间的欧式距离
def calDist(X1 , X2 ):
  sum = 0
  for x1 , x2 in zip(X1 , X2):
    sum += (x1 - x2) ** 2
  return sum ** 0.5
#获取一个点的ε-邻域(记录的是索引)
def getNeibor(data , dataSet , e):
  res = []
  for i in range(dataSet.shape[0]):
    if calDist(data , dataSet[i])<e:
      res.append(i)
  return res
#密度聚类算法
def DBSCAN(dataSet , e , minPts):
  coreObjs = {}#初始化核心对象集合
  C = {}
  n = dataSet.shape[0]
  #找出所有核心对象,key是核心对象的index,value是ε-邻域中对象的index
  for i in range(n):
    neibor = getNeibor(dataSet[i] , dataSet , e)
    if len(neibor)>=minPts:
      coreObjs[i] = neibor
  oldCoreObjs = coreObjs.copy()
  k = 0#初始化聚类簇数
  notAccess = list(range(n))#初始化未访问样本集合(索引)
  while len(coreObjs)>0:
    OldNotAccess = []
    OldNotAccess.extend(notAccess)
    cores = coreObjs.keys()
    #随机选取一个核心对象
    randNum = random.randint(0,len(cores)-1)
    cores=list(cores)
    core = cores[randNum]
    queue = []
    queue.append(core)
    notAccess.remove(core)
    while len(queue)>0:
      q = queue[0]
      del queue[0]
      if q in oldCoreObjs.keys() :
        delte = [val for val in oldCoreObjs[q] if val in notAccess]#Δ = N(q)∩Γ
        queue.extend(delte)#将Δ中的样本加入队列Q
        notAccess = [val for val in notAccess if val not in delte]#Γ = Γ\Δ
    k += 1
    C[k] = [val for val in OldNotAccess if val not in notAccess]
    for x in C[k]:
      if x in coreObjs.keys():
        del coreObjs[x]
  return C
# 代码入口
dataSet = loadDataSet(r"E:\jupyter\sklearn学习\sklearn聚类\DataSet.txt")
print(dataSet)
print(dataSet.shape)
C = DBSCAN(dataSet, 0.11, 5)
draw(C, dataSet)

结果图:

python实现密度聚类(模板代码+sklearn代码)

下面是调用sklearn库的实现

db = skc.DBSCAN(eps=1.5, min_samples=3).fit(dataSet) #DBSCAN聚类方法 还有参数,matric = ""距离计算方法
labels = db.labels_ #和X同一个维度,labels对应索引序号的值 为她所在簇的序号。若簇编号为-1,表示为噪声
print('每个样本的簇标号:')
print(labels)
raito = len(labels[labels[:] == -1]) / len(labels) #计算噪声点个数占总数的比例
print('噪声比:', format(raito, '.2%'))
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0) # 获取分簇的数目
print('分簇的数目: %d' % n_clusters_)
print("轮廓系数: %0.3f" % metrics.silhouette_score(X, labels)) #轮廓系数评价聚类的好坏
for i in range(n_clusters_):
  print('簇 ', i, '的所有样本:')
  one_cluster = X[labels == i]
  print(one_cluster)
  plt.plot(one_cluster[:,0],one_cluster[:,1],'o')
plt.show()
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。