web-dev-qa-db-ja.com

ジェネレーターはイテレーターではありませんか?

ジェネレーター(ものを生成する関数)がありますが、それを_gensim.Word2Vec_に渡そうとすると、次のエラーが発生します。

TypeError:ジェネレーターを文の引数として渡すことはできません。イテレータを試してください。

ジェネレーターは一種のイテレーターではありませんか?そうでない場合、それからイテレータを作成するにはどうすればよいですか?

ライブラリコードを見ると、for x in enumerate(sentences)のような文を単純に反復しているように見えます。これは私のジェネレーターで問題なく機能します。では、何がエラーの原因ですか?

21
riv

ジェネレーターは使い果たされたループを1回繰り返した後です。 Word2vecは単にセンテンスを複数回トラバースする必要があり(おそらく、特定のインデックスのアイテムを取得します。これは、ポップすることしかできないスタックの一種であるジェネレーターでは不可能です)、したがって、リストなどのより堅実なものが必要です。

特に彼らのコードでは、2つの異なる関数を呼び出し、どちらも文を反復処理します(したがって、ジェネレーターを使用すると、2番目の関数は空のセットで実行されます)

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

GeneratorTypeではない__iter__を実装するものなら何でも動作するはずです。したがって、関数を反復可能なインターフェイスでラップし、関数を複数回トラバースできることを確認してください。つまり、

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

コレクションを2回印刷します

11
lejlot

以前のポスターで言及されているように、ジェネレーターはイテレーターと同様に機能しますが、2つの大きな違いがあります。ジェネレーターが使い果たされることと、インデックスを作成できないことです。

このページでドキュメントをすばやく調べました--- 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文字列)のリストです。

関数内のロジックには、アイテムのインデックス作成など、本質的に1つ以上のリストプロパティが必要であると思います。明示的なassertステートメントがあるか、エラーを発生させるifステートメントがある可能性があります。

問題を解決できる簡単なハックは、ジェネレーターをリスト内包表記に変えることです。プログラムはCPUパフォーマンスの低下を維持し、メモリ使用量を増やしますが、これにより少なくともコードが機能するはずです。

my_iterator = [x for x in generator_obj]
7
Alex Volkov

Gensimが誤解を招くエラーメッセージをスローしているようです。

Gensimは、データを複数回反復したいと考えています。ほとんどのライブラリは入力からリストを作成するだけなので、ユーザーは複数の反復可能なシーケンスを提供することを気にする必要はありません。もちろん、メモリ内リストの生成は非常にリソースを消費する可能性がありますが、たとえばファイルを反復処理する場合は、ファイル全体をメモリに保存せずに実行できます。

あなたの場合、ジェネレーターをリスト内包表記に変更するだけで問題が解決するはずです。

3
Tamas Hegedus

他の回答では、GensimはWord2Vecモデルを構築するために2つのパスが必要であると指摘しています。1つは語彙を構築するため(self.build_vocab)、2つ目はモデルをトレーニングするため(self.train)です。 build_vocabメソッドとtrainメソッドを分解することで、ジェネレーターを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)
2
David C