使用torch.nn.Embedding for GloVe:我们应该微调嵌入还是直接使用它们



虽然迁移学习/微调最近的语言模型(如BERT和XLNET(是一种非常常见的做法,但GloVe的情况如何?

基本上,当使用GloVe来获得可以由下游NN使用的密集向量表示时,我看到了两个选项。

1( 微调GloVe嵌入(pytorch术语,启用梯度(

2( 只需使用不带渐变的嵌入即可。

例如,给定GloVe的嵌入矩阵,我做

embed = nn.Embedding.from_pretrained(torch.tensor(embedding_matrix, dtype=torch.float))
...
dense = nn.Linear(...)

最好的做法是只使用GloVe来获得向量表示(并且只训练密集层和潜在的其他层(,还是也可以微调嵌入矩阵?

您绝对应该微调单词嵌入矩阵。事情是这样的,当你用GloVe单词嵌入初始化单词嵌入矩阵时,你的单词嵌入已经捕获了数据的大部分语义属性。然而,你希望你的单词嵌入是针对你解决的任务量身定制的,即特定任务(Check Yang(。现在,假设你的数据集中没有足够的数据,你就无法独自学习单词嵌入矩阵(如果你用随机向量初始化单词嵌入矩阵(。正因为如此,您需要使用在巨大数据集上训练过的通用向量对其进行初始化。

需要记住的一件非常重要的事情→因为模型的其余部分将被随机初始化,当你开始训练你的单词嵌入矩阵时,你可能会遭受灾难性的遗忘(查看Howard和Ruder以及Kirkpatrick等人的工作(,也就是说,梯度将是巨大的,因为你的模型将大大低于前几批的数据,你将完全失去初始向量。您可以通过以下方式克服此问题:

  1. 对于前几个时期,不要微调单词嵌入矩阵,只需保持原样:embeddings = nn.Embedding.from_pretrained(glove_vectors, freeze=True)

  2. 在模型的其余部分学习到适合您的训练数据后,降低学习率,解冻嵌入模块embeddings.weight.requires_grad = True,然后继续训练。

按照上述步骤操作,您将两全其美。换句话说,您的单词嵌入在为自己的下游任务量身定制的同时,仍将捕获语义属性。最后,有一些作品(例如Check Ye Zhang(表明,立即微调是可以的,但我会选择更安全的选择。

没有理由不微调GloVe嵌入,以便为您的最终任务获得更好的分数,除非您必须与使用原始嵌入的另一个模型保持链接(例如,用于解释结果(。

当为目标函数微调嵌入时,单词嵌入将(潜在地(失去其初始属性(在单词相似性和类比任务中表现良好(。

使用单词嵌入只是一种不使用随机向量初始化的方法,那么保持随机向量固定有意义吗?

有几篇文章对单词嵌入进行了微调,例如这一篇:https://arxiv.org/abs/1505.07931

我假设你有足够的训练数据。否则,最好让单词嵌入固定,因为它涉及较少的训练参数,从而避免过拟合。

最新更新