当前位置:   article > 正文

Transformer结构介绍和Pyotrch代码实现_pytorch 和transformer

pytorch 和transformer

Transformer结构介绍和Pyotrch代码实现

关注B站查看更多手把手教学:

肆十二-的个人空间-肆十二-个人主页-哔哩哔哩视频 (bilibili.com)

基本结构介绍

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层的堆叠得到最终的输出序列。

Pytorch代码实现

以下是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的形状相同,即(序列长度, 批量大小, 特征维度)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120

注意:上面的代码只是一个结构上的骨架,它缺少了嵌入层(Embedding Layer)、位置编码(Positional Encoding)、层归一化(Layer Normalization)、dropout等关键组件,这些在实际应用中都是必要的。此外,输入数据srctgt在这里只是随机生成的张量,用于演示模型的输入和输出形状。在实际应用中,你需要用实际的嵌入向量和位置编码来替换这些随机数据。同时,你也需要处理padding和mask,以确保模型能够正确地处理变长序列。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/359781
推荐阅读
相关标签
  

闽ICP备14008679号