pytorch seq2seq模型中加入teacher_forcing机制

在循环内加的teacher forcing机制,这种为目标确定的时候,可以这样加。

目标不确定,需要在循环外加。

decoder.py 中的修改

"""
实现解码器
"""
import torch.nn as nn
import config
import torch
import torch.nn.functional as F
import numpy as np
import random

class Decoder(nn.Module):
    def __init__(self):
        super(Decoder, self).__init__()

        self.embedding = nn.Embedding(num_embeddings=len(config.ns),
                                      embedding_dim=50,
                                      padding_idx=config.ns.PAD)

        # 需要的hidden_state形状:[1,batch_size,64]
        self.gru = nn.GRU(input_size=50,
                          hidden_size=64,
                          num_layers=1,
                          bidirectional=False,
                          batch_first=True,
                          dropout=0)

        # 假如encoder的hidden_size=64,num_layer=1 encoder_hidden :[2,batch_sizee,64]

        self.fc = nn.Linear(64, len(config.ns))

    def forward(self, encoder_hidden,target):

        # 第一个时间步的输入的hidden_state
        decoder_hidden = encoder_hidden  # [1,batch_size,encoder_hidden_size]
        # 第一个时间步的输入的input
        batch_size = encoder_hidden.size(1)
        decoder_input = torch.LongTensor([[config.ns.SOS]] * batch_size).to(config.device)  # [batch_size,1]
        # print("decoder_input:",decoder_input.size())

        # 使用全为0的数组保存数据,[batch_size,max_len,vocab_size]
        decoder_outputs = torch.zeros([batch_size, config.max_len, len(config.ns)]).to(config.device)

        for t in range(config.max_len):
            decoder_output_t, decoder_hidden = self.forward_step(decoder_input, decoder_hidden)
            decoder_outputs[:, t, :] = decoder_output_t

            # 获取当前时间步的预测值
            value, index = decoder_output_t.max(dim=-1)
            if random.randint(0,100) >70:    #teacher forcing机制
                decoder_input = target[:,t].unsqueeze(-1)
            else:
                decoder_input = index.unsqueeze(-1)  # [batch_size,1]
            # print("decoder_input:",decoder_input.size())
        return decoder_outputs, decoder_hidden

    def forward_step(self, decoder_input, decoder_hidden):
        ‘‘‘
        计算一个时间步的结果
        :param decoder_input: [batch_size,1]
        :param decoder_hidden: [batch_size,encoder_hidden_size]
        :return:
        ‘‘‘

        decoder_input_embeded = self.embedding(decoder_input)
        # print("decoder_input_embeded:",decoder_input_embeded.size())

        out, decoder_hidden = self.gru(decoder_input_embeded, decoder_hidden)

        # out :【batch_size,1,hidden_size】

        out_squeezed = out.squeeze(dim=1)  # 去掉为1的维度
        out_fc = F.log_softmax(self.fc(out_squeezed), dim=-1)  # [bathc_size,vocab_size]
        # out_fc.unsqueeze_(dim=1) #[bathc_size,1,vocab_size]
        # print("out_fc:",out_fc.size())
        return out_fc, decoder_hidden

    def evaluate(self, encoder_hidden):

        # 第一个时间步的输入的hidden_state
        decoder_hidden = encoder_hidden  # [1,batch_size,encoder_hidden_size]
        # 第一个时间步的输入的input
        batch_size = encoder_hidden.size(1)
        decoder_input = torch.LongTensor([[config.ns.SOS]] * batch_size).to(config.device)  # [batch_size,1]
        # print("decoder_input:",decoder_input.size())

        # 使用全为0的数组保存数据,[batch_size,max_len,vocab_size]
        decoder_outputs = torch.zeros([batch_size, config.max_len, len(config.ns)]).to(config.device)

        decoder_predict = []  # [[],[],[]]  #123456  ,targe:123456EOS,predict:123456EOS123
        for t in range(config.max_len):
            decoder_output_t, decoder_hidden = self.forward_step(decoder_input, decoder_hidden)
            decoder_outputs[:, t, :] = decoder_output_t

            # 获取当前时间步的预测值
            value, index = decoder_output_t.max(dim=-1)
            decoder_input = index.unsqueeze(-1)  # [batch_size,1]
            # print("decoder_input:",decoder_input.size())
            decoder_predict.append(index.cpu().detach().numpy())

        # 返回预测值
        decoder_predict = np.array(decoder_predict).transpose()  # [batch_size,max_len]
        return decoder_outputs, decoder_predict

  seq2seq.py

