赞
踩
关注B站查看更多手把手教学:
Transformer结构是近年来自然语言处理(NLP)领域的重要突破,它完全基于注意力机制(Attention Mechanism)来实现,克服了传统RNN模型无法并行计算以及容易丢失长距离依赖信息的问题。
Transformer模型主要由Encoder和Decoder两部分组成。这两部分都包含多个相同的层,每层都由一个自注意力(Self-Attention)子层和一个前馈神经网络(Feed Forward Neural Network)子层组成。在每个子层之间还使用了残差连接(Residual Connection)和层归一化(Layer Normalization)。
在Encoder部分,输入序列首先经过Word Embedding和Positional Encoding,然后输入到多个Encoder层中。在每个Encoder层中,输入序列会先经过Self-Attention子层,该子层会计算输入序列中每个位置的表示对所有位置的依赖关系,得到加权后的表示。然后,加权后的表示会经过Feed Forward Neural Network子层进行非线性变换。最后,通过残差连接和层归一化得到该层的输出。
在Decoder部分,与Encoder类似,输入序列也会经过Word Embedding和Positional Encoding。但是,在Decoder的Self-Attention子层中,需要考虑到不能看到未来信息的问题,因此需要使用Masked Self-Attention。此外,Decoder还需要一个Encoder-Decoder Attention子层来计算对Encoder输出的依赖关系。最后,通过多个Decoder层的堆叠得到最终的输出序列。
以下是Transformer结构的一个简化版实现,包括Encoder和Decoder部分,以及相应的代码注释。请注意,为了简洁起见,这个实现省略了一些高级功能,如dropout、层标准化中的可学习参数等。
import torch import torch.nn as nn import torch.nn.functional as F # Transformer模型 class Transformer(nn.Module): def __init__(self, d_model, nhead, num_encoder_layers, num_decoder_layers, dim_feedforward=2048): super(Transformer, self).__init__() # Encoder部分 self.encoder = Encoder(d_model, nhead, num_encoder_layers, dim_feedforward) # Decoder部分 self.decoder = Decoder(d_model, nhead, num_decoder_layers, dim_feedforward) def forward(self, src, tgt, src_mask=None, tgt_mask=None, memory_mask=None, src_key_padding_mask=None, tgt_key_padding_mask=None): # Encoder得到memory memory = self.encoder(src, src_mask=src_mask, src_key_padding_mask=src_key_padding_mask) # Decoder得到输出 output = self.decoder(tgt, memory, tgt_mask=tgt_mask, memory_mask=memory_mask, tgt_key_padding_mask=tgt_key_padding_mask) return output # Encoder class Encoder(nn.Module): def __init__(self, d_model, nhead, num_layers, dim_feedforward=2048): super(Encoder, self).__init__() # 多层EncoderLayer堆叠 self.layers = nn.ModuleList([ EncoderLayer(d_model, nhead, dim_feedforward) for _ in range(num_layers) ]) def forward(self, src, src_mask=None, src_key_padding_mask=None): # 逐层通过EncoderLayer for layer in self.layers: src = layer(src, src_mask=src_mask, src_key_padding_mask=src_key_padding_mask) return src # EncoderLayer class EncoderLayer(nn.Module): def __init__(self, d_model, nhead, dim_feedforward=2048): super(EncoderLayer, self).__init__() # Self-Attention子层 self.self_attn = nn.MultiheadAttention(d_model, nhead) # 前馈神经网络子层 self.linear1 = nn.Linear(d_model, dim_feedforward) self.linear2 = nn.Linear(dim_feedforward, d_model) # 残差连接和层归一化(这里省略了层归一化) # 注意:在实际应用中,应该加上层归一化和dropout def forward(self, src, src_mask=None, src_key_padding_mask=None): # Self-Attention attn_output, _ = self.self_attn(src, src, src, attn_mask=src_mask, key_padding_mask=src_key_padding_mask) src = src + attn_output # 残差连接 # FFN ffn_output = F.relu(self.linear1(src)) ffn_output = self.linear2(ffn_output) src = src + ffn_output # 残差连接 return src # Decoder class Decoder(nn.Module): def __init__(self, d_model, nhead, num_layers, dim_feedforward=2048): super(Decoder, self).__init__() # 多层DecoderLayer堆叠 self.layers = nn.ModuleList([ DecoderLayer(d_model, nhead, dim_feedforward) for _ in range(num_layers) ]) def forward(self, tgt, memory, tgt_mask=None, memory_mask=None, tgt_key_padding_mask=None, memory_key_padding_mask=None): # 逐层通过DecoderLayer for layer in self.layers: tgt = layer(tgt, memory, tgt_mask=tgt_mask, memory_mask=memory_mask, tgt_key_padding_mask=tgt_key_padding_mask, memory_key_padding_mask=memory_key_padding_mask) return tgt # DecoderLayer class DecoderLayer(nn.Module): def __init__(self, d_model, nhead, dim_feedforward=2048): super(DecoderLayer, self).__init__() # Self-Attention子层(Masked) self.self_attn = nn.MultiheadAttention(d_model, nhead) # Encoder-Decoder Attention子层 self.encoder_decoder_attn = nn.MultiheadAttention(d_model, nhead) # 前馈神经网络子层 self.linear1 = nn.Linear(d_model, dim_feedforward) self.linear2 = nn.Linear(dim_feedforward, d_model) # 残差连接和层归一化(这里省略了层归一化) # 注意:在实际应用中,应该加上层归一化和dropout def forward(self, tgt, memory, tgt_mask=None, memory_mask=None, tgt_key_padding_mask=None, memory_key_padding_mask=None): # Self-Attention(Masked) attn_output, _ = self.self_attn(tgt, tgt, tgt, attn_mask=tgt_mask, key_padding_mask=tgt_key_padding_mask) tgt = tgt + attn_output # 残差连接 # Encoder-Decoder Attention attn_output, _ = self.encoder_decoder_attn(tgt, memory, memory, attn_mask=memory_mask, key_padding_mask=memory_key_padding_mask) tgt = tgt + attn_output # 残差连接 # FFN ffn_output = F.relu(self.linear1(tgt)) ffn_output = self.linear2(ffn_output) tgt = tgt + ffn_output # 残差连接 return tgt # 示例使用 d_model = 512 # 输入和输出的维度 nhead = 8 # 注意力头数 num_encoder_layers = 6 # Encoder层数 num_decoder_layers = 6 # Decoder层数 dim_feedforward = 2048 # 前馈神经网络维度 # 实例化模型 model = Transformer(d_model, nhead, num_encoder_layers, num_decoder_layers, dim_feedforward) # 假设输入数据(这里只是示例,实际数据需要预处理) src = torch.rand(10, 32, d_model) # (序列长度, 批量大小, 特征维度) tgt = torch.rand(10, 32, d_model) # 同上 # 前向传播(注意:这里的输入没有经过嵌入层和位置编码,实际应用中需要添加) output = model(src, tgt) print(output.shape) # 应该与tgt的形状相同,即(序列长度, 批量大小, 特征维度)
注意:上面的代码只是一个结构上的骨架,它缺少了嵌入层(Embedding Layer)、位置编码(Positional Encoding)、层归一化(Layer Normalization)、dropout等关键组件,这些在实际应用中都是必要的。此外,输入数据src
和tgt
在这里只是随机生成的张量,用于演示模型的输入和输出形状。在实际应用中,你需要用实际的嵌入向量和位置编码来替换这些随机数据。同时,你也需要处理padding和mask,以确保模型能够正确地处理变长序列。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。