文章目录
- 介绍
- DBSCAN()函数介绍
- 实例
- 参数选择
- 实例
- 整理数据
- 选择eps和min_samples
- 建立模型
作者:张双双
介绍
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()