深入浅出 Transformer

Transformer 背后的核心概念:注意力机制、编码器-解码器架构、多头注意力等等。

图片

一、理解注意力机制

注意力机制能够集中注意力在输入序列的某些部分,同时忽略其他部分,就像我们人类在理解句子时关注特定的单词或短语一样。

自注意力是种特定类型的注意力机制,也称为内部注意力。想象一下,当你阅读一句话时,你的大脑会自动突出显示重要的单词或短语来理解意思。这就是神经网络中自注意力的基本原理。它使序列中的每个单词都能“关注”其他单词,包括自己在内,以更好地理解上下文。

二、自注意力是如何工作的?

考虑一句话:“The cat sat on the mat.”

嵌入

首先,模型将输入序列中的每个单词嵌入到一个高维向量表示中。这个嵌入过程允许模型捕捉单词之间的语义相似性。

查询、键和值向量

接下来,模型为序列中的每个单词计算三个向量:查询向量、键向量和值向量。在训练过程中,模型学习这些向量,每个向量都有不同的作用。查询向量表示单词的查询,即模型在序列中寻找的内容。键向量表示单词的键,即序列中其他单词应该注意的内容。值向量表示单词的值,即单词对输出所贡献的信息。

注意力分数

一旦模型计算了每个单词的查询、键和值向量,它就会为序列中的每一对单词计算注意力分数。这通常通过取查询向量和键向量的点积来实现,以评估单词之间的相似性。

SoftMax 归一化

然后,使用 softmax 函数对注意力分数进行归一化,以获得注意力权重。这些权重表示每个单词应该关注序列中其他单词的程度。注意力权重较高的单词被认为对正在执行的任务更为关键。

加权求和

最后,使用注意力权重计算值向量的加权和。这产生了每个序列中单词的自注意力机制输出,捕获了来自其他单词的上下文信息。

图片

下面是一个计算注意力分数的简单解释:

# 安装 PyTorch
!pip install torch==2.2.1+cu121# 导入库
import torch
import torch.nn.functional as F# 示例输入序列
input_sequence = torch.tensor([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 0.9]])# 生成 Key、Query 和 Value 矩阵的随机权重
random_weights_key = torch.randn(input_sequence.size(-1), input_sequence.size(-1))
random_weights_query = torch.randn(input_sequence.size(-1), input_sequence.size(-1))
random_weights_value = torch.randn(input_sequence.size(-1), input_sequence.size(-1))# 计算 Key、Query 和 Value 矩阵
key = torch.matmul(input_sequence, random_weights_key)
query = torch.matmul(input_sequence, random_weights_query)
value = torch.matmul(input_sequence, random_weights_value)# 计算注意力分数
attention_scores = torch.matmul(query, key.T) / torch.sqrt(torch.tensor(query.size(-1), dtype=torch.float32))# 使用 softmax 函数获得注意力权重
attention_weights = F.softmax(attention_scores, dim=-1)# 计算 Value 向量的加权和
output = torch.matmul(attention_weights, value)print("自注意力机制后的输出:")
print(output)

三、Transformer 模型的基础

编码器-解码器架构

在Transformer的核心是其编码器-解码器架构—两个关键组件之间的共生关系,分别负责处理输入序列和生成输出序列。编码器和解码器中的每一层都包含相同的子层,包括自注意力机制和前馈网络。这种架构不仅有助于全面理解输入序列,而且能够生成上下文丰富的输出序列。

位置编码

尽管Transformer模型具有强大的功能,但它缺乏对元素顺序的内在理解—这是位置编码所解决的一个缺点。通过将输入嵌入与位置信息结合起来,位置编码使模型能够区分序列中元素的相对位置。这种细致的理解对于捕捉语言的时间动态和促进准确理解至关重要。

多头注意力

Transformer模型的一个显著特征是它能够同时关注输入序列的不同部分—这是多头注意力实现的。通过将查询、键和值向量分成多个头,并进行独立的自注意力计算,模型获得了对输入序列的细致透视,丰富了其表示,带有多样化的上下文信息。

前馈网络

与人类大脑能够并行处理信息的能力类似,Transformer模型中的每一层都包含一个前馈网络—一种能够捕捉序列中元素之间复杂关系的多功能组件。通过使用线性变换和非线性激活函数,前馈网络使模型能够在语言的复杂语义景观中航行,促进文本的稳健理解和生成。

四、Transformer 组件的详细说明

#import libraries
import math
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F

1、位置编码

在Transformer模型中,位置编码是一个关键组件,它将关于标记位置的信息注入到输入嵌入中。

