如何最佳处理word2vec词汇中没有的单词

时间:2019-02-15 12:15:36

标签: python numpy optimization gensim word2vec

我有大约一千万个句子的列表,每个句子最多包含70个单词。

我在每个单词上运行gensim word2vec,然后取每个句子的简单平均值。问题是我使用的是min_count = 1000,所以很多单词不在词汇表中。

为解决这个问题,我将vocab数组(包含大约10000个单词)与每个句子相交,如果该交集中至少剩余一个元素,则返回其简单平均值,否则返回零向量

问题在于,即使在拆分为多个线程时,在整个数据集上运行每个平均值时都需要花费很长时间,并且我想获得一个更好的解决方案,使其运行速度更快。

我正在EC2 r4.4xlarge实例上运行它。

我已经尝试过切换到doc2vec,这速度更快,但结果不如word2vec的简单平均值。

word2vec_aug_32x = Word2Vec(sentences=sentences, 
                        min_count=1000, 
                        size=32, 
                        window=2,
                        workers=16, 
                        sg=0)

vocab_arr = np.array(list(word2vec_aug_32x.wv.vocab.keys()))

def get_embedded_average(sentence):
    sentence = np.intersect1d(sentence, vocab_arr)
    if sentence.shape[0] > 0:
        return np.mean(word2vec_aug_32x[sentence], axis=0).tolist()
    else:
        return np.zeros(32).tolist()

pool = multiprocessing.Pool(processes=16)

w2v_averages = np.asarray(pool.map(get_embedded_average, np.asarray(sentences)))
pool.close()

如果您对以嵌入句子为目的的不同算法或技术有任何建议,并且可以解决我的问题,那么我很乐意阅读。

2 个答案:

答案 0 :(得分:4)

您可以使用FastText代替Word2Vec。 FastText能够通过查看子词信息(字符ngram)来嵌入词汇外的词。 Gensim还具有FastText实现,该实现非常易于使用:

from gensim.models import FastText

model = FastText(sentences=training_data, size=128, ...)

word = 'hello' # can be out of vocabulary
embedding = model[word] # fetches the word embedding

答案 1 :(得分:1)

通常,Doc2Vec文本向量的实用性与普通的单词平均向量相比非常相似(或进行了调整,更好)。 (毕竟,这些算法非常相似,它们以相同的形式处理相同的数据,并且创建的模型大小相同。)如果下降很大,则您的{{1 }}过程。

正如@AnnaKrogager所指出的,FastText可以通过使用单词片段合成猜测向量来处理词汇量不足的单词。 (这需要单词具有这种相同根源的语言。)矢量可能不是很好,但通常比完全忽略未知单词或使用全零矢量或随机插入矢量要好。

是否将其分配给所有有助于运行时的进程?因为在子流程之间来回发送大量的工作量,并且Python中的子流程会导致内存需求激增,而且这种开销甚至虚拟内存交换都可能超过并行性的任何其他好处。 。