2017-05-29 5 views
0

gensim(ver 1.0.1)doc2vecを使用して、ドキュメントのコサインの類似性を取得しようとしています。これは比較的シンプルなはずですが、私は余弦類似性を行うことができるように文書のベクトルを検索する際に問題があります。私が訓練で与えたラベルで文書を検索しようとすると、重大なエラーが発生します。例えばgensimでdocvectorにアクセスする際の問題

print(model.docvecs['4_99.txt'])4_99.txtとしてはそのようなキーが存在しないことを私に教えてくれます。

私はprint(model.docvecs.doctags)を印刷する場合は、私はこのようなものを参照してください。 '4_99.txt_3': Doctag(offset=1644, word_count=12, doc_count=1)

だから、すべての文書について、doc2vecは、「ドキュメント名のアンダースコア番号」

として各文を保存していることが表示されますので、私は A)が誤って訓練や B)は、私がsimilarity(d1, d2)

を行うことができますように、ドキュメントベクトルを取得する方法を理解していないいずれかの誰もが、ここで私を助けることはできますか?ここで

は、私は私のdoc2vecを訓練する方法である:

#Obtain txt abstracts and txt patents 
filedir = os.path.abspath(os.path.join(os.path.dirname(__file__))) 
files = os.listdir(filedir) 

#Doc2Vec takes [['a', 'sentence'], 'and label'] 
docLabels = [f for f in files if f.endswith('.txt')] 

sources = {} #{'2_139.txt': '2_139.txt'} 
for lable in docLabels: 
    sources[lable] = lable 
sentences = LabeledLineSentence(sources) 


model = Doc2Vec(min_count=1, window=10, size=100, sample=1e-4, negative=5, workers=8) 
model.build_vocab(sentences.to_array()) 
for epoch in range(10): 
    model.train(sentences.sentences_perm()) 

model.save('./a2v.d2v') 

これは、このクラスを使用しています

class LabeledLineSentence(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 LabeledSentence(utils.to_unicode(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(LabeledSentence(utils.to_unicode(line).split(), [prefix + '_%s' % item_no])) 
    return self.sentences 

def sentences_perm(self): 
    shuffle(self.sentences) 
    return self.sentences 

私は私が得るのを助けるためにウェブのチュートリアル(https://medium.com/@klintcho/doc2vec-tutorial-using-gensim-ab3ac03d3a1)からこのクラスを得ましたDoc2Vecの奇妙なデータフォーマッティングの必要性について私は完全に正直であると理解していません。ここに書かれているこのクラスは、文ごとに_nを追加したようですが、チュートリアルではファイル名を指定してドキュメントベクトルを取得しているようです...ここで何が間違っていますか?

答えて

1

gensim Doc2Vecクラスは、訓練中に渡したドキュメント「タグ」をdoc-vectorsのキーとして使用します。

そして、そのLabeledLineSentenceクラスは、ドキュメントタグに_nを追加しています。具体的には、関連ファイルの行番号が表示されます。

トレーニング中に提供された同じキーを使用してベクトルをリクエストする必要があります。実際には1行あたりのベクトルが必要な場合は_nとなります。

各ファイルを独自のドキュメントにする場合は、ファイル全体をドキュメントとして使用するようにコーパスクラスを変更する必要があります。参照しているチュートリアルを見ると、ではありませんが、そのような名前が付いていますが、そのバリアントは使用していないことを示す第2のLabeledLineSentenceクラスがあるようです。

別途、ループしてtrain()を複数回呼び出す必要はなく、手動でalphaを調整します。 train()がコーパスを複数回繰り返しているgensimの最近のバージョンでは、あなたが意図していることをほぼ確実に実行していません。 gensimの最新バージョンでは、Web上の古い例の多くがこの誤りを奨励しているので、あなたがそのように呼び出すとエラーになることさえあります。

train()を一度呼び出すだけで、モデルを構築したときに指定した回数だけコーパスを繰り返し処理します。 (デフォルトは5ですが、初期化パラメータのiterで制御可能です。また、Doc2Vecコーパスでは10以上が一般的です)

関連する問題