与循环神经网络(RNNs)或卷积神经网络(CNNs)不同,由于其置换不变性,Transformers 缺乏对标记位置的内在知识。位置编码通过为模型提供位置信息来解决这一限制,使其能够按照正确的顺序处理序列。

位置编码的概念

通常在将输入嵌入传入Transformer模型之前,会将位置编码添加到嵌入中。它由一组具有不同频率和相位的正弦函数组成,允许模型根据它们在序列中的位置区分标记。

位置编码的公式如下

假设您有一个长度为L的输入序列,并且需要在该序列中找到第k个对象的位置。位置编码由不同频率的正弦和余弦函数给出:

图片

其中:

  • k:输入序列中对象的位置,0≤k<L/2
  • d:输出嵌入空间的维度
  • P(k,j):位置函数,用于将输入序列中的位置k映射到位置矩阵的索引(k,j)
  • n:用户定义的标量,由《Attention Is All You Need》的作者设置为10,000
  • i:用于将列索引映射到0≤i<d/2的值,单个i值同时映射到正弦和余弦函数。

不同的位置编码方案

在Transformer中使用了各种位置编码方案,每种方案都有其优点和缺点:

  • 固定位置编码:在这种方案中,位置编码是预定义的,并对所有序列固定不变。虽然简单高效,但固定位置编码可能无法捕捉序列中的复杂模式。

  • 学习位置编码:另一种选择是在训练过程中学习位置编码,使模型能够自适应地从数据中捕捉位置信息。学习位置编码提供了更大的灵活性,但需要更多的参数和计算资源。

位置编码的实现

# 位置编码的实现
class PositionalEncoding(nn.Module):def __init__(self, d_model, max_len=5000):super(PositionalEncoding, self).__init__()# 计算位置编码pe = torch.zeros(max_len, d_model)position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-torch.log(torch.tensor(10000.0)) / d_model))pe[:, 0::2] = torch.sin(position * div_term)pe[:, 1::2] = torch.cos(position * div_term)pe = pe.unsqueeze(0)self.register_buffer('pe', pe)def forward(self, x):x = x + x + self.pe[:, :x.size(1)]return x# 示例用法
d_model = 512
max_len = 100
num_heads = 8# 位置编码
pos_encoder = PositionalEncoding(d_model, max_len)# 示例输入序列
input_sequence = torch.randn(5, max_len, d_model)# 应用位置编码
input_sequence = pos_encoder(input_sequence)
print("输入序列的位置编码:")
print(input_sequence.shape)

2、多头注意力机制

在Transformer架构中,多头注意力机制是一个关键组件,它使模型能够同时关注输入序列的不同部分。它允许模型捕捉序列内的复杂依赖关系和关联,从而提高了语言翻译、文本生成和情感分析等任务的性能。

图片

多头注意力机制具有几个优点:

  • 并行化:通过同时关注输入序列的不同部分,多头注意力显著加快了计算速度,使其比传统的注意力机制更加高效。
  • 增强表示:每个注意力头都关注输入序列的不同方面,使模型能够捕捉各种模式和关系。这导致输入的表示更丰富、更强大,增强了模型理解和生成文本的能力。
  • 改进泛化性:多头注意力使模型能够关注序列内的局部和全局依赖关系,从而提高了跨不同任务和领域的泛化性。

多头注意力的计算:

  • 线性变换:输入序列经历可学习的线性变换,将其投影到多个较低维度的表示,称为“头”。每个头关注输入的不同方面,使模型能够捕捉各种模式。
  • 缩放点积注意力:每个头独立地计算输入序列的查询、键和值表示之间的注意力分数。这一步涉及计算令牌及其上下文之间的相似度,乘以模型深度的平方根进行缩放。得到的注意力权重突出了每个令牌相对于其他令牌的重要性。
  • 连接和线性投影:来自所有头的注意力输出被连接并线性投影回原始维度。这个过程将来自多个头的见解结合起来,增强了模型理解序列内复杂关系的能力。

多头注意力的实现

