seq2seq架构

在这里插入图片描述

seq2seq简介

在这里插入图片描述

  • 输入:划分为序列的词向量

  • 输出:针对每一个词向量对应的译文

从上图中可知, seq2seq模型架构, 包括两部分分别是encoder(编码器)和decoder(解码器),
编码器和解码器的内部实现都使⽤了GRU模型, 这⾥它要完成的是⼀个中⽂到英⽂的翻译: 欢迎 来 北京 --> welcome to BeiJing. 编码器⾸先处理中⽂输⼊"欢迎 来 北京", 通过GRU模型获得每个时间步的输出张量,最后将它们拼接成⼀个中间语义张量c, 接着解码器将使⽤这个中间语义张量c以及每⼀个时间步的隐层张量, 逐个⽣成对应的翻译语⾔。

  • 注意:此处编码器的输入和输出与GRU相同;解码器的输入包括隐藏层和每一次都作用的中间语义张量,还有被译文的词张量表(这点在之后构建解码器时可以体现)

1.编码器

1.1 基于GRU的编码器结构

在这里插入图片描述

class EncoderRNN(nn.Module):
    def __init__(self, input_size, hidden_size):
        """它的初始化参数有两个, input_size代表编码器的输入尺寸即源语言的词表大小(单词个数),
        hidden_size代表GRU的隐层节点数, 也代表词嵌入维度(想要将每个词embedding的维度), 同时又是GRU的输入尺寸"""
        super(EncoderRNN, self).__init__()
        # 将参数hidden_size传入类中
        self.hidden_size = hidden_size
        # 实例化nn中预定义的Embedding层, 它的参数分别是input_size, hidden_size
        # 这里的词嵌入维度即hidden_size
        self.embedding = nn.Embedding(input_size, hidden_size)
        # 然后实例化nn中预定义的GRU层, 它的参数是hidden_size
        #(输入张量和隐藏层维度都为hidden_size;隐藏层数默认为1)
        self.gru = nn.GRU(hidden_size, hidden_size)

    def forward(self, input, hidden):
        """编码器前向逻辑函数中参数有两个, input代表源语言的Embedding层输入张量
           hidden代表编码器层gru的初始隐层张量"""
        # 将输入张量进行embedding操作, 并使其形状变为(1,1,-1),-1代表自动计算维度
        # 理论上,我们的编码器每次只以一个词作为输入, 因此词汇映射后的尺寸应该是[1, embedding]
        # 而这里转换成三维的原因是因为torch中预定义gru必须使用三维张量作为输入, 因此我们拓展了一个维度
        output = self.embedding(input).view(1, 1, -1)
        # 然后将embedding层的输出和传入的初始hidden作为gru的输入传入其中,
        # 获得最终gru的输出output和对应的隐层张量hidden, 并返回结果
        output, hidden = self.gru(output, hidden)
        return output, hidden

    def initHidden(self):
        """初始化隐层张量函数"""
        # 将隐层张量初始化成为1x1xself.hidden_size大小的0张量
        return torch.zeros(1, 1, self.hidden_size, device=device)

2.解码器

2.1 构建基于GRU的解码器

在这里插入图片描述

class DecoderRNN(nn.Module):
    def __init__(self, hidden_size, output_size):
        """初始化函数有两个参数,hidden_size代表解码器中GRU的输入尺寸,也是它的隐层节点数
           output_size代表整个解码器的输出尺寸, 也是我们希望得到的指定尺寸即目标语言的词表大小"""
        super(DecoderRNN, self).__init__()
        # 将hidden_size传入到类中
        self.hidden_size = hidden_size
        # 实例化一个nn中的Embedding层对象, 它的参数output这里表示目标语言的词表大小
        # hidden_size表示目标语言的词嵌入维度
        self.embedding = nn.Embedding(output_size, hidden_size)
        # 实例化GRU对象,输入参数都是hidden_size,代表它的输入尺寸和隐层节点数相同
        self.gru = nn.GRU(hidden_size, hidden_size)
        # 实例化线性层, 对GRU的输出做线性变化, 获我们希望的输出尺寸output_size
        # 因此它的两个参数分别是hidden_size, output_size
        self.out = nn.Linear(hidden_size, output_size)
        # 最后使用softmax进行处理,以便于分类
        self.softmax = nn.LogSoftmax(dim=1)#列上进行


    def forward(self, input, hidden):
        """解码器的前向逻辑函数中, 参数有两个, input代表目标语言的Embedding层输入张量
           hidden代表解码器GRU的初始隐层张量"""
        # 将输入张量进行embedding操作, 并使其形状变为(1,1,-1),-1代表自动计算维度
        # 原因和解码器相同,因为torch预定义的GRU层只接受三维张量作为输入
        output = self.embedding(input).view(1, 1, -1)
        # 然后使用relu函数对输出进行处理,根据relu函数的特性, 将使Embedding矩阵更稀疏,以防止过拟合
        output = F.relu(output)
        # 接下来, 将把embedding的输出以及初始化的hidden张量传入到解码器gru中
        output, hidden = self.gru(output, hidden)
        # 因为GRU输出的output也是三维张量,第一维没有意义(尺寸为1*1*hidden_size),因此可以通过output[0]来降维
        # 再传给线性层做变换, 最后用softmax处理以便于分类(output[0]表示output的第0层)
        output = self.softmax(self.out(output[0]))#self.out(output[0])尺寸为1*hidden_size
        return output, hidden

    def initHidden(self):
        """初始化隐层张量函数"""
        # 将隐层张量初始化成为1x1xself.hidden_size大小的0张量
        return torch.zeros(1, 1, self.hidden_size, device=device)

2.2 构建基于GRU和Attention的解码器

