DBSCAN聚类的python实现


作者:张双双

介绍

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,python中的sklearn.cluster库可以实现DBSCAN聚类。

DBSCAN()函数介绍

DBSCAN(eps=0.5,
	min_samples=5,
	metric='euclidean',
	mtric_params=None,
	algorithm='auto',
	leaf_size=30,
	p=None,
	n_jobs=1)

参数介绍

  • 1.eps:邻域半径;
  • 2.min_samples:一个核心对象应该拥有的最少样本数;
  • 3.metric:计算样本之间距离的公式,默认metric=‘euclidean’,即欧式距离;
  • 4.algorithm:用来找最近邻样本点算法{‘auto’,‘ball_tree’,‘ke_tree’}
  • 5.leaf_size:kd_tree或ball_tree中的叶子节点数;决定了搜索快慢;

实例

import matplotlib.pyplot as plt 
import numpy as np 
from sklearn import datasets 
from sklearn.cluster import DBSCAN

iris = datasets.load_iris() 
X = iris.data[:, :4] # #表示我们只取特征空间中的4个维度

estimator = DBSCAN(eps=0.4,min_samples=9) # 构造聚类器
estimator.fit(X) # 聚类
label_pred2 = estimator.labels_ # 获取聚类标签


# 绘制结果
x0 = X[label_pred2 == 0]
x1 = X[label_pred2 == 1]
x2 = X[label_pred2 == 2]
plt.scatter(x0[:, 0], x0[:, 1], c="red", marker='o', label='label0') 
plt.scatter(x1[:, 0], x1[:, 1], c="green", marker='*', label='label1') 
plt.scatter(x2[:, 0], x2[:, 1], c="blue", marker='+', label='label2') 
plt.xlabel('sepal length') 
plt.ylabel('sepal width') 
plt.legend(loc=2) 
plt.show()

在这里插入图片描述

参数选择

DBSCAN()中有两个参数非常重要,即,邻域半径eps和核心点邻域内的最少样本数min_samples。
对于eps的选取我们可以利用k-distance碎石图来实现:

  • 1)选取k值,建议取k为2*维度-1。(其中维度为特征数)
  • 2) 计算并绘制k-distance图。(计算出每个点到距其第k近的点的距离,然后将这些距离从大到小排序后进行绘图。)
  • 3)找到拐点位置的距离,即为Eps的值。

min_samples的取值为上述k值加1,即:min_samples=k + 1 。

实例

整理数据

import numpy as np
from sklearn.datasets import make_moons
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
np.random.seed(2021)

data = np.ones([1005,2])
data[:1000] = make_moons(n_samples=1000,noise=0.05,random_state=2022)[0]
data[1000:] = [[-1,-0.5],
                [-0.5,-1],
                [-1,1.5],
                [2.5,-0.5],
                [2,1.5]]
print(data.shape)
plt.scatter(data[:,0],data[:,1],color="c")
plt.show()

在这里插入图片描述

选择eps和min_samples

def select_MinPts(data,k):
    k_dist = []
    for i in range(data.shape[0]):
        dist = (((data[i] - data)**2).sum(axis=1)**0.5)
        dist.sort()
        k_dist.append(dist[k])
    return np.array(k_dist)
k = 3  # 此处k取 2*2 -1 
k_dist = select_MinPts(data,k)
k_dist.sort()
plt.plot(np.arange(k_dist.shape[0]),k_dist[::-1])

在这里插入图片描述

建立模型

dbscan_model = DBSCAN(eps=0.1,min_samples=k+1)
label = dbscan_model.fit_predict(data)

class_1 = []
class_2 = []
noise = []
for index,value in enumerate(label):
    if value == 0:
        class_1.append(index)
    elif value == 1:
        class_2.append(index)
    elif value == -1:
        noise.append(index)
plt.scatter(data[class_1,0],data[class_1,1],color="g",label="class 1")
plt.scatter(data[class_2,0],data[class_2,1],color="b",label = "class 2")
plt.scatter(data[noise,0],data[noise,1],color="r",label = "noise")
plt.legend()
plt.show()

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值