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

Ian*_*Ian 6 python machine-learning gensim scikit-learn word2vec

我正在分析大约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

例如,我希望所有的"衣服"字组聚集在一起(它们是非聚集的@ 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))
Run Code Online (Sandbox Code Playgroud)

Nic*_*ini 1

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

  • 根据您的问题调整min_samplesDBSCAN 中的值,在我的例子中,默认值 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)
    
    Run Code Online (Sandbox Code Playgroud)