【问题标题】:Sentence iterator to pass to Gensim language model传递给 Gensim 语言模型的句子迭代器
【发布时间】:2019-10-21 11:00:19
【问题描述】:

我对 NLP 比较陌生,我正在尝试创建自己的词嵌入,并在我的个人文档语料库中进行训练。

我正在尝试实现以下代码来创建自己的词嵌入:

model = gensim.models.Word2Vec(sentences)

句子是句子的列表。 因为我不能传递成千上万的句子,所以我需要一个迭代器

# with mini batch_dir a directory with the text files
# MySentences is a class iterating over sentences.
sentences = MySentences(minibatch_dir) # a memory-friendly iterator

我从 gensim 的创建者那里找到了这个解决方案:

class MySentences(object):
    def __init__(self, dirname):
        self.dirname = dirname

    def __iter__(self):
        for fname in os.listdir(self.dirname):
            for line in open(os.path.join(self.dirname, fname)):
                yield line.split()

它对我不起作用。 如果我知道如何从每个文档中获取句子列表,如何创建迭代器?

第二个非常相关的问题: 如果我的目标是比较特定语料库中的文档相似性,那么从头开始使用该特定语料库的所有文档创建词嵌入总是比使用 GloVec 或 word2vec 更好? 文档数量在 40000 左右。

干杯

更多预告

【问题讨论】:

  • “对我不起作用”是什么意思? (是否有错误?结果不理想?)您的数据的初始格式是什么? (许多示例假设并且效果最好,如果您可以创建一个纯文本文件,其中每个“文档”都在自己的行中。)如果您有一个巨大的文件,那么使用从磁盘上的巨型文件工作的迭代器是一个好主意语料库,只有 40K 文档不是很大——对于 Word2Vec/Doc2Vec 来说非常小——并且可能适合作为列表在内存中使用。也就是说,您可以“传递成千上万的句子”。
  • (对于您的第二个“更好”问题,尚不清楚您正在考虑哪两个选项。如果您有足够的自己的数据,则生成的词嵌入通常是比从其他地方导入的更好——你一定会拥有所有你的词的向量,并且在它们特定领域的意义上。但取决于你的数据和最终目标的微妙之处,来自其他地方的向量可能会有所帮助——在所有情况下都没有“通常更好”。)
  • a) 即使我可以让代码也适用于可能拥有大约 250000 个文档、x 50 页 x 30 行 = 25x10^6 个句子的其他人。 2600万句列表……我会试试的。但据我所知,逐句传递可能允许我创建嵌入位的单词。但是您是对的,我可能会尝试使用蛮力并将所有内容全部通过。在内存中生成一个包含 2600 万个句子的列表可能需要一段时间(从一堆文档中生成句子非常耗时;使用 NLTK 和 spacy 进行句子分割需要大量调整以避免错误)
  • b) 这两个选项是,获取我的 40000 个文档并自己创建词向量(嵌入)或 b) 使用 Glovec 或 Word2vec 的词向量。
  • 是的,如果你有 2600 万个句子,那么来自磁盘文件的迭代器是一个更好的解决方案,并且应该可以像许多在线示例中那样工作。因此,如果您仍然遇到问题,请明确说明您遇到的错误/故障以及源数据的格式 - 并且问题应该很容易解决。

标签: python nlp gensim word2vec word-embedding


【解决方案1】:

您的插图类MySentences 假设每行一个句子。您的数据可能并非如此。

需要注意的一点是 - 调用 Word2Vec(sentences, iter=1) 将在句子迭代器上运行两次(或者,通常是 iter+1 次;默认 iter=5)。第一遍收集单词及其频率以构建内部字典树结构。第二遍和后续遍训练神经模型。这两个(或,iter+1)通道也可以手动启动,以防您的输入流是不可重复的(您只能负担一个通道),并且您可以通过其他方式初始化词汇表:

model = gensim.models.Word2Vec(iter=1)  # an empty model, no training yet
model.build_vocab(some_sentences)  # can be a non-repeatable, 1-pass generator
model.train(other_sentences)  # can be a non-repeatable, 1-pass generator

例如,如果您尝试读取存储在数据库中的数据集,则直接从数据库中流式传输文本的生成器函数将抛出 TypeError:

TypeError: You can't pass a generator as the sentences argument. Try an iterator.

一个生成器只能使用一次,然后就被遗忘了。因此,您可以编写一个具有迭代器接口但在后台使用生成器的包装器。

class SentencesIterator():
    def __init__(self, generator_function):
        self.generator_function = generator_function
        self.generator = self.generator_function()

    def __iter__(self):
        # reset the generator
        self.generator = self.generator_function()
        return self

    def __next__(self):
        result = next(self.generator)
        if result is None:
            raise StopIteration
        else:
            return result

生成器函数也被存储,因此它可以像这样在 Gensim 中重置和使用:

from gensim.models import FastText

sentences = SentencesIterator(tokens_generator)
model = FastText(sentences) 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-29
    • 1970-01-01
    • 2012-06-02
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    相关资源
    最近更新 更多