【问题标题】:Changes of clustering results after each time run in Python scikit-learnPython scikit-learn 每次运行后聚类结果的变化
【发布时间】:2025-12-28 20:35:12
【问题描述】:

我有一堆句子,我想使用 scikit-learn 谱聚类对它们进行聚类。我已经运行了代码并没有问题地得到结果。但是,每次我运行它时,我都会得到不同的结果。我知道这是启动的问题,但我不知道如何解决它。这是我在句子上运行的代码的一部分:

vectorizer = TfidfVectorizer(norm='l2',sublinear_tf=True,tokenizer=tokenize,stop_words='english',charset_error="ignore",ngram_range=(1, 5),min_df=1)
X = vectorizer.fit_transform(data)
# connectivity matrix for structured Ward
connectivity = kneighbors_graph(X, n_neighbors=5)
# make connectivity symmetric
connectivity = 0.5 * (connectivity + connectivity.T)
distances = euclidean_distances(X)
spectral = cluster.SpectralClustering(n_clusters=number_of_k,eigen_solver='arpack',affinity="nearest_neighbors",assign_labels="discretize")
spectral.fit(X)

数据是句子的列表。每次代码运行时,我的聚类结果都会有所不同。如何使用光谱聚类获得一致的结果。我对 Kmean 也有同样的问题。这是我的 Kmean 代码:

vectorizer = TfidfVectorizer(sublinear_tf=True,stop_words='english',charset_error="ignore")
X_data = vectorizer.fit_transform(data)
km = KMeans(n_clusters=number_of_k, init='k-means++', max_iter=100, n_init=1,verbose=0)
km.fit(X_data)

感谢您的帮助。

【问题讨论】:

    标签: python scikit-learn cluster-analysis k-means spectral


    【解决方案1】:

    使用 k-means 时,您希望在 KMeans 中设置 random_state 参数(参见 documentation)。将此设置为 int 或 RandomState 实例。

    km = KMeans(n_clusters=number_of_k, init='k-means++', 
                max_iter=100, n_init=1, verbose=0, random_state=3425)
    km.fit(X_data)
    

    这很重要,因为 k-means 不是确定性算法。它通常从一些随机初始化过程开始,这种随机性意味着不同的运行将在不同的点开始。为伪随机数生成器播种可确保这种随机性对于相同的种子始终相同。

    不过,我不确定光谱聚类示例。来自random_state 参数上的documentation:“一个伪随机数生成器,用于在eigen_solver == 'amg' 和K-Means 初始化时初始化lobpcg 特征向量分解。”在这些情况下似乎不包含 OP 的代码,但设置参数可能值得一试。

    【讨论】:

    • 感谢 Kmean 的提示。随机状态设置真的会影响结果吗?例如,如果我设置 random_state=2222,它会改变结果吗?我也试试看看。关于光谱聚类,我在发布这个问题之前检查了文档,但关于启动的内容不多。它们有一个随机状态,但我会像 Kmean 中的那样设置它,看看它会如何变化。再次感谢。
    • @user3430235 我认为这完全取决于您的数据。我没有广泛使用它,但我得到的印象是 k-means 实际上对起始值相当敏感。当然,这就是开发 k-means++ 的部分原因,以获得更一致的良好起始值,但这仍然可能是一个值得考虑的问题。另一种常见的策略是使用不同的种子多次运行它并选择最好的。
    • 默认情况下,该实现实际上运行了 10 次 K-Means,并使用了最好的聚类结果。所以是的,它确实会影响除琐碎情况之外的所有输出。
    • @AndreasMueller 如果我使用 10 n_init 并将 random_state 指定为 n_init=10, random_state=3425 ,这有意义吗? n_init 是使用不同质心种子运行 k-means 算法的次数。由于固定的random_state,质心是否会改变??
    • 一开始就设置随机状态,不是每次初始化,原因很明显...
    【解决方案2】:

    正如其他人已经指出的那样,k-means 通常是通过 随机 初始化来实现的。 故意你可以得到不同的结果。

    该算法只是一种启发式算法。它可能会产生次优的结果。多次运行它可以让您有更好的机会找到好的结果。

    在我看来,当每次运行的结果差异很大时,这表明数据根本不能用 k-means 很好地聚类。在这种情况下,你的结果并不比随机的好多少。 如果数据真的适合k-means聚类,结果会比较稳定!如果它们不同,则聚类可能大小不一样,或者可能分离不好;和其他算法可能会产生更好的结果。

    【讨论】:

    • 如果我使用 n_init=10 并将 random_state 指定为 n_init=10, random_state=0 ,这有意义吗? n_init 是使用不同质心种子运行 k-means 算法的次数。由于固定的random_state,质心是否会改变??
    【解决方案3】:

    我遇到了类似的问题,但我希望来自另一个分布的数据集以与原始数据集相同的方式进行聚类。例如,原始数据集的所有彩色图像都在cluster 0 中,原始数据集的所有灰度图像都在cluster 1 中。对于另一个数据集,我希望彩色图像/灰色图像也位于 cluster 0cluster 1 中。

    这是我从 Kaggler 窃取的代码 - 除了将 random_state 设置为种子之外,您还使用 KMeans 返回的 k-mean 模型对其他数据集进行聚类。这工作得相当好。但是,我找不到官方的scikit-Learn 文件这么说。

    # reference - https://www.kaggle.com/kmader/normalizing-brightfield-stained-and-fluorescence
    from sklearn.cluster import KMeans
    
    seed = 42
    def create_color_clusters(img_df,  cluster_count = 2, cluster_maker=None):
        if cluster_maker is None:
            cluster_maker = KMeans(cluster_count, random_state=seed)
            cluster_maker.fit(img_df[['Green', 'Red-Green', 'Red-Green-Sd']])
    
        img_df['cluster-id'] = np.argmin(cluster_maker.transform(img_df[['Green', 'Red-Green', 'Red-Green-Sd']]),-1)
    
    
        return img_df, cluster_maker
    
    # Now K-Mean your images `img_df` to two clusters
    img_df, cluster_maker = create_color_clusters(img_df, 2)
    # Cluster another set of images using the same kmean-model
    another_img_df, _ = create_color_clusters(another_img_df, 2, cluster_maker)
    

    但是,即使将random_state 设置为int seed 也不能确保相同的数据在机器上总是以相同的顺序分组。相同的数据可能在一台机器上聚集为group 0,在另一台机器上聚集为group 1。但至少使用相同的 K-Means 模型(我的代码中为 cluster_maker),我们确保来自另一个分布的数据将以与原始数据集相同的方式进行聚类。

    【讨论】:

      【解决方案4】:

      通常在运行具有许多局部最小值的算法时,通常会采用随机方法并以不同的初始状态多次运行该算法。这将为您提供多个结果,通常选择误差最低的一个作为最佳结果。

      当我使用 K-Means 时,我总是运行几次并使用最佳结果。

      【讨论】:

        最近更新 更多