transformer的学习:Attention is all you need

目录

整体概述:​编辑​编辑

encoder:

embedding:

​编辑

self-attention:

向量的相似度计算:

qkv怎么来的​编辑

softmax:

code

multi-head-attention

位置编码:

残差&&FFN:

decoder:

cross-attention

self-attention

Linear + softmax

Train&&loss

ref:


找到了一篇写的很好的贴子,记录一些学习笔记:

https://jalammar.github.io/illustrated-transformer/

注意力机制(Attention),这是现代深度学习模型中常见的一种方法。注意力机制在神经机器翻译应用中起到了提升性能的作用。本文将介绍Transformer模型,它利用注意力机制提高了模型的训练速度。在某些任务中,Transformer模型的性能超过了Google神经机器翻译模型。然而,最大的好处来自于Transformer模型在并行化方面的优势。实际上,Google Cloud建议使用Transformer模型作为参考模型来使用他们的Cloud TPU服务。

Transformer模型是在论文《Attention is All You Need》中提出的。TensorFlow的一个实现可以在Tensor2Tensor软件包中找到。哈佛大学的自然语言处理研究组创建了一个带有PyTorch实现的指南。

整体概述:

Transformers = encoders + decoders

Encoders = 6 * encoder

Decoders = 6 * decoder

Encoder = self-attention + feed forward nn

Decoder = self-attention + encoder-decoder attention(cross attention) + Feed Forward

encoder-decoder attention:q来自decoder,k和v来自encoder

encoder:

embedding:

文本-->数字,计算机只认识数字

在Transformer模型中,输入序列的词嵌入(word embedding)是模型的一部分,用于将离散的词或标记映射到连续的向量表示。Transformer中的词嵌入被称为输入嵌入(input embedding)。

输入嵌入的作用是将输入序列中的每个词或标记转换为连续的低维向量表示,以便模型能够对其进行处理。这些嵌入向量可以捕捉词语之间的语义和语法信息,从而提供有关词语的上下文表示。

通常情况下,输入嵌入是通过一个可训练的矩阵(通常称为嵌入矩阵)来实现的。该矩阵的大小为词汇表的大小(词汇表中唯一词汇的数量)乘以词嵌入的维度。在训练过程中,嵌入矩阵的参数会随着模型的训练而学习得到。

在Transformer中,输入嵌入通常与位置编码进行相加,以融合词汇和位置信息。这样,每个输入位置都具有一个综合的表示,其中包括词汇信息和相对位置信息。

需要注意的是,Transformer模型中的嵌入层可以是单独的一层,也可以与其他层(如位置编码层、注意力层、前馈神经网络层)一起构成一个整体的模型。输入嵌入在Transformer中起到了将离散的输入序列转换为连续的向量表示的重要作用,为模型提供了有效的输入表示。

torch.nn.embedding()实现

self-attention:

计算相似度。把文本embedding为一个个的词向量token,然后直接相乘(投影)来计算相似度。

上面可以看出it和the animal的相似度很高,以为it就是代指the animal,和because的相似度很低,没啥关系,一个是关系代词,一个是因果连词。

在Transformer模型中,自注意力机制(self-attention)是其核心组成部分之一,也被称为注意力机制(attention mechanism)。自注意力机制允许模型在处理输入序列时,根据序列中不同位置的相关性动态地分配注意力权重。

自注意力机制的目的是对输入序列中的每个位置进行编码,并建立位置之间的关联。它通过计算一个注意力分数来确定每个位置与其他位置之间的关联强度,然后利用这些关联强度对位置的表示进行加权求和。

在Transformer中,自注意力机制的计算过程分为三个步骤:查询(query)、键(key)和值(value)。

  1. 查询(Query):对于每个位置,通过一个线性变换将输入序列中的每个位置映射到一个查询向量,表示该位置的特征。

  2. 键(Key)和值(Value):同样,通过线性变换将输入序列中的每个位置映射到键向量和值向量。键向量用于计算注意力权重,值向量用于加权求和。

  3. 注意力计算:利用查询向量、键向量和值向量计算注意力权重。注意力权重表示每个位置与其他位置之间的关联强度。一般使用点积注意力或加性注意力机制来计算注意力权重。

    1. 点积注意力:通过计算查询向量和键向量之间的点积,然后进行标准化处理,得到注意力权重。

    2. 加性注意力:通过将查询向量和键向量进行线性变换后相加,并应用激活函数,然后进行标准化处理,得到注意力权重。

  4. 加权求和:利用注意力权重对值向量进行加权求和,得到每个位置经过注意力机制后的表示。