# 多头注意力的代码实现
class MultiHeadAttention(nn.Module):def __init__(self, d_model, num_heads):super(MultiHeadAttention, self).__init__()self.num_heads = num_headsself.d_model = d_modelassert d_model % num_heads == 0self.depth = d_model // num_heads# 查询、键和值的线性投影self.query_linear = nn.Linear(d_model, d_model)self.key_linear = nn.Linear(d_model, d_model)self.value_linear = nn.Linear(d_model, d_model)# 输出线性投影self.output_linear = nn.Linear(d_model, d_model)def split_heads(self, x):batch_size, seq_length, d_model = x.size()return x.view(batch_size, seq_length, self.num_heads, self.depth).transpose(1, 2)def forward(self, query, key, value, mask=None):# 线性投影query = self.query_linear(query)key = self.key_linear(key)value = self.value_linear(value)# 分割头部query = self.split_heads(query)key = self.split_heads(key)value = self.split_heads(value)# 缩放点积注意力scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(self.depth)# 如果提供了掩码,则应用掩码if mask is not None:scores += scores.masked_fill(mask == 0, -1e9)# 计算注意力权重并应用softmaxattention_weights = torch.softmax(scores, dim=-1)# 应用注意力到值attention_output = torch.matmul(attention_weights, value)# 合并头部batch_size, _, seq_length, d_k = attention_output.size()attention_output = attention_output.transpose(1, 2).contiguous().view(batch_size,seq_length, self.d_model)# 线性投影attention_output = self.output_linear(attention_output)return attention_output# 示例用法
d_model = 512
max_len = 100
num_heads = 8
d_ff = 2048# 多头注意力
multihead_attn = MultiHeadAttention(d_model, num_heads)# 示例输入序列
input_sequence = torch.randn(5, max_len, d_model)# 多头注意力
attention_output= multihead_attn(input_sequence, input_sequence, input_sequence)
print("attention_output shape:", attention_output.shape)

3、前馈网络

在Transformer的背景下,前馈网络在处理信息和从输入序列中提取特征方面发挥着关键作用。它们是模型的支柱,促进了不同层之间表示的转换。

前馈网络的作用

每个Transformer层内的前馈网络负责对输入表示应用非线性变换。它使模型能够捕捉数据中的复杂模式和关系,促进了高级特征的学习。

前馈层的结构和功能

前馈层由两个线性变换组成,两者之间通过一个非线性激活函数(通常是ReLU)分隔。

  • 线性变换1:使用可学习的权重矩阵将输入表示投影到更高维度的空间中。
  • 非线性激活:第一个线性变换的输出通过非线性激活函数(例如ReLU)传递。这引入了模型的非线性,使其能够捕捉数据中的复杂模式和关系。
  • 线性变换2:激活函数的输出然后通过另一个可学习的权重矩阵投影回原始的维度空间中。

前馈网络的实现

# 前馈网络的代码实现
class FeedForward(nn.Module):def __init__(self, d_model, d_ff):super(FeedForward, self).__init__()self.linear1 = nn.Linear(d_model, d_ff)self.linear2 = nn.Linear(d_ff, d_model)self.relu = nn.ReLU()def forward(self, x):# 线性变换1x = self.relu(self.linear1(x))# 线性变换2x = self.linear2(x)return x# 示例用法
d_model = 512
max_len = 100
num_heads = 8
d_ff = 2048# 多头注意力
multihead_attn = MultiHeadAttention(d_model, num_heads)# 前馈网络
ff_network = FeedForward(d_model, d_ff)# 示例输入序列
input_sequence = torch.randn(5, max_len, d_model)# 多头注意力
attention_output= multihead_attn(input_sequence, input_sequence, input_sequence)# 前馈网络
output_ff = ff_network(attention_output)
print('input_sequence',input_sequence.shape)
print("output_ff", output_ff.shape)

4、编码器

在Transformer模型中起着至关重要的作用,其主要任务是将输入序列转换为有意义的表示,捕捉输入的重要信息。

图片

编码器由多个层组成,每个层依次包含以下组件:输入嵌入、位置编码、多头自注意力机制和位置逐点前馈网络。

  1. 输入嵌入:我们首先将输入序列转换为密集向量表示,称为输入嵌入。我们使用预训练的词嵌入或在训练过程中学习的嵌入,将输入序列中的每个单词映射到高维向量空间中。
  2. 位置编码:我们将位置编码添加到输入嵌入中,以将输入序列的顺序信息合并到其中。这使得模型能够区分序列中单词的位置,克服了传统神经网络中缺乏顺序信息的问题。
  3. 多头自注意力机制:在位置编码之后,输入嵌入通过一个多头自注意力机制。这个机制使编码器能够根据单词之间的关系权衡输入序列中不同单词的重要性。通过关注输入序列的相关部分,编码器可以捕捉长距离的依赖关系和语义关系。
  4. 位置逐点前馈网络:在自注意力机制之后,编码器对每个位置独立地应用位置逐点前馈网络。这个网络由两个线性变换组成,两者之间通过一个非线性激活函数(通常是ReLU)分隔。它有助于捕捉输入序列中的复杂模式和关系。

