我试图弄清楚嵌入层如何用于预训练的基于 BERT 的模型。我正在使用 pytorch 并尝试剖析以下模型:
import torch
model = torch.hub.load('huggingface/pytorch-transformers', 'model', 'bert-base-uncased')
model.embeddings
这个BERT模型有199个不同的命名参数,其中前5个属于嵌入层(第一层)
==== Embedding Layer ====
embeddings.word_embeddings.weight (30522, 768)
embeddings.position_embeddings.weight (512, 768)
embeddings.token_type_embeddings.weight (2, 768)
embeddings.LayerNorm.weight (768,)
embeddings.LayerNorm.bias (768,)
据我了解,该模型接受任意大小(通常为 32、64 或其他)形状的输入,并且[Batch, Indices]是标记化输入句子中每个单词的相应索引。最大长度为512。一个输入样本可能如下所示:BatchIndicesIndices
[[101, 1996, 4248, 2829, 4419, 14523, 2058, 1996, 13971, 3899, 102]]
这仅包含 1 个批次,是句子“The quick brown fox jumps over the lazy dog”的标记化形式。
第一个word_embeddings权重会将每个数字转换Indices为跨768维度(嵌入维度)的向量。
现在,position_embeddings权重用于编码输入句子中每个单词的位置。在这里我很困惑为什么要学习这个参数?看看 BERT 模型的另一种实现,位置嵌入是一种静态转换。这似乎也是在变压器模型中进行位置编码的传统方式。查看替代实现,它使用正弦和余弦函数对输入中的交错对进行编码。我尝试比较model.embeddings.position_embeddings.weight和pe,但我看不到任何相似之处。在 A.2 预训练程序(第 13 页)下的最后一句中,该论文指出
然后,我们训练 512 序列的其余 10% 的步骤来学习位置嵌入。
为什么位置嵌入权重是学习的而不是预定义的?
位置嵌入之后的下一层是token_type_embeddings. 在这里,我对模型如何推断段标签感到困惑。如果我理解正确,每个输入句子都由[SEP]标记分隔。在上面的示例中,只有 1 个[SEP]标记,并且段标签必须0用于该句子。但最多可以有 2 个段标签。如果是这样,这两个段是分开处理还是并行处理都与一个“数组”相同?模型如何处理多个句段?
最后,这 3 个嵌入的输出被添加在一起并通过我理解的 layernorm。但是,在将模型微调到下游任务时,这些嵌入层中的权重是否会调整?