自注意力机制可以将输入序列中的不同位置之间的相关性进行建模,从而使模型能够根据输入的上下文动态地分配注意力。这种机制使得Transformer能够在处理序列任务时更好地捕捉长距离依赖关系,提高模型的性能和泛化能力。注意力机制被广泛应用于自然语言处理和机器翻译等任务中。

x-->q,k,v 使用fc,把维度从embedding后的x的512 mapping到64

key:可以看作一本书的目录

value:某一章节(key)里面的内容

query:你的查询关键词

除以8(论文中使用的键向量维度的平方根 - 64)。这样做可以使梯度更加稳定。将结果通过softmax操作进行处理。Softmax函数对得分进行归一化,使得它们都为正值且总和为1。

softmax后的值表示的是相似度权重weight的意思,即最后的权重分配中,k1分的权重是0.88,k2只有0.12,表达的意思是k1和q1更加相似,所以权重更大。

比如:q1是猫a,k1是猫b,k2是狗,那么猫a和猫b的相似度>猫a和狗的相似度,所以猫b的权重是0.88,狗的权重是0.12

Z = sum(权重 * value)

向量的相似度计算:

Cos (θ) = (A·B) / (||A|| ||B||)

余弦相似度是一种衡量两个向量在向量空间中夹角大小的方法。 在二维空间中,我们可以将向量看作是从原点出发的箭头,而余弦相似度就是这两个箭头夹角的余弦值。 这个值介于-1和1之间,值越大表示两个向量越相似,值越小表示两个向量越不相似。 二、余弦相似度的计算 余弦相似度的计算公式为:cos (θ) = (A·B) / (||A|| ||B||),其中A和B是两个向量,||A||和||B||分别表示A和B的模(长度),A·B表示A和B的点积。

假设我们规定||A||和||B||分别表示A和B的模(长度)都是1,那么

Cos (θ) = (A·B)

相似度就是两个向量的点积。

qkv怎么来的

mlp实现的,conv1d

softmax:

Softmax函数是一个常用的数学函数,通常用于将一组实数转换为概率分布。Softmax函数接受一个实数向量作为输入,并将每个元素转换为非负数,使得所有元素之和等于1,表示它们在概率分布中的概率。

softmax(x) = [exp(x₁) / (exp(x₁) + exp(x₂) + ... + exp(xₙ)),exp(x₂) / (exp(x₁) + exp(x₂) + ... + exp(xₙ)),

...exp(xₙ) / (exp(x₁) + exp(x₂) + ... + exp(xₙ))]

例如:

计算的结果可能是一些其他值:21,6,3--》softmax:

Sum = e(21) + e(6) + e(3)

softmax(x1) = e(21) / sum

softmax(x2) = e(6) / sum

softmax(x3) = e(3) / sum

softmax(x) =[ e(21) / sum ,e(6) / sum , e(3) / sum ]

code

# attention
class ScaledDotProductAttention(nn.Module):
    """ Scaled Dot-Product Attention """
    def __init__(self, scale):
        super().__init__()
        self.scale = scale
        self.softmax = nn.Softmax(dim=2)

    def forward(self, q, k, v, mask=None):
        u = torch.bmm(q, k.transpose(1, 2))  # 1.Matmul,(bs,2,4)
        u = u / self.scale  # 2.Scale
        if mask is not None:
            mask[0,1,1] = 1
            u = u.masked_fill(mask, -np.inf)  # 3.Mask atten, e(-inf) = 0
        attn = self.softmax(u)  # 4.Softmax (bs,2,4)2query,4key, u:4*64,4key,64 length
        output = torch.bmm(attn, v)  # 5.Output:bs,2(query个数),64(value长度)
        return attn, output

