【问题标题】:Missing words in word2vec vocabularyword2vec 词汇表中缺少单词
【发布时间】:2019-07-07 08:08:10
【问题描述】:

我正在使用来自here 的 mikolov 实现在我自己的文本语料库上训练 word2vec。即使我将最小计数设置为 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

【问题讨论】:

    标签: word2vec


    【解决方案1】:

    只要您使用的是 Python,您可能希望使用 gensim 包中的 Word2Vec 实现。它完成了原始 Mikolov/Googleword2vec.c 所做的一切,甚至更多,而且通常具有性能竞争力。

    特别是,UTF-8 编码不会有任何问题——虽然我不确定 Mikolov/Google word2vec.c 是否正确处理 UTF-8。而且,这可能是您的差异的根源。

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

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

    • 找到一些词,或至少一个有代表性的词,您的令牌计数预计会出现在最终模型中,但实际上并没有。查看那些是否有任何共同特征——包括文件中的上下文。这可能会揭示为什么这两个计数不同。

    再次,我怀疑与 UTF-8 相关,或者可能与 word2vec.c 中的其他实现限制(例如最大字长)相关,这些限制未反映在基于 Python 的字库中。

    【讨论】:

    • 谢谢,我的文本文件是 utf8 编码的,所以可能是编码相关的错误。我将尝试 gensim 实现。
    【解决方案2】:

    您可以使用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

    【讨论】:

      猜你喜欢
      • 2019-09-25
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-28
      • 2016-06-06
      • 2023-01-27
      • 1970-01-01
      相关资源
      最近更新 更多