请澄清带注释的 Transformer 编码器 LayerNorm 实现是否正确。
Transformer paper说子层的输出是
LayerNorm(x + Dropout(SubLayer(x)))
。
LayerNorm
应在 DropOut(SubLayer(x))
之后应用,根据论文:但是,Annotated Transformer
实现会
x + DropOut(SubLayer(LayerNorm(x)))
,其中
LayerNorm
应用于 beforeSublayer
,这是相反的方式。class SublayerConnection(nn.Module):
"""
A residual connection followed by a layer norm.
Note for code simplicity the norm is first as opposed to last.
"""
def __init__(self, size, dropout):
super(SublayerConnection, self).__init__()
self.norm = LayerNorm(size)
self.dropout = nn.Dropout(dropout)
def forward(self, x, sublayer):
"Apply residual connection to any sublayer with the same size."
return x + self.dropout(sublayer(self.norm(x))) # <--- LayerNorm before SubLayer
原论文在Residual Connection和Layer Normalization之前将Dropout应用于Sub-Layer(Multi Head Attention)。这称为后归一化
。dropout到每个子层的输出,before
它被添加到归一化的子层输入(x)和(层)。
但是,最近的方法是预归一化,其中 LayerNorm 应用于子层中的输入 x,如让我们构建 GPT:从头开始,用代码拼写出来。
在过去的五年里,关于 Transformer 的细节几乎没有改变,但有些东西与原始论文略有不同。您会看到在变换(多头注意力)之后应用了加法和范数。但现在更常见的是在变换之前应用LayerNorm,因此出现了Layer Norm的重新洗牌。这称为预规范制定,这也是我们要实施的。
Annotated Transformer 也遵循这种方法。