输入嵌入和位置编码的编码器的实现

# 编码器的代码实现
class EncoderLayer(nn.Module):def __init__(self, d_model, num_heads, d_ff, dropout):super(EncoderLayer, self).__init__()self.self_attention = MultiHeadAttention(d_model, num_heads)self.feed_forward = FeedForward(d_model, d_ff)self.norm1 = nn.LayerNorm(d_model)self.norm2 = nn.LayerNorm(d_model)self.dropout = nn.Dropout(dropout)def forward(self, x, mask):# 自注意力层attention_output= self.self_attention(x, x,x, mask)attention_output = self.dropout(attention_output)x = x + attention_outputx = self.norm1(x)# 前馈层feed_forward_output = self.feed_forward(x)feed_forward_output = self.dropout(feed_forward_output)x = x + feed_forward_outputx = self.norm2(x)return xd_model = 512
max_len = 100
num_heads = 8
d_ff = 2048# 多头注意力
encoder_layer = EncoderLayer(d_model, num_heads, d_ff, 0.1)# 示例输入序列
input_sequence = torch.randn(1, max_len, d_model)# 多头注意力
encoder_output= encoder_layer(input_sequence, None)
print("encoder output shape:", encoder_output.shape)

5、解码器

在Transformer模型中,解码器在基于输入序列的编码表示生成输出序列方面起着至关重要的作用。它接收来自编码器的编码输入序列,并将其用于生成最终的输出序列。

图片

解码器的功能

解码器的主要功能是生成输出序列,同时注意到输入序列的相关部分和先前生成的标记。它利用输入序列的编码表示来理解上下文,并对生成下一个标记做出明智的决策。

解码器层及其组件

  1. 输出嵌入右移:在处理输入序列之前,模型将输出嵌入向右移动一个位置。这确保解码器中的每个标记在训练期间都能从先前生成的标记接收到正确的上下文。
  2. 位置编码:与编码器类似,模型将位置编码添加到输出嵌入中,以合并标记的顺序信息。这种编码帮助解码器根据标记在序列中的位置进行区分。
  3. 掩码的多头自注意力机制:解码器采用掩码的多头自注意力机制,以便注意输入序列的相关部分和先前生成的标记。在训练期间,模型应用掩码以防止注意到未来的标记,确保每个标记只能注意到前面的标记。
  4. 编码器-解码器注意力机制:除了掩码的自注意力机制外,解码器还包括编码器-解码器注意力机制。这种机制使解码器能够注意到输入序列的相关部分,有助于生成受输入上下文影响的输出标记。
  5. 位置逐点前馈网络:在注意力机制之后,解码器对每个标记独立地应用位置逐点前馈网络。这个网络捕捉输入和先前生成的标记中的复杂模式和关系,有助于生成准确的输出序列。

解码器的实现

# 解码器的代码实现
class DecoderLayer(nn.Module):def __init__(self, d_model, num_heads, d_ff, dropout):super(DecoderLayer, self).__init__()self.masked_self_attention = MultiHeadAttention(d_model, num_heads)self.enc_dec_attention = MultiHeadAttention(d_model, num_heads)self.feed_forward = FeedForward(d_model, d_ff)self.norm1 = nn.LayerNorm(d_model)self.norm2 = nn.LayerNorm(d_model)self.norm3 = nn.LayerNorm(d_model)self.dropout = nn.Dropout(dropout)def forward(self, x, encoder_output, src_mask, tgt_mask):# 掩码的自注意力层self_attention_output= self.masked_self_attention(x, x, x, tgt_mask)self_attention_output = self.dropout(self_attention_output)x = x + self_attention_outputx = self.norm1(x)# 编码器-解码器注意力层enc_dec_attention_output= self.enc_dec_attention(x, encoder_output, encoder_output, src_mask)enc_dec_attention_output = self.dropout(enc_dec_attention_output)x = x + enc_dec_attention_outputx = self.norm2(x)# 前馈层feed_forward_output = self.feed_forward(x)feed_forward_output = self.dropout(feed_forward_output)x = x + feed_forward_outputx = self.norm3(x)return x# 定义DecoderLayer的参数
d_model = 512  # 模型的维度
num_heads = 8  # 注意力头的数量
d_ff = 2048    # 前馈网络的维度
dropout = 0.1  # 丢弃概率
batch_size = 1 # 批量大小
max_len = 100  # 序列的最大长度# 定义DecoderLayer实例
decoder_layer = DecoderLayer(d_model, num_heads, d_ff, dropout)src_mask = torch.rand(batch_size, max_len, max_len) > 0.5
tgt_mask = torch.tril(torch.ones(max_len, max_len)).unsqueeze(0) == 0# 将输入张量传递到DecoderLayer
output = decoder_layer(input_sequence, encoder_output, src_mask, tgt_mask)# 输出形状
print("Output shape:", output.shape)

