Python 如何将Gensim doc2vec与预先训练的词向量一起使用?

Python 如何将Gensim doc2vec与预先训练的词向量一起使用?,python,nlp,gensim,word2vec,doc2vec,Python,Nlp,Gensim,Word2vec,Doc2vec,我最近在Gensim中发现了doc2vec。我如何在doc2vec中使用预先训练好的词向量(如word2vec原始网站中的词向量) 或者doc2vec从它用于段落向量训练的相同句子中获取单词向量 谢谢。Radim刚刚在gensim的doc2vec功能上发布了一条消息(我相信昨天-你的问题是及时的!) Gensim支持从加载预训练向量,如中所述。我最近也在使用Doc2Vec。我正在考虑使用LDA结果作为单词向量,并修复这些单词向量以获得文档向量。但结果并不十分有趣。也许只是我的数据集不太好。 代码

我最近在Gensim中发现了doc2vec。我如何在doc2vec中使用预先训练好的词向量(如word2vec原始网站中的词向量)

或者doc2vec从它用于段落向量训练的相同句子中获取单词向量

谢谢。

Radim刚刚在gensim的doc2vec功能上发布了一条消息(我相信昨天-你的问题是及时的!)


Gensim支持从加载预训练向量,如中所述。

我最近也在使用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"]
请注意,“DBOW”(
dm=0
)训练模式不需要甚至不创建单词向量作为训练的一部分。它只学习能够依次预测每个单词的文档向量(很像word2vec skip gram训练模式)

(在gensim 0.12.0之前,在另一条评论中提到了参数
train_words
,一些文档建议将其与words联合训练。然而,我认为这从未真正起作用。从gensim 0.12.0开始,有一个参数
dbow_words
,它可以在dbow doc的同时跳过gram train words-向量。请注意,这会使培训花费更长的时间–与
窗口相关的因素。因此,如果您不需要单词向量,您仍然可以禁用此选项。)

在“DM”培训方法中(
DM=1
),单词向量在过程中与文档向量一起进行固有的训练,并且可能也会影响文档向量的质量。理论上可以从以前的数据中预初始化单词向量。但我不知道有什么强有力的理论或实验理由可以确信这将改善文档向量

我按照这些思路进行的一个零碎的实验表明,doc向量训练开始得更快——在最初几次传球后预测质量更好——但随着传球次数的增加,这种优势逐渐消失。无论你是保持单词向量不变,还是让它们在新的训练中继续调整,都可能是一个重要的考虑因素降额…但哪种选择更好可能取决于您的目标、数据集以及预先存在的词向量的质量/相关性

(您可以使用
intersect\u word2vec\u格式()重复我的实验)
方法在gensim 0.12.0中可用,并尝试通过
syn0\u lock
值使预加载向量抵抗新的训练。但请记住,这是一个实验领域:doc2vec的基本结果不依赖于重用的词向量,甚至不必改进。)

允许加载预先训练好的单词向量来训练doc2vec。您有一个如何使用它的示例。单词向量必须是C-word2vec工具文本格式:每个单词向量一行,首先是一个表示单词的字符串,然后是空格分隔的浮点值,每个嵌入维度一个

这项工作属于一个团队,他们声称使用预先训练的单词嵌入实际上有助于构建文档向量。然而,无论我是否加载预先训练的嵌入,我都得到了几乎相同的结果


编辑:事实上,我的实验有一个显著的不同。当我加载预训练的嵌入时,我对doc2vec进行了一半的迭代训练,以获得几乎相同的结果(训练的时间比训练的时间长,在我的任务中产生了更糟糕的结果)。

谢谢Aaron..确实及时的问题:)这是在教程中写的:“…如果你只想学习标签的表示法,并保留单词表示法不变,那么该模型也有标志train_words=False”.我知道你可以对word2vec使用预训练向量..问题是,我如何用这些预训练向量来称呼doc2vec?@Stergios:也许我误解了这个问题(我自己也还在跌跌撞撞地完成这一过程)。但推理似乎还没有真正实现——请看。谢天谢地,至少有几个人在积极地进行这项工作。我猜这一序列类似于:1)加载预先训练过的向量;2)为你看不见的句子创建一个带有新标签的向量;3)调用最相似的(“新标签“)。或者,为多个看不见的句子创建向量,并计算这些向量之间的距离。但这只是一个猜测。我知道这有点旧,但您是否设法找到了如何让GloVe和doc2vec协同工作的方法?我认为预先训练的词向量可以改善使用DM=1获得的结果,尤其是在小数据集上,因为因此,如果我在训练数据中有“我喜欢热巧克力”这句话,但是“温暖”这个词从来没有出现过,那么我的模型就不知道应该指定什么向量“我喜欢热巧克力”“如果我不预先初始化向量,对吗?但word2vec初始化将有助于为两个句子分配类似的向量。这只是一个猜测,我不知道这是不是真的。我也不知道doc2vec如何处理看不见的单词。所以假设我在训练中看到了一些单词X,然后我推断出文档的向量,其中也包含看不见的单词Y。这些是随机向量还是被忽略?当我使用word2vec预初始化时,行为会有所不同吗?因为语料库中有更多的单词?或者,我只能预初始化在培训doc2vec模型时也会遇到的字向量吗