Word2Vec词汇中的单词缺失

时间:2019-02-13 13:14:12

标签: word2vec

我正在使用here中mikolov的实现在我自己的文本语料库上训练word2vec。即使我将min-count设置为1,也并非所有来自语料库的唯一单词都得到一个向量。是否有我可能遗漏的参数,这可能就是并非所有唯一单词都得到一个向量的原因吗?还有什么可能是原因?

为了测试word2vecs的行为,我编写了以下脚本,该脚本提供了一个文本文件,其中包含20058个句子和278896个单词(所有单词和标点符号之间用空格分隔,每行只有一个句子)。

import subprocess


def get_w2v_vocab(path_embs):
    vocab = set()
    with open(path_embs, 'r', encoding='utf8') as f:
        next(f)
        for line in f:
            word = line.split(' ')[0]
            vocab.add(word)
    return vocab - {'</s>'}


def train(path_corpus, path_embs):
    subprocess.call(["./word2vec", "-threads", "6", "-train", path_corpus,
                     "-output", path_embs, "-min-count", "1"])


def get_unique_words_in_corpus(path_corpus):
    vocab = []
    with open(path_corpus, 'r', encoding='utf8') as f:
        for line in f:
            vocab.extend(line.strip('\n').split(' '))
    return set(vocab)

def check_equality(expected, actual):
    if not expected == actual:
        diff = len(expected - actual)
        raise Exception('Not equal! Vocab expected: {}, Vocab actual: {}, Diff: {}'.format(len(expected), len(actual), diff))
    print('Expected vocab and actual vocab are equal.')



def main():
    path_corpus = 'test_corpus2.txt'
    path_embs = 'embeddings.vec'
    vocab_expected = get_unique_words_in_corpus(path_corpus)
    train(path_corpus, path_embs)
    vocab_actual = get_w2v_vocab(path_embs)
    check_equality(vocab_expected, vocab_actual)


if __name__ == '__main__':
    main()

此脚本为我提供以下输出:

Starting training using file test_corpus2.txt
Vocab size: 33651
Words in train file: 298954
Alpha: 0.000048  Progress: 99.97%  Words/thread/sec: 388.16k  Traceback (most recent call last):
  File "test_w2v_behaviour.py", line 44, in <module>
    main()
  File "test_w2v_behaviour.py", line 40, in main
    check_equality(vocab_expected, vocab_actual)
  File "test_w2v_behaviour.py", line 29, in check_equality
    raise Exception('Not equal! Vocab expected: {}, Vocab actual: {}, Diff: {}'.format(len(expected), len(actual), diff))
Exception: Not equal! Vocab expected: 42116, Vocab actual: 33650, Diff: 17316

2 个答案:

答案 0 :(得分:1)

只要您使用的是Python,就可能要使用Word2Vec包中的gensim实现。它可以执行原始Mikolov / Google word2vec.c所做的所有工作,并且可以完成更多工作,并且通常具有竞争力。

尤其是,它对UTF-8编码不会有任何问题-尽管我不确定Mikolov / Google word2vec.c是否能正确处理UTF-8。而且,这可能是您差异的原因。

如果您需要深入了解差异,我建议:

  • 让您的get_unique_words_in_corpus()还统计/报告其标记化创建的非唯一单词的总数。如果这与298954报告的word2vec.c不同,那么从对源文件中的“单词”有相同的基线了解来看,这两个过程显然无法正常工作。

  • 查找您的令牌计数希望在最终模型中出现的某些单词或至少一个代表性单词,而不是。复查那些文件的任何共同特征-包括文件中的上下文。这可能会揭示为什么这两个记号不同。

同样,我怀疑与UTF-8相关,或者与word2vec.c中的其他实现限制(例如最大单词长度)有关,而这些未在基于Python的单词计数中反映出来。

答案 1 :(得分:0)

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

from gensim.models import FastText as ft

model = ft(sentences=training_data,)

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

请参见https://stackoverflow.com/a/54709303/3275464