python实现基于密度的DBscan 聚类算法(含代码和数据

DBscan算法是典型的基于密度的聚类算法,假定类别可以通过样本分布的紧密程度决定。在DBscan算法中,将样本密集的一个区域内的点作为一个cluster,再将相连的clueter聚合为一个cluster。

  • 把所有的数据点区分并标记为核心点、边界点和噪音点
    删除噪音点
  • 所有在半径Eps内的核心点间由边相连
  • 联通的核心点作为一组成为一个cluster
  • 分配每一个边界点到它所落入的核心点半径范围内的cluster中

若在某点半径Eps内有>=minPts个点,则该点就是核心点,
若点不是核心点,但是被其他核心点包括,则为边界点
若又不是核心点,又没被包括,则为离群点(噪音点
在这里插入图片描述

  1. 距离选择
    DBscan对不同的距离指标总体上效果差异不大,选择欧式距离作为距离指标。
  2. 参数选择
    在DBscan中不需要预先决定cluster的数目,算法自动决定聚类的数目,但是需要设定Eps和MinPts两个参数。在本实验中对扫描半径Eps最小包含点MinPts 的取值如下:
    minPts = [3 4 5 6 7 8 9]
    Eps = [0.2 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29]

dbscan.py

import numpy as np
import data_utils as du

def get_cores_area(data, dist_matrix, eps, minPts):
    core_points = {}
    if dist_matrix is None:
        dist_matrix = pairwise_distance(data, data)

    for i, core_near_dis in enumerate(dist_matrix):
        inner_points = []	# 包含的点
        for j, dis in enumerate(core_near_dis):
            if i == j:
                continue
            if dis < eps:
                inner_points.append(j)
            if len(inner_points) >= minPts:
                core_points[i] = inner_points	# 标记核心点族群所包含的点
    return core_points

# 计算两点欧式距离
def pairwise_distance(x, y):
    xx = np.sum(x * x, axis=1, keepdims=True)
    yy = np.sum(y * y, axis=1, keepdims=True)
    xy = np.matmul(x, y.T)
    d = xx + yy.T - 2 * xy
    return d


def dbscan(data, eps, minPts):
    dist_matrix = pairwise_distance(data, data)
    cores_area = get_cores_area(data, dist_matrix, eps, minPts)
    clusters = []
    while len(cores_area) > 0:
        cluster = set()
        visit_set = set()
        core, nears = cores_area.popitem()
        visit_set.add(core)
        visit_set.update(nears)
        while len(visit_set) > 0:
            point = visit_set.pop()
            cluster.add(point)
            if point in cores_area:
                visit_set.update(cores_area.pop(point))
        clusters.append(cluster)

    cluster = np.zeros(len(data))
    for i, c in enumerate(clusters):
        for item in c:
            cluster[item] = i
    return cluster


if __name__ == '__main__':
    # print("----DBscan----")
    data, labels = du.read_data()
    eps_set = np.arange(0.15, 0.3, 0.01).round(2)
    minPts_set = np.arange(3, 10, 1)
    for eps in eps_set:
        for minPts in minPts_set:
            print("eps=", eps, ", minPts=", minPts)
            cluster = dbscan(data, eps, minPts)
            purity, fscore, precision, recall = du.standard(cluster)
            print("purity=", purity, ", F-score=", fscore)
    # print("----------------")

data_utils.py

import pandas as pd
import numpy as np


def read_data():
    pf = pd.read_csv('Frogs_MFCCs.csv', encoding='utf-8')
    data = np.array(pf)
    f_data = data[:, 0:22].astype(np.float)
    return f_data, data[:, 22]

def standard(cluster):
    data, labels = read_data()
    label_set = sorted(list(set(labels)))
    purity = get_purity(cluster, labels, label_set)
    fscore, precision, recall, TP, FP, FN, TN = f_score(cluster, labels)
    return purity, fscore, precision, recall

if __name__ == '__main__':
    f_data, labels = read_data()
    label_set = list(set(labels))

代码及数据下载:https://download.csdn.net/download/SAM2un/12036441

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值