聚类分析 | K-Means, DBSCAN在python中的使用

本文介绍了如何在Python中使用DBSCAN和K-Means进行聚类分析。重点讲解了DBSCAN算法的执行流程,包括核心点、密度可达和噪声的识别,以及算法如何构建联通分支。同时提到了K-Means的表现,但未详细展开。
摘要由CSDN通过智能技术生成

今天主要实现的是dbscan,总结一下dbscan算法的思路,防止以后遗忘:

  1. 调用dbscan时,指定半径、最小密度。
  2. 在dbscan中,通过clusterId记录联通分支(类)的数量,遍历N个点,对每个点进行判断,如果已有标记(被捕获到某一联通分支),跳过;如无,进行簇(联通分支)分类。在簇分类前,先进行密度检测,求出N个点中距离当前点距离小于指定半径点点,压入seeds列表,返回簇分类。
  3. 在簇分类中检查seeds列表的长度(捕获的半径内点的个数)。
  4. 如果小于最小密度,说明当前点直接密度可达点不合要求,当前点不是核心点。标记为噪声这里要注意,最开始可能会想,它可能是核心点的附庸点,而未必是噪声,这就是dbscan为什么不受噪声影响的原因!在后面,我们会在不断的更新中,剔除伪噪声!
  5. 而如果大于等于最小密度,对seeds中的点进行标记,所属簇id修改为当前的簇。
  6. 接下来要进行的这一步类似于队列操作:遍历seeds列表中的所有点,对每个点重新调用3中的函数,依次去捕获邻近的直接密度可达点,对返回对chiled_seeds队列做判断。如果child_seeds中的个数达到最小密度,说明这个点也是核心点,那么就将这个点的child_seeds中内容覆盖seeds。内层套for循环对新seeds点进行遍历:如果新seeds里的点从未被标记,将该点所属的簇标记为当前簇,同时将新点压入seeds;如果有噪声标记,用簇标记覆盖噪声
  7. 不断重复,得到所有的联通分支。

dbscan最困难的地方在于4 6两步,看起来觉得很好理解,但是实际写的时候会有很多问题,才反应过来为什么是内层套for,每次对seeds进行覆盖,而不是不断入队。要搞清楚,我们实际上做的有三种操作:

  • 找联通分支
  • 找核心点
  • 找可达点

只有核心点才可以进行转移,直接标记为某一簇!我们先进行的是核心点的寻找与转移,在找不到新的核心点后,将非核心点分配给半径内(直接密度可达)的核心点,这时就形成了一个联通分支。剩余的非核心点标记为噪声。(后面会不断更新,最终剩下的就是真噪声)
一定要理清楚这个过程。

import numpy as np
import pandas as pd
from sklearn.decomposition import NMF #调用sklearn中的nmf
import matplotlib.pyplot as plt
import math
import time

UNCLASSIFIED = False
NOISE = 0

#输入向量a, b  输出两向量欧氏距离
def dist(a, b):
    return np.linalg.norm(a - b) #求范式

#输入向量a, b  判断是否在eps范围之内
def epscheck(a, b, eps):
    return dist(a, b) < eps

#输入数据集, 查询点id, 半径大小 输出在eps范围内的点的id
def region_query(data, pointId, eps):
    nPoints = data.shape[1]#共有多少个点
    seeds = []#初始化空列表
    for i in range(nPoints):
        if epscheck(data[:, pointId], data[:, i], eps):#判断当前点是否在查询点直接密度可达范围内
            seeds.append(i)#如果是,压入list
    return seeds

#输入数据集, 分类结果, 待分类点id, 簇id, 半径大小, 最小点个数   输出能否成功分类
def expand_cluster(data, clusterResult, pointId, clusterId, eps, minPts):
    seeds = region_query(data, pointId, eps)#查找在eps范围内的点的id

    if len(seeds) < minPts:  # 不满足minPts条件的为噪声点
        clusterResult[pointId] = NOISE#当前点没有直接可达的核心点 是噪声点
        return False

    else:
        clusterResult[pointId] = clusterId  # 划分到该簇
        for seedId in seeds:#当前核心点捕获的所有直接密度可达点(非核心非噪声点)
            clusterResult[seedId] = clusterId# 划分到该簇


        '''本步骤实质上相当于队列'''
        while len(seeds) > 0:  # 持续扩张 核心点逐次转移到当前联通分支内的各个附庸点 判断能否成为新的核心点
            currentPoint = seeds
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值