我正在分析大约2M原始单词的语料库。我使用gensim的word2vec构建模型,使用sklearn TSNE嵌入向量,并使用sklearn DBSCAN对向量(来自word2vec,而不是TSNE)进行聚类。 TSNE输出看起来很正确:2D空间中单词的布局似乎反映了它们的语义。那里有一组拼写错误,衣服等等。
但是,我在让DBSCAN输出有意义的结果时遇到了麻烦。它似乎标注了" 0"组(图像中的彩色蓝绿色)。随着我增加epsilon," 0"小组接管一切。以下是epsilon = 10和epsilon = 12.5的屏幕截图。在epsilon = 20的情况下,几乎所有东西都在同一组中。
我希望,例如,"服装"所有人的话语聚集在一起(他们“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))
答案 0 :(得分:1)
据我所知,word2vec的各种可视化,矢量可能不会很好地聚类。
首先,word2vec目标中没有任何内容可以鼓励群集。相反,它优化单词以模仿邻居,因此附近的单词将获得类似的向量。这对替换目标一词来说是必要的。
其次,基于这些情节,我不确定那里有低密度区域的“密集”区域。相反,数据通常看起来更像是一个大blob。但是当几乎所有的载体都在那个大块中时,它们几乎都会在同一个簇中!
最后但并非最不重要的是,大多数单词可能不会集群。是的,数字可能会聚集。你期望动词与名词聚类,但“忍受”和“熊”与word2vec相同,所以“bar”(动词和名词)等等 - 这些聚类的多边形太多了即使嵌入是完美的,也要分开!
你最好的猜测是增加未成年人并降低epsilon,直到大多数数据都是噪音,你会发现一些剩余的群集。
答案 1 :(得分:0)
我遇到了同样的问题并尝试了这些解决方案,在此发布,希望它可以帮助您或其他人:
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)