集群是否用于涉及大量数据的真实系统/产品?细微差别是如何处理的?

数据挖掘 聚类 文本挖掘
2021-09-24 02:18:32

我正在使用大约 250 万个短文本数据(帖子,平均数据元素中大约 10 个单词)的真实数据集。我想将类似的帖子组合在一起。因此,在进行标准预处理后,我在数据集上应用了 KMeans 聚类。在矢量化之后(我做了 TfIdf),矩阵很大(250 万行和大约 60 k 列)。我进行了 SVD + LSA 转换,使其更小(250 万 x 150)。我给出了 200 作为聚类数并应用了 K 均值。我必须说,结果不是很糟糕。有些集群具有相似的帖子(不是语义,而是相似的词),但也有随机放置的集群。

由于数据量大,我无法有效地可视化结果或衡量集群的好坏。虽然我尝试实施轮廓系数、肘部方法来寻找最佳集群数量,但我遇到了持续的内存错误。我不知道 150 是否是降维期间使用的正确数字。您能否建议任何其他方法来解决这些问题?

当我达到这一点时,我开始怀疑聚类作为一种方法的有效性。我很想知道是否有人在大型生产规模系统中使用集群,如果是,人们使用什么样的技术?

请在下面找到代码:

`

 tfidf_vectorizer = TfidfVectorizer(max_df=0.5, max_features=200000,
                                 min_df=0.001,decode_error='ignore', stop_words='english',strip_accents='ascii',use_idf=True, ngram_range=(1,2),tokenizer=tokenizeAndFilter,lowercase=True)`

`    tfidf_matrix = tfidf_vectorizer.fit_transform(tokens.values()) #fit the vectorizer to synopses


    svd = TruncatedSVD(150)
    normalizer = Normalizer(copy=False)
    lsa = make_pipeline(svd, normalizer)

    X = lsa.fit_transform(tfidf_matrix) 
    feature_names = tfidf_vectorizer.get_feature_names()

    with open(path+'terms.csv','w') as f:
       for col in tfidf_matrix.nonzero()[1]:
          f.write(feature_names[col]+','+str( tfidf_matrix[0, col]))
          f.write('\n')

        sil_dict={}
        for n_clusters in range(50,500,10):
            km=KMeans(n_clusters=n_clusters,init='k-means++',max_iter=500,n_init=1)
        km.fit(X)
            label = km.labels_
            sil_coeff = silhouette_score(X, label, metric='cosine',n_jobs=10)
    #        print("For n_clusters={}, The Silhouette Coefficient is {}".format(n_cluster, sil_coeff))
        sil_dict[n_clusters]=sil_coeff
            with open('kmeans_model'+str(n_clusters)+'.pkl','wb') as f:
               cPickle.dump(km,f)



    original_centroids=svd.inverse_transform(km.cluster_centers_)
    order_centroids=original_centroids.argsort()[:,::-1]

    terms=tfidf_vectorizer.get_feature_names()
    clusters=collections.defaultdict(list)
    k=0
    for i in km.labels_:
        clusters[i].append(tokens.values()[k])
        k+=1
        for i in range(10):
            print i
            for j in order_centroids[i, :10]:
                  print(terms[j] )
        for key,valueList in clusters.items():
            with open(path+'\\'+OUTPUTFILE+'_'+str(key)+'.csv','w') as f:
                 for value in valueList:
                    f.write(value+'\n')

`

3个回答
  1. 聚类(大部分)不适用于海量数据。

    由于您无法自动化结果评估和验证(忘记“内部”措施,它们是无用的),也不能以任何有意义的方式使用自动结果(部分原因是集群对于自动使用来说太不可靠了)。

    聚类需要你研究结果,学习,然后决定下一步做什么。你不能自动化这个。

    它是探索性的。研究数据的工具;不是机器自动预测标签的工具。有些集群会好,有些会坏。这很好,你有一些很好的集群!只是不要依赖集群中的所有内容。总会有不属于任何集群的数据通常,会有一些集群对您没有任何意义,或者太琐碎而无法使用或感兴趣。

  2. 结果不会随着数据大小而提高。

  3. 方法不能很好地扩展。

    大多数聚类方法(包括 k-means)的最坏情况运行时间为 O(n^2) 或 O(n^3)。这真是有问题。但由于他们正在分析一个 NP-hard 问题,所以这是相当不错的。

    所以我想,你处理一个样本。

  4. 现在 RAM 很大,而向量很紧凑。

    您通常可以将十亿个向量压缩到 RAM 中。因此,任何与数字向量(而不是视频和图像)一起使用的东西——比如 k-means——都适合于主内存。没有必要比这更大。

我同意 Anony-Mousse 的观点,如果您不能轻松地可视化生成的集群并手动评估它们,那么这种技术可能不会很有用。

话虽如此...

  • 选择要减少到的维数:通常,您根据执行降维后丢失原始数据的总方差的多少来决定可接受的信息丢失水平。然后在不低于此限制的情况下使维度数量尽可能少。
  • 选择集群数量:您可以查看维基百科,了解人们如何评估这一点的一些信息。如果您将点与其分配的集群中心的平均距离作为指标,那么一种常见的方法是将这个“误差”绘制为集群数量的函数。显然,随着集群的增加,它总是会变得更小,但有时会出现“弯头”,当您添加更多集群时,您将不再获得更多“物有所值”。

看起来您正在使用 sklearn,因此您可以仔细查看这些工具的文档和用户指南。

已经提供了很好的答案,但我会加两分钱。对我有用的是随机抽样并进行层次聚类。由于它需要创建一个距离矩阵,因此样本大小必须足够小以适应内存。

根据结果​​,您可以选择最佳聚类数。请注意,您应该对随机样本、距离测量和标准化数据的方式进行一些尝试(z-score 对我来说效果最好,我建议您阅读这篇论文)。

简而言之,对层次聚类的修补可能如下所示:

from sklearn import datasets
from matplotlib import pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage
from scipy import stats

# import some data to play with
iris = datasets.load_iris()
X = iris.data
Y = iris.target

X_std = stats.zscore(X)

Z = linkage(X_std,'ward')

# calculate full dendrogram
plt.figure(figsize=(5, 5))
plt.title('Hierarchical Clustering Dendrogram')
plt.xlabel('sample index')
plt.ylabel('distance')
dendrogram(
    Z,
    leaf_rotation=90.,  # rotates the x axis labels
    leaf_font_size=8.,  # font size for the x axis labels
)
plt.show()

这里有一个很棒的教程

你提到了剪影图 - 我会做与层次聚类相同的事情。绘制足够大的随机样本以适应内存并查看绘图。重复此操作以查看您是否使用不同的样本获得相似的结果。

最后,你有没有人可以讨论集群的数量?由于这不是精确的方法,而只是其他人提到的探索性的,因此拥有业务知识可能具有很大的价值。