if __name__ == "__main__":
    batch  = 192
    # n_q, n_k, n_v = 2, 4, 4      # 2 query,4 key,4 value,总共2*4=8个weight
    n_q, n_k, n_v = 200, 480*640, 480*640      # 2 query,4 key,4 value,总共2*4=8个weight
    d_q, d_k, d_v = 128, 128, 64 #
    # n_q, n_k, n_v = 1208, 1208, 1208  # 2 query,4 key,4 value,总共2*4=8个weight
    # d_q, d_k, d_v = 64, 64, 64  #
    q = torch.randn(batch, n_q, d_q) # bs*2*128
    k = torch.randn(batch, n_k, d_k) # bs*4*128
    v = torch.randn(batch, n_v, d_v) # bs*4*64
    mask = torch.zeros(batch, n_q, n_k).bool()

    attention = ScaledDotProductAttention(scale=np.power(d_k, 0.5))  # scale是query和key长度128的根号
    attn, output = attention(q, k, v, mask=mask)

multi-head-attention

在传统的注意力机制中,给定一个查询(Query)和一组键值对(Key-Value Pairs),注意力机制通过计算查询与每个键之间的相关度,然后将这些相关度应用于对应值的加权和。这种单头的注意力机制可以捕捉到一种特定的关注模式,但可能无法充分表达序列中丰富的关系。

多头注意力通过引入多个子注意力头来解决这个问题。在每个子头中,通过对查询、键和值进行独立的线性变换,然后计算相应的注意力权重。最后,将所有子头的注意力权重加权和作为最终的输出。

具体来说,多头注意力可以分为以下几个步骤:

  1. 线性变换:对查询、键和值进行线性变换,将它们映射到不同的表示空间。这可以通过矩阵乘法实现,其中每个子头都有自己的权重矩阵。

  2. 注意力计算:对于每个子头,通过计算查询与键的内积,然后进行缩放(通常是除以查询维度的平方根),得到注意力得分。注意力得分可以表示查询与键的相关度。

  3. 注意力权重:通过将注意力得分经过 softmax 函数进行归一化,得到每个键的注意力权重。这些权重决定了对应值的重要程度。

  4. 加权和:将每个子头的注意力权重与对应的值相乘,然后将它们加权求和得到最终的输出表示。

多头注意力的优势在于它能够并行计算多个子头,从而提高模型的计算效率。同时,每个子头可以关注输入序列中不同的部分,从而捕捉到更丰富的关系。最终的输出表示将多个子头的信息整合在一起,以提供更全面的表示能力。

我可以把输入的x分解为一个qkv,也可以分解为8个qkv(8 heads)

多头的本质无非就是多了几组参数,模型参数越大,拟合能力越强

import torch.nn as nn
import torch
import numpy as np
from attention import ScaledDotProductAttention

class MultiHeadAttention(nn.Module):
    """ Multi-Head Attention """
    def __init__(self, n_head, d_k_, d_v_, d_k, d_v, d_o):
        super().__init__()

        self.n_head = n_head
        self.d_k = d_k
        self.d_v = d_v

        self.fc_q = nn.Linear(d_k_, n_head * d_k)  # d_k_  = d_q_,  (128)d_k_ != d_k(256)
        self.fc_k = nn.Linear(d_k_, n_head * d_k)
        self.fc_v = nn.Linear(d_v_, n_head * d_v)

        self.attention = ScaledDotProductAttention(scale=np.power(d_k, 0.5))

        self.fc_o = nn.Linear(n_head * d_v, d_o)

    def forward(self, q, k, v, mask=None):
        n_head, d_q, d_k, d_v = self.n_head, self.d_k, self.d_k, self.d_v

        batch, n_q, d_q_ = q.size()
        batch, n_k, d_k_ = k.size()
        batch, n_v, d_v_ = v.size()
        """一组qkv(各自random来,可以不同) linear 多组 qkv
        q,k,v来自相同的x就是self-attention,否则就是cross attention"""
        q = self.fc_q(q)  # 1.单头变多头, (bs,2,128) -->(bs,2,2048) ,16倍
        k = self.fc_k(k)  # (bs,4,128) -->(bs,4,2048)
        v = self.fc_v(v)  # (bs,4,64) --> (bs,4,1024)
        q = q.view(batch, n_q, n_head, d_q).permute(2, 0, 1, 3).contiguous().view(-1, n_q, d_q)  # (8,2,256)
        k = k.view(batch, n_k, n_head, d_k).permute(2, 0, 1, 3).contiguous().view(-1, n_k, d_k)
        v = v.view(batch, n_v, n_head, d_v).permute(2, 0, 1, 3).contiguous().view(-1, n_v, d_v)

        if mask is not None:
            mask = mask.repeat(n_head, 1, 1)
        attn, output = self.attention(q, k, v, mask=mask)  # 2.当成单头注意力求输出

        output = output.view(n_head, batch, n_q, d_v).permute(1, 2, 0, 3).contiguous().view(batch, n_q, -1)  # 3.Concat
        output = self.fc_o(output)  # 4.仿射变换得到最终输出

        return attn, output


