2017-12-31 204 views
0

私はword2vecと優れたチュートリアルを使用してdoc2vecherehereを始めるしようとすると、コードサンプルを使用しようとしています。私はline_clean()の句読点、ストップワードなどを削除する方法を追加しました。doc2vec/gensim - エポックでシャッフル文章の問題

しかし、私はトレーニングの反復で呼ばれるline_clean()メソッドに問題があります。私はグローバルメソッドの呼び出しがそれを台無しにしていることを理解していますが、私はこの問題をどのように回避するか分からない。

Iteration 1 
Traceback (most recent call last): 
    File "/Users/santino/Dev/doc2vec_exp/doc2vec_exp_app/doc2vec/untitled.py", line 96, in <module> 
    train() 
    File "/Users/santino/Dev/doc2vec_exp/doc2vec_exp_app/doc2vec/untitled.py", line 91, in train 
    model.train(sentences.sentences_perm(),total_examples=model.corpus_count,epochs=model.iter) 
    File "/Users/santino/Dev/doc2vec_exp/doc2vec_exp_app/doc2vec/untitled.py", line 61, in sentences_perm 
    shuffled = list(self.sentences) 
AttributeError: 'TaggedLineSentence' object has no attribute 'sentences' 

私のコードは以下の通りです:

import gensim 
from gensim import utils 
from gensim.models.doc2vec import TaggedDocument 
from gensim.models import Doc2Vec 
import os 
import random 
import numpy 
from sklearn.linear_model import LogisticRegression 
import logging 
import sys 
from nltk import RegexpTokenizer 
from nltk.corpus import stopwords 

tokenizer = RegexpTokenizer(r'\w+') 
stopword_set = set(stopwords.words('english')) 


def clean_line(line): 
    new_str = unicode(line, errors='replace').lower() #encoding issues 
    dlist = tokenizer.tokenize(new_str) 
    dlist = list(set(dlist).difference(stopword_set)) 
    new_line = ' '.join(dlist) 
    return new_line 


class TaggedLineSentence(object): 
    def __init__(self, sources): 
     self.sources = sources 

     flipped = {} 

     # make sure that keys are unique 
     for key, value in sources.items(): 
      if value not in flipped: 
       flipped[value] = [key] 
      else: 
       raise Exception('Non-unique prefix encountered') 

    def __iter__(self): 
     for source, prefix in self.sources.items(): 
      with utils.smart_open(source) as fin: 
       for item_no, line in enumerate(fin): 
        yield TaggedDocument(utils.to_unicode(clean_line(line)).split(), [prefix + '_%s' % item_no]) 

    def to_array(self): 
     self.sentences = [] 
     for source, prefix in self.sources.items(): 
      with utils.smart_open(source) as fin: 
       for item_no, line in enumerate(fin): 
        self.sentences.append(TaggedDocument(utils.to_unicode(clean_line(line)).split(), [prefix + '_%s' % item_no])) 
     return(self.sentences) 

    def sentences_perm(self): 
     shuffled = list(self.sentences) 
     random.shuffle(shuffled) 
     return(shuffled) 


def train(): 
    #create a list data that stores the content of all text files in order of their names in docLabels 
    doc_files = [f for f in os.listdir('./data/') if f.endswith('.csv')] 

    sources = {} 
    for doc in doc_files: 
     doc2 = os.path.join('./data',doc) 
     sources[doc2] = doc.replace('.csv','') 

    sentences = TaggedLineSentence(sources) 


    # #iterator returned over all documents 
    model = gensim.models.Doc2Vec(size=300, min_count=2, alpha=0.025, min_alpha=0.025) 
    model.build_vocab(sentences) 

    #training of model 
    for epoch in range(10): 
     #random.shuffle(sentences) 
     print 'iteration '+str(epoch+1) 
     #model.train(it) 
     model.alpha -= 0.002 
     model.min_alpha = model.alpha 
     model.train(sentences.sentences_perm(),total_examples=model.corpus_count,epochs=model.iter) 
    #saving the created model 
    model.save('reddit.doc2vec') 
    print "model saved" 

train() 

答えて

3

者はgensimの最新バージョンのための偉大なチュートリアルではありません。特にalpha/min_alphaのマニュアル管理でループ内でtrain()を複数回呼び出すのは悪い考えです。あなたのコードには間違ったことが起こります。たとえば、ほとんどのユーザーには何のメリットもありません。 min_alphaをデフォルトから変更せずに、train()を正確に1回呼び出すと、ちょうどepochs回の反復が行われ、学習率alphaが最大値から最小値まで正しく減衰します。少なくともないto_array()が呼び出された後まで - - と、まだコードがその存在しないプロパティにアクセスしようとしているあなたのTaggedLineSentenceクラスがsentences性質を持っていないため

あなたの具体的なエラーです。

to_array()/sentences_perm()のアプローチは少し壊れています。このような反復可能なクラスを使用する理由は、通常、大きなデータセットをメインメモリから取り出し、ディスクからストリーミングすることです。しかし、to_array()は、クラス内にキャッシュして、すべてをロードするだけで、反復可能な利点は排除されます。あなたは、完全なデータセットを簡単にメモリに収まるので、あなただけの...

sentences = list(TaggedLineSentence(sources) 

...反復-から、ディスクに一度、その後、メモリ内のリストにコーパスを保つことができない、という余裕があれば。

トレーニング中に繰り返しシャッフルする必要はありません。訓練データに何らかの既存の塊りがある場合のみ - 特定の単語/トピックを含むすべての例が注文の上部または下部にまとめられているように、ネイティブの秩序が訓練の問題を引き起こす可能性があります。その場合は、トレーニングの前にシャッフルを1回だけ行うだけで十分です。だから、もう一度、あなたのデータがメモリに収まる、あなただけ...

sentences = random.shuffle(list(TaggedLineSentence(sources) 

を行うことができますと仮定し...一度、あなたは以下の(1回)build_vocab()train()の両方にDoc2Vecに渡す大丈夫ですsentencesを持っています。