Gensim Doc2Vec - 为什么infer_vector()使用alpha?

时间:2018-05-07 10:50:07

标签: gensim embedding sentence doc2vec

我尝试将句子映射到向量,以使句子相互比较。为了测试gensim的Doc2Vec模型,我下载了sklearn的新闻组数据集并在其上训练了模型。

为了比较两个句子,我使用了model.infer_vector(),我想知道为什么两个使用同一个句子的调用给了我不同的向量:

model = Doc2Vec(vector_size=100, window=8, min_count=5, workers=6)
model.build_vocab(documents)

epochs=10
for epoch in range(epochs):
    print("Training epoch %d" % (epoch+1))
    model.train(documents,  total_examples=len(documents), epochs=epochs)

    v1 = model.infer_vector("I feel good")
    v2 = model.infer_vector("I feel good")
    print(np.linalg.norm(v1-v2)) 

输出:

  

训练时代1

     

0.41606528

     

训练时代2

     

0.43440753

     

训练时代3

     

0.3203116

     

训练时代4

     

0.3039317

     

训练时代5

     

0.68224543

     

训练时代6

     

0.5862567

     

训练时代7

     

0.5424634

     

训练时代8

     

0.7618142

     

训练时代9

     

0.8170159

     

训练时代10

     

0.6028216

如果我设置alpha和min_alpha = 0,我会得到“我感觉很好”和“感觉很好”的一致向量,但是模型在每个时代都给了我相同的向量,所以它似乎没有学到任何东西:

  

训练时代1

     

0.043668125

     

训练时代2

     

0.043668125

     

训练时代3

     

0.043668125

     

训练时代4

     

0.043668125

     

训练时代5

     

0.043668125

     

训练时代6

     

0.043668125

     

训练时代7

     

0.043668125

     

训练时代8

     

0.043668125

     

训练时代9

     

0.043668125

     

训练时代10

     

0.043668125

所以我的问题是:

  1. 为什么我甚至可以为推理指定学习率?我希望模型只在训练期间而不是在推理过程中改变。

  2. 如果我指定alpha = 0进行推理,为什么这两个向量之间的距离在不同时期不会改变?

1 个答案:

答案 0 :(得分:2)

推理使用alpha因为它与训练是相同的迭代调整过程,仅限于更新一个新文本示例的一个新向量。

所以是的,模型的各种权重都被冻结了。但是,一个新的向量的权重(维度)从小的随机值开始,就像每个其他向量也开始一样,然后在多个训练周期中逐渐推进,以使向量更好地作为用于预测文本单词的doc-vector。然后返回最终的新向量。

这些微调从较大的起始alpha值开始,最后变为可忽略不计的min_alpha。如果alpha为0.0,则不会发生任何训练/推断,因为对可更新权重的每次微调校正在应用之前都会乘以0.0,这意味着不会发生任何变化。

与此不同的是,您的代码存在许多可能妨碍预期结果的问题:

  • 通过循环调用train() epochs次,然后为epochs提供大于1的值,实际上您实际执行epochs * epochs次培训通行证

  • 此外,通过不指定alphamin_alpha,每次调用train()都会将有效alpha从其高值下降到每次调用的低值 - a锯齿模式不适用于这种随机梯度下降优化。 (您的日志中应该有关于此错误的警告。)

很少需要在循环中多次调用train()。只需调用一次,使用正确的epochs值,它就会做正确的事:多次通过,具有平滑衰减的alpha学习率。

另外,在致电infer_vector()时:

  • 它需要一个令牌列表,就像培训示例的words属性一样,documents - 不是字符串中的项目。 (通过提供字符串,它看起来像一个字符列表,因此它将推断文档['I', ' ', 'f', 'e', 'e', 'l', ' ', 'g', 'o', 'o', 'd'] 而不是 ['I', 'feel', 'good']的文档向量。)

  • 这些代币应该与培训文件一样进行预处理 - 例如,如果它们在那里小写,它们应该小写,然后转到infer_vector()

  • 默认参数passes=5非常小,特别是对于短文本 - 许多报告更好的结果,数值为数百或数百

  • 默认参数alpha=0.1与训练默认值0.025相比有些大;使用训练值(特别是使用更多passes)通常可以提供更好的结果

最后,就像训练期间的算法利用随机化(调整单词预测上下文窗口,或随机抽样负面示例,或随机下采样高频词),推理也是如此。因此,即使提供完全相同的令牌也不会自动产生完全相同的推断向量。

但是,如果模型已经过充分训练,并且如上所述调整推理以获得更好的结果,则相同文本的向量应非​​常非常接近。并且因为这是一个随机算法,在运行之间存在一些固有的“抖动”,所以最好使您的下游评估并使用容忍这么小的差异。 (并且,如果您反而看到较大的差异,请更正其他模型/推理问题,通常需要更多数据或其他参数调整。)

如果你想强制确定性,那么在gensim project issue中讨论如何做到这一点。但是,理解&容忍小方差通常更符合这种随机影响算法的选择。