私は最近、Gensim への doc2vec の追加に出会いました。事前にトレーニングされた単語ベクトル (word2vec の元の Web サイトにあるものなど) を doc2vec で使用するにはどうすればよいですか?
それとも、doc2vec は、段落ベクトルのトレーニングに使用するのと同じ文から単語ベクトルを取得していますか?
ありがとう。
"DBOW" ( dm=0
) トレーニング モードは、トレーニングの一部として単語ベクトルを必要とせず、作成さえしないことに注意してください。各単語を順番に予測するのが得意なドキュメント ベクトルを学習するだけです (word2vec スキップグラム トレーニング モードと同様)。
(gensim 0.12.0 より前はtrain_words
、別のコメントで言及されているパラメーターがありました。いくつかのドキュメントでは、単語を共同トレーニングすることが示唆されていました。しかし、これが実際に機能したとは思いません。gensim 0.12.0 以降では、パラメーターdbow_words
、これは、DBOW doc-vectors と同時に単語をスキップグラムトレーニングするように機能します. これにより、トレーニングに時間がかかることに注意してくださいwindow
.
「DM」トレーニング方法 ( dm=1
) では、単語ベクトルはドキュメント ベクトルと共にプロセス中に本質的にトレーニングされ、ドキュメント ベクトルの品質にも影響を与える可能性があります。理論的には、以前のデータから単語ベクトルを事前に初期化することは可能です。しかし、これがドキュメントベクトルを改善すると確信できる強力な理論的または実験的理由はわかりません。
私がこれらの線に沿って実行した断片的な実験の 1 つでは、doc-vector トレーニングの開始が早くなり、最初の数回のパスで予測品質が向上することが示されましたが、この利点はパスが増えるにつれて薄れていきました。単語ベクトルを一定に保つか、新しいトレーニングに合わせて調整し続けるかどうかも重要な考慮事項になる可能性があります...しかし、どちらを選択するのが良いかは、目標、データセット、既存の品質/関連性によって異なります。単語ベクトル。
(gensim 0.12.0 で利用可能な方法で私の実験を繰り返し、値intersect_word2vec_format()
を介してプリロードされたベクターを新しいトレーニングに耐性にするさまざまなレベルを試すことができsyn0_lockf
ます。ただし、これは実験的な領域であることを覚えておいてください: 基本的な doc2vec の結果は「再利用された単語ベクトルに依存するか、必要に応じて改善する必要さえあります。)
さて、私も最近Doc2Vecを使っています。そして、LDAの結果を単語ベクトルとして使用し、それらの単語ベクトルを修正してドキュメントベクトルを取得することを考えていました。しかし、結果はあまり興味深いものではありません。たぶん、私のデータセットがそれほど良くないだけです。コードは以下のとおりです。Doc2Vec は単語ベクトルとドキュメント ベクトルを一緒に辞書 doc2vecmodel.syn0 に保存します。ベクトル値を直接変更できます。唯一の問題は、syn0 内のどの位置がどの単語またはドキュメントを表しているかを調べる必要があることです。ベクトルは辞書 syn0 にランダムな順序で格納されます。
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
from gensim import corpora, models, similarities
import gensim
from sklearn import svm, metrics
import numpy
#Read in texts into div_texts(for LDA and Doc2Vec)
div_texts = []
f = open("clean_ad_nonad.txt")
lines = f.readlines()
f.close()
for line in lines:
div_texts.append(line.strip().split(" "))
#Set up dictionary and MMcorpus
dictionary = corpora.Dictionary(div_texts)
dictionary.save("ad_nonad_lda_deeplearning.dict")
#dictionary = corpora.Dictionary.load("ad_nonad_lda_deeplearning.dict")
print dictionary.token2id["junk"]
corpus = [dictionary.doc2bow(text) for text in div_texts]
corpora.MmCorpus.serialize("ad_nonad_lda_deeplearning.mm", corpus)
#LDA training
id2token = {}
token2id = dictionary.token2id
for onemap in dictionary.token2id:
id2token[token2id[onemap]] = onemap
#ldamodel = models.LdaModel(corpus, num_topics = 100, passes = 1000, id2word = id2token)
#ldamodel.save("ldamodel1000pass.lda")
#ldamodel = models.LdaModel(corpus, num_topics = 100, id2word = id2token)
ldamodel = models.LdaModel.load("ldamodel1000pass.lda")
ldatopics = ldamodel.show_topics(num_topics = 100, num_words = len(dictionary), formatted = False)
print ldatopics[10][1]
print ldatopics[10][1][1]
ldawordindex = {}
for i in range(len(dictionary)):
ldawordindex[ldatopics[0][i][1]] = i
#Doc2Vec initialize
sentences = []
for i in range(len(div_texts)):
string = "SENT_" + str(i)
sentence = models.doc2vec.LabeledSentence(div_texts[i], labels = [string])
sentences.append(sentence)
doc2vecmodel = models.Doc2Vec(sentences, size = 100, window = 5, min_count = 0, dm = 1)
print "Initial word vector for word junk:"
print doc2vecmodel["junk"]
#Replace the word vector with word vectors from LDA
print len(doc2vecmodel.syn0)
index2wordcollection = doc2vecmodel.index2word
print index2wordcollection
for i in range(len(doc2vecmodel.syn0)):
if index2wordcollection[i].startswith("SENT_"):
continue
wordindex = ldawordindex[index2wordcollection[i]]
wordvectorfromlda = [ldatopics[j][wordindex][0] for j in range(100)]
doc2vecmodel.syn0[i] = wordvectorfromlda
#print doc2vecmodel.index2word[26841]
#doc2vecmodel.syn0[0] = [0 for i in range(100)]
print "Changed word vector for word junk:"
print doc2vecmodel["junk"]
#Train Doc2Vec
doc2vecmodel.train_words = False
print "Initial doc vector for 1st document"
print doc2vecmodel["SENT_0"]
for i in range(50):
print "Round: " + str(i)
doc2vecmodel.train(sentences)
print "Trained doc vector for 1st document"
print doc2vecmodel["SENT_0"]
#Using SVM to do classification
resultlist = []
for i in range(4143):
string = "SENT_" + str(i)
resultlist.append(doc2vecmodel[string])
svm_x_train = []
for i in range(1000):
svm_x_train.append(resultlist[i])
for i in range(2210,3210):
svm_x_train.append(resultlist[i])
print len(svm_x_train)
svm_x_test = []
for i in range(1000,2210):
svm_x_test.append(resultlist[i])
for i in range(3210,4143):
svm_x_test.append(resultlist[i])
print len(svm_x_test)
svm_y_train = numpy.array([0 for i in range(2000)])
for i in range(1000,2000):
svm_y_train[i] = 1
print svm_y_train
svm_y_test = numpy.array([0 for i in range(2143)])
for i in range(1210,2143):
svm_y_test[i] = 1
print svm_y_test
svc = svm.SVC(kernel='linear')
svc.fit(svm_x_train, svm_y_train)
expected = svm_y_test
predicted = svc.predict(svm_x_test)
print("Classification report for classifier %s:\n%s\n"
% (svc, metrics.classification_report(expected, predicted)))
print("Confusion matrix:\n%s" % metrics.confusion_matrix(expected, predicted))
print doc2vecmodel["junk"]
Radim は gensim の doc2vec 機能に関するチュートリアルを投稿しました (昨日、私は信じています - あなたの質問はタイムリーです!)。
Gensim は、gensim models.word2vec API ドキュメントで説明されているように、C 実装からの事前トレーニング済みベクトルの読み込みをサポートしています。