五、Transformer 模型架构

图片

Transformer模型概述

Transformer模型由编码器和解码器模块堆叠在一起,用于处理输入序列并生成输出序列。

编码器

  • 编码器模块处理输入序列,提取特征并创建输入的丰富表示。
  • 它由多个编码器层组成,每个层包含自注意力机制和前馈网络。
  • 自注意力机制允许模型同时关注输入序列的不同部分,捕捉依赖关系和关联。
  • 我们将位置编码添加到输入嵌入中,以提供有关序列中标记位置的信息。

解码器

  • 解码器模块以编码器的输出作为输入,并生成输出序列。
  • 与编码器类似,它由多个解码器层组成,每个层包含自注意力、编码器-解码器注意力和前馈网络。
  • 除了自注意力外,解码器还包含编码器-解码器注意力,以在生成输出时关注输入序列。
  • 与编码器类似,我们将位置编码添加到输入嵌入中,以提供位置信息。

连接和标准化

  • 在编码器和解码器模块的每一层之间,都有残差连接后跟层标准化。
  • 这些机制有助于在网络中流动梯度,并有助于稳定训练。

完整的Transformer模型通过将多个编码器和解码器层堆叠在一起来构建。每个层独立处理输入序列,使模型能够学习分层表示并捕获数据中的复杂模式。编码器将其输出传递给解码器,后者根据输入生成最终的输出序列。

Transformer模型的实现

# TRANSFORMER的实现
class Transformer(nn.Module):def __init__(self, src_vocab_size, tgt_vocab_size, d_model, num_heads, num_layers, d_ff,max_len, dropout):super(Transformer, self).__init__()# 定义编码器和解码器的词嵌入层self.encoder_embedding = nn.Embedding(src_vocab_size, d_model)self.decoder_embedding = nn.Embedding(tgt_vocab_size, d_model)# 定义位置编码层self.positional_encoding = PositionalEncoding(d_model, max_len)# 定义编码器和解码器的多层堆叠self.encoder_layers = nn.ModuleList([EncoderLayer(d_model, num_heads, d_ff, dropout)for _ in range(num_layers)])self.decoder_layers = nn.ModuleList([DecoderLayer(d_model, num_heads, d_ff, dropout)for _ in range(num_layers)])# 定义线性层self.linear = nn.Linear(d_model, tgt_vocab_size)self.dropout = nn.Dropout(dropout)# 生成掩码def generate_mask(self, src, tgt):src_mask = (src != 0).unsqueeze(1).unsqueeze(2)tgt_mask = (tgt != 0).unsqueeze(1).unsqueeze(3)seq_length = tgt.size(1)nopeak_mask = (1 - torch.triu(torch.ones(1, seq_length, seq_length), diagonal=1)).bool()tgt_mask = tgt_mask & nopeak_maskreturn src_mask, tgt_mask# 前向传播def forward(self, src, tgt):src_mask, tgt_mask = self.generate_mask(src, tgt)# 编码器输入的词嵌入和位置编码encoder_embedding = self.encoder_embedding(src)en_positional_encoding = self.positional_encoding(encoder_embedding)src_embedded = self.dropout(en_positional_encoding)# 解码器输入的词嵌入和位置编码decoder_embedding = self.decoder_embedding(tgt)de_positional_encoding = self.positional_encoding(decoder_embedding)tgt_embedded = self.dropout(de_positional_encoding)enc_output = src_embeddedfor enc_layer in self.encoder_layers:enc_output = enc_layer(enc_output, src_mask)dec_output = tgt_embeddedfor dec_layer in self.decoder_layers:dec_output = dec_layer(dec_output, enc_output, src_mask, tgt_mask)output = self.linear(dec_output)return output# 示例用法
src_vocab_size = 5000
tgt_vocab_size = 5000
d_model = 512
num_heads = 8
num_layers = 6
d_ff = 2048
max_len = 100
dropout = 0.1transformer = Transformer(src_vocab_size, tgt_vocab_size, d_model, num_heads, num_layers, 
d_ff, max_len, dropout)# 生成随机示例数据
src_data = torch.randint(1, src_vocab_size, (5, max_len))  # (batch_size, seq_length)
tgt_data = torch.randint(1, tgt_vocab_size, (5, max_len))  # (batch_size, seq_length)
transformer(src_data, tgt_data[:, :-1]).shape

