4. Transformer_3_解码器部分

1. 解码器介绍

2. 解码器层

2.1 解码器层的作用

作为解码器的组成单元,每个解码器层根據给定的输入向目标方向进行特征提取操作,即解码过程;

2.2 解码器层的代码分析

init中:参数:size, self_attn, src_attn, feed_forward, dropout;size词嵌入维度、self_attn自注意力机制、src_attn一般注意力、feed_forward前馈全连接层对象、dropout随机失活的系数;

forward中:参数: x, memory, source_mask, target_mask;x是来自解码器端的输入、memory来自编码器的输出结果、target_mask作用在第一个子层连接层结构即sentence_mask防止未来信息被掩盖、source_mask即padding_mask对目标文本的语句的pad进行mask;x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, target_mask))第一个子连接层:输入的第一个参数x即为解码器的x、lambda式对应的为 实现子层连接结构 class SubLayerConnectionforward(self, x, sublayer)中的 sublayerself.self_attn(..)返回的是自注意力机制(QKV都=x)的对象;最终返回一个新的x。

再送给第二个子连接层:x = self.sublayer[1](x, lambda x: self.src_attn(x, m, m, source_mask))输入的第一个参数x是上一步输出的第一个子连接层的输出结果、第二个参数返回的self.src_attn(x, m, m, source_mask)不是自注意力,而是一般注意力(Q=x,KV=m,Q!=K=V);再将返回的结果送给第三个子连接层 feed_forward;

python 复制代码
# todo 1.定义解码器层(由3个子连接层构成)
class DecoderLayer(nn.Module):
    def __init__(self, size, self_attn, src_attn, feed_forward, dropout):
        super(DecoderLayer, self).__init__()
        # size词嵌入维度,self_attn自注意力机制QKV,src_attn一般注意力机制Q!=K=V,feed_forward前馈全连接层
        self.size = size
        self.self_attn = self_attn
        self.src_attn = src_attn
        self.feed_forward = feed_forward
        # 克隆3个子层连接对象
        self.sub_layers = clones(SublayerConnection(size, dropout), 3)

    def forward(self, y, encoder_output, source_mask, target_mask):
        # y[2,4,512]:来自解码器的输入,encoder_output[2,4,512]:来自编码器的输出结果,
        # source_mask:作用在第二个子层连接结构的多头注意力机制对象上,进行padding_mask,
        # target_mask:作用在第一个子层连接结构的多头自注意力机制对象上,进行sentence_mask
        # 1.将y送入第一个子层连接结构得到 多头自注意力机制 + add + norm 之后的结果
        y1 = self.sub_layers[0].forward(y, lambda y: self.self_attn(y, y, y, target_mask))
        # y1 = self.sub_layers[0](y, lambda y: self.self_attn(y, y, y, target_mask)) #forward可省略

        # 2.将y1送入第二个子层连接结构得到 多头注意力机制 + add + norm 之后的结果
        y2 = self.sub_layers[1].forward(y1, lambda y1: self.src_attn(y1, encoder_output, encoder_output, source_mask))
        # y2 = self.sub_layers[1](y1, lambda y1: self.src_attn(y1, encoder_output, encoder_output, source_mask))
        # 3.将y2送入第三个子层连接结构得到 前馈全连接层+add+norm 之后的结果
        y3 = self.sub_layers[2](y2, self.feed_forward)
        return y3


# 定义解码器(由3个子连接层构成) 测试
def test_decoder_layer():
    # 定义假如解码器端的输入也是2行6列
    y = torch.tensor([[3, 4, 7, 10, 5, 70],
                      [2, 5, 8, 19, 20, 34]])
    # 1.经过embedding层得到的词嵌入结果
    my_embed = Embedding(vocab_size=2000, d_model=512)
    embed_y = my_embed(y)
    print(f'解码器embedding之后的结果:{embed_y.shape}')  # [2, 6, 512]
    # 2.经过position encoding位置编码层得到的位置编码信息
    my_pe = PositionEncoding(d_model=512, dropout_p=0.1, max_len=60)
    position_y = my_pe(embed_y)
    print(f'解码器位置编码之后结果:{position_y.shape}')  # [2, 6, 512]
    # 3.实例化多头自注意力机制的对象
    self_atten = MultiHeadAttention(embedding_dim=512, head=8, dropout=0.1)
    src_atten = copy.deepcopy(self_atten)
    # 4.实例化前馈全连接层对象
    feed_forward = FeedForward(d_model=512, d_ff=1024)
    # 5.实例化解码器层对象
    decoder_layer = DecoderLayer(size=512, self_attn=self_atten, src_attn=src_atten, feed_forward=feed_forward,
                                 dropout=0.1)
    # 6.整理解码器层的输入:y, encoder_output, source_mask, target_mask
    encoder_output = test_encoder()
    print(f'编码器层输出的结果:{encoder_output.shape}')  # [2, 4, 512]
    # target_mask --> 解码器的query和key --> [2, 6, 512] --> query和key的转置相乘之后 --> [2, 6, 6]
    target_mask = torch.zeros(8, 6, 6)
    # target_mask --> 解码器的query --> [2, 6, 512] --> 和key(编码器) --> [2, 4, 512] --> query和key的转置相乘之后 --> [2, 6, 4]
    source_mask = torch.zeros(8, 6, 4)
    output = decoder_layer(position_y, encoder_output, source_mask, target_mask)
    print(f'解码器层得到结果:{output.shape}')  # [2, 6, 512]


