醋醋百科网

Good Luck To You!

python密度聚类

前两天讲解了K-mean聚类和层次聚类的原理和实现方法,今天讲解经典聚类算法的最后一个那就是密度聚类。在此之前再给同学们补充一下昨天的层次聚类机器学习包调用的代码:

from sklearn.cluster import AgglomerativeClustering#导入层次聚类库
cluster = AgglomerativeClustering(n_clusters=4, affinity='euclidean', linkage='ward') #聚类数为4 
cluster.fit_predict(data_scaled)#训练数据

密度聚类的基本思想

密度顾名思义就是在固定的半径内存在的个体数,而聚类就是把符合这条件的个体结合起来形成一个族。下面的几个概念,可以帮助同学们理解聚类算法的操作过程。

核心对象:假定给定的最少样本量个体数为5,那么如果某点(Q)的半径邻域内至少包含5个样本,则该点(Q)为核心对象

异常点:不属于任何一个簇的样本点。(噪音点)

下面给同学讲讲密度聚类的基本步骤:

首先要确定半径大小,给定聚类的最小个数。数据中抽出一个未经处理的点Q,计算每个点到点Q的距离,如果距离小于给定的半径,那么这个可以说是Q点与该点可以组成簇,如果这个半径内的个数大于聚类的最小个数,那么可以把Q点成为核心对象,其他点为点Q的半径领域内的点。寻找下个点,直到每个点都被遍历一遍。把不属于任何一个簇的点称为异常点。

由上可知,最重要的就是半径的设定和个数的确定。这里就有同学要问了,怎样确定才是最合理的呢!这个要看具体数据具体分析,或者多尝试不同设定取最好效果。同样密度聚类所需的距离算法依旧是欧式距离。

代码部分:

import matplotlib.pyplot as plt
import pandas as pd
import random

def calDist(X1 , X2):
    sum = 0
    for x1 , x2 in zip(X1 , X2):
        sum += (x1 - x2) ** 2
    return sum ** 0.5

def getbor(data , dataSet , e):
    res = []
    date=pd.DataFrame(dataSet)
    for i in range(date.shape[0]):
        if calDist(data , dataSet[i])<e:#计算一个点到其他带点的欧式距离,如果小于半径则加入一个类中
            res.append(i)
    return res

def DBSCAN(dataSet , e , minPts):
    Objs = {}#初始化核心对象集合
    C = {}#每个类的标号和个数
    data=pd.DataFrame(dataSet)
    n = data.shape[0]
    #找出所有核心对象,key是核心对象的index,value是ε-邻域中对象的index
    for i in range(n):
        neibor = getbor(dataSet[i] , dataSet , e)#判断该点
        if len(neibor)>=minPts:#如果这个类的个数大于给定的minPts个数
            Objs[i] = neibor
            #将这个簇加入Objs字典中
    oldObjs = Objs.copy()
    k = 0#初始化聚类簇数
    notAccess = list(range(n))
    #初始化未访问样本集合(索引)
    
    
    while len(Objs)>0:
        OldNotAccess = []
        OldNotAccess.extend(notAccess)
        cores = Objs.keys()
        #随机选取一个核心对象
        randNum = random.randint(0,len(cores))
        
        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 oldObjs.keys() :
                delte = [val for val in oldObjs[q] if val in notAccess]
                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 Objs.keys():
                del Objs[x]
    return C
if __name__ == '__main__':
    C = DBSCAN(dataSet, 0.11 , 5)

以上代码没有包括画图部分,绘制图片的代码前两篇都以及提及(这篇就不写了)。

总结:这三天给同学讲解了三种不同聚类方法,它们都有一个共同点那就是距离的计算都采用了欧式距离。

K-mean聚类计算的欧式距离是基于聚类中心点与样本点之间的距离,该距离中心点可以不属于样本点,但是必须是该簇的几何中心点。K-mean聚类需要提前确定聚类个数。

层次聚类计算的欧式距离是基于样本点与样本点之间的距离,样本点应属于不同的族,样本点可以来自族中距离其他族最远的点也可以来自距离其他族最近的点计算族间聚类。层次聚类的聚类个数可以通过树形图进行参考选择。

密度聚类也是计算不同样本点之间的距离,唯一不同的是属于哪个族的条件是用开始设定的半径大小决定的,并且密度聚类存在核心点,也就是该点这设定的半径内包含的设置的族内个数,密度聚类需要确定密度半径和密度个数,并且密度聚类还可以选出噪音点。

总的来说各有优缺点,大家可以看情况使用。

每日日语语法:

常用疑问句:(注意一下疑问句最后搭配ですか使用)

多少钱

多少岁

为什么

怎么样

哪一个

いくら

おいくつ

どうして

どう

どれ

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言