为了账号安全,请及时绑定邮箱和手机立即绑定

从 gensim word2vec 模型中删除旧“单词”的最佳方法是什么?

从 gensim word2vec 模型中删除旧“单词”的最佳方法是什么?

当年话下 2023-08-08 16:21:13
我有一个从项目-项目图构建的“语料库”,这意味着每个句子都是一个图行走路径,每个单词都是一个项目。我想在语料库上训练 word2vec 模型以获得项目的嵌入向量。该图每天都会更新,因此 word2vec 模型会以增加的方式(使用Word2Vec.save()和Word2Vec.load())进行训练,以不断更新项目的向量。与文字不同,我的语料库中的项目有其生命周期,并且每天都会添加新项目。为了防止模型大小不断增长,我需要删除达到其生命周期的项目,同时保持模型可训练。我想出了下面的代码,但我不确定它是否正确和正确:from gensim.models import Word2Vecimport numpy as nptexts = [["a", "b", "c"], ["a", "h", "b"]]m = Word2Vec(texts, size=5, window=5, min_count=1, workers=1)print(m.wv.index2word)print(m.wv.vectors)# drop old wordswordsToDrop = ["b", "c"]for w in wordsToDrop:    i = m.wv.index2word.index(w)    m.wv.index2word.pop(i)    m.wv.vectors = np.delete(m.wv.vectors, i, axis=0)    del m.wv.vocab[w]print(m.wv.index2word)print(m.wv.vectors)m.save("m.model")del m# increased trainingnew = [["a", "e", "n"], ["r", "s"]]m = Word2Vec.load("m.model")m.build_vocab(new, update=True)m.train(new, total_examples=m.corpus_count, epochs=2)print(m.wv.index2word)print(m.wv.vectors)删除和增加训练后,m.wv.index2word和m.wv.vectors仍然元素对应吗?上面的代码有副作用吗?如果我的方法不好,有人可以给我一个例子来展示如何正确删除旧的“单词”并保持模型可训练吗?
查看完整描述

1 回答

?
函数式编程

TA贡献1807条经验 获得超9个赞

Word2Vec一旦单词被“切入”包含范围,就没有官方支持从 Gensim 模型中删除单词。

即使添加单词的能力也没有很好的基础,因为该功能并不基于任何经过验证/已发布的模型更新方法Word2Vec,并且通过学习选择掩盖了更新批次如何影响模型的困难权衡-速率或批次是否完全代表现有词汇。最安全的做法是定期从头开始重新训练模型,使用包含所有相关单词的足够示例的完整语料库。

因此,我的主要建议是定期用经过所有仍然相关数据训练的新模型替换您的模型。这将确保它不再在过时的术语上浪费模型状态,并且所有仍然有效的术语都接受了同等的交错训练。

经过这样的重置后,词向量将无法与之前“模型时代”的词向量相比较。(同一个词,即使它的有形含义没有改变,也可能处于任意不同的位置 - 但与其他向量的相对关系应该保持良好或更好。)但是,同样的比较漂移任何一组小批量更新也会发生这种情况,这些更新不会平等地“接触”每个现有单词,只是以某种无法量化的速度。

OTOH,如果您认为需要保持这种增量更新,即使知道注意事项,您也可以修补模型结构以保留旧模型中尽可能多的合理内容并继续训练。

到目前为止,您的代码是一个合理的开始,缺少正确功能的一些重要注意事项:

  • 由于删除较早的单词会更改较晚的单词的索引位置,因此您需要更新vocab[word].index每个幸存单词的值,以匹配新的index2word排序。例如,完成所有删除后,您可以执行以下操作:

for i, word in enumerate(m.wv.index2word):
    m.wv.vocab[word].index = i
  • 因为在您的(默认负采样)Word2Vec模型中,还有另一个与模型输出层相关的每个单词权重数组,它也应该同步更新,以便每个单词检查正确的输出值粗略地说,每当您从 中删除一行时m.wv.vectors,您都应该从 中删除同一行m.traininables.syn1neg

  • 因为幸存的词汇具有不同的相对词频,负采样和下采样(由参数控制sample)函数都应该处理不同的预先计算的结构来帮助他们的选择。对于负采样使用的累积分布表,这非常简单:

m.make_cum_table(m.wv)

如果这些内部结构与您现有的操作同步正确更新,则模型可能处于一致的状态以进行进一步的训练。(但请注意:这些结构在即将发布的版本中发生了很大变化gensim-4.0.0,因此在升级时任何自定义篡改都需要更新。)

另一项效率说明:np.delete()每次调用该操作时,该操作都会创建一个新数组,即幸存数组的完整大小,并复制旧值。因此,使用它从非常大的原始数组中一次删除多行可能需要大量冗余分配/复制/垃圾收集。您也许可以在最后调用它一次,并列出要删除的所有索引。

但实际上:更简单、更有根据的方法,也可能产生明显更好的连续可比向量,是在可能的情况下或发生大量变化时使用所有当前数据进行重新训练。


查看完整回答
反对 回复 2023-08-08
  • 1 回答
  • 0 关注
  • 196 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号