if __name__ == '__main__':
    test_decoder_layer()

3. 解码器

解码器是由6个解码器层堆叠而成;

3.1 解码器的作用

根据编码器的结果以及上一次预测的结果,对下一次可能出现的'值'进行特征表示;

3.2 解码器的代码分析

解码器是由6个解码器层堆叠而成;

init中:参数:layer, N;克隆了6个解码器层,最后一个进行规范化,前向传播时将这6层循环迭代,第一层的得到的结果送入第二层,第二层的结果送到第三层,...,一直送到第6层,第6层得到的结果经过norm得到最终结果;

python 复制代码
import torch
import torch.nn as nn
import torch.nn.functional as F
import math
import copy
from dm1_input import *
from dm2_encoder import *


# todo 1.定义解码器层(由3个子连接层构成)
class DecoderLayer(nn.Module):
    def __init__(self, size, self_attn, src_attn, feed_forward, dropout):
        super(DecoderLayer, self).__init__()
        # size词嵌入维度,self_attn自注意力机制QKV,src_attn一般注意力机制Q!=K=V,feed_forward前馈全连接层
        self.size = size
        self.self_attn = self_attn
        self.src_attn = src_attn
        self.feed_forward = feed_forward
        # 克隆3个子层连接对象
        self.sub_layers = clones(SublayerConnection(size, dropout), 3)

    def forward(self, y, encoder_output, source_mask, target_mask):
        # y[2,4,512]:来自解码器的输入,encoder_output[2,4,512]:来自编码器的输出结果,
        # source_mask:作用在第二个子层连接结构的多头注意力机制对象上,进行padding_mask,
        # target_mask:作用在第一个子层连接结构的多头自注意力机制对象上,进行sentence_mask
        # 1.将y送入第一个子层连接结构得到 多头自注意力机制 + add + norm 之后的结果
        y1 = self.sub_layers[0].forward(y, lambda y: self.self_attn(y, y, y, target_mask))
        # y1 = self.sub_layers[0](y, lambda y: self.self_attn(y, y, y, target_mask)) #forward可省略

        # 2.将y1送入第二个子层连接结构得到 多头注意力机制 + add + norm 之后的结果
        y2 = self.sub_layers[1].forward(y1, lambda y1: self.src_attn(y1, encoder_output, encoder_output, source_mask))
        # y2 = self.sub_layers[1](y1, lambda y1: self.src_attn(y1, encoder_output, encoder_output, source_mask))
        # 3.将y2送入第三个子层连接结构得到 前馈全连接层+add+norm 之后的结果
        y3 = self.sub_layers[2](y2, self.feed_forward)
        return y3


# 定义解码器(由3个子连接层构成) 测试
def test_decoder_layer():
    # 定义假如解码器端的输入也是2行6列
    y = torch.tensor([[3, 4, 7, 10, 5, 70],
                      [2, 5, 8, 19, 20, 34]])
    # 1.经过embedding层得到的词嵌入结果
    my_embed = Embedding(vocab_size=2000, d_model=512)
    embed_y = my_embed(y)
    print(f'解码器embedding之后的结果:{embed_y.shape}')  # [2, 6, 512]
    # 2.经过position encoding位置编码层得到的位置编码信息
    my_pe = PositionEncoding(d_model=512, dropout_p=0.1, max_len=60)
    position_y = my_pe(embed_y)
    print(f'解码器位置编码之后结果:{position_y.shape}')  # [2, 6, 512]
    # 3.实例化多头自注意力机制的对象
    self_atten = MultiHeadAttention(embedding_dim=512, head=8, dropout=0.1)
    src_atten = copy.deepcopy(self_atten)
    # 4.实例化前馈全连接层对象
    feed_forward = FeedForward(d_model=512, d_ff=1024)
    # 5.实例化解码器层对象
    decoder_layer = DecoderLayer(size=512, self_attn=self_atten, src_attn=src_atten, feed_forward=feed_forward,
                                 dropout=0.1)
    # 6.整理解码器层的输入:y, encoder_output, source_mask, target_mask
    encoder_output = test_encoder()
    print(f'编码器层输出的结果:{encoder_output.shape}')  # [2, 4, 512]
    # target_mask --> 解码器的query和key --> [2, 6, 512] --> query和key的转置相乘之后 --> [2, 6, 6]
    target_mask = torch.zeros(8, 6, 6)
    # target_mask --> 解码器的query --> [2, 6, 512] --> 和key(编码器) --> [2, 4, 512] --> query和key的转置相乘之后 --> [2, 6, 4]
    source_mask = torch.zeros(8, 6, 4)
    output = decoder_layer(position_y, encoder_output, source_mask, target_mask)
    print(f'解码器层得到结果:{output.shape}')  # [2, 6, 512]


