DBSCAN密度聚类算法原理解读及python实现

题记没有落脚到数据结构的对算法的理解都是没有灵魂的复制粘贴!
DBSCAN密度聚类算法原理解读及python实现_第1张图片
其实很多算法,我们通过开源的算法包比如sklearn,tensorflow等,实现都很简单,几行代码,调调参数就出来了,一般也不会出现什么大问题。但是我觉得实际得算法他应该跟诗歌一样,每个人对它得理解和未来得改动应该是都有些微得差别得,而这些微得差别正推动者科研得进步。这就需要从原理和实现上深入得了解和直观感受。而掉包,是缺少这一丝灵气的。

DBSCAN密度聚类算法

西瓜书上对于密度聚类的讲解:
DBSCAN密度聚类算法原理解读及python实现_第2张图片
DBSCAN密度聚类算法原理解读及python实现_第3张图片
DBSCAN密度聚类算法原理解读及python实现_第4张图片
聚类的过程示例:
DBSCAN密度聚类算法原理解读及python实现_第5张图片
直观理解:
可以这样理解DBSCAN:
1、在空间上如果在小于eps的距离上存在大于或者等于MinPts个个体,那么这几个个体就可以看作一个小的团伙,刚开始有M个团伙。
2、这个团伙内的每个成员都可以将手伸出到eps距离外。外面的人只要被拉到就变成了这个团伙的人。
3、直到刚开始的M个团伙都被拉完了,算法也就停止了。

分析

1、算法主要过程是距离的计算,并就近样本的选取
2、在每个“团体”向外伸张的过程明显是个深度优先或者广度优先遍历问题。
3、所有可以用对列来存储这个节点进行广度优先遍历。

算法python实现

代码很短,基本逻辑都在了。

import numpy as np
import pandas as pd
import collections
matrix_data = np.asarray(pd.read_csv("../../state/rawData/CompleteOrder.csv", header=None))
from core.cluster.caculationDistance import euclideanDistance
allDistance=euclideanDistance(matrix_data,matrix_data)
eps=110
minPts=3
allCluster=[]
#直接可达矩阵
matrixDirect=allDistance<eps
#每个样本点的pts
directDensity=matrixDirect.sum(axis=1)-1#减去1的作用是去掉自己
#核心对象集
cluster=[i for i,v in enumerate(directDensity) if v>minPts]
while cluster:#通过密度可达一直到核心集为空
    """
    这里求取样本之间的直接可达用的是笨方法,直接计算出所有的然后去筛选,
    可以想想这种方法的时间复杂度是很大的。为改进依据距离找点效率比较低
    的现状,需要用到的改进算法:
    1、kd_tree
    2、ball_tree
    3、brute
    
    特点:
    1、对于两个参数的设置非常的敏感
    2、当数据分布及其不均匀时不好用
    
    在量级相差较大的数据集上不适合应用该方法进行聚类。刚好印证了我研究该数据集的问题
    """

    randCluster=cluster[np.random.randint(len(cluster))]
    #广度优先遍历
    beVisited={
     }
    myQue=collections.deque()
    myQue.append(randCluster)
    while myQue:
        bePop=myQue.popleft()
        if not beVisited.get(bePop,False):#没有访问过
            beVisited[bePop]=True
            for i,v in enumerate(matrixDirect[bePop]):
                if v and not beVisited.get(i,False):
                    myQue.append(i)
        else:
            pass
    thisCluster=beVisited.keys()
    allCluster.append(thisCluster)
    cluster=list(set(cluster).difference(thisCluster))
print("聚类结果")
print(allCluster)

改进

很明显为我在求取距离的过程中采取暴力运算的方法,效率比较低,改进依据距离找点效率比较低的现状,需要用到的改进算法:
1、kd_tree
2、ball_tree
3、brute
用sklearn工具包求取的过程中可以通过algrathom这个参数进行设置。
DBSCAN密度聚类算法原理解读及python实现_第6张图片

后记

有些问题(比如我遇到的)通过密度聚类不管怎样调参,死活都聚类不出来。主要原因是数据分布的太不均匀(可以理解为非常不均匀的荷塘中间有几个小溪连着),比如不均匀到样本间量级相差都很大的情况,这种时候就不适合用密度聚类,可以自己找数据验证下。

你可能感兴趣的:(算法,算法巩固,聚类,算法,python,数据结构,密度聚类)