我的 Doc2Vec 代码,经过许多 loops/epochs 的培训,并没有给出好的结果。可能出了什么问题?

My Doc2Vec code, after many loops/epochs of training, isn't giving good results. What might be wrong?

我正在使用以下代码训练 Doc2Vec 模型,其中 tagged_data 是我之前设置的 TaggedDocument 个实例的列表:

max_epochs = 40

model = Doc2Vec(alpha=0.025, 
                min_alpha=0.001)

model.build_vocab(tagged_data)

for epoch in range(max_epochs):
    print('iteration {0}'.format(epoch))
    model.train(tagged_data,
                total_examples=model.corpus_count,
                epochs=model.iter)
    # decrease the learning rate
    model.alpha -= 0.001
    # fix the learning rate, no decay
    model.min_alpha = model.alpha

model.save("d2v.model")
print("Model Saved")

当我稍后检查模型结果时,它们并不好。可能出了什么问题?

不要在你自己的试图做 alpha 算术的循环中多次调用 .train()

没有必要,而且容易出错。

具体来说,在上面的代码中,将原始 0.025 alpha 递减 0.001 四十次导致 (0.025 - 40*0.001) -0.015 final alpha,这对于许多训练时期来说也是负面的。但是负 alpha 学习率 是荒谬的:它本质上要求模型在 错误的 方向上稍微调整其预测,而不是在 right 方向上一点点,在每次批量训练更新时。 (此外,由于 model.iter 默认为 5,上面的代码实际上执行了 40 * 5 次训练——200 —— 这可能不是有意识的意图。但这只会让读者感到困惑代码和缓慢的训练,并非完全破坏结果,例如 alpha 处理不当。)

这里还有其他常见的错误变体。如果 alpha0.0001 递减,40 次递减只会将最终的 alpha 减少到 0.021 – 而这种 SGD 风格的正确做法(随机梯度下降) 线性学习率衰减是为了让值“非常接近 0.000”结束。如果用户开始修改 max_epochs – 毕竟,它是一个从顶部拉出的参数! – 但不要每次都调整减量,它们很可能远低于或远超过 0.000.

所以不要使用这种模式。

不幸的是,许多糟糕的在线示例相互复制了这种反模式,在他们自己的epochsalpha处理中犯了严重的错误.请不要复制他们的错误,并请让他们的作者知道他们在任何出现此问题的地方都在误导人们。

上面的代码可以通过更简单的替换来改进:

max_epochs = 40
model = Doc2Vec()  # of course, if non-default parameters needed, use them here
                   # most users won't need to change alpha/min_alpha at all
                   # but many will want to use more than default `epochs=5`

model.build_vocab(tagged_data)
model.train(tagged_data, total_examples=model.corpus_count, epochs=max_epochs)

model.save("d2v.model")

此处,.train() 方法将准确执行 epochs 的请求数量,平滑地将内部有效 alpha 从其默认起始值​​减少到接近零。 (很少需要更改起始 alpha,但即使您愿意,只需在初始模型创建时设置一个新的非默认值就足够了。)

另外:请注意,稍后调用 infer_vector() 将重用在创建模型时指定的 epochs。如果未指定任何内容,将使用默认值 epochs=5 - 通常小于训练或推理的最佳值。因此,如果您发现更大数量的 epochs(例如 10、20 或更多)更适合训练,请记住也至少使用相同数量的 epochs 进行推理。 (.infer_vector() 采用可选的 epochs 参数,该参数可以覆盖模型构造时设置的任何值。