如何为 Transformer 实现位置明智的前馈神经网络?

AAY*_*ANE 5 machine-learning transformer-model neural-network pytorch

我很难理解 Transformer 架构中的位置明智前馈神经网络。

在此输入图像描述

让我们以机器翻译任务为例,其中输入是句子。从图中我了解到,对于每个单词,不同的前馈神经网络用于自注意力子层的输出。前馈层应用类似的线性变换,但每个变换的实际权重和偏差不同,因为它们是两个不同的前馈神经网络。

参考LinkPositionWiseFeedForward ,这是神经网络的类

class PositionwiseFeedForward(nn.Module):
    "Implements FFN equation."
    def __init__(self, d_model, d_ff, dropout=0.1):
        super(PositionwiseFeedForward, self).__init__()
        self.w_1 = nn.Linear(d_model, d_ff)
        self.w_2 = nn.Linear(d_ff, d_model)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):
        return self.w_2(self.dropout(F.relu(self.w_1(x))))
Run Code Online (Sandbox Code Playgroud)

我的问题是:

我不认为这有任何立场方面的问题。这是一个简单的两层全连接神经网络。假设 x是句子中每个单词的嵌入列表,句子中的每个单词都由上层使用相同的权重和偏差集进行转换。(如果我错了,请纠正我)

我期望找到类似将每个单词嵌入传递到单独Linear层的东西,该层将具有不同的权重和偏差,以实现与图中所示类似的效果。

ami*_*ola 5

我也有同样的疑问,但我确实同意@Rabin Adhikari 的答案。

在提供的实现中,x传递给该forward方法的 是 shape 的张量(batch_size, sequence_length, embedding_dimension),而不是它的扁平版本(具有 shape (batch_size, sequence_length * embedding_dimension))。(相同的)前馈层仅适用于每个批次和序列中每个位置的最后一个维度(嵌入维度),因此是位置方面的

这解释了论文中的引用,该引用也在下面的答案和您的问题中

虽然不同位置的线性变换是相同的,但它们从(编码器)层到(编码器)层使用不同的参数。

很容易看出,向位置前馈层提供由相同标记的重复组成的序列(此处由通过 获得的简单嵌入表示torch.ones()),您将获得每个标记的相同输出嵌入。

feed_forward = PositionwiseFeedForward(d_model=5, d_ff=3, dropout=0)
input_embeddings = torch.ones(1, 10, 5)
ff_outputs = feed_forward(input_embeddings)

ff_outputs, ff_outputs.shape
# --> (tensor([[[-0.5512, -0.3976,  0.4570,  0.5153,  0.4252],
                [-0.5512, -0.3976,  0.4570,  0.5153,  0.4252],
                [-0.5512, -0.3976,  0.4570,  0.5153,  0.4252],
                [-0.5512, -0.3976,  0.4570,  0.5153,  0.4252],
                [-0.5512, -0.3976,  0.4570,  0.5153,  0.4252],
                [-0.5512, -0.3976,  0.4570,  0.5153,  0.4252],
                [-0.5512, -0.3976,  0.4570,  0.5153,  0.4252],
                [-0.5512, -0.3976,  0.4570,  0.5153,  0.4252],
                [-0.5512, -0.3976,  0.4570,  0.5153,  0.4252],
                [-0.5512, -0.3976,  0.4570,  0.5153,  0.4252]]],
                grad_fn=<ViewBackward0>), torch.Size([1, 10, 5]))
Run Code Online (Sandbox Code Playgroud)

我还想引用《使用 Transformers 进行自然语言处理》一书中的引述

请注意,前馈层通常nn.Linear应用于形状张量(batch_size, input_dim),它独立地作用于批次的每个元素。这实际上对于除最后一个维度之外的任何维度都是正确的,因此当我们传递形状张量时,(batch_size, seq_len, hidden_dim)该层将独立应用于批次和序列的所有标记嵌入。

最终,重要的是要观察到,通过这种方式您可以获得批次中每个令牌的隐藏状态,这使得该架构非常灵活。


kmk*_*urn 1

它确实只是一个前馈网络,而不是每个位置都有一个单独的前馈网络。我不知道\xe2\x80\x99t为什么论文说\xe2\x80\x9cposition-wise\xe2\x80\x9d。正如你所说,这里\xe2\x80\x99s 没有什么真正的位置方面的东西。

\n