if __name__ == "__main__":
    batch = 2
    n_q, n_k, n_v = 2, 4, 4
    d_q_, d_k_, d_v_ = 128, 128, 64
    # 192,1408
    q = torch.randn(batch, n_q, d_q_)
    k = torch.randn(batch, n_k, d_k_)
    v = torch.randn(batch, n_v, d_v_)
    mask = torch.zeros(batch, n_q, n_k).bool()

    mha = MultiHeadAttention(n_head=8, d_k_=128, d_v_=64, d_k=256, d_v=128, d_o=128)
    attn, output = mha(q, k, v, mask=mask)

在对单词"it"进行编码时,一个注意力头(attention head)主要关注"the animal",而另一个注意力头则主要关注"tired"。从某种意义上说,模型对单词"it"的表示融入了"animal"和"tired"两个单词的一些表示信息。

这种现象是由于自注意力机制的特性所导致的。在自注意力机制中,每个单词都可以与其他单词进行交互,并根据其在句子中的上下文关系来计算权重。在编码单词"it"时,注意力头会根据输入句子的整体语义进行选择性地关注相关的单词。

因此,一个注意力头可能更关注与"it"在语义上相关的"the animal",而另一个注意力头则更关注与"it"在语义上相关的"tired"。这种注意力分配的机制使得模型在表示"it"时同时包含了与"the animal"和"tired"相关的一些信息。

通过这种方式,模型可以在编码过程中将相关的上下文信息融入到每个单词的表示中,从而更好地捕捉单词之间的语义关联。这种融合的表示有助于提高模型对整个句子的理解和语义表达能力。

位置编码:

位置编码是一种用于为序列数据中的每个位置赋予特定的编码信息的技术。在自注意力机制(如Transformer模型)中,位置编码被用于为输入序列中的每个单词或位置赋予其相对位置的信息,这样模型可以利用这些位置信息来更好地建模单词之间的顺序关系。

在Transformer模型中,常用的位置编码方法是使用正弦和余弦函数来生成位置向量。具体而言,对于序列中的每个位置i和每个维度j,位置编码向量PE(i, j)可以通过以下公式计算得到:

PE(i, 2j) = sin(i / 10000^(2j/d_model))

PE(i, 2j+1) = cos(i / 10000^(2j/d_model))

其中,i表示位置,j表示维度,d_model表示模型的维度。通过这种方式,位置编码向量中的奇数维度用正弦函数编码,偶数维度用余弦函数编码。这样,不同位置的位置编码向量在不同维度上的数值差异可以反映出它们之间的相对位置关系。

位置编码向量可以与输入的词向量相加,从而将位置信息融入到词向量中。这样,模型在进行自注意力计算时不仅考虑单词的语义信息,还会考虑它们在序列中的相对位置关系。位置编码的引入有助于模型更好地捕捉序列数据中的顺序信息,提高模型对序列的理解能力。

需要注意的是,位置编码是在模型的输入阶段添加的,它不会随着训练而更新。它提供了一种固定的表示方式,用于传达位置信息给模型。

该算法使用正弦和余弦函数来生成位置编码向量,具有以下几个原因:

  1. 周期性:正弦和余弦函数具有周期性的特性,可以在位置编码中表达不同位置之间的相对距离。通过使用这两个函数,我们可以创建一种循环的模式,使得相同距离的位置在编码向量中具有相似的值。

  2. 连续性:正弦和余弦函数是连续的函数,可以提供平滑的变化。这样,在相邻位置之间的微小变化也可以在位置编码中得到对应的微小变化,从而更好地捕捉到位置之间的细微差异。

  3. 兼容性:位置编码算法与Transformer模型的自注意力机制相兼容。在自注意力计算中,位置编码向量可以与输入的词向量相加,从而将位置信息融入到模型中。由于正弦和余弦函数的周期性和连续性特征,位置编码向量与词向量的加和操作可以保持一定的平衡,不会引入过大的变动。

