DBSCAN算法的原理与实现

本文介绍了DBSCAN(密度基空间聚类)算法的原理,它是一种能处理任意形状聚类且不受噪声影响的聚类方法。通过示例代码展示了如何在Python中实现DBSCAN,包括距离矩阵计算、核心样本点判断和分类过程。最终,通过可视化结果证明了DBSCAN在聚类圆形簇和识别噪声点上的有效性。
摘要由CSDN通过智能技术生成

DBSCAN算法的原理与实现

原理

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)有噪声的基于密度的空间聚类算法,关于算法的原理,可以参照下面这两篇博客,重点关注第一篇博客,介绍的比较简单易懂:
ChaoSimple:常用聚类算法(一) DBSCAN算法
刘建平Pinard:DBSCAN密度聚类算法

代码逻辑

上面两篇博客虽然比较好的介绍了DBSCAN算法的基本原理,但都没有说清楚编程实现的基本思路,所以这里主要介绍DBSCAN算法的代码实现逻辑,请看下图:

DBSCAN算法流程图

代码及结果展示

源代码

import math
from numpy import random
import numpy as np
import matplotlib.pyplot as plt
class DBSCAN(object):
    def __init__(self,dataSet:np.array,MinPts:int,r:float,dType) -> None:
        self.dataSet=dataSet
        self.MinPts=MinPts
        self.r=r
        # 距离计算方法:
        # 0 欧式距离
        # 1 曼哈顿距离
        self.dType=dType
        self.dMatrix()
    def dMatrix(self):
        # 初始化距离矩阵
        nrow,ncol=self.dataSet.shape
        dMatrix=np.zeros((nrow,nrow))
        for i in range(nrow-1):
            for j in range(i+1,nrow):
                start=self.dataSet[i,:]
                end=self.dataSet[j,:]
                diff=np.abs(start-end)
                if self.dType:
                    dist=np.sum(diff)
                else:
                    dist=np.sqrt(np.sum(diff**2))
                dMatrix[i,j]=dist
                dMatrix[j,i]=dist
        self.dMatrix=dMatrix
    def isCore(self,i,nrow):
        # 判断第i个样本点是不是核心样本点
        dists=self.dMatrix[i,:]
        indexs=list()
        n=0
        for j in range(nrow):
            if j==i:
                continue
            if dists[j]<=self.r:
                n+=1
                indexs.append(j)
        if n>=self.MinPts:
            flag=True
        else:
            flag=False
        return flag,indexs
    def classify(self):
        nrow,_=self.dataSet.shape
        # 初始化分类结果
        result=np.zeros(nrow)
        k=0 #当前聚类数
        # 遍历所有样本点
        for i in range(nrow):
            if result[i]:
                continue #样本点已经分类
            else:
                flag,indexs=self.isCore(i,nrow)
                if flag:
                    k+=1
                    result[i]=k
                    for j in indexs:
                        if result[j]:
                            continue
                        else:
                            result[j]=k
                            flag1,indexs1=self.isCore(j,nrow)
                            if flag1:
                                indexs.extend(indexs1)
        self.result=result
if __name__=='__main__':
    # 开始测试程序
    dataSet=list()
    # 产生大圆
    for i in range(1000):
        r=random.rand()+4.5
        rad=random.rand()*np.pi*2
        dataSet.append([r*math.cos(rad),r*math.sin(rad)])
    # 产生小圆
    for i in range(1000):
        r=random.rand()+1.5
        rad=random.rand()*np.pi*2
        dataSet.append([r*math.cos(rad),r*math.sin(rad)])
    # 产生随机噪声点
    for i in range(100):
        dataSet.append([random.rand()*10-5,random.rand()*10-5])
    dataSet=np.array(dataSet)
    DB=DBSCAN(dataSet,5,0.5,0)
    DB.classify()
    plt.figure(figsize=(10,10))
    plt.scatter(dataSet[DB.result==2,0],dataSet[DB.result==2,1],color='blue',marker='o')
    plt.scatter(dataSet[DB.result==1,0],dataSet[DB.result==1,1],color='green',marker='+')
    plt.scatter(dataSet[DB.result==0,0],dataSet[DB.result==0,1],color='red',marker='<')
    plt.show()
    

结果图

DBSCAN结果图
从图中可以看到,样本点被较好的分成了绿色和蓝色两类,聚类簇呈两个圆环,因此也验证了DBSCAN聚类算法对于聚类簇的形状没有偏移的特性,而类似于K均值聚类等基于空间距离的聚类算法就只能用于凸样本点聚类。
此外,向样本集中加入的噪声点也被较好的识别了出来,即结果图中红色三角形符号的样本点,验证了DBSCAN算法在聚类的同时也能识别样本集中的噪声点和离群值。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值