六、模型的训练与评估

训练Transformer模型涉及优化其参数以最小化损失函数,通常使用梯度下降和反向传播。一旦训练完成,就会使用各种指标评估模型的性能,以评估其解决目标任务的有效性。

训练过程

梯度下降和反向传播:

  • 在训练期间,将输入序列输入模型,并生成输出序列。
  • 将模型的预测与地面真相进行比较,涉及使用损失函数(例如交叉熵损失)来衡量预测值与实际值之间的差异。
  • 梯度下降用于更新模型的参数,使损失最小化的方向。
  • 优化器根据这些梯度调整参数,迭代更新它们以提高模型性能。

学习率调度:

  • 可以应用学习率调度技术来动态调整训练期间的学习率。
  • 常见策略包括热身计划,其中学习率从低开始逐渐增加,以及衰减计划,其中学习率随时间降低。

评估指标

困惑度:

  • 困惑度是用于评估语言模型性能的常见指标,包括Transformer。
  • 它衡量模型对给定标记序列的预测能力。
  • 较低的困惑度值表示更好的性能,理想值接近词汇量大小。

BLEU分数:

  • BLEU(双语评估研究)分数通常用于评估机器翻译文本的质量。
  • 它将生成的翻译与一个或多个由人类翻译人员提供的参考翻译进行比较。
  • BLEU分数范围从0到1,较高的分数表示更好的翻译质量。

七、训练和评估的实现

# Transformer 模型的训练和评估
criterion = nn.CrossEntropyLoss(ignore_index=0)
optimizer = optim.Adam(transformer.parameters(), lr=0.0001, betas=(0.9, 0.98), eps=1e-9)# 训练循环
transformer.train()for epoch in range(10):optimizer.zero_grad()output = transformer(src_data, tgt_data[:, :-1])loss = criterion(output.contiguous().view(-1, tgt_vocab_size), tgt_data[:, 1:].contiguous().view(-1))loss.backward()optimizer.step()print(f"第 {epoch+1} 轮:损失= {loss.item():.4f}")# 虚拟数据
src_data = torch.randint(1, src_vocab_size, (5, max_len))  # (batch_size, seq_length)
tgt_data = torch.randint(1, tgt_vocab_size, (5, max_len))  # (batch_size, seq_length)# 评估循环
transformer.eval()
with torch.no_grad():output = transformer(src_data, tgt_data[:, :-1])loss = criterion(output.contiguous().view(-1, tgt_vocab_size), tgt_data[:, 1:].contiguous().view(-1))print(f"\n虚拟数据的评估损失= {loss.item():.4f}")

八、高级主题和应用

包括不同的注意力变体、BERT(来自 Transformers 的双向编码器表示)和 GPT(生成式预训练 Transformer),以及它们的实际应用。

不同的注意力变体

注意力机制是 Transformer 模型的核心,使其能够专注于输入序列的相关部分。各种注意力变体的提议旨在增强 Transformer 的能力。

  1. 缩放点积注意力:是原始 Transformer 模型中使用的标准注意力机制。它将查询和键向量的点积作为注意力分数,同时乘以维度的平方根进行缩放。
  2. 多头注意力:注意力的强大扩展,利用多个注意力头同时捕捉输入序列的不同方面。每个头学习不同的注意力模式,使模型能够并行关注输入的各个部分。
  3. 相对位置编码:引入相对位置编码以更有效地捕捉标记之间的相对位置关系。这种变体增强了模型理解标记之间顺序关系的能力。

BERT(来自 Transformers 的双向编码器表示)

BERT 是一个具有里程碑意义的基于 Transformer 的模型,在 NLP 领域产生了深远影响。它通过掩码语言建模和下一句预测等目标,在大规模文本语料库上进行预训练。BERT 学习了单词的深层上下文表示,捕捉双向上下文,使其在广泛的下游 NLP 任务中表现良好。

from transformers import BertModel, BertTokenizertokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')inputs = tokenizer("Hello, world!", return_tensors="pt")
outputs = model(**inputs)
print(outputs)

GPT(生成式预训练 Transformer)

GPT 是一个基于 Transformer 的模型,以其生成能力而闻名。与双向的 BERT 不同,GPT 采用仅解码器的架构和自回归训练来生成连贯且上下文相关的文本。研究人员和开发人员已经成功地将 GPT 应用于各种任务,如文本完成、摘要、对话生成等。