假设我们仍然使用示例中的文本序列:"I love natural language processing.",并假设d_model为4。

对于单词"I",我们计算其位置编码向量。

对于每个位置i和每个维度j,位置编码向量PE(i, j)可以通过以下公式计算得到:

每个位置i一般的维度都是64?dimension是512?

位置1的位置编码向量 PE(1, 0):

PE(1, 0) = sin(1 / 10000^(0/4))

= sin(1 / 10000^0)

= sin(1 / 1)

= sin(1)

≈ 0.8415

位置1的位置编码向量 PE(1, 1):

PE(1, 1) = cos(1 / 10000^(1/4))

= cos(1 / 10000^0.25)

= cos(1 / 1.7783)

≈ cos(0.5623)

≈ 0.8253

对于单词"love",我们同样计算其位置编码向量。

位置2的位置编码向量 PE(2, 0):

PE(2, 0) = sin(2 / 10000^(0/4))

= sin(2 / 10000^0)

= sin(2 / 1)

= sin(2)

≈ 0.9093

位置2的位置编码向量 PE(2, 1):

PE(2, 1) = cos(2 / 10000^(1/4))

= cos(2 / 10000^0.25)

= cos(2 / 1.7783)

≈ cos(1.1246)

≈ 0.4546

class PositionalEncoding(nn.Module):

    def __init__(self, d_hid, n_position=200):
        super(PositionalEncoding, self).__init__()
        # Not a parameter
        # 将tensor注册成buffer, optim.step()的时候不会更新
        self.register_buffer('pos_table', self._get_sinusoid_encoding_table(n_position, d_hid))

    def _get_sinusoid_encoding_table(self, n_position, d_hid):
        ''' Sinusoid position encoding table '''
        # TODO: make it with torch instead of numpy

        def get_position_angle_vec(position):
            # 2i, 所以此处要//2. 
            return [position / np.power(10000, 2 * (hid_j // 2) / d_hid) for hid_j in range(d_hid)]

        sinusoid_table = np.array([get_position_angle_vec(pos_i) for pos_i in range(n_position)])
        sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2])  # dim 2i 偶数
        sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2])  # dim 2i+1 奇数

        return torch.FloatTensor(sinusoid_table).unsqueeze(0) # shape:(1, maxLen(n_position), d_hid)

    def forward(self, x):
        return x + self.pos_table[:, :x.size(1)].clone().detach() # 数据、梯度均无关

残差&&FFN:

Transformer模型中的残差连接是一种技术,用于在不同层之间传递信息并减轻梯度消失的问题。它通过将输入信号与层内计算的结果相加,从而将原始输入的信息直接传递到网络的后续层。

class PositionwiseFeedForward(nn.Module):
    ''' A two-feed-forward-layer module '''

    def __init__(self, d_in, d_hid, dropout=0.1):
        super().__init__()
        self.w_1 = nn.Linear(d_in, d_hid) # position-wise
        self.w_2 = nn.Linear(d_hid, d_in) # position-wise
        self.layer_norm = nn.LayerNorm(d_in, eps=1e-6)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):

        residual = x

        x = self.w_2(F.relu(self.w_1(x)))
        x = self.dropout(x)
        # add & norm
        x += residual

        x = self.layer_norm(x)

        return x

decoder:

在Transformer解码器中,它采用了自注意力机制(self-attention)和多头注意力机制(multi-head attention)来编码输入序列的上下文信息,并利用位置编码对序列中的位置信息进行建模。解码器通过逐步进行自注意力计算和前馈神经网络(Feed-Forward Network)的处理,生成目标序列的每个元素。

cross-attention

解码器的目标是根据输入的上下文信息和先前生成的元素,以逐步生成目标序列。它可以根据任务的不同而有所调整,例如在机器翻译任务中,解码器可以逐步生成目标语言的单词;在图像生成任务中,解码器可以逐步生成图像的像素值。

kv来自encoder,q来自decoder

