Python实现DBSCAN聚类算法,可视化

英文全称:Density-Based Spatial Clustering of Applications with Noise

基本思想:

算法的思想大致是把所有的样本分成三类,一个是核心点(周围的样本点足够多),边缘点(周围的样本点不够多,但是在核心点的邻域内),孤立点(周围没有太多点,也不在核心点的邻域内)。

算法流程:

取出一个没有被分类的孤立点,如果它是核心点或者边缘点,就把他可以连接到的点们和他聚成一个簇,如果是孤立点,就把他单独作为一簇(或者当作噪声去掉)。

算法需要确定两个参数,一个是邻域大小,一个是邻域内点的个数,改变邻域大小会影响到邻域内点的个数。

优点是可以处理不同的形状簇,可以去除噪声。

缺点是有两个超参数,需要人工设定这两个参数。

代码1,命名为datahelper.py,被代码2引用:

import matplotlib.pyplot as plt
import numpy as np
import random
#随机生成大致是K个类别的点,用均匀分布生成中心点的位置,用高斯分布生成中心点周围的点
def generatorN(K):
    #np.random.seed()
    center=[[np.random.rand(1)*20,np.random.rand(1)*20] for _ in range(K)]
    _data=[]
    for _x, _y in center:
        _data.append([np.random.randn(100)+_x ,np.random.randn(100)+_y])

    _data = np.transpose(_data, (0, 2, 1)).reshape((-1, 2))

    np.random.shuffle(_data)
    return _data
#画图
def draw_data(_groups):
    #fig=plt.figure(dpi=180)
    plt.title("画图")
    for xys in _groups.values():
        xs=[xy[0] for xy in xys]
        ys=[xy[1] for xy in xys]
        plt.scatter(xs,ys)
    plt.show()

代码2,直接运行:

#DBSCAN

import data_helper
#判断是不是已经分好簇了
def in_groups(_x,_y):
    for xys in groups.values():
        for p_x,p_y in xys:

            if p_x==_x and p_y==_y:
                return True
    return False
#获取一个点所有的邻居
def get_neighbors(_x,_y):

    _neighbors=[]
    for p_x,p_y in data:
        if p_x==_x and p_y==_y:#自己不是自己的邻居
            continue
        if (p_x-_x)**2+(p_y-_y)**2<=distance_thresh:
            _neighbors.append([p_x,p_y])

    return _neighbors
def get_grouped_pts():
    _count=0
    for xys in groups.values():
        _count+=len(xys)
    return _count
def get_ungrouped_p():
    for p_x,p_y in data:
        if not in_groups(p_x,p_y):
            return p_x,p_y
    return None
#groups
min_pts = 13
distance_thresh =2.35
groups={}
#存放聚类信息,格式(x,y):[[x1,y1],[x2,y2]...],xy是这个簇中最先被选中的点
data=data_helper.generatorN(5)#生成原始数据
judged=[]#判断某个点有没有被判断过
count=0
while len(data)!=get_grouped_pts():
    x,y=get_ungrouped_p()
    stack=[[x,y]]
    groups[(x, y)] = [[x,y]]
    #把这个点可以连接到的点加入整个簇
    while len(stack)!=0:
        x_,y_=stack.pop()
        neighbors = get_neighbors(x_, y_)
        if len(neighbors)>=min_pts:
            for neighbor in neighbors:
                if neighbor not in judged:
                    stack.append(neighbor)
                    judged.append(neighbor)
            for neighbor in neighbors:
                if not in_groups(*neighbor):
                    groups[(x, y)].append(neighbor)
data_helper.draw_data(groups)

 

  • 2
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

York1996

您的打赏,是我更新的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值