from transformers import GPT2LMHeadModel, GPT2Tokenizertokenizer = GPT2Tokenizer.from_pretrained('gpt2')
model = GPT2LMHeadModel.from_pretrained('gpt2')input_text = "Once upon a time, "
inputs=tokenizer(input_text,return_tensors='pt')
output=tokenizer.decode(model.generate(**inputs,max_new_tokens=100,)[0],skip_special_tokens=True)
input_ids = tokenizer(input_text, return_tensors='pt')print(output)

九、总结

Transformer 通过其捕捉上下文和理解语言的能力,彻底改变了自然语言处理(NLP)领域。

通过注意力机制、编码器-解码器架构和多头注意力,它们使得诸如机器翻译和情感分析等任务得以在前所未有的规模上实现。

研究论文

  • 《Attention is All You Need》 

  • 《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》

  • 《Language Models are Unsupervised Multitask Learners》

  • Attention in transformers, visually explained

  • Transformer Neural Networks, ChatGPT’s foundation

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

眼图仪参数理解和一些测量指标

参考资料&#xff1a; https://www.eet-china.com/mp/a35960.html 一&#xff1a;关于眼图仪&#xff1a; :::warning ●如果追溯历史&#xff0c;大约47年前&#xff0c;眼图就已经开始广泛应用。在1962年-2002的40年间&#xff0c;眼图的测量方法是基于采样示波器的传统方法…

C++默认构造函数的合成

编译器只在编译期需要的时候合成默认构造函数&#xff0c;而不是在用户需要的时候 文章目录 引入编译器合成默认构造函数的四种情况情况一 类中包含带有默认构造函数的类的成员对象情况二 派生类的基类带有默认构造函数情况三 类带有一个虚函数情况四 派生自一个虚基类的类 参考…

Day53|动态规划part14: 1143.最长公共子序列、1035. 不相交的线、53. 最大子序和

1143. 最长公共子序列 这题有点像递增子序列和公共子数组的组合&#xff0c; 要求公共子序列不一定非要是连续的。 确定dp数组下标及其含义 dp[i][j]表示text1[i - 1]与text2[j - 1]结尾的最高公共子序列。 长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的…

Redis 服务等过期策略和内存淘汰策略解析

redis服务是基于内存运行的&#xff0c;所以很多数据都存放在内存中&#xff0c;但是内存又不是无限的&#xff0c;所以redis就引出了key的过期和淘汰策略。 一、Redis的过期策略&#xff1a; 我们在set key的时候&#xff0c;可以给它设置一个过期时间&#xff0c;比如expire …

【神经网络结构可视化】PlotNeuralNet的安装、测试及创建自己的神经网络结构可视化图形

文章目录 前提准备1、下载MikTeX2、下载Git bash3、下载PlotNeuralNet 进行测试1、解压PlotNeuralNet-master.zip2、打开Git bash3、 在my_project中查看生成的pdf文件 创建自己的神经网络结构可视化图形 前提准备 1、下载MikTeX 下载链接&#xff1a; MikTeX ( https://mikt…

【图解计算机网络】TCP协议三次握手与四次挥手

TCP协议三次握手与四次挥手 三次握手流程为什么是三次握手&#xff0c;而不是两次或四次四次挥手流程TIME_WAIT 为什么要等待 2MSL为什么握手是三次&#xff0c;挥手是四次&#xff1f; 三次握手流程 首先是客户端&#xff08;也就是我们的浏览器&#xff09;发送一个SYN标志位…

C++11 数据结构5 队列的概念,队列的顺序存储,实现,测试

一&#xff0c;队列的概念 队列是一种特殊的受限制的线性表。 队列&#xff08;queue&#xff09;是只允许在一端进行插入操作&#xff0c;而在另一端进行删除操作的线性表。 队列是一种先进先出的t&#xff08;First In First Out&#xff09;的线性表&#xff0c;简称FIF…

请编写函数fun,其功能是:将所有大于1小于整数m的非素数存入xx所指数组中,非素数的个数通过k传回。

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法完整代码和详细的解析。 题干 请编…

NDK 基础(五)—— C++ 高级特性2

1、左值右值 在 C 中&#xff0c;左值&#xff08;lvalue&#xff09;和右值&#xff08;rvalue&#xff09;是用于描述表达式的术语&#xff0c;它们与赋值操作和内存中对象的生命周期有关。 **左值&#xff08;lvalue&#xff09;**是指可以出现在赋值操作符左侧的表达式&a…

商店数据(九)