"""
完成seq2seq模型
"""
import torch.nn as nn
from encoder import Encoder
from decoder import Decoder

class Seq2Seq(nn.Module):
    def __init__(self):
        super(Seq2Seq, self).__init__()
        self.encoder = Encoder()
        self.decoder = Decoder()

    def forward(self, input, input_len,target):
        encoder_outputs, encoder_hidden = self.encoder(input, input_len)
        decoder_outputs, decoder_hidden = self.decoder(encoder_hidden,target)
        return decoder_outputs

    def evaluate(self, input, input_len):
        encoder_outputs, encoder_hidden = self.encoder(input, input_len)
        decoder_outputs, decoder_predict = self.decoder.evaluate(encoder_hidden)
        return decoder_outputs, decoder_predict

  train.py

"""
进行模型的训练
"""
import torch
import torch.nn.functional as F
from seq2seq import Seq2Seq
from torch.optim import Adam
from dataset import get_dataloader
from tqdm import tqdm
import config
import numpy as np
import pickle
from matplotlib import pyplot as plt
from eval import eval
import os

model = Seq2Seq().to(config.device)
optimizer = Adam(model.parameters())

if os.path.exists("./models/model.pkl"):
    model.load_state_dict(torch.load("./models/model.pkl"))
    optimizer.load_state_dict(torch.load("./models/optimizer.pkl"))

loss_list = []

def train(epoch):
    data_loader = get_dataloader(train=True)
    bar = tqdm(data_loader, total=len(data_loader))

    for idx, (input, target, input_len, target_len) in enumerate(bar):
        input = input.to(config.device)
        target = target.to(config.device)
        input_len = input_len.to(config.device)
        optimizer.zero_grad()
        decoder_outputs = model(input, input_len,target)  # [batch_Size,max_len,vocab_size]
        predict = decoder_outputs.view(-1, len(config.ns))
        target = target.view(-1)
        loss = F.nll_loss(predict, target, ignore_index=config.ns.PAD)
        loss.backward()
        optimizer.step()
        loss_list.append(loss.item())
        bar.set_description("epoch:{} idx:{} loss:{:.6f}".format(epoch, idx, np.mean(loss_list)))

        if idx % 100 == 0:
            torch.save(model.state_dict(), "./models/model.pkl")
            torch.save(optimizer.state_dict(), "./models/optimizer.pkl")
            pickle.dump(loss_list, open("./models/loss_list.pkl", "wb"))

if __name__ == ‘__main__‘:
    for i in range(5):
        train(i)
        eval()

    plt.figure(figsize=(50, 8))
    plt.plot(range(len(loss_list)), loss_list)
    plt.show()

  

原文地址:https://www.cnblogs.com/LiuXinyu12378/p/12343829.html

时间: 2024-11-08 15:53:38

pytorch seq2seq模型中加入teacher_forcing机制的相关文章

pytorch seq2seq模型示例

以下代码可以让你更加熟悉seq2seq模型机制 """ test """ import numpy as np import torch import torch.nn as nn import torch.optim as optim from torch.autograd import Variable # 创建字典 seq_data = [['man', 'women'], ['black', 'white'], ['king', 'que

【从零开始学习YOLOv3】7. 教你在YOLOv3模型中添加Attention机制

前言:[从零开始学习YOLOv3]系列越写越多,本来安排的内容比较少,但是在阅读代码的过程中慢慢发掘了一些新的亮点,所以不断加入到这个系列中.之前都在读YOLOv3中的代码,已经学习了cfg文件.模型构建等内容.本文在之前的基础上,对模型的代码进行修改,将之前Attention系列中的SE模块和CBAM模块集成到YOLOv3中. 1. 规定格式 正如[convolutional],[maxpool],[net],[route]等层在cfg中的定义一样,我们再添加全新的模块的时候,要规定一下cfg

