Machine Learning & Recommendation & NLP & DL机器学习100天

Pytorch学习记录-使用神经网络训练Seq2Seq总结

2019-04-21  本文已影响5人  我的昵称违规了

昨天的学习记录,想想还是总结一下流程看。

1. 数据预处理流程

1.1 tokenize使用加载好的分词器进行分词(如果使用spacy这类分词器,先加载分词器)
1.2 将分词结果放入Field中
1.3 加载平行语料库,使用splits将语料库拆分为train、valid、test,同时加上src和trg标签
1.4 使用build_vocab构建词汇表,将SRC、TRG两个Field转为词汇表
1.5 构建迭代器,使用BucketIterator.splits将train、valid、test三个数据集转为迭代器 在预处理阶段有两组数据:(1)训练好的平行语料库、(2)要处理的语料
- 训练好的平行语料库做了处理,拆分成了traindata/validdata/testdata,然后做成迭代器trainiter/validiter/testiter。
- 要处理的语料进行分词处理,放入Field成为SRC和TRG,最后生成词汇表

2. 构建模型

2.1 构建Encoder 相关参数

class Encoder(nn.Module):
    def __init__(self, input_dim, emb_dim, hid_dim, n_layers, dropout):
        super(Encoder,self).__init__()

        self.input_dim=input_dim
        self.emb_dim=emb_dim
        self.hid_dim=hid_dim
        self.n_layers=n_layers
        self.dropout=dropout

        self.embedding=nn.Embedding(input_dim,emb_dim)
        self.rnn=nn.LSTM(emb_dim,hid_dim,n_layers,dropout=dropout)

        self.dropout=nn.Dropout(dropout)
    def forward(self, src):
        embedded=self.dropout(self.embedding(src))
        outputs, (hidden,cell)=self.rnn(embedded)
        return hidden ,cell

2.2 构建Decoder 相关参数和Encoder类似

class Decoder(nn.Module):
    def __init__(self, output_dim, emb_dim, hid_dim, n_layers, dropout):
        super(Decoder,self).__init__()

        self.emb_dim=emb_dim
        self.hid_dim=hid_dim
        self.output_dim=output_dim
        self.n_layers=n_layers
        self.dropout=dropout

        self.embedding=nn.Embedding(output_dim,emb_dim)
        self.rnn=nn.LSTM(emb_dim,hid_dim,n_layers,dropout=dropout)
        self.out=nn.Linear(hid_dim,output_dim)

        self.dropout=nn.Dropout(dropout)
    def forward(self, input,hidden,cell):
        input=input.unsqueeze(0)
        embedded=self.dropout(self.embedding(input))
        output, (hidden,cell)=self.rnn(embedded,(hidden,cell))
        prediction=self.out(output.squeeze(0))
        return prediction,hidden ,cell

2.3 构建Seq2Seq
在这里有一个有意思的Teacher Forcing,这是个训练的小技巧。因为 Seq2Seq 会把前一个时间点的输出当成后一个时间点的输入,如果我们在前个时间点做了错误的结论,那往后所有的时间点都会受到这个错误影响,这个连锁反应会让训练容易摆荡不定。 于是我们就想到对于用于生成式的 RNN,如果他在第 t 个时间搞错了,没关系,我们派个老师把错误的答案给偷偷纠正成对的,尽管学生记忆中仍觉得之前说的是对的,但在看到了正确的输入后,至少还有浪子回头的可能。 不过,学生最终还是得踏出校园,自己探求人生的答案。同样的,在测试阶段,我们并没有正确答案,模型必须试着自立自强可惜这往往会遇到些困难,因为在训练时被老师过度保护了,输出与输入间的递归性并没被妥善地训练到。

确认之前Encoder和Decoder层数一致。

class Seq2Seq(nn.Module):
    def __init__(self, encoder, decoder, device):
        super(Seq2Seq,self).__init__()

        self.encoder = encoder
        self.decoder = decoder
        self.device = device

        assert encoder.hid_dim == decoder.hid_dim, \
            "Hidden dimensions of encoder and decoder must be equal!"
        assert encoder.n_layers == decoder.n_layers, \
            "Encoder and decoder must have equal number of layers!"
    def forward(self, src,trg,teacher_forcing_ratio=0.5):
        # src = [src sent len, batch size]
        # trg = [trg sent len, batch size]
        # teacher_forcing_ratio是使用教师强制的概率
        # 例如。如果teacher_forcing_ratio是0.75,我们75%的时间使用groundtruth输入
        batch_size=trg.shape[1]
        max_len=trg.shape[0]
        trg_vocab_size=self.decoder.output_dim
        outputs = torch.zeros(max_len, batch_size, trg_vocab_size).to(self.device)
        hidden, cell=self.encoder(src)
        input=trg[0,:]
        for t in range(1, max_len):
            output, hidden, cell = self.decoder(input, hidden, cell)
            outputs[t] = output
            teacher_force = random.random() < teacher_forcing_ratio
            top1 = output.max(1)[1]
            input = (trg[t] if teacher_force else top1)
        return outputs
上一篇 下一篇

猜你喜欢

热点阅读