Pytorch 使用torch.nn.嵌入手套:我们应该微调嵌入物还是按原样使用它们?

Pytorch 使用torch.nn.嵌入手套:我们应该微调嵌入物还是按原样使用它们?,pytorch,glove,Pytorch,Glove,虽然转移学习/微调最近的语言模型,如BERT和XLNET,到目前为止是一种非常普遍的做法,但这对手套来说又如何呢 基本上,当使用手套获得下游NNs可以使用的密集向量表示时,我看到了两种选择 1) 微调手套嵌入(以pytorch术语表示,启用渐变) 2) 只需使用无梯度的嵌入 例如,给定手套的嵌入矩阵,我会 embed = nn.Embedding.from_pretrained(torch.tensor(embedding_matrix, dtype=torch.float)) ... dens

虽然转移学习/微调最近的语言模型,如BERT和XLNET,到目前为止是一种非常普遍的做法,但这对手套来说又如何呢

基本上,当使用手套获得下游NNs可以使用的密集向量表示时,我看到了两种选择

1) 微调手套嵌入(以pytorch术语表示,启用渐变)

2) 只需使用无梯度的嵌入

例如,给定手套的嵌入矩阵,我会

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

最好的做法是单独使用手套来获得矢量表示(并且只训练密集层和潜在的其他层),还是对嵌入矩阵进行微调

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

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

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

有几篇文章对单词embedings进行了微调,例如:


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

您应该完全微调单词嵌入矩阵。事情是这样的,当您使用手套单词嵌入来初始化单词嵌入矩阵时,您的单词嵌入将已经捕获数据的大部分语义属性。但是,您希望您的单词嵌入适合您解决的任务,即特定于任务的(检查)。现在,假设您的数据集中没有足够的数据,您无法自己学习单词嵌入矩阵(如果您使用随机向量初始化单词嵌入矩阵)。正因为如此,您希望使用在大型数据集上训练过的、通用的向量对其进行初始化

要记住一件非常重要的事情→ 由于模型的其余部分将随机初始化,当您开始训练单词嵌入矩阵时,可能会遭受灾难性遗忘(检查和的工作),即,梯度将非常大,因为您的模型将严重不适合前几个批次的数据,你会完全失去初始向量。您可以通过以下方式克服此问题:

  • 对于前几个时代,不要微调单词嵌入矩阵,保持原样:
    embeddings=nn.embedding.from\u pretrained(手套向量,freeze=True)

  • 在模型的其余部分学习适合您的训练数据后,降低学习率,解冻您的嵌入模块
    embeddings.weight.requires\u grad=True
    ,然后继续训练


  • 通过遵循上述步骤,您将两全其美。换句话说,您的单词嵌入仍将捕获语义属性,同时为您自己的下游任务进行定制。最后,有一些作品(例如,检查)表明,立即微调是可以的,但我会选择更安全的选项。

    如果最佳纪元数相对较小,例如3-5个,那么立即微调嵌入也可能是有意义的,对吗?太棒了!不,一点也不,你可以用冻结的嵌入矩阵训练模型直到收敛(实际上,这是推荐的方法),然后解冻嵌入矩阵,让模型训练几个时代。酷,谢谢!你是否碰巧对这种程序有一个合理的参考?来自(也包括在答案中)的论文是NLP中迁移学习的一个很好的来源。虽然它经历了语言模型微调的过程,但建议的方法适用于其他地方。谢谢,这非常有用!:)