密集合成器的实现

15

我正在尝试理解合成器论文 (https://arxiv.org/pdf/2005.00743.pdf 1),其中描述了密集型合成器机制,该机制应替换Transformer架构中描述的传统注意力模型。

enter image description here

密集合成器(Dense Synthesizer)的描述如下:

enter image description here

所以我尝试实现这个层,它看起来像这样,但我不确定我是否做对了:

class DenseSynthesizer(nn.Module):
    def __init__(self, l, d):
        super(DenseSynthesizer, self).__init__()
        self.linear1 = nn.Linear(d, l)
        self.linear2 = nn.Linear(l, l)

    def forward(self, x, v):
        # Equation (1) and (2)
        # Shape: l x l
        b = self.linear2(F.relu(self.linear1(x)))   
        # Equation (3)
        # [l x l] x [l x d] -> [l x d]
        return torch.matmul(F.softmax(b), v) 

使用方法:

l, d = 4, 5

x, v =  torch.rand(l, d), torch.rand(l, d)

synthesis = DenseSynthesizer(l, d)
synthesis(x, v) 

例子:

x和v都是张量:

x = tensor([[0.0844, 0.2683, 0.4299, 0.1827, 0.1188],
         [0.2793, 0.0389, 0.3834, 0.9897, 0.4197],
         [0.1420, 0.8051, 0.1601, 0.3299, 0.3340],
         [0.8908, 0.1066, 0.1140, 0.7145, 0.3619]])

v = tensor([[0.3806, 0.1775, 0.5457, 0.6746, 0.4505],
         [0.6309, 0.2790, 0.7215, 0.4283, 0.5853],
         [0.7548, 0.6887, 0.0426, 0.1057, 0.7895],
         [0.1881, 0.5334, 0.6834, 0.4845, 0.1960]])

通过密集合成的前向传递,它返回:

>>> synthesis = DenseSynthesizer(l, d)
>>> synthesis(x, v) 

tensor([[0.5371, 0.4528, 0.4560, 0.3735, 0.5492],
        [0.5426, 0.4434, 0.4625, 0.3770, 0.5536],
        [0.5362, 0.4477, 0.4658, 0.3769, 0.5468],
        [0.5430, 0.4461, 0.4559, 0.3755, 0.5551]], grad_fn=<MmBackward>)

实现和理解密集合成器是否正确?

从理论上讲,它与接收两个不同输入并在前向传播的不同点利用它们的多层感知器有何不同?


也在 https://discuss.pytorch.org/t/implementation-of-the-dense-synthesizer/79783 上提问了。 - alvas
1
看起来是正确的。是的,它只是一个MLP。不确定这是否是您期望的答案? - BlackBear
1
问题出在公式2的符号表示上。至少对我来说,不清楚他们是如何执行线性变换的。它可以是(d, l)(l, l),就像你的实现一样,也可以是(d, d)(d, l)。我认为后者可能效果更好。 - Mohammad Arvan
1
此外,(d, d)(d, l) 更符合 QK^t 注意力的对齐方式。 - Mohammad Arvan
1
@MohammadArvan 我认为你对于 (d,d)->(d,l) 是正确的,这与表1中密集变量的参数数量相匹配。 - BlackBear
1个回答

4

密集合成器的实现和理解正确吗?

不完全正确,根据论文,linear1 = nn.Linear(d,d),而不是(d,l)。当然,如果X.shape=(l,d),那么按照矩阵乘法规则就无法工作。

这是因为:

enter image description here enter image description here

因此,对于X中的每个Xi应用F,其中i在[1,l]中。

然后将产生的矩阵B传递给softmax函数并乘以G(x)。因此,您需要修改代码以顺序处理输入,然后使用返回的矩阵计算Y

它与接受两个不同输入并在前向传播的不同点处使用它有什么不同之处?

要理解这一点,我们需要把事情放到上下文中,在编码器-解码器上下文中首次描述引入注意机制的想法在此处描述:https://arxiv.org/pdf/1409.0473.pdf

核心思想是允许模型使用神经网络控制如何检索来自编码器的上下文向量,而不仅仅依赖于最后编码的状态:

enter image description here

有关更多详细信息,请参见此帖子

变压器引入了使用“多头注意力”(请参见下图)来减轻计算负担并仅专注于注意机制本身的想法。此帖子

https://arxiv.org/pdf/1706.03762.pdf

enter image description here

输入图像描述

Dense合成器在其中扮演什么角色?

它简单地使用F(.)替换了点积(如在您帖子中的第一张图片所示)。 如果你用F替换softmax中的内容,你就得到了Y的方程。

输入图像描述

结论

这是一个MLP但是在序列处理的上下文中逐步应用于输入。

谢谢


我认为密集合成器注意机制并不是逐步应用于输入的。它一次性应用于变压器架构的编码器/解码器块中输入的所有状态,而且并没有明确地跨越编码器到解码器。您能否对逐步说明进行一些解释? - alvas
@alvas,这在F函数本身的定义中已经说明了:“F(.),一个带参数的函数,用于将输入的Xid维投影到l维”。F(.)应用于X中的每个标记,F(Xi)= Bi。否则,矩阵形状不兼容进行乘法运算。 - Yoan B. M.Sc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接