Gensim Word2vec 模型在增加训练期间不会更新前一个词的嵌入权重
Gensim Word2vec model is not updating the previous word's embedding weights during increased training
我想以增加的方式训练之前训练过的 word2vec 模型,如果在之前的训练过程中已经看到该词,则更新该词的权重,并创建和更新尚未出现的新词的权重在之前的训练过程中看到。例如:
from gensim.models import Word2Vec
# old corpus
corpus = [["0", "1", "2", "3"], ["2", "3", "1"]]
# first train on old corpus
model = Word2Vec(sentences=corpus, size=2, min_count=0, window=2)
# checkout the embedding weights for word "1"
print(model["1"])
# here comes a new corpus with new word "4" and "5"
newCorpus = [["4", "1", "2", "3"], ["1", "5", "2"]]
# update the previous trained model
model.build_vocab(newCorpus, update=True)
model.train(newCorpus, total_examples=model.corpus_count, epochs=1)
# check if new word has embedding weights:
print(model["4"]) # yes
# check if previous word's embedding weights are updated
print(model["1"]) # output the same as before
似乎前一个词的嵌入没有更新,即使前一个词的上下文在新语料库中已经改变。谁能告诉我如何更新之前的嵌入权重?
原问题的答案
尝试在前后打印它们(或者甚至只是几个主要尺寸,例如 print(model['1'][:5])
),看看它们是否发生了变化。
或者,在开始时,使 preEmbed
成为值的适当 副本 (例如:preEmbed = model['1'].copy()
)。
我想您会看到这些值真的发生了变化。
您当前的 preEmbed
变量将只是一个 查看 到随基础数组一起更改的数组中,因此将始终 return True
s 供您稍后检查。
查看关于 Numpy Copies & Views 的文章将有助于解释更多示例的情况。
更新代码的答案
可能在您随后的 single-epoch 训练中,'1'
的所有示例都通过 sample
下采样功能被跳过,因为 '1'
是 very-frequent 你的小语料库中的单词:占所有单词的 28.6%。 (在现实的 natural-language 语料库中,most-frequent 词不会超过所有词的百分之几。)
我怀疑如果您使用 sample=0
禁用此下采样功能,您会看到预期的变化。
(请注意,此功能对于足够的训练数据非常有用,更一般地说,关于 Word2Vec
和相关算法的很多事情,尤其是它们的核心优势,需要大量不同的数据——而且不会'使用 toy-sized 数据集时效果不佳或表现不佳。)
另请注意:您的第二个 .train()
应该对 newCorpus
使用明确准确的计数。 (使用 total_examples=model.corpus_count
到 re-use 缓存的语料库计数在您提供额外数据时可能并不总是合适的,即使它在这里工作正常。)
另一件需要注意的事情:一旦你开始使用模型进行 more-sophisticated 操作,如 .most_similar()
,它会缓存一些计算数据用于 vector-to-vector 比较,并且这些数据不会总是(至少通过 gensim-3.8.3
)通过更多的培训来刷新。因此,您可能必须丢弃该数据(在 gensim-3.8.3
中 model.wv.vectors_norm = None
)以确保获得新的 unit-normed 向量或新的 most_similar()
(及相关方法)结果。
我想以增加的方式训练之前训练过的 word2vec 模型,如果在之前的训练过程中已经看到该词,则更新该词的权重,并创建和更新尚未出现的新词的权重在之前的训练过程中看到。例如:
from gensim.models import Word2Vec
# old corpus
corpus = [["0", "1", "2", "3"], ["2", "3", "1"]]
# first train on old corpus
model = Word2Vec(sentences=corpus, size=2, min_count=0, window=2)
# checkout the embedding weights for word "1"
print(model["1"])
# here comes a new corpus with new word "4" and "5"
newCorpus = [["4", "1", "2", "3"], ["1", "5", "2"]]
# update the previous trained model
model.build_vocab(newCorpus, update=True)
model.train(newCorpus, total_examples=model.corpus_count, epochs=1)
# check if new word has embedding weights:
print(model["4"]) # yes
# check if previous word's embedding weights are updated
print(model["1"]) # output the same as before
似乎前一个词的嵌入没有更新,即使前一个词的上下文在新语料库中已经改变。谁能告诉我如何更新之前的嵌入权重?
原问题的答案
尝试在前后打印它们(或者甚至只是几个主要尺寸,例如 print(model['1'][:5])
),看看它们是否发生了变化。
或者,在开始时,使 preEmbed
成为值的适当 副本 (例如:preEmbed = model['1'].copy()
)。
我想您会看到这些值真的发生了变化。
您当前的 preEmbed
变量将只是一个 查看 到随基础数组一起更改的数组中,因此将始终 return True
s 供您稍后检查。
查看关于 Numpy Copies & Views 的文章将有助于解释更多示例的情况。
更新代码的答案
可能在您随后的 single-epoch 训练中,'1'
的所有示例都通过 sample
下采样功能被跳过,因为 '1'
是 very-frequent 你的小语料库中的单词:占所有单词的 28.6%。 (在现实的 natural-language 语料库中,most-frequent 词不会超过所有词的百分之几。)
我怀疑如果您使用 sample=0
禁用此下采样功能,您会看到预期的变化。
(请注意,此功能对于足够的训练数据非常有用,更一般地说,关于 Word2Vec
和相关算法的很多事情,尤其是它们的核心优势,需要大量不同的数据——而且不会'使用 toy-sized 数据集时效果不佳或表现不佳。)
另请注意:您的第二个 .train()
应该对 newCorpus
使用明确准确的计数。 (使用 total_examples=model.corpus_count
到 re-use 缓存的语料库计数在您提供额外数据时可能并不总是合适的,即使它在这里工作正常。)
另一件需要注意的事情:一旦你开始使用模型进行 more-sophisticated 操作,如 .most_similar()
,它会缓存一些计算数据用于 vector-to-vector 比较,并且这些数据不会总是(至少通过 gensim-3.8.3
)通过更多的培训来刷新。因此,您可能必须丢弃该数据(在 gensim-3.8.3
中 model.wv.vectors_norm = None
)以确保获得新的 unit-normed 向量或新的 most_similar()
(及相关方法)结果。