2017-06-16 121 views
1

我正在使用gensim庫通過doc2vec模型在Python中構建NLP聊天應用程序。我有硬編碼的文檔並給出了一組訓練示例,我通過拋出用戶問題來測試模型,然後找到大多數類似的文檔作爲第一步。在這種情況下,我的測試問題是來自培訓示例的文檔的精確副本。如何提高doc2vec模型中兩個文檔(句子)的餘弦相似度?

import gensim 
from gensim import models 
sentence = models.doc2vec.LabeledSentence(words=[u'sampling',u'what',u'is',u'tell',u'me',u'about'],tags=["SENT_0"]) 
sentence1 = models.doc2vec.LabeledSentence(words=[u'eligibility',u'what',u'is',u'my',u'limit',u'how',u'much',u'can',u'I',u'claim'],tags=["SENT_1"]) 
sentence2 = models.doc2vec.LabeledSentence(words=[u'eligibility',u'I',u'am',u'retiring',u'how',u'much',u'can',u'claim',u'have', u'resigned'],tags=["SENT_2"]) 
sentence3 = models.doc2vec.LabeledSentence(words=[u'what',u'is',u'my',u'eligibility',u'post',u'my',u'promotion'],tags=["SENT_3"]) 
sentence4 = models.doc2vec.LabeledSentence(words=[u'what',u'is', u'my',u'eligibility' u'post',u'my',u'promotion'], tags=["SENT_4"]) 
sentences = [sentence, sentence1, sentence2, sentence3, sentence4] 
class LabeledLineSentence(object): 
    def __init__(self, filename): 
     self.filename = filename 
    def __iter__(self): 
     for uid, line in enumerate(open(filename)): 
      yield LabeledSentence(words=line.split(), labels=['SENT_%s' % uid]) 
model = models.Doc2Vec(alpha=0.03, min_alpha=.025, min_count=2) 
model.build_vocab(sentences) 
for epoch in range(30): 
    model.train(sentences, total_examples=model.corpus_count, epochs = model.iter) 
    model.alpha -= 0.002 # decrease the learning rate` 
    model.min_alpha = model.alpha # fix the learning rate, no decay 
model.save("my_model.doc2vec") 
model_loaded = models.Doc2Vec.load('my_model.doc2vec') 
print (model_loaded.docvecs.most_similar(["SENT_4"])) 

結果:

[('SENT_1', 0.043695494532585144), ('SENT_2', 0.0017897281795740128), ('SENT_0', -0.018954679369926453), ('SENT_3', -0.08253869414329529)] 

SENT_4SENT_3相似度只有-0.08253869414329529當它應該是1,因爲它們是完全一樣的。我應該如何提高這個準確度?有沒有培訓文件的具體方式,我錯過了什麼?

+0

所有SENT_4和SENT_3首先是不完全一樣的。看看單詞「promotion」 –

+0

糾正後:[('SENT_1',0.043695494532585144),('SENT_2',0.0017897281795740128),('SENT_0',-0.018954679369926453),('SENT_3',-0.08253869414329529)] – Kshitiz

回答

1

Word2Vec/Doc2Vec在玩具大小的示例(如少量文本,簡短文本和少量總字)上效果不佳。許多理想的屬性只能通過數百萬字或數萬個文檔的訓練集可靠實現。

特別是,只有5個例子,只有十幾個或兩個單詞,但是建模向量100維,訓練不會被迫做主要的事情,這使word-vectors/doc-vectors很有用:將表示壓縮成稠密嵌入,其中相似項目需要在向量空間中彼此靠近地增量式微移,因爲沒有辦法在巨型查找表排序中保留所有原始變化。除了語料庫變體以外,您的相同標記SENT_3SENT_4可以採用截然不同的文檔向量,並且該模型仍然足夠大以在其培訓任務(基本上,「過度擬合」)方面做得很好,而沒有期望的最終狀態類似的文字有相似的向量被迫。

有時您可以通過更多的訓練迭代以及更小的模型(根據矢量size)從小數據集中擠出更多的含義,但實際上:這些矢量需要大量不同的數據集才能變得有意義。

這是主要問題。其他一些低效或錯誤,在您的示例代碼:

  • 您的代碼不使用類LabeledLineSentence,所以沒有必要在這裏包括它 - 這是無關緊要的樣板。 (另外,TaggedDocument是在最近gensim版本的words + tags文檔類首選的名稱,而不是LabeledSentence)的alpha

  • 您的自定義管理和min_alpha是不可能做任何有用的東西。除非你已經有了一些工作,理解算法,然後想嘗試微妙的優化,否則這些最好保留默認值。

  • train()會做自己的迭代,所以你不需要在外循環中多次調用它。 (這段代碼的寫入在第一個循環中執行,迭代的值爲alpha,值從0.03逐漸下降到0.025,然後在0.028的固定α處進行5次迭代,然後在0.026處再進行5次迭代,然後在α減小的情況下再進行5次迭代27次,以固定的α爲-0.028結束於第30個循環。這是一個無意義的結局值 - 學習率永遠不會是負值 - 在無意義的進展結束時。即使有一個大的數據集,這150次迭代,在負alpha值的一半左右發生的事情,可能會產生奇怪的結果。)