在数据挖掘和机器学习领域,聚类算法是用来将数据集中的样本划分成若干个簇的常用方法。不同的聚类算法适用于不同类型的数据集,并且对参数的敏感度也各不相同。本文通过生成的二维数据集,比较了多种聚类算法的特性和效果,包括参数敏感度和对不同数据结构的适应性。
为了进行比较,生成了几个具有不同特性的二维数据集。除了最后一个数据集外,其他数据集的参数都经过了调整,以产生良好的聚类结果。一些算法对参数值的敏感度高于其他算法。最后一个数据集是一个“空”情况的例子,其中数据是同质的,没有好的聚类。在这个例子中,空数据集使用了与它上面行中的数据集相同的参数,这代表了参数值和数据结构之间的不匹配。
虽然这些例子为提供了一些关于算法的直观理解,但这种直观理解可能不适用于非常高维的数据。在本文中,将通过Python代码和matplotlib库来可视化这些聚类算法的效果。首先,需要导入必要的库,并生成数据集。
import time
import warnings
from itertools import cycle, islice
import matplotlib.pyplot as plt
import numpy as np
from sklearn import cluster, datasets, mixture
from sklearn.neighbors import kneighbors_graph
from sklearn.preprocessing import StandardScaler
接下来,生成了几个不同特性的数据集,包括有噪声的圆圈、有噪声的新月形、不同方差的簇、以及无结构的数据。这些数据集的大小足够大,以便可以看到算法的可扩展性,但也不会太大,以免运行时间过长。
n_samples = 500
seed = 30
noisy_circles = datasets.make_circles(n_samples=n_samples, factor=0.5, noise=0.05, random_state=seed)
noisy_moons = datasets.make_moons(n_samples=n_samples, noise=0.05, random_state=seed)
blobs = datasets.make_blobs(n_samples=n_samples, random_state=seed)
rng = np.random.RandomState(seed)
no_structure = rng.rand(n_samples, 2), None
然后,设置了聚类算法的参数。对于每个数据集,都调整了参数以获得最佳的聚类结果。还为最后一个数据集保留了与上一行数据集相同的参数,以展示参数值和数据结构不匹配的情况。
plt.figure(figsize=(9*2+3, 13))
plt.subplots_adjust(left=0.02, right=0.98, bottom=0.001, top=0.95, wspace=0.05, hspace=0.01)
plot_num = 1
default_base = {
"quantile": 0.3,
"eps": 0.3,
"damping": 0.9,
"preference": -200,
"n_neighbors": 3,
"n_clusters": 3,
"min_samples": 7,
"xi": 0.05,
"min_cluster_size": 0.1,
"allow_single_cluster": True,
"hdbscan_min_cluster_size": 15,
"hdbscan_min_samples": 3,
"random_state": 42,
}
datasets = [
(noisy_circles, {"damping": 0.77, "preference": -240, "quantile": 0.2, "n_clusters": 2, "min_samples": 7, "xi": 0.08,}),
(noisy_moons, {"damping": 0.75, "preference": -220, "n_clusters": 2, "min_samples": 7, "xi": 0.1,}),
# ... 更多数据集和参数设置 ...
]
在设置好参数后,创建了各种聚类对象,并使用不同的聚类算法对每个数据集进行拟合。还计算了每个算法的运行时间,并在图表中显示了聚类结果。
for i_dataset, (dataset, algo_params) in enumerate(datasets):
params = default_base.copy()
params.update(algo_params)
X, y = dataset
X = StandardScaler().fit_transform(X)
bandwidth = cluster.estimate_bandwidth(X, quantile=params["quantile"])
connectivity = kneighbors_graph(X, n_neighbors=params["n_neighbors"], include_self=False)
connectivity = 0.5 * (connectivity + connectivity.T)
# ... 创建聚类对象并进行拟合 ...