在解码器中,输出的每一步会被作为下一个时间步骤中底层解码器的输入,并且解码器会像编码器一样将其解码结果向上传递。与编码器输入类似,解码器输入也会经过嵌入和位置编码的处理,以指示每个单词的位置。

self-attention

在Transformer解码器中,自注意力层的操作方式与编码器中的略有不同:

在解码器中,自注意力层只能关注输出序列中的先前位置(单向attention,encoder的attention是双向的,即后中间的单词既可以和前面又可以和后面的词attention,而decoder中的只能和前面的词attention)。为了实现这一点,在自注意力计算中,在进行softmax之前,将未来位置进行掩码(将其设置为负无穷)。

过程就是mask住下一个词和他后面的词,预测下一个词,然后把预测的下一个词作为输入在预测下一个词。

Linear + softmax

在Transformer解码器中,解码器堆栈的输出是一个浮点数向量。我们如何将其转换为单词?这是最终的线性层和其后的Softmax层的任务。

线性层是一个简单的全连接神经网络,将解码器堆栈生成的向量投影到一个更大的向量中,称为logits向量。

假设我们的模型知道10,000个唯一的英文单词(模型的“输出词汇表”),这些单词是从训练数据集中学习得到的。这将使logits向量的宽度为10,000个单元格,每个单元格对应一个唯一单词的分数。这就是我们如何解释线性层之后的模型输出。

然后,Softmax层将这些分数转换为概率(都是正数,总和为1.0)。选择具有最高概率的单元格,并将与之相关联的单词作为该时间步骤的输出生成。

简而言之,通过线性层和Softmax层,将解码器堆栈的输出转换为概率分布,并根据最高概率选择输出的单词。

Train&&loss

训练过程中,未经训练的Transformer模型也会经历完全相同的前向传播过程。但由于我们在带标签的训练数据集上进行训练,我们可以将模型的输出与实际正确输出进行比较。

为了可视化这一点,让我们假设我们的输出词汇表只包含六个单词("a","am","i","thanks","student"和"<eos>",表示句子的结束)。

假设我们正在训练我们的模型,这是训练阶段的第一步,我们正在使用一个简单的例子进行训练——将"merci"翻译成"thanks"。

这意味着我们希望输出是一个概率分布,指示单词"thanks"。但由于这个模型尚未经过训练,目前实现这一点的可能性较低。

在训练的初始阶段,模型的参数是随机初始化的,它对输入序列"merci"的翻译可能会得到不正确的输出。由于模型尚未学习到正确的翻译关系,输出的概率分布可能会在词汇表中的不同单词上分散,而不是集中在"thanks"上。

通过训练过程中的反向传播和参数更新,模型逐渐学习到输入序列"merci"与目标序列"thanks"之间的对应关系,并且输出概率分布逐渐偏向于正确的单词。随着训练的进行,模型的输出将逐渐接近我们所期望的目标。

要比较两个概率分布,我们可以简单地将一个概率分布减去另一个概率分布。有关更多详细信息,请参考交叉熵和Kullback-Leibler散度。

但请注意,这只是一个过度简化的例子。更实际地说,我们将使用长度超过一个单词的句子。例如,输入为"je suis étudiant",期望输出为"i am a student"。这实际上意味着我们希望我们的模型连续输出概率分布,其中:

  • 每个概率分布由宽度为vocab_size的向量表示(在我们的玩具示例中为6,但更实际地可能是30,000或50,000等数字)。

  • 第一个概率分布在与单词"i"相关的单元格中具有最高的概率。

  • 第二个概率分布在与单词"am"相关的单元格中具有最高的概率。

  • 依此类推,直到第五个输出分布指示了'<end of sentence>'符号,该符号在由10,000个元素构成的词汇表中也有一个单元格与之对应。

在生成输出时,模型可以一次选择具有最高概率的单词,并忽略其他单词,这被称为贪婪解码。这是一种方法。另一种方法是保留前两个最高概率的单词(例如,'I'和'a'),然后在下一步中运行模型两次:一次假设第一个输出位置为单词'I',另一次假设第一个输出位置为单词'a',并且考虑到位置#1和#2,选择产生较少错误的版本。我们对位置#2、#3等进行类似的操作。这种方法称为"beam search",在我们的示例中,beam_size为2(表示始终保留两个未完成翻译的假设),top_beams也为2(表示我们将返回两个翻译结果)。这些都是您可以进行实验的超参数。

