生成器不是迭代器?

Generator is not an iterator?

我有一个生成器(一个生成东西的函数),但是当试图将它传递给 gensim.Word2Vec 时,我收到以下错误:

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

生成器不是迭代器的一种吗?如果没有,我如何从中创建迭代器?

查看库代码,它似乎只是简单地迭代像 for x in enumerate(sentences) 这样的句子,这对我的生成器来说工作得很好。那么是什么导致了错误?

生成器在一个循环后耗尽。 Word2vec 只需要多次遍历句子(并且可能获得给定索引的项目,这对于生成器来说是不可能的,它只是一种只能弹出的堆栈),因此需要更可靠的东西,比如列表。

特别是在他们的代码中,他们调用了两个不同的函数,都对句子进行迭代(因此,如果您使用生成器,第二个函数将 运行 在一个空集上)

self.build_vocab(sentences, trim_rule=trim_rule)
self.train(sentences)

它应该与任何实现 __iter__ 而不是 GeneratorType 的东西一起工作。所以将你的函数包装在一个可迭代的接口中,并确保你可以多次遍历它,这意味着

sentences = your_code
for s in sentences:
  print s
for s in sentences:
  print s

打印你的collection两次

gensim 似乎抛出了误导性的错误消息。

Gensim 想要多次迭代您的数据。大多数库只是根据输入构建一个列表,因此用户不必关心提供多个可迭代序列。当然,生成内存中的列表可能会非常耗费资源,而例如遍历文件时,可以在不将整个文件存储在内存中的情况下完成。

对于您的情况,只需将生成器更改为列表推导即可解决问题。

正如之前的海报所提到的,生成器的行为类似于迭代器,但有两个显着差异:生成器会耗尽,并且您无法索引一个。

我快速查找了文档,在此页面上 -- https://radimrehurek.com/gensim/models/word2vec.html

文档指出

gensim.models.word2vec.Word2Vec(sentences=None, size=100, alpha=0.025, window=5, min_count= 5、max_vocab_size=None, sample=0, seed=1, workers=1, min_alpha=0.0001, sg=1, hs=1, negative=0, cbow_mean=0, hashfxn=, iter=1, null_word=0, trim_rule=None, sorted_vocab=1) ...

从可迭代的句子中初始化模型。每个句子都是将用于训练的单词列表(unicode 字符串)。

我敢猜测函数内部的逻辑本质上需要一个或多个列表属性,例如项目索引,可能有一个显式的断言语句或引发错误的 if 语句。

可以解决您的问题的一个简单技巧是将您的生成器变成列表推导式。您的程序将承受 CPU 性能损失并将增加其内存使用量,但这至少应该使代码正常工作。

my_iterator = [x for x in generator_obj]

其他答案指出 Gensim 需要两遍来构建 Word2Vec 模型:一次构建词汇表 (self.build_vocab),第二次训练模型 (self.train).您仍然可以通过拆分 build_vocabtrain 方法将生成器传递给 train 方法(例如,如果您正在传输数据)。

from gensim.models import Word2Vec

model = Word2Vec()
sentences = my_generator()  # first pass
model.build_vocab(sentences)

sentences = my_generator()  # second pass of same data
model.train(sentences2, 
            total_examples=num_sentences,  # total number of documents to process
            epochs=model.epochs)