【动手学习pytorch笔记】30.seq2seq

本文探讨了seq2seq模型中的编码器-解码器结构,包括双向RNN编码器、GRU单元和Transformer的融合,以及训练与推理时的不同策略。重点介绍了如何通过注意力机制衡量句子序列的预测质量,并展示了如何在训练和预测阶段处理填充和遮蔽。

seq2seq

理论

在这里插入图片描述

编码器是一个RNN,因为任务是机器翻译,所以是双向的

解码器用另外一个RNN输出

之前看过Transformer对这个很熟悉

需要注意的一点是,在做训练和做推理的时候是有区别的

在这里插入图片描述

在训练时,我们是有正确的翻译的,所以解码器的每次输入都是正确的翻译

而在推理时,智能用我们预测的词当作解码器RNN下一个时间步的输入

那么现在我实在预测一个句子序列,而不是和之前一样预测一个词了,那么怎么衡量一个句子序列的好坏呢

在这里插入图片描述

比如p2p_2p2,预测序列一共有AB,BB,BC,CD四种,在标签序列中出现过的只有AB,BC,CD,所以p2p_2p2=3/4

因为p是小于1的值,长的匹配有更高的权重并且预测越短,取exp以后就越小,产生惩罚效果

代码

import collections
import math
import torch
from torch import nn
from d2l import torch as d2l

编码器

#@save
class Seq2SeqEncoder(d2l.Encoder):
    """用于序列到序列学习的循环神经网络编码器"""
    def __init__(self, vocab_size, embed_size, num_hiddens, num_layers,
                 dropout=0, **kwargs):
        super(Seq2SeqEncoder, self).__init__(**kwargs)
        # 嵌入层
        self.embedding = nn.Embedding(vocab_size, embed_size)
        self.rnn = nn.GRU(embed_size, num_hiddens, num_layers,
                          dropout=dropout)

    def forward(self, X, *args):
        # 输出'X'的形状:(batch_size,num_steps,embed_size)
        X = self.embedding(X)
        # 在循环神经网络模型中,第一个轴对应于时间步
        X = X.permute(1, 0, 2)
        # 如果未提及状态,则默认为0
        output, state = self.rnn(X)
        # output的形状:(num_steps,batch_size,num_hiddens)
        # state[0]的形状:(num_layers,batch_size,num_hiddens)
        return output, state

embedding词嵌入,把one-hot编码映射到词嵌入矩阵,博客没写过,自己知道就行,词嵌入矩阵可以理解为一个词表

测试一下

encoder = Seq2SeqEncoder(vocab_size=10, embed_size=8, num_hiddens=16,num_layers=2)
encoder.eval()
X = torch.zeros((4, 7), dtype=torch.long)
output, state = encoder(X)
output.shape

查看output和state的大小

torch.Size([7, 4, 16])

(时间步数,批量大小,隐藏单元数)

state.shape
torch.Size([2, 4, 16])

(隐藏层的数量,批量大小,隐藏单元数)

output是RNN模型输出的,编码器是没有最后Linear输出层的,所以大小 =(隐藏层的数量,批量大小,隐藏单元数)

state,双隐藏层的编码器,本来隐藏状态的大小 = (批量大小,隐藏单元数)

解码器

class Seq2SeqDecoder(d2l.Decoder):
    """用于序列到序列学习的循环神经网络解码器"""
    def __init__(self, vocab_size, embed_size, num_hiddens, num_layers,
                 dropout=0, **kwargs):
        super(Seq2SeqDecoder, self).__init__(**kwargs)
        self.embedding = nn.Embedding(vocab_size, embed_size)
        self.rnn = nn.GRU(embed_size + num_hiddens, num_hiddens, num_layers,
                          dropout=dropout)
        self.dense = nn.Linear(num_hiddens, vocab_size)

    def init_state(self, enc_outputs, *args):
        return enc_outputs[1]

    def forward(self
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值