通过使用beam search,可以在生成过程中保留多个可能的翻译假设,而不仅仅是贪婪地选择单个单词。这有助于处理复杂的输出空间,提高模型生成正确翻译的概率。您可以根据任务的要求和实际情况对beam_size和top_beams进行调整和优化。

ref:

https://arxiv.org/abs/1706.03762

https://blog.research.google/2017/08/transformer-novel-neural-network.html

https://www.youtube.com/watch?v=rBCqOTEfxvg

https://colab.research.google.com/github/tensorflow/tensor2tensor/blob/master/tensor2tensor/notebooks/hello_t2t.ipynb

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/478417.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 2617. 网格图中最少访问的格子数【单调栈优化dp+二分】

原题链接&#xff1a;2617. 网格图中最少访问的格子数 题目描述&#xff1a; 给你一个下标从 0 开始的 m x n 整数矩阵 grid 。你一开始的位置在 左上角 格子 (0, 0) 。 当你在格子 (i, j) 的时候&#xff0c;你可以移动到以下格子之一&#xff1a; 满足 j < k < gri…

嵌入式开发--STM32G431RBTx-定时器中断流水灯

嵌入式开发–STM32G431RBTx-定时器中断流水灯 定时器工作原理 如图有反映stm32g431的定时器资源。 共10个定时器 定时器定时器类型个数TIM6&#xff0c;7基本定时器2TIM2&#xff0c;3&#xff0c;4全功能通用定时器3TIM15&#xff0c;16&#xff0c;17通用定时器(只有1或2个…

Linux_开发工具_yum_vim_gcc/g++_gdb_make/makefile_进度条_git_2

文章目录 一、Linux软件包管理器yum1. centos7 中安装软件方式2.安装&#xff0c;卸载&#xff0c;查看3.yum源4.安装lrzsz5.安装扩展源 二、Linux编辑器-vim1.安装vim2.vim的三种模式3.命令模式-文本批量化操作4.vim配置 三、Linux编译器-gcc/g使用1.安装2.gcc如何完成1、 预处…

SpringBoot3使用响应Result类返回的响应状态码为406

Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: No acceptable representation] 解决方法&#xff1a;Result类上加上Data注解

【算法刷题】Day33

文章目录 1. 最长湍流子数组题干&#xff1a;算法原理&#xff1a;1. 状态表示&#xff1a;2. 状态转移方程3. 初始化4. 填表顺序5. 返回值 代码&#xff1a; 2. 最长递增子序列题干&#xff1a;算法原理&#xff1a;1. 状态表示&#xff1a;2. 状态转移方程3. 初始化4. 填表顺…

链表递归-leetcode两两交换相邻链表中的结点

两两交换相邻链表中的结点 题目&#xff1a; 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 示例1 输入&#xff1a;head [1,2,3,4] 输出&#xff1a;[2,1…

文件怎么做扫码预览?创建文件活码的步骤有哪些?

现在文件可以通过扫描二维码的方式来获取&#xff0c;与传统的通过聊天软件来传输相比&#xff0c;二维码方式的应用更加的方便&#xff0c;其他人只需要通过扫描一张二维码就可以在手机上浏览或者下载文件&#xff0c;通过手机就可以预览、存储。 文件二维码的制作方法也很简…

C语言牛客网刷题

1.最大公约数和最小公倍数的组合问题 &#xff08;1&#xff09;在调试的过程中涉及到很大的数据&#xff0c;我们我们在定义变量的时候定义为long long类型 &#xff08;2&#xff09;这个里面我们自定义了max2用来求最大公约数&#xff0c;min2用来求最小公倍数 &#xff0…

稀碎从零算法笔记Day23-LeetCode:翻转二叉树

题型&#xff1a;链表、二叉树 链接&#xff1a;226. 翻转二叉树 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 这道题适合就着样例来做 题目样例 …

sqlite3 交叉编译

#1.下载源码并解压 源码路径如下&#xff0c;下载autoconf版本 SQLite Download Page 解压 tar -zxvf sqlite-autoconf-3450200.tar.gz cd sqlite-autoconf-3450200 mkdir build # 2. 配置源代码 # 假设你已经安装了交叉编译工具链&#xff0c;如gcc-arm-linux-gnueabih…

