seq2seq文本翻译任务

1.seq2seq模型

目标:

seq2seq意思即向模型输入一个sequence,模型自己决定输出一个sequence。应用于文本翻译任务,我们期望告诉模型一段英语,模型输出一段翻译的结果,翻译的内容和长度都是由机器自己决定的。

模型

包含两部分,分别为encoder和decoder。下面尝试在翻译任务的语境中解释这个模型。

encoder(编码器):将输入的一段英文序列(machine learning)编码为向量H,H 包含了input的语义信息。

decoder(解码器):负责解析向量H,并逐步生成一个翻译结果序列。具体说来,我们期望decoder先接收一个事先约定好的start向量和初始向量H,输出‘机’字,我们再将输出向量‘机’反馈给decoder,模型输出‘器’向量… 如此迭代,直到模型输出END(事先约定好的向量),表示输出结束。

在这里插入图片描述

实现

RNN满足上述场景需求。记RNN的外部记忆状态状态为H。Encoder主要包含一个RNN,输入为一段英文序列词向量,将最后一个词向量对应的外部记忆H作为模型的输出。注意这里的RNN迭代次数固定为输入序列长度,每次迭代完成后,即清空外部记忆H。重新开始另一个sequence的学习/预测。

decoder同样主要包含一个RNN。RNN的input为H和start向量,只需迭代一步,即获得 output “机”,同时更新了外部记忆H,再将“机”输入模型,迭代一步,获得“器”,同时更新外部记忆H。如此往复,直到获得END向量,或达到最大长度。

2.实践

如何训练?

为加速模型收敛,在训练阶段,采用teach forcing的办法。

直接将label(期望的翻译结果)输入Decoder,取Decoder的输出作为Output,和label计算loss。注意,前一个label的后面用于计算的label差一列。

举例来说,输入的label为 “<START> 机 器 学 习",用于计算损失的loss为“机 器 学 习 <END>”。

在预测阶段,我们期望模型行为为:①根据encoder提取的英文序列的语义信息,判断出第一个字应该是“机”。②假设这个判断正确,将它作为条件,再判断下一个字应该是“器”…

如何处理一个batch内不同长度的序列?

有两种解决办法:

①直接设batch为1.

②用batch中最大长度序列补齐其他向量,同时记住每个序列的原始长度。

在encoder的forward函数中,根据每个序列的原始长度,采样对应长度的隐藏状态作为传递给decoder的外部记忆H。

decoder中也类似,将超出label序列原始长度的时间步输出直接置0,确保不会影响损失计算。

代码

注:这个简洁实现只是为了说明原理,故没有划分训练集。
数据集:https://download.csdn.net/download/yao_20020402/86398278

from collections import Counter
import nltk
import random
import numpy as np
import torch.nn as nn
import torch
import torch.optim as optim
import torch.nn.functional as F
# nltk.download('punkt')
device=torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
with open("./train.txt",encoding='utf-8',mode='r') as f:
    content=[i.split('\t') for i in f.read().split("\n") if len(i)>0]
cn_corpus=''
en_corpus=''
for i in content:
    en_corpus+=' '
    en_corpus+=i[0]
    cn_corpus+=i[1]
#建立词表
en_word_fre_dict=Counter(nltk.word_tokenize(en_corpus))
en_word_fre=[[word,en_word_fre_dict[word]] for word in en_word_fre_dict]
en_word_fre_sorted=sorted(en_word_fre,key=lambda x:x[1],reverse=True)
en_id_word=['','BE']
en_id_word+=[i[0] for i in en_word_fre_sorted]
en_word_id={
   word:id for id,word in enumerate(en_id_word)}

cn_word_fre_dict=Counter([i for i in cn_corpus])
cn_word_fre=[[word,cn_word_fre_dict[word]] for word in cn_word_fre_dict]
cn_word_fre_sorted=sorted(cn_word_fre,key=lambda x:x[1],reverse=True)
cn_id_word=['','BE']
cn_id_word+=[i[0] for i in cn_word_fre_sorted]
cn_word_id={
   word:id for id,word in enumerate(cn_id_word)}
content_id=list(
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值