Skip to content

Transformer#

论文内容批注#

一些背景#

  1. BELU一种自动评估机器翻译文本的指标。BLEU 得分是一个 0 到 1 之间的数字,用于衡量机器翻译文本与一组高质量参考翻译的相似度。0 表示机器翻译的输出与参考翻译没有重叠(低质量),而 1 表示其与参考翻译完全重叠(高质量)。

事实表明,BLEU 得分与人类对翻译质量的判断有很好的相关性。请注意,即使是人工翻译也无法达到 1.0 的满分。一般来说,>40%就算是很高质量的翻译,>60%则往往超过人工翻译。

  1. LSTM

Seq2Seq#

这个模型非常的有趣,需要不定输出的模型都可以通过使用得到比较好的效果

Encoder#

  1. 下图中的论文说明了,normalization的位置并不固定。 20240423152859.png

  2. attention 是否可以增添一些限制呢?这些也已经有人研究过了。 20240423155537.png

  3. Beam search:用来解决搜索问题的一种技术,它是一种启发式搜索算法,用于在图或树中搜索最优路径。Beam search 是一种贪心算法,它在每一步都保留 k 个最有希望的解,然后在下一步中继续扩展这些解。这样,Beam search 会在搜索空间中保留 k 条路径,而不是只保留一条路径。这样,Beam search 可以在搜索空间中保留多个解,从而提高搜索效率。

  4. optimize的时候也可以硬train一发,把decoder当作agent来进行reward。 Berkley blog

  5. schedule sampling 可以用来解决训练和测试的不一致问题。 论文

Decoder#

在Decoder中就有了cross attention。

代码解释#

self-attention#

资源

这个部分其实非常推荐去看21spring李宏毅老师的视频,有很多启发性的内容!!! 以及一个对比讲解视频

其实Query Key Value 个人认为还是一个比较好理解的逻辑,可以通过3b1b的可视化进行更好的理解。但此外来说,它非常取巧的进行了一种类似于矩阵乘法的操作,来加速了运算速度,并且类似全连接层,加入了全局信息。\

20240422133911.png 20240422133928.png

self-attention
class FeedForwardNetwork(nn.Module):
    def __init__(self, hidden_size, filter_size, dropout_rate):
        super(FeedForwardNetwork, self).__init__()

        self.layer1 = nn.Linear(hidden_size, filter_size)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout(dropout_rate)
        self.layer2 = nn.Linear(filter_size, hidden_size)

        initialize_weight(self.layer1)
        initialize_weight(self.layer2)

    def forward(self, x):
        x = self.layer1(x)
        x = self.relu(x)
        x = self.dropout(x)
        x = self.layer2(x)
        return x


class MultiHeadAttention(nn.Module):
    def __init__(self, hidden_size, dropout_rate, head_size=8):
        super(MultiHeadAttention, self).__init__()

        self.head_size = head_size

        self.att_size = att_size = hidden_size // head_size
        self.scale = att_size ** -0.5

        self.linear_q = nn.Linear(hidden_size, head_size * att_size, bias=False)
        self.linear_k = nn.Linear(hidden_size, head_size * att_size, bias=False)
        self.linear_v = nn.Linear(hidden_size, head_size * att_size, bias=False)
        initialize_weight(self.linear_q)
        initialize_weight(self.linear_k)
        initialize_weight(self.linear_v)

        self.att_dropout = nn.Dropout(dropout_rate)

        self.output_layer = nn.Linear(head_size * att_size, hidden_size,
                                    bias=False)
        initialize_weight(self.output_layer)

    def forward(self, q, k, v, mask, cache=None):
        orig_q_size = q.size()

        d_k = self.att_size
        d_v = self.att_size
        batch_size = q.size(0)

        # head_i = Attention(Q(W^Q)_i, K(W^K)_i, V(W^V)_i)
        q = self.linear_q(q).view(batch_size, -1, self.head_size, d_k)
        if cache is not None and 'encdec_k' in cache:
            k, v = cache['encdec_k'], cache['encdec_v']
        else:
            k = self.linear_k(k).view(batch_size, -1, self.head_size, d_k)
            v = self.linear_v(v).view(batch_size, -1, self.head_size, d_v)

            if cache is not None:
                cache['encdec_k'], cache['encdec_v'] = k, v

        q = q.transpose(1, 2)                  # [b, h, q_len, d_k]
        v = v.transpose(1, 2)                  # [b, h, v_len, d_v]
        k = k.transpose(1, 2).transpose(2, 3)  # [b, h, d_k, k_len]

        # Scaled Dot-Product Attention.
        # Attention(Q, K, V) = softmax((QK^T)/sqrt(d_k))V
        q.mul_(self.scale)
        x = torch.matmul(q, k)  # [b, h, q_len, k_len]
        x.masked_fill_(mask.unsqueeze(1), -1e9)
        x = torch.softmax(x, dim=3)
        x = self.att_dropout(x)
        x = x.matmul(v)  # [b, h, q_len, attn]

        x = x.transpose(1, 2).contiguous()  # [b, q_len, h, attn]
        x = x.view(batch_size, -1, self.head_size * d_v)

        x = self.output_layer(x)

        assert x.size() == orig_q_size
        return x

Last update: 2024年5月7日 14:22:49
Created: 2023年11月16日 19:30:38