目录 65.店铺入驻字段表 66.店铺分类表 67.店铺配置表 68.店铺快递公司关联表 69.店铺资料附加表 70.店铺入驻流程表 71.店铺运费模板表 72.消息类型表 65.店铺入驻字段表 CREATE TABLE wst_bases (id int(11) NOT NULL AUTO_INCREMENT COMMENT 自增id,flowld int(11)…

如何安全进行速卖通自养号测评操作?

对于新加入的卖家而言&#xff0c;进行销量测评显得尤为关键。速卖通平台上的新店往往难以获得活动的扶持&#xff0c;且初始流量相当有限。因此&#xff0c;开店的首要任务便是积极展开测评工作&#xff0c;努力积累初始的评论和销售记录。测评的益处颇为显著&#xff0c;它不…

SpringBoot项目启动,传参有哪些方式?

SpringBoot项目启动&#xff0c;传参有哪些方式&#xff1f; 1.Spring级别的参数 直接在启动 Spring Boot 应用的命令行中使用 -- 后跟参数名和值的方式来传递参数。 记住&#xff1a;一般是对于Spring Boot应用特有的配置参数&#xff0c;确保它们遵循Spring Boot的配置属性命…

【视频打架行为数据集】打斗场景视频数据集简要介绍

一、UBI-Fight&#xff08;异常事件检测数据集&#xff09; 介绍 UBI-Fights 数据集是一个独特的全新大型数据集&#xff0c;涉及特定的异常检测并仍然在打斗场景中提供广泛的多样性&#xff0c;该数据集包含 80 小时的视频&#xff0c;在帧级别进行了完全注释。由 1000 个视…

# 从浅入深 学习 SpringCloud 微服务架构(五)Consul(2)

从浅入深 学习 SpringCloud 微服务架构&#xff08;五&#xff09;Consul&#xff08;2&#xff09; 段子手168 一、consul 集群&#xff1a;consul 集群的基础知识 1、启动 sonsul 服务命令&#xff1a; 以开发者模式快速启动&#xff1a; consul agent -dev -client0.0.0…

13.JAVAEE之HTTP协议

HTTP 最新的版本应该是 HTTP/3.0 目前大规模使用的版本 HTTP/1.1 使用 HTTP 协议的场景 1.浏览器打开网站 (基本上) 2.手机 APP 访问对应的服务器 (大概率) 学习 HTTP 协议, 重点学习 HTTP 的报文格式 前面的 TCP/IP/UDP 和这些不同, HTTP 的报文格式,要分两个部分来看待.请求…

移动端日志采集与分析最佳实践

前言 做为一名移动端开发者&#xff0c;深刻体会日志采集对工程师来说具有重要意义&#xff0c;遇到问题除了 debug 调试就是看日志了&#xff0c;通过看日志可以帮助我们了解应用程序运行状况、优化用户体验、保障数据安全依据&#xff0c;本文将介绍日志采集的重要性、移动端…

高级防爬还得是公众号

平时一天也就1K的流量&#xff0c;最近流量暴涨&#xff0c;已经用自研的WAF防火墙阻挡了很多恶意攻击和爬虫&#xff0c;已经过滤掉很多低级攻击和爬取了。 多出的流量&#xff0c;也仅仅多了一个导航 dh.yu7s.com 用户&#xff0c;多时没有用的机器人爬虫&#xff0c;不封掉浪…

EXCEL表格中的数字,为什么每次打开会自动变成日期?

一、典型现象 在工作中&#xff0c;有时会发现公司里的报表&#xff0c;经过多人多次的重复的使用和修改后&#xff0c;会出现这种情况&#xff1a; 1.在表格里按照需要输入数字&#xff0c;保存工作簿。 2.然而&#xff0c;再次打开工作簿&#xff0c;里面的数字变成日期&a…

c#学习入门2

十、运算符 1&#xff09;算术运算符是用于数值类型变量计算的运算符&#xff0c;它返回的结果是数值 1.赋值符号 2.算数运算符 加 减- 乘* 除/ 取余% 3.算数运算符的优先级 4.算术运算符的复合运算 5.算术运算符的自增减 2&#xff09;字符串拼接 1.字符串拼接方式1 注意&…

自定义View-旋转变色圆角三角形的绘制

本文字数&#xff1a;3151字 预计阅读时间&#xff1a;20分钟 在现代设计中&#xff0c;动效图在APP的UI界面中所起到的作用无疑是显著的。相比于静态的界面&#xff0c;动效更符合人类的自然认知体系&#xff0c;它有效地降低了用户的认知负载&#xff0c;UI动效俨然已经成为了…