2024年React初学者入门路线指南

在这篇文章中&#xff0c;我们一步一步探索了如何从零基础开始学习React&#xff0c;并逐渐成长为一名初级开发者。通过理解基础概念、实践构建静态和动态项目&#xff0c;最终发展到创建复杂的应用程序并加入到个人作品集中&#xff0c;您现在已经准备好迈向React开发者的职业…

Vue3:网页项目中路由的设计和配置

为了避免我每次建项目配路由的时候都回去翻网课&#xff0c;打算整一博客 路由设计 不同网页的路由设计思路基本相同&#xff0c;分为一级路由和二级路由&#xff0c;基本设计思路如下图 以我之前做过的招新系统管理端为例&#xff0c;可设计出如下路由 路由配置 还是以招新系…

背包问题总结

背包问题总结 一、01背包 原题链接&#xff1a;2. 01背包问题 - AcWing题库 思路分析 dp问题最重要的是状态转移方程。那么我们首先来定义一下状态&#xff1a; dp[i][j] 表示前 i 个物品&#xff0c;背包容量不超过 j 时的最大价值。 那么要怎么更新状态呢&#xff1f; …

Windows server 2008 R2共享文件配置和web网站的发布 试题一(Windows部分)

Windows server 2008 R2共享文件配置和web网站的发布 试题一&#xff08;Windows部分&#xff09; 设置虚拟机与本机互通设置虚拟机IP关闭虚拟机防火墙设置本机IP测试本机与虚拟机是否可以互通 开启文件共享function discovery resource publication服务的开启SSDP Discovery服…

SpringBoot-03 | SpringBoot自动配置

SpringBoot-03 | SpringBoot自动配置 原理分析代码示例源码剖析SpringBootConfiguration&#xff1a;组合注解&#xff0c;标记当前类为配置类ComponentScanEnableAutoConfigurationImport加载spring.factoriesrun初始化加载spring.factoriesspring.factories中的钩子类 网上盗…

【最后2天】京东云游戏云服务器0门槛抽奖送!云服务器选购推荐 京东云 阿里云 腾讯云对比 幻兽帕鲁 雾锁王国 省钱学生党

好消息&#xff1a;抽奖活动开启&#xff01;时间&#xff1a;3月17日——3月24日 最高奖品&#xff1a;16G 6个月&#xff1b;32G 3个月 抽奖规则&#xff1a;B站点赞评论关注即可参与抽奖&#xff0c;3.24日公布获奖名单。 抽奖地址&#xff1a; 【首次抽奖】16G、32G免费…

每日学习笔记:C++ STL 容器的杂谈

三种自定义STL容器 string作为STL容器 C风格数组作为STL容器 C11以后 C11以前 容器元素类型是引用 使用智能指针存储元素 使用引用外覆器 各容器使用时机 如何分别用两种不同的排序准则来存储同批数据&#xff1f; 解决方案&#xff1a;将容器元素改为智能指针即可。 根据排…

CentOS/RHEL 6.5 上 NFS mount 挂起kernel bug

我本身有四台机器做WAS集群&#xff0c;挂载nfs&#xff0c;其中随机一台客户端计算机端口关闭释放将进入不良状态&#xff0c;对 NFSv4 挂载的任何访问都将挂起&#xff08;例如“ls&#xff0c;cd 或者df均挂起”&#xff09;。这意味着没有人并且所有需要访问共享的用户进程…

【笔记】以论文发表形式通俗理解 TCP/IP模型

【笔记】以论文发表形式通俗理解 TCP/IP模型 前言TCP/IP模型理论通俗理解 前言 在网络基础学习过程中&#xff0c;以前只对TCP/IP理解个字面&#xff0c;网上查一下能知道个字面意思&#xff0c;但是连起来到底是什么意思&#xff0c;还是一知半解的&#xff0c;停留在表面&am…

实型数据详解

1 实型常量的表示方法 实数(real number)又称浮点数(floating-point number)。实数有两种表示形式: (1)十进制小数形式。它由数字和小数点组成(注意必须有小数点)。.123、123.、123.0、0.0都是十进制小数形式。 (2)指数形式。如123e3或123E3都代表123x103。但注意字母e(或E)…