如何对字符串进行KMeans聚类

我是一名数据工程师,对机器学习方法的理解有限,正在尝试在开始编码之前找到一个我能理解的好策略。我想做的是根据键值对创建聚类,其中键是名称,值是一些字符串列表。

目标是根据各自的字符串列表的相似性,创建名称的自然聚类。

例如,在这个数据集中,我期望的自然分组应该是狮子/豹子和浣熊/负鼠,因为单词teeth, tail和carnivore的相似性。

我已经尝试过一种方法,即比较一个条目,例如狮子,遍历每个列表并与其他值进行比较,如果在另一个列表中找到一个值,则分配一个相似性分数。然而,我非常希望使用像K-means聚类算法这样的方法来学习如何使用它,同时我认为/希望它能提供更有意义的一系列聚类。

我觉得我卡住的地方是如何将文本转换为数值表示以及如何最好地做到这一点,之后我觉得我可以遵循一些KMeans教程,但如果有人对如何处理这个问题有任何建议,我会非常感兴趣的。


回答:

解决这个问题有很多方法。但总的来说,这里有一些简单的替代方案 –

  1. 向量表示 – 使用独热编码或TF-IDF来表示句子
  2. 特征提取(可选) – 在大型复杂句子的情况下,您可能希望使用主题模型来提取主题级别的特征。
  3. 聚类 – 可以使用任何聚类方法,如K-means

这里是一个示例代码。

1. 导入和数据

from sklearn.preprocessing import MultiLabelBinarizerfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.decomposition import LatentDirichletAllocationfrom sklearn.cluster import KMeansimport pandas as pddf = pd.DataFrame({"name":['lion','leopard','racoon','possum'], "features":[    ['mane', 'teeth', 'tail', 'carnivore'],     ['spots', 'teeth', 'tail', 'carnivore'],     ['stripes', 'teeth', 'omnivore', 'small'],     ['teeth', 'omnivore', 'small']]})print(df)
      name                           features0     lion     [mane, teeth, tail, carnivore]1  leopard    [spots, teeth, tail, carnivore]2   racoon  [stripes, teeth, omnivore, small]3   possum           [teeth, omnivore, small]

2. 向量表示

您可以使用来自sklearn的多标签二值化器对句子进行独热编码

mlb = MultiLabelBinarizer()vec = mlb.fit_transform(df['features'])vectors = pd.DataFrame(vec, columns=mlb.classes_)vectors
   carnivore  mane  omnivore  small  spots  stripes  tail  teeth0          1     1         0      0      0        0     1      11          1     0         0      0      1        0     1      12          0     0         1      1      0        1     0      13          0     0         1      1      0        0     0      1

或者您可以使用来自sklearn的tf-idf向量化器

tfidf = TfidfVectorizer()vec = tfidf.fit_transform(df['features'].apply(' '.join).to_list())vectors = pd.DataFrame(vec.todense(), columns=tfidf.get_feature_names())print(vectors)
   carnivore      mane  omnivore     small     spots   stripes      tail  \0   0.497096  0.630504  0.000000  0.000000  0.000000  0.000000  0.497096   1   0.497096  0.000000  0.000000  0.000000  0.630504  0.000000  0.497096   2   0.000000  0.000000  0.497096  0.497096  0.000000  0.630504  0.000000   3   0.000000  0.000000  0.640434  0.640434  0.000000  0.000000  0.000000         teeth  0  0.329023  1  0.329023  2  0.329023  3  0.423897  

3. 特征提取(可选)

接下来,我们可以选择使用来自sklearn的LDA来创建主题作为下一步聚类的特征。请注意,您可以在这里使用其他降维或分解方法,但LDA专门用于主题建模,并且非常易于解释(如下面所示),所以我使用了它。

假设数据有2个主题。

#使用LDA创建主题级别特征lda = LatentDirichletAllocation(n_components=2, verbose=0)lda_features = lda.fit_transform(vec)lda_features
array([[0.19035075, 0.80964925],       [0.19035062, 0.80964938],       [0.81496776, 0.18503224],       [0.79598858, 0.20401142]])

为了了解LDA如何决定主题,查看主题-词矩阵来理解主题的组成是有用的。

#主题-词矩阵pd.DataFrame(lda.components_,              index=['topic1', 'topic2'],              columns=tfidf.get_feature_names()).round(1)
        carnivore  mane  omnivore  small  spots  stripes  tail  teethtopic1        0.5   0.5       1.6    1.6    0.5      1.1   0.5    1.3topic2        1.5   1.1       0.5    0.5    1.1      0.5   1.5    1.1

如您所见,代表“食肉动物”主题的词汇属于第二个主题,而代表“杂食动物”动物的词汇代表第一个主题。根据您的数据和内容中的复杂性模式,您的数据包含的潜在主题数量,最好使用网格搜索来找到模型的最佳主题数量。或者,您可以像我一样做出假设。

4. 聚类

最后,让我们使用k-means聚类根据特征的相似性对句子进行分组。

首先,我们先在不使用LDA的情况下进行聚类。

#直接在独热向量或Tfidf向量上使用k-meanskmeans = KMeans(n_clusters=2)kmeans.fit(vec)df['pred'] = kmeans.predict(vec)print(df)
      name                           features  pred0     lion     [mane, teeth, tail, carnivore]     01  leopard    [spots, teeth, tail, carnivore]     02   racoon  [stripes, teeth, omnivore, small]     13   possum           [teeth, omnivore, small]     1

接下来,我们同样做,但这次使用LDA特征。

#聚类主题级别特征kmeans = KMeans(n_clusters=2)kmeans.fit(lda_features)df['pred'] = kmeans.predict(lda_features)
      name                           features  pred0     lion     [mane, teeth, tail, carnivore]     01  leopard    [spots, teeth, tail, carnivore]     02   racoon  [stripes, teeth, omnivore, small]     13   possum           [teeth, omnivore, small]     1

注意:在进行任何聚类工作时,每次重新运行时标签可能会发生变化,但除非数据/参数发生变化,否则不会干扰聚类。也就是说,有时您可能会看到聚类0被标记为聚类1,反之亦然。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注