【问题标题】:Copying embeddings for gensim word2vec复制 gensim word2vec 的嵌入
【发布时间】:2019-06-15 00:06:36
【问题描述】:

我想看看我是否可以简单地为 gensim 的 Word2Vec 设置新的权重而无需训练。我从 scikit-learn(来自 sklearn.datasets import fetch_20newsgroups)获得了 20 个新闻组数据集,并在其上训练了一个 Word2Vec 实例:

model_w2v = models.Word2Vec(sg = 1, size=300)
model_w2v.build_vocab(all_tokens)
model_w2v.train(all_tokens, total_examples=model_w2v.corpus_count, epochs = 30)

这里的 all_tokens 是标记化的数据集。 然后我在没有训练的情况下创建了一个新的 Word2Vec 实例

model_w2v_new = models.Word2Vec(sg = 1, size=300)
model_w2v_new.build_vocab(all_tokens)

并将新 Word2Vec 的嵌入设置为等于第一个

model_w2v_new.wv.vectors = model_w2v.wv.vectors

大部分功能都按预期工作,例如

model_w2v.wv.similarity( w1='religion', w2 = 'religions')
> 0.4796233
model_w2v_new.wv.similarity( w1='religion', w2 = 'religions')
> 0.4796233

model_w2v.wv.words_closer_than(w1='religion', w2 = 'judaism')
> ['religions']
model_w2v_new.wv.words_closer_than(w1='religion', w2 = 'judaism')
> ['religions']

entities_list = list(model_w2v.wv.vocab.keys()).remove('religion')

model_w2v.wv.most_similar_to_given(entity1='religion',entities_list = entities_list)
> 'religions'
model_w2v_new.wv.most_similar_to_given(entity1='religion',entities_list = entities_list)
> 'religions'

但是,most_similar 不起作用:

model_w2v.wv.most_similar(positive=['religion'], topn=3)
[('religions', 0.4796232581138611),
 ('judaism', 0.4426296651363373),
 ('theists', 0.43141329288482666)]

model_w2v_new.wv.most_similar(positive=['religion'], topn=3)
>[('roderick', 0.22643062472343445),
> ('nci', 0.21744996309280396),
> ('soviet', 0.20012077689170837)]

我错过了什么?

免责声明。我在datascience.stackexchange 上发布了这个问题,但没有得到回应,希望在这里有更好的运气。

【问题讨论】:

  • 令人惊讶的问题。这可能是距离计算方式的问题。你能分享model_w2v_new.wv.most_similar_cosmul(positive=['religion'], topn=3) 的输出吗?也许其中一个模型默认计算余弦距离而不是欧几里得
  • model_w2v_new.wv.most_similar_cosmul(positive=['religion'], topn=3)model_w2v_new.wv.most_similar(positive=['religion'], topn=3) 具有相同的效果和相同的结果。 gojomo在下面给出了答案。

标签: gensim word2vec word-embedding


【解决方案1】:

通常,您的方法应该有效。

您遇到的具体问题可能是由您采取的额外探测步骤引起的,并且未显示在代码中,因为您没有理由认为它很重要:@ 上的某种 most_similar() 类似操作987654322@ after 它的build_vocab() 调用但之前 后者,故障操作。

传统上,most_similar() 计算在已标准化为单位长度的向量版本上进行。第一次需要这些单位范数向量时,会对其进行计算,然后将其缓存在模型中。因此,如果您随后将原始向量替换为其他值,但不丢弃这些缓存值,您将看到与您报告的结果一样的结果——本质上是随机的,反映了随机初始化但从未训练过的起始向量值.

如果发生这种情况,仅仅丢弃缓存的值应该会导致下一个most_similar() 正确刷新它们,然后您应该会得到您期望的结果:

model_w2v_new.wv.vectors_norm = None

【讨论】:

  • 是的,model_w2v_new.wv.vectors_norm = 没有成功,谢谢。
  • most_similar() 计算是否对已归一化为单位长度并已兑现的向量版本进行操作,但其他函数,例如most_similar_to_given不要?
  • 使用缓存的单位范数向量会快得多,如果它们可用的话,特别是对于像most_similar() 这样的操作,它必须为 每个 向量计算一个值模型——因此也在全向量数组上使用批量数组操作,而不是 most_similar_to_given() 所依赖的一次一个计算。 (most_similar_to_given() 可以而且或许应该使用相同的缓存值,但不会获得那么多的加速。)
  • 谢谢。 “'most_similar_to_given()' 可以并且也许应该使用相同的缓存值,”。它绝对可以使用它。就我而言,我将一个词与语料库中的所有其他词进行比较,'most_similar_to_given()' 需要 >0.6 秒,'most_similar()' 需要 ~2ms
  • 请注意,仅使用缓存值不会缩小全速差距。 most_similar() 操作也更快,因为它可以对整个数组执行批量数组操作,这通常使用本机优化例程而不是 Python 循环。做到这一点的唯一方法是将所有相关向量放在一个连续的内存数组中——对于大量“给定”向量,创建这样一个额外的数组副本将是另一个麻烦。因此,如果您真的要与“全部”甚至“批次”进行比较,您应该直接使用most_similar(),并过滤结果——没有其他方法可以与之竞争。
猜你喜欢
  • 1970-01-01
  • 2018-11-02
  • 2017-09-21
  • 2019-02-07
  • 2019-05-17
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
  • 2017-07-10
相关资源
最近更新 更多