Seq2Seq模型与注意力机制

Seq2Seq模型 基本原理 核心思想:将一个作为输入的序列映射为一个作为输出的序列 编码输入 解码输出 解码第一步,解码器进入编码器的最终状态,生成第一个输出 以后解码器读入上一步的输出,生成当前步输出 组成部件: Encoder Decoder 连接两者的固定大小的State Vector 解码方法 最核心部分,大部分的改进 贪心法 选取一种度量标准后,在当前状态下选择最佳的一个结果,直到结束 计算代价低 局部最优解 集束搜索(Beam Search) 启发式算法 保存beam size个当

Deep Learning基础--理解LSTM/RNN中的Attention机制

导读 目前采用编码器-解码器 (Encode-Decode) 结构的模型非常热门,是因为它在许多领域较其他的传统模型方法都取得了更好的结果.这种结构的模型通常将输入序列编码成一个固定长度的向量表示,对于长度较短的输入序列而言,该模型能够学习出对应合理的向量表示.然而,这种模型存在的问题在于:当输入序列非常长时,模型难以学到合理的向量表示. 在这篇博文中,我们将探索加入LSTM/RNN模型中的attention机制是如何克服传统编码器-解码器结构存在的问题的. 通过阅读这篇博文,你将会学习到: 传

吴裕雄--天生自然 pythonTensorFlow自然语言处理:Seq2Seq模型--训练

import tensorflow as tf # 1.参数设置. # 假设输入数据已经用9.2.1小节中的方法转换成了单词编号的格式. SRC_TRAIN_DATA = "F:\\TensorFlowGoogle\\201806-github\\TensorFlowGoogleCode\\Chapter09\\train.en" # 源语言输入文件. TRG_TRAIN_DATA = "F:\\TensorFlowGoogle\\201806-github\\TensorF

PyTorch 1.0 中文官方教程:混合前端的 seq2seq 模型部署

译者:cangyunye 作者: Matthew Inkawhich 本教程将介绍如何是seq2seq模型转换为PyTorch可用的前端混合Torch脚本. 我们要转换的模型是来自于聊天机器人教程 Chatbot tutorial. 你可以把这个教程当做Chatbot tutorial的第二篇章,并且部署你的预训练模型,或者你也可以依据本文使用我们采取的预训练模型.就后者而言,你可以从原始的Chatbot tutorial参考更详细的数据预处理,模型理论和定义以及模型训练. 什么是混合前端(Hy

动手学pytorch-注意力机制和Seq2Seq模型

注意力机制和Seq2Seq模型 1.基本概念 2.两种常用的attention层 3.带注意力机制的Seq2Seq模型 4.实验 动手学pytorch-注意力机制和Seq2Seq模型 原文地址:https://www.cnblogs.com/54hys/p/12317068.html

seq2seq模型

一.什么是seq2seq模型 seq2seq全称为:sequence to sequence ,是2014年被提出来的一种Encoder-Decoder结构.其中Encoder是一个RNN结构(LSTM.GRU.RNN等). 主要思想是输入一个序列,通过encoder编码成一个语义向量c(context),然后decoder成输出序列.这个结构重要的地方在于输入序列和输出序列的长度是可变的. 应用场景:机器翻译.聊天机器人.文档摘要.图片描述等 二.Encoder-Decoder结构 最初Enc

[Pytorch]深度模型的显存计算以及优化

原文链接:https://oldpan.me/archives/how-to-calculate-gpu-memory 前言 亲,显存炸了,你的显卡快冒烟了! torch.FatalError: cuda runtime error (2) : out of memory at /opt/conda/conda-bld/pytorch_1524590031827/work/aten/src/THC/generic/THCStorage.cu:58 想必这是所有炼丹师们最不想看到的错误,没有之一.