Python中每次运行后聚类结果的变化scikit-learn

kcwpcxri  于 2023-11-16  发布在  Python
关注(0)|答案(5)|浏览(163)

我有一堆句子,我想使用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)


我很感激你的帮助。

vwkv1x7d

vwkv1x7d1#

当使用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参数的文档中:“当eigen_solver == 'amg'和K-Means初始化时,用于初始化lobpcg特征向量分解的伪随机数生成器。”OP的代码似乎不包含在这些情况下,尽管设置参数可能值得一试。

x3naxklr

x3naxklr2#

正如其他人已经注意到的,k-means通常是用 * 随机化 * 初始化来实现的。这是 * 故意的 *,你可以得到不同的结果。
该算法只是一个启发式的。它可能会产生次优的结果。多次运行它会给你一个更好的机会找到一个好的结果。
在我看来,当结果在运行之间变化很大时,这表明数据根本没有很好地使用k-means聚类。在这种情况下,你的结果并不比随机好多少。**如果数据真的适合k-means聚类,结果将相当稳定!**如果它们变化,聚类可能不具有相同的大小,或者可能没有很好地分离;而其它算法可以产生更好的结果。

a1o7rhls

a1o7rhls3#

我也有类似的问题,但我希望来自另一个分布的数据集以与原始数据集相同的方式进行聚类。例如,原始数据集的所有彩色图像都在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)我们确保来自另一个分布的数据将以与原始数据集相同的方式进行聚类。

camsedfj

camsedfj4#

通常,当运行具有许多局部最小值的算法时,通常采用随机方法,并在不同的初始状态下多次运行算法。这将给你给予多个结果,并且具有最低误差的结果通常被选择为最佳结果。
当我使用K-Means时,我总是多次运行它并使用最佳结果。

dnph8jn4

dnph8jn45#

经过长时间的搜索和阅读,以下是我的意见。
1.在n_init=中使用>5或10的数字以在这些初始化中产生最佳结果。

  1. random_state=中不同的数字会导致不同的聚类结果,根据我的经验,即使数据分布均匀,结果也可能有很小的偏差。
    1.对一个大的n_init号和一个random_state号进行多次尝试可以产生一致的好结果。计算机在处理时似乎优先考虑n_init
    1.高维数据可能需要在Kmeans链接之前进行主成分分析(PCA)

汇总答案:每次聚类结果的变化都是自然的,无需担心,只需要保存每次的结果即可。

相关问题