描述
我使用 build_vocab_from_file()
函数训练了一个 Doc2Vec 模型。这样我可以在索引为 0 的位置手动添加一个 <PAD>
标记。这个标记在原始数据集中没有出现,但在我的程序的后续部分需要使用。
重现步骤/代码/语料库
下面是一个简单的示例,展示了我想要实现的目标:
import collections, sys
import gensim
from gensim import models
from gensim.models.doc2vec import TaggedDocument
lines = [u'It is a truth universally acknowledged',
u'This was invitation enough.',
u'An invitation to dinner was soon afterwards dispatched']
words = [line.split() for line in lines]
doc_labels = [u'text0', u'tex1', u'text2']
word_freq = collections.Counter([w for line in words for w in line])
word_freq['<PAD>'] = sys.maxint # this ensure that the pad token has index 0 in gensim's vocabulary
class DocIterator(object):
def __init__(self, docs, labels):
self.docs = docs
self.labels = labels
def __iter__(self):
for idx, doc in enumerate(self.docs):
yield TaggedDocument(words=doc, tags=[self.labels[idx]])
doc_it = DocIterator(words, doc_labels)
model = gensim.models.Doc2Vec(vector_size=100, min_count=0)
model.build_vocab_from_freq(word_freq)
model.train(doc_it, total_examples=len(lines), epochs=10)
预期结果
预期 model.docvecs.count
的大小为 3(而不是 0)。
实际结果
实际 model.docvecs.count
的大小为 0print(model.docvecs.count)
-> 0
版本
Linux-3.19.0-82-generic-x86_64-with-Ubuntu-15.04-vivid
('Python', '2.7.9 (default, Apr 2 2015, 15:33:21)
[GCC 4.9.2]')
('NumPy', '1.14.3')
('SciPy', '1.1.0')
('gensim', '3.4.0')
('FAST_VERSION', 1)
现在我的问题是:
- 如何正确使用
build_vocab_from_freq()
以获得有效的模型? - 如果无法实现这一点,如何在特定索引值强制 gensim 在词汇表中包含一个未见过的标记?
3条答案
按热度按时间nimxete21#
Doc2Vec
需要在预训练阶段发现所有语料库tags
并分配/初始化它们的向量。但是,这个(新的,从共享超类继承的方法)build_vocab_from_freq()
并没有做Doc2Vec
需要的所有事情,只做了Word2Vec
需要的事情。它需要被重写或者在Doc2Vec
中标记为不支持,或者添加一个辅助方法来帮助设置Doc2Vec
状态。(@manneshiva?)在完成这些之前,你可以查看
build_vocab()
在Doc2Vec
情况下做了哪些额外的事情,并手动将其应用到你的模型中。但是,既然你有一个完整的语料库迭代器,你是否可以直接使用标准的build_vocab()
作为解决方法呢?ajsxfq5m2#
谢谢。在这种情况下,我将使用
build_vocab()
:<PAD>
令牌不在原始数据集中,我无法稍后使用build_vocab(..., update=True)
添加它。这会导致段错误,因为 Doc2Vec 不支持词汇扩展(参见 Segmentation fault using build_vocab(..., update=True) for Doc2Vec #1019)。<PAD>
令牌作为附加文档(以免干扰正常计算文档向量),我无法轻松保证<PAD>
令牌将被分配索引0。由于词汇表中的索引是按频率顺序分配的,我必须创建一个充满<PAD>
令牌的整个文档,其计数高于数据集中任何其他单词。这是非常不希望看到的,因为:(i) 我事先不知道单词频率;(ii) 它会无故占用内存。我调查过的另一个选项是使用
null_word
。然而,build_vocab()
会覆盖任何现有的词汇表:vom3gejh3#
感谢alexandry-augustin的报告,对我来说这看起来像是一个bug,有几个修复版本。
build_vocab
相似(即端到端)