深入解析 Transformer 解码器:核心模块和代码实现详解

13. decoder

深入解析 Transformer 解码器:核心模块和代码实现详解

在 Transformer 中,解码器(Decoder)是一个关键组件,它负责生成目标序列的每个词。解码器的设计允许模型在生成目标词时,结合编码器的输出信息,逐步生成上下文相关的输出序列。本文将带你逐步实现一个完整的 Transformer 解码器。


Transformer 解码器的主要组成部分

一个完整的 Transformer 解码器通常包含以下几个部分:

  1. 输入嵌入层(Embedding Layer):将目标序列中的每个词转换为向量表示。
  2. 位置编码(Positional Encoding):为每个词向量加上位置信息,使模型能够捕捉词序。
  3. 堆叠多个解码器块(Decoder Blocks):通常包含 6-12 个解码器块,每个块负责将当前词与前面词的上下文信息融合。
  4. 输出层:最终将解码器的输出用于生成目标词或用于其他下游任务。

解码器类实现:构建解码器主架构

以下代码实现了一个 TransformerDecoder 类,其中包括输入嵌入、位置编码、多个解码器块以及输出层:

import torch
import torch.nn as nn
import math

class PositionalEncoding(nn.Module):
    def __init__(self, embed_size, max_length=100):
        super(PositionalEncoding, self).__init__()
        self.encoding = torch.zeros(max_length, embed_size)
        position = torch.arange(0, max_length, dtype=torch.float).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, embed_size, 2).float() * (-math.log(10000.0) / embed_size))
        self.encoding[:, 0::2] = torch.sin(position * div_term)
        self.encoding[:, 1::2] = torch.cos(position * div_term)
        self.encoding = self.encoding.unsqueeze(0)

    def forward(self, x):
        return x + self.encoding[:, :x.size(1), :].to(x.device)

class TransformerDecoder(nn.Module):
    def __init__(self, tgt_vocab_size, embed_size, num_layers, heads, forward_expansion, dropout, max_length):
        super(TransformerDecoder, self).__init__()
        # 目标嵌入层
        self.word_embedding = nn.Embedding(tgt_vocab_size, embed_size)
        self.position_encoding = PositionalEncoding(embed_size, max_length)

        # 解码器层堆叠
        self.layers = nn.ModuleList(
            [DecoderBlock(embed_size, heads, forward_expansion, dropout) for _ in range(num_layers)]
        )

        # 输出层
        self.fc_out = nn.Linear(embed_size, tgt_vocab_size)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x, enc_out, src_mask, tgt_mask):
        # 1. 嵌入和位置编码
        out = self.word_embedding(x)
        out = self.position_encoding(out)
        out = self.dropout(out)

        # 2. 通过多个解码器块
        for layer in self.layers:
            out = layer(out, enc_out, src_mask, tgt_mask)

        # 3. 输出层生成目标词
        out = self.fc_out(out)

        return out


代码解析:逐步解析 Transformer 解码器实现

1. 输入嵌入层和位置编码

self.word_embedding = nn.Embedding(tgt_vocab_size, embed_size)
self.position_encoding = PositionalEncoding(embed_size, max_length)

  • word_embedding:将目标序列的词索引转换为嵌入向量,使得模型能够处理目标序列。
  • position_encoding:为每个词的嵌入向量加上位置信息,使模型能够识别目标序列中的词序。

2. 多个解码器块的堆叠

self.layers = nn.ModuleList(
    [DecoderBlock(embed_size, heads, forward_expansion, dropout) for _ in range(num_layers)]
)

  • 使用 ModuleList 创建多个 DecoderBlock,其中每个块都包含自注意力、编码器-解码器注意力、前馈神经网络和正则化层。
  • num_layers 是解码器块的数量,通常设置为 6,但可根据任务调整。

3. 输出层

self.fc_out = nn.Linear(embed_size, tgt_vocab_size)

  • 输出层将嵌入向量转化为词汇表大小的向量,用于生成目标序列中的下一个词。

