DBSCAN,不像k-均值方法那样假设集群呈球形,或是把数据集分成不同的需要人工设定分界点的层级。顾名思义,基于密度的聚类把标签分配给样本点密集的区域。而且它不一定把每个点都分配到集群中去,但是能够去除噪声点。
创建新的半月形结构数据集来比较k-均值聚类、层次聚类和DBSCAN:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.cluster import DBSCAN
from sklearn.cluster import KMeans
from sklearn.cluster import AgglomerativeClustering
# 创建新的半月形结构数据集
X, y = make_moons(n_samples=200, noise=0.05, random_state=0)
plt.scatter(X[:, 0], X[:, 1])
plt.tight_layout()
#plt.savefig('images/11_14.png', dpi=300)
plt.show()
# 从使用k-均值算法和全连接聚类开始,来看一下前面讨论过的那些聚类
# 算法是否能成功地把半月形集群彼此分开
f, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 3))
km = KMeans(n_clusters=2, random_state=0)
y_km = km.fit_predict(X)
ax1.scatter(X[y_km == 0, 0], X[y_km == 0, 1],
edgecolor='black',
c='lightblue', marker='o', s=40, label='cluster 1')
ax1.scatter(X[y_km == 1, 0], X[y_km == 1, 1],
edgecolor='black',
c='red', marker='s', s=40, label='cluster 2')
ax1.set_title('K-means clustering')
ac = AgglomerativeClustering(n_clusters=2,
affinity='euclidean',
linkage='complete')
y_ac = ac.fit_predict(X)
ax2.scatter(X[y_ac == 0, 0], X[y_ac == 0, 1], c='lightblue',
edgecolor='black',
marker='o', s=40, label='cluster 1')
ax2.scatter(X[y_ac == 1, 0], X[y_ac == 1, 1], c='red',
edgecolor='black',
marker='s', s=40, label='cluster 2')
ax2.set_title('Agglomerative clustering')
plt.legend()
plt.tight_layout()
# plt.savefig('images/11_15.png', dpi=300)
plt.show()
# 采用DBSCAN算法:基于密度的方法
# DBSCAN算法的优势 ——可以完成任意形状的数据聚类
# eps:表示的是半径,越大类别数越少——参数越大的话,多个簇和大部分对象会归并到同一个簇中
# Eps取得值过大,会导致大多数点都聚到同一个簇中,Eps过小,会导致一个簇的分裂;
# min_samples:给定点在邻域内成为核心对象的最小邻域点数
# min_samples的值取得过大,会导致同一个簇中点被标记为离群点,
# min_samples过小,会导致发现大量的核心点。
db = DBSCAN(eps=0.2, min_samples=5, metric='euclidean')
y_db = db.fit_predict(X)
plt.scatter(X[y_db == 0, 0], X[y_db == 0, 1],
c='lightblue', marker='o', s=40,
edgecolor='black',
label='cluster 1')
plt.scatter(X[y_db == 1, 0], X[y_db == 1, 1],
c='red', marker='s', s=40,
edgecolor='black',
label='cluster 2')
plt.legend()
plt.tight_layout()
#plt.savefig('images/11_16.png', dpi=300)
plt.show()
运行结果图:
k-均值算法不能在两个集群之间分出彼此,层次聚类算法也遇到了复杂形状的挑战: