有没有办法保存和加载 Gensim Doc2Vec 模型的词汇表
Is there a way to save and load the vocabulary of a Gensim Doc2Vec model
edit
火车语料库是我在这一步之前构建的Spark数据框。我从 parquet 格式加载它并创建了一个 "Feed" class 给 Gensim lib 火车语料库上的迭代器:
class Feed():
def __init__(self, train_data):
self.train_data = train_data
def __iter__(self):
for row in self.train_data.rdd.toLocalIterator():
yield \
gensim.models.doc2vec.TaggedDocument(\
words=[kw.lower() for kw in row["keywords"]] + list(row["tokens_filtered"]),\
tags=[row["id"]])
sdf = spark.read.parquet(save_dirname)
train_corpus = Feed(sdf)
end edit
我希望在约 900 万个新闻文本文档上训练 Gensim Doc2Vec 模型。这是我的模型定义:
model = gensim.models.doc2vec.Doc2Vec(
workers=8,
vector_size=300,
min_count=50,
epochs=10)
第一步是获取词汇:
model.build_vocab(train_corpus)
90 分钟后结束。这是此过程结束时的日志记录信息:
INFO:gensim.models.doc2vec:collected 4202859 word types and 8950263 unique tags from a corpus of 8950339 examples and 1565845381 words
INFO:gensim.models.word2vec:Loading a fresh vocabulary
INFO:gensim.models.word2vec:min_count=50 retains 325027 unique words (7% of original 4202859, drops 3877832)
INFO:gensim.models.word2vec:min_count=50 leaves 1546772183 word corpus (98% of original 1565845381, drops 19073198)
INFO:gensim.models.word2vec:deleting the raw counts dictionary of 4202859 items
INFO:gensim.models.word2vec:sample=0.001 downsamples 9 most-common words
INFO:gensim.models.word2vec:downsampling leaves estimated 1536820314 word corpus (99.4% of prior 1546772183)
INFO:gensim.models.base_any2vec:estimated required memory for 325027 words and 300 dimensions: 13472946500 bytes
然后我在火车语料库上用迭代器class训练模型:
model.train(train_corpus, total_examples=nb_rows, epochs=model.epochs)
最后的训练日志是:
INFO:gensim.models.base_any2vec:EPOCH 1 - PROGRESS: at 99.99% examples, 201921 words/s, in_qsize 16, out_qsize 0
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 7 more threads
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 6 more threads
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 5 more threads
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 4 more threads
但它永远不会完成剩余的线程。
这不是我第一次遇到这个问题,即使火车语料库要小得多。通常,我会重新启动整个过程(词汇设置和模型训练)并继续进行。
至此,为了节省时间,我不想再计算词汇量,而是将之前计算成功的词汇量放到位,只尝试再次训练模型。有没有办法只保存模型的词汇部分,然后加载它直接在火车语料库上训练模型?
至于挂起的原因,看起来您通常都在做正确的事情,但您的 train_corpus
可能出了问题,您没有展示其结构。
Double-check 它的实现,也许编辑您的问题以显示其 type/initialization 的更多细节。查看日志以查看是否有证据表明任何线程遇到错误导致它们处于未按要求进行报告的状态。
您可以 .save()
Doc2Vec
模型的各个部分,例如 model.wv.save(wv_path)
– 但没有简单的方法可以从这些 sub-parts 重建模型。 (这是可能的,但需要仔细注意对象的所需状态,查看源代码,并且容易出错。)
而且,更重要的是,您可以随时 .save()
完整的 Doc2Vec
模型 – 这可能是满足您需求的更好方法。也就是说,您可以在 build_vocab()
之后 .save()
,或者在调用 .train()
之后
如果实际上您当前的挂起是在某个笔记本中,您可以在其中中断挂起操作,并在新单元格中执行新代码,您可能可以从那里保存模型,调试您的 train_corpus
,然后 re-load & re-train – 只要语料库 size/vocabulary 与 build_vocab()
中学到的内容相匹配。
但是,这样的partially-trained.save()
,到头来,会受到已经发生的nearly-complete训练的影响。因此,最终结果不会只是您的配置参数的真实反映,还有一堆多余的 ad-hoc 训练。
如果您想 "clear" 在 re-load 保存一个 Doc2Vec
模型后,部分训练的挥之不去的影响,我相信以下应该做到:
model.trainables.reset_weights(model.hs, model.negative, model.wv, model.docvecs)
edit
火车语料库是我在这一步之前构建的Spark数据框。我从 parquet 格式加载它并创建了一个 "Feed" class 给 Gensim lib 火车语料库上的迭代器:
class Feed():
def __init__(self, train_data):
self.train_data = train_data
def __iter__(self):
for row in self.train_data.rdd.toLocalIterator():
yield \
gensim.models.doc2vec.TaggedDocument(\
words=[kw.lower() for kw in row["keywords"]] + list(row["tokens_filtered"]),\
tags=[row["id"]])
sdf = spark.read.parquet(save_dirname)
train_corpus = Feed(sdf)
end edit
我希望在约 900 万个新闻文本文档上训练 Gensim Doc2Vec 模型。这是我的模型定义:
model = gensim.models.doc2vec.Doc2Vec(
workers=8,
vector_size=300,
min_count=50,
epochs=10)
第一步是获取词汇:
model.build_vocab(train_corpus)
90 分钟后结束。这是此过程结束时的日志记录信息:
INFO:gensim.models.doc2vec:collected 4202859 word types and 8950263 unique tags from a corpus of 8950339 examples and 1565845381 words
INFO:gensim.models.word2vec:Loading a fresh vocabulary
INFO:gensim.models.word2vec:min_count=50 retains 325027 unique words (7% of original 4202859, drops 3877832)
INFO:gensim.models.word2vec:min_count=50 leaves 1546772183 word corpus (98% of original 1565845381, drops 19073198)
INFO:gensim.models.word2vec:deleting the raw counts dictionary of 4202859 items
INFO:gensim.models.word2vec:sample=0.001 downsamples 9 most-common words
INFO:gensim.models.word2vec:downsampling leaves estimated 1536820314 word corpus (99.4% of prior 1546772183)
INFO:gensim.models.base_any2vec:estimated required memory for 325027 words and 300 dimensions: 13472946500 bytes
然后我在火车语料库上用迭代器class训练模型:
model.train(train_corpus, total_examples=nb_rows, epochs=model.epochs)
最后的训练日志是:
INFO:gensim.models.base_any2vec:EPOCH 1 - PROGRESS: at 99.99% examples, 201921 words/s, in_qsize 16, out_qsize 0
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 7 more threads
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 6 more threads
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 5 more threads
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 4 more threads
但它永远不会完成剩余的线程。 这不是我第一次遇到这个问题,即使火车语料库要小得多。通常,我会重新启动整个过程(词汇设置和模型训练)并继续进行。
至此,为了节省时间,我不想再计算词汇量,而是将之前计算成功的词汇量放到位,只尝试再次训练模型。有没有办法只保存模型的词汇部分,然后加载它直接在火车语料库上训练模型?
至于挂起的原因,看起来您通常都在做正确的事情,但您的 train_corpus
可能出了问题,您没有展示其结构。
Double-check 它的实现,也许编辑您的问题以显示其 type/initialization 的更多细节。查看日志以查看是否有证据表明任何线程遇到错误导致它们处于未按要求进行报告的状态。
您可以 .save()
Doc2Vec
模型的各个部分,例如 model.wv.save(wv_path)
– 但没有简单的方法可以从这些 sub-parts 重建模型。 (这是可能的,但需要仔细注意对象的所需状态,查看源代码,并且容易出错。)
而且,更重要的是,您可以随时 .save()
完整的 Doc2Vec
模型 – 这可能是满足您需求的更好方法。也就是说,您可以在 build_vocab()
之后 .save()
,或者在调用 .train()
之后
如果实际上您当前的挂起是在某个笔记本中,您可以在其中中断挂起操作,并在新单元格中执行新代码,您可能可以从那里保存模型,调试您的 train_corpus
,然后 re-load & re-train – 只要语料库 size/vocabulary 与 build_vocab()
中学到的内容相匹配。
但是,这样的partially-trained.save()
,到头来,会受到已经发生的nearly-complete训练的影响。因此,最终结果不会只是您的配置参数的真实反映,还有一堆多余的 ad-hoc 训练。
如果您想 "clear" 在 re-load 保存一个 Doc2Vec
模型后,部分训练的挥之不去的影响,我相信以下应该做到:
model.trainables.reset_weights(model.hs, model.negative, model.wv, model.docvecs)