在这里插入图片描述

  • 这里可以找到注意力机制中的Q、K、V;
    • Q:embedded
    • K:prev _hidden
    • V:encoder_outputs
    class AttnDecoderRNN(nn.Module):
        def __init__(self, hidden_size, output_size, dropout_p=0.1, max_length=MAX_LENGTH):#MAX_LENGTH=10
            """初始化函数中的参数有4个, hidden_size代表解码器中GRU的输入尺寸,也是它的隐层节点数
               output_size代表整个解码器的输出尺寸, 也是我们希望得到的指定尺寸即目标语言的词表大小
               dropout_p代表我们使用dropout层时的置零比率,默认0.1, max_length代表句子的最大长度"""
            super(AttnDecoderRNN, self).__init__()
            # 将以下参数传入类中
            self.hidden_size = hidden_size
            self.output_size = output_size
            self.dropout_p = dropout_p
            self.max_length = max_length

            # 实例化一个Embedding层, 输入参数是self.output_size和self.hidden_size
            self.embedding = nn.Embedding(self.output_size, self.hidden_size)
            # 根据attention的QKV理论,attention的输入参数为三个Q,K,V,
            # 我们这里使用的是第一步中的第一种计算方式, 因此需要一个线性变换的矩阵, 实例化nn.Linear
            # 因为它的输入是Q,K的拼接, 所以输入的第一个参数是self.hidden_size * 2,第二个参数是self.max_length
            # 这里的Q是解码器的Embedding层的输出, K是解码器GRU的隐层输出,因为首次隐层还没有任何输出,会使用编码器的隐层输出
            # 而这里的V是编码器层的输出
            self.attn = nn.Linear(self.hidden_size * 2, self.max_length)
            # 接着我们实例化另外一个线性层, 它是attention理论中的第四步的线性层,用于规范输出尺寸
            # 这里它的输入来自第三步的结果, 因为第三步的结果是将Q与第二步的结果进行拼接, 因此输入维度是self.hidden_size * 2
            self.attn_combine = nn.Linear(self.hidden_size * 2, self.hidden_size)
            # 接着实例化一个nn.Dropout层,并传入self.dropout_p
            self.dropout = nn.Dropout(self.dropout_p)
            # 之后实例化nn.GRU, 它的输入和隐层尺寸都是self.hidden_size
            self.gru = nn.GRU(self.hidden_size, self.hidden_size)
            # 最后实例化gru后面的线性层,也就是我们的解码器输出层.
            self.out = nn.Linear(self.hidden_size, self.output_size)

        def forward(self, input, hidden, encoder_outputs):
            """forward函数的输入参数有三个, 分别是源数据输入张量, 初始的隐层张量, 以及解码器的输出张量"""

            # 根据结构计算图, 输入张量进行Embedding层并扩展维度
            embedded = self.embedding(input).view(1, 1, -1)  # 输出1*1*hidden_size
            # 使用dropout进行随机丢弃,防止过拟合
            embedded = self.dropout(embedded)

            # 进行attention的权重计算, 哦我们呢使用第一种计算方式:
            # 将Q,K进行纵轴拼接, 做一次线性变化, 最后使用softmax处理获得结果
            # embedded[0], hidden[0]尺寸均为1*hidden_size;attn_weights输出为1*10
            attn_weights = F.softmax(
                self.attn(torch.cat((embedded[0], hidden[0]), 1)), dim=1)

            # 然后进行第一步的后半部分, 将得到的权重矩阵与V做矩阵乘法计算, 当二者都是三维张量且第一维代表为batch条数时, 则做bmm运算
            # 即,(1*1*MAX_LENGTH)1*1*10   (1*MAX_LENGTH*hidden_size)1*10*25
            attn_applied = torch.bmm(attn_weights.unsqueeze(0),
                                     encoder_outputs.unsqueeze(0))

            # 之后进行第二步, 通过取[0]是用来降维, 根据第一步采用的计算方法, 需要将Q与第一步的计算结果再进行拼接
            output = torch.cat((embedded[0], attn_applied[0]), 1)

            # 最后是第三步, 使用线性层作用在第三步的结果上做一个线性变换并扩展维度,得到输出
            output = self.attn_combine(output).unsqueeze(0)

            # attention结构的结果使用relu激活
            output = F.relu(output)

            # 将激活后的结果作为gru的输入和hidden一起传入其中
            output, hidden = self.gru(output, hidden)

            # 最后将结果降维并使用softmax处理得到最终的结果  这里的1和 -1都可以
            output = F.log_softmax(self.out(output[0]), dim=1)
            # 返回解码器结果,最后的隐层张量以及注意力权重张量
            return output, hidden, attn_weights

        def initHidden(self):
            """初始化隐层张量函数"""
            # 将隐层张量初始化成为1x1xself.hidden_size大小的0张量
            return torch.zeros(1, 1, self.hidden_size, device=device)

参考资料

视频讲解

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Transformer seq2seq是一种基于Transformer模型的seq2seq模型。它使用编码器-解码器架构,输入一个序列,输出另一个序列。与传统的seq2seq模型相比,Transformer seq2seq使用Transformer blocks来代替循环网络。这种模型广泛应用于语音识别、机器翻译、语音翻译、语音合成和聊天机器人训练等NLP问题。它的泛用性很高,但有些特定任务可能需要使用经过定制的模型来获得更好的结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Transformer与seq2seq](https://download.csdn.net/download/weixin_38705558/14034735)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Transformer神经网络学习笔记——Seq2Seq模型和Transformer](https://blog.csdn.net/qq_50199113/article/details/131562854)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Transformer、Attention与seq2seq model](https://blog.csdn.net/weixin_41712499/article/details/103199986)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值