用DBSCAN聚类word2vec输出的故障排除技巧

2024-05-14 19:42:33 发布

您现在位置:Python中文网/ 问答频道 /正文

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

但是,我很难让DBSCAN输出有意义的结果。它似乎标记了“0”组中的几乎所有内容(图片中的浅绿色)。当我增加epsilon时,“0”组接管了一切。下面是epsilon=10和epsilon=12.5的截图。当epsilon=20时,几乎所有的东西都在同一组中。在

epsilon 10epsilon 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))

Tags: infrom模型importlabelsmodel聚类word2vec
2条回答

我也遇到了同样的问题,我试着用这些方法,把它贴在这里,希望能对你或其他人有所帮助:

  • 调整DBSCAN中的min_samples值以适应您的问题,在我的例子中,默认值4太高了,因为有些集群也可以由2个单词组成。在
  • 显然,从一个更好的语料库开始可以解决您的问题,如果模型初始化得不好,它将无法执行
  • 也许DBSCAN不是更好的选择,我也在为这个问题接近K均值

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

    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)
    

从word2vec的各种可视化效果来看,这些向量可能不会很好地聚集在一起。在

首先,word2vec目标中没有任何东西会鼓励集群。相反,它通过优化词与相邻词的相似度,使相邻词得到相似向量。这对于单词替换的目的是必要的。在

第二,根据这些地块,我不确定是否存在由低密度区域隔开的“密集”区域。相反,数据通常看起来更像一个大团。但当几乎所有的向量都在那个大团中时,它们几乎都在同一个簇中!在

最后,但并非最不重要的是,大多数单词可能不会聚集在一起。是的,数字可能会聚集在一起。你可以期待动词与名词的组合,但是“to bear”和“a bear”与word2vec相同,“bar”(动词和名词)等也是一样的-即使嵌入得很完美,这样的簇还是有太多的多义词无法很好地分开!在

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

相关问题 更多 >

    热门问题