K-Means算法初始化策略的影响评估

机器学习领域,K-Means算法是一种广泛使用的聚类方法。该算法通过迭代地移动聚类中心,将数据点分配给最近的聚类中心,以最小化每个点到其聚类中心的距离的平方和。然而,K-Means算法的一个关键问题是其对初始聚类中心的选择非常敏感,这可能导致算法收敛到局部最优解而非全局最优解。为了解决这个问题,研究者们提出了多种初始化策略,如“k-means++”和“随机初始化”。本文旨在评估这些初始化策略对于算法收敛鲁棒性的影响,通过分析聚类中心的相对标准偏差来衡量。

实验设计

实验中,使用了两种K-Means模型:标准的KMeans和MiniBatchKMeans。对于每种模型,分别采用了两种初始化方法:“k-means++”和“随机初始化”。通过改变参数n_init的值,即初始化的次数,来评估不同初始化策略的效果。实验中,生成了一个2D网格的高斯聚类数据集,这些聚类之间间隔较远,以便于观察初始化策略对算法收敛的影响。

实验结果

实验结果表明,对于KMeans模型,使用“k-means++”初始化策略相比于“随机初始化”策略,能够更有效地提高算法的收敛鲁棒性。具体来说,随着n_init参数值的增加,使用“k-means++”初始化的KMeans模型的聚类中心的相对标准偏差显著降低,表明算法的收敛更加稳定。而对于MiniBatchKMeans模型,虽然“k-means++”初始化策略同样能够提高收敛鲁棒性,但其效果不如KMeans模型明显。这可能是因为MiniBatchKMeans模型在每次迭代中只使用部分数据,从而减少了初始化策略对算法收敛的影响。

以下是使用Python和scikit-learn库实现上述实验的代码示例。代码中首先定义了数据生成函数make_data,用于生成2D网格的高斯聚类数据集。然后,定义了实验的主函数,其中使用了不同的K-Means模型和初始化策略,并通过改变n_init参数的值来评估不同初始化策略的效果。最后,代码中还包含了绘制实验结果的函数,以直观地展示不同初始化策略对算法收敛的影响。

import matplotlib.pyplot as plt import numpy as np from sklearn.cluster import KMeans, MiniBatchKMeans from sklearn.utils import check_random_state, shuffle # 设置随机数种子以保证实验结果的可重复性 random_state = np.random.RandomState(0) # 数据生成函数 def make_data(random_state, n_samples_per_center, grid_size, scale): centers = np.array([[i, j] for i in range(grid_size) for j in range(grid_size)]) noise = random_state.normal(scale=scale, size=(n_samples_per_center, centers.shape[1])) X = np.concatenate([c + noise for c in centers]) y = np.concatenate([[i] * n_samples_per_center for i in range(len(centers))]) return shuffle(X, y, random_state=random_state) # 实验的主函数 def main(): n_runs = 5 n_init_range = np.array([1, 5, 10, 15, 20]) n_samples_per_center = 100 grid_size = 3 scale = 0.1 plt.figure() plots = [] legends = [] cases = [ (KMeans, "k-means++", {}, "^-"), (KMeans, "random", {}, "o-"), (MiniBatchKMeans, "k-means++", {"max_no_improvement": 3}, "x-"), (MiniBatchKMeans, "random", {"max_no_improvement": 3, "init_size": 500}, "d-"), ] for factory, init, params, format in cases: inertia = np.empty((len(n_init_range), n_runs)) for run_id in range(n_runs): X, y = make_data(run_id, n_samples_per_center, grid_size, scale) for i, n_init in enumerate(n_init_range): km = factory(n_clusters=len(centers), init=init, random_state=run_id, n_init=n_init, **params).fit(X) inertia[i, run_id] = km.inertia_ p = plt.errorbar(n_init_range, inertia.mean(axis=1), inertia.std(axis=1), fmt=format) plots.append(p[0]) legends.append("%s with %s init" % (factory.__name__, init)) plt.xlabel("n_init") plt.ylabel("inertia") plt.legend(plots, legends) plt.title("Mean inertia for various k-means init across %d runs" % n_runs) plt.show() if __name__ == "__main__": main()
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485