使用DBSCAN群集word2vec输出的故障排除提示

时间:2017-01-23 21:22:24

标签: python machine-learning scikit-learn word2vec gensim

我正在分析大约2M原始单词的语料库。我使用gensim的word2vec构建模型,使用sklearn TSNE嵌入向量,并使用sklearn DBSCAN对向量(来自word2vec,而不是TSNE)进行聚类。 TSNE输出看起来很正确:2D空间中单词的布局似乎反映了它们的语义。那里有一组拼写错误,衣服等等。

但是,我在让DBSCAN输出有意义的结果时遇到了麻烦。它似乎标注了" 0"组(图像中的彩色蓝绿色)。随着我增加epsilon," 0"小组接管一切。以下是epsilon = 10和epsilon = 12.5的屏幕截图。在epsilon = 20的情况下,几乎所有东西都在同一组中。

epsilon 10 epsilon 12.5

我希望,例如,"服装"所有人的话语聚集在一起(他们“unclustered @ eps = 10”)。我还期望更多的是100个集群,而不是5到12个集群,并且能够使用epsilon控制集群的大小和数量。

然后是几个问题。我是否正确理解DBSCAN的使用?还有其他聚类算法可能是更好的选择吗?我怎么知道我的数据的聚类算法是什么?

考虑到TSNE看起来是对的,假设我的模型调得很好是否安全?

我可以使用哪些其他技术来将问题与群集隔离开来?我怎么知道它是我的word2vec模型,我使用DBSCAN还是其他什么?

这是我用来执行DBSCAN的代码:

import sys
import gensim
import json
from optparse import OptionParser

import numpy as np
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler

# snip option parsing

model = gensim.models.Word2Vec.load(options.file);
words = sorted(model.vocab.keys())
vectors = StandardScaler().fit_transform([model[w] for w in words])

db = DBSCAN(eps=options.epsilon).fit(vectors)
labels = db.labels_
core_indices = db.core_sample_indices_

n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
print("Estimated {:d} clusters".format(n_clusters), file=sys.stderr)

output = [{'word': w, 'label': np.asscalar(l), 'isCore': i in core_indices} for i, (l, w) in enumerate(zip(labels, words))]
print(json.dumps(output))

2 个答案:

答案 0 :(得分:1)

据我所知,word2vec的各种可视化,矢量可能不会很好地聚类。

首先,word2vec目标中没有任何内容可以鼓励群集。相反,它优化单词以模仿邻居,因此附近的单词将获得类似的向量。这对替换目标一词来说是必要的。

其次,基于这些情节,我不确定那里有低密度区域的“密集”区域。相反,数据通常看起来更像是一个大blob。但是当几乎所有的载体都在那个大块中时,它们几乎都会在同一个簇中!

最后但并非最不重要的是,大多数单词可能不会集群。是的,数字可能会聚集。你期望动词与名词聚类,但“忍受”和“熊”与word2vec相同,所以“bar”(动词和名词)等等 - 这些聚类的多边形太多了即使嵌入是完美的,也要分开!

你最好的猜测是增加未成年人并降低epsilon,直到大多数数据都是噪音,你会发现一些剩余的群集。

答案 1 :(得分:0)

我遇到了同样的问题并尝试了这些解决方案,在此发布,希望它可以帮助您或其他人:

  • 将DBSCAN中的min_samples值修改为您的问题,在我的情况下,默认值4太高,因为某些群集也可能由2个单词组成。
  • 显然,从一个更好的语料库开始可能是你的问题的解决方案,如果模型被严重初始化,它将无法执行
  • 也许DBSCAN不是更好的选择,我也在接近K-Means来解决这个问题

  • 迭代模型的创建也有助于我更好地理解选择哪些参数:

    for eps in np.arange(0.1, 50, 0.1):
        dbscan_model = DBSCAN(eps=eps, min_samples=3, metric_params=None, algorithm="auto", leaf_size=30, p=None, n_jobs=1)
        labels = dbscan_model.fit_predict(mat_words)
    
        clusters = {}
        for i, w in enumerate(words_found):
            clusters[w] = labels[i]
        dbscan_clusters = sorted(clusters.items(), key=operator.itemgetter(1))
        n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
        n_noise = len([lab for lab in labels if lab == -1])
        print("EPS: ", eps, "\tClusters: ", n_clusters, "\tNoise: ", n_noise)