前向传播过程解析

  1. 词嵌入和位置编码

    out = self.word_embedding(x)
    out = self.position_encoding(out)
    out = self.dropout(out)
    
    
    • 将输入的目标序列转换为词向量表示。
    • 为词向量添加位置编码,使模型能够识别词序。
    • Dropout 防止过拟合。
  2. 逐层通过解码器块

    for layer in self.layers:
        out = layer(out, enc_out, src_mask, tgt_mask)
    
    
    • 将目标序列传递给每一个解码器块。
    • 每个块中的编码器-解码器注意力层会根据编码器的输出信息和目标序列上下文,生成更精细的解码信息。
    • src_masktgt_mask 分别用于在编码器-解码器注意力中屏蔽源序列和目标序列中的填充部分,确保模型关注有效信息。
  3. 输出层生成目标词

    out = self.fc_out(out)
    
    
    • 通过线性层生成目标词汇表大小的分布,用于选择下一个生成的目标词。

实现解码器块(Decoder Block)

为了更完整地理解解码器的工作机制,我们还需要实现 DecoderBlock。一个解码器块由以下几个部分组成:

  1. 自注意力层(Masked Self-Attention Layer):防止模型看到未来的词。
  2. 编码器-解码器注意力层(Encoder-Decoder Attention Layer):将编码器的输出与解码器当前状态结合,获取上下文信息。
  3. 前馈神经网络层(Feed-Forward Network Layer):提升解码器的表达能力。
  4. LayerNorm 和 Dropout 层:保持数值稳定,防止过拟合。
class DecoderBlock(nn.Module):
    def __init__(self, embed_size, heads, forward_expansion, dropout):
        super(DecoderBlock, self).__init__()
        self.attention = MultiHeadAttention(embed_size, heads)
        self.norm1 = nn.LayerNorm(embed_size)
        self.norm2 = nn.LayerNorm(embed_size)
        self.norm3 = nn.LayerNorm(embed_size)

        self.encoder_decoder_attention = MultiHeadAttention(embed_size, heads)
        self.feed_forward = FeedForward(embed_size, forward_expansion)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x, enc_out, src_mask, tgt_mask):
        attention = self.attention(x, x, x, tgt_mask)
        x = self.dropout(self.norm1(attention + x))

        enc_dec_attention = self.encoder_decoder_attention(x, enc_out, enc_out, src_mask)
        x = self.dropout(self.norm2(enc_dec_attention + x))

        forward = self.feed_forward(x)
        out = self.dropout(self.norm3(forward + x))

        return out


解码器块的前向传播解析

  1. 自注意力层:Masked Self-Attention 屏蔽未来的词,确保解码器生成当前词时不会看到之后的词。

    attention = self.attention(x, x, x, tgt_mask)
    x = self.dropout(self.norm1(attention + x))
    
    
  2. 编码器-解码器注意力层:结合编码器的输出,通过 Encoder-Decoder Attention 提取源句子的信息。

    enc_dec_attention = self.encoder_decoder_attention(x, enc_out, enc_out, src_mask)
    x = self.dropout(self.norm2(enc_dec_attention + x))
    
    
  3. 前馈神经网络:进一步处理信息,提升特征的表达能力。

    forward = self.feed_forward(x)
    out = self.dropout(self.norm3(forward + x))
    
    

测试 Transformer 解码器

以下代码用于测试 TransformerDecoder 类,确保其可以正常运行:

# 设置参数
tgt_vocab_size = 10000  # 假设目标词汇表大小
embed_size = 512
num_layers = 6
heads = 8
forward_expansion = 4
dropout = 0.1
max_length = 100
seq_length = 20
batch_size = 2

# 假设输入
x = torch.randint(0, tgt_vocab_size, (batch_size, seq_length))
enc_out

 = torch.rand(batch_size, seq_length, embed_size)
src_mask, tgt_mask = None, None

# 实例化解码器并前向传播
decoder = TransformerDecoder(tgt_vocab_size, embed_size, num_layers, heads, forward_expansion, dropout, max_length)
out = decoder(x, enc_out, src_mask, tgt_mask)

print("解码器的输出形状:", out.shape)

期望输出形状(batch_size, seq_length, tgt_vocab_size),例如 (2, 20, 10000)


总结

通过实现和逐步分析 Transformer 解码器模块,我们可以看到它是如何结合编码器输出,在生成目标序列时保持语义和上下文一致的。希望本文能帮助你理解解码器的实现过程。后续内容可以深入研究完整的 Transformer 模型搭建,包括编码器与解码器的组合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值