# todo 2.定义解码器(由6个解码器层堆叠而成)
class Decoder(nn.Module):
    def __init__(self, layer, N):
        super(Decoder, self).__init__()
        # 克隆6个解码器层
        self.layers = clones(layer, N)
        # 规范化层
        self.norm = LayerNorm(layer.size)

    def forward(self, y, encoder_output, source_mask, target_mask):
        for layer in self.layers:
            y = layer(y, encoder_output, source_mask, target_mask)
        return self.norm(y)


# 定义解码器(由6个解码器层堆叠而成) 测试
def test_decoder():
    # 定义假如解码器端的输入也是2行6列
    y = torch.tensor([[3, 4, 7, 10, 5, 70],
                      [2, 5, 8, 19, 20, 34]])
    # 1.经过embedding层得到的词嵌入结果
    my_embed = Embedding(vocab_size=2000, d_model=512)
    embed_y = my_embed(y)
    print(f'解码器embedding之后的结果:{embed_y.shape}')  # [2, 6, 512]
    # 2.经过position encoding位置编码层得到的位置编码信息
    my_pe = PositionEncoding(d_model=512, dropout_p=0.1, max_len=60)
    position_y = my_pe(embed_y)
    print(f'解码器位置编码之后结果:{position_y.shape}')  # [2, 6, 512]
    # 3.实例化多头自注意力机制的对象
    self_atten = MultiHeadAttention(embedding_dim=512, head=8, dropout=0.1)
    src_atten = copy.deepcopy(self_atten)
    # 4.实例化前馈全连接层对象
    feed_forward = FeedForward(d_model=512, d_ff=1024)
    # 5.实例化解码器层对象
    decoder_layer = DecoderLayer(size=512, self_attn=self_atten, src_attn=src_atten, feed_forward=feed_forward,
                                 dropout=0.1)
    # 6.整理解码器层的输入:y, encoder_output, source_mask, target_mask
    encoder_output = test_encoder()
    print(f'编码器层输出的结果:{encoder_output.shape}')  # [2, 4, 512]
    # target_mask --> 解码器的query和key --> [2, 6, 512] --> query和key的转置相乘之后 --> [2, 6, 6]
    target_mask = torch.zeros(8, 6, 6)
    # target_mask --> 解码器的query --> [2, 6, 512] --> 和key(编码器) --> [2, 4, 512] --> query和key的转置相乘之后 --> [2, 6, 4]
    source_mask = torch.zeros(8, 6, 4)
    # 实例化解码器对象
    decoder = Decoder(decoder_layer, N=6)
    output = decoder(position_y, encoder_output, source_mask, target_mask)
    print(f'解码器层得到结果:{output.shape}')  # [2, 6, 512]


if __name__ == '__main__':
    # test_decoder_layer()
    test_decoder()
相关推荐
逻辑君3 小时前
Foresight研究报告【20260023】
人工智能·深度学习·机器学习·数学建模
Henry Zhu1233 小时前
大语言模型地基模块-Transformer详解
transformer
数智工坊4 小时前
【ROS 2 全栈入门指南三】:Action、参数与Launch文件全链路指南
android·stm32·嵌入式硬件·学习·机器人
AI探索先锋4 小时前
[特殊字符] Siri AI 炸场 WWDC!苹果联手谷歌 Gemini 打造“真·AI助手“,13人公司掀翻Transformer|AI科技热线
人工智能·transformer·wwdc
JobDocLS4 小时前
Jetson Orin的用法
深度学习
问心无愧05134 小时前
ctf show web入门109
android·前端·笔记
me8324 小时前
【AI面试】小白理解大模型:自注意力机制如何使大模型能够捕捉长距离依赖关系,它跟RNN有什么区别?
人工智能·rnn·深度学习·ai
Kobebryant-Manba5 小时前
学习模型构造
python·深度学习·学习