【NLP6-使用seq2seq模型架构实现英译法任务】

使用seq2seq模型架构实现英译法任务

目标

1、更深一步了解seq2seq模型架构和翻译数据集

2、掌握适用基于GRU的seq2seq模型实现翻译过程

3、掌握Attention机制在解码器端的实现过程

seq2seq模型架构

encoder编码器 Decoder解码器

数据预览
基于GRU的seq2seq模型架构实现翻译的过程
1、导入必备工具包
from io import open #从io工具包导入open方法
import unicodedata   #用于字符规范化
import re   #用于正则表达式
import random
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch import optim   #torch中预定义的优化方法工具包
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
2、对持久化文件中数据进行处理,以满足模型训练要求

2.1、将指定语言中的词汇映射成数值

# 2、对持久化文件中数据进行处理,以满足模型训练要求
#定义起始标志
SOS_token =0
#定义介绍标志
EOS_token =1class Lang():def __init__(self,name):"""初始化name:参数代表传入某种语言的名字"""self.name = name#初始化单词到索引的映射字典self.word2index = {}#初始化索引到单词的映射字典,其中0,1对应的SOS,EOS已经在字典中了self.index2word ={0:"SOS",1:"EOS"}#初始化词汇对应的数字索引,从2开始,因为0,1已经被开始字符和结束字符占用了self.n_words =2def addSentence(self,sentence):"""添加句子的函数,将整个句子中所有的单词依次添加到字典中因为英文,法文都是空格进行分割的语言,直接进行分词就可以"""for word in sentence.split(' '):self.addWord(word)def addWord(self,word):"""添加单词到类内字典中,将单词转换为数字首先判断word是否已经在self.word2index字典的key中"""if word not in self.word2index:#添加的时候,索引值取当前类中单词的总数量self.word2index[word] = self.n_words#再添加翻转的字典self.index2word[self.n_words]=word#第三步更新类内的单词总数量self.n_words +=1name = 'eng'
sentence ="hello I am Jay"
eng1 = Lang(name)
eng1.addSentence(sentence)print("word2index:",eng1.word2index)
print("index2word:",eng1.index2word)
print("n_words:",eng1.n_words)

word2index: {‘hello’: 2, ‘I’: 3, ‘am’: 4, ‘Jay’: 5}
index2word: {0: ‘SOS’, 1: ‘EOS’, 2: ‘hello’, 3: ‘I’, 4: ‘am’, 5: ‘Jay’}
n_words: 6

2.2、字符规范化

#字符规范化
#将unicode 转为Ascii,我们可以认为是去掉一些语言中的重音标记
def unicodeToAscii(s):return ''.join(c for c in unicodedata.normalize('NFD',s)if unicodedata.category(c) !='Mn')#定义字符串规范化函数
def normalizeString(s):#第一步使字符转变为小写并去除两侧的空白符,再调用上面的函数转换为ASCII字符串s = unicodeToAscii(s.lower().strip())#在.!?前面加一个空格s = re.sub(r"([.!?])",r" \1",s)s = re.sub(r"[^a-zA-Z.!?]+",r" ",s)return ss="Are you kidding me?"nsr = normalizeString(s)
print(nsr)

are you kidding me ?
input_lang: <main.Lang object at 0x000002437ECABDD8>

2.3、将持久化文件中的数据加载到内存,并实例化类Lang

#将持久化文件中的数据加载到内存,并实例化Lang
data_path = 'D:\data\code_and_data\eng-fra.txt'
def readLangs(lang1,lang2):#lang1:源语言的名字  lang2:目标语言的名字# 整个函数返回对应的两个类对象,以及语言对的列表lines = open(data_path,encoding='utf-8').read().strip().split('\n')#对lines列表中的句子进行标准化处理,并以\t进行再次划分,形成子列表pairs =[[normalizeString(s) for s in l.split('\t')] for l in lines]#直接初始化两个类对象input_lang = Lang(lang1)output_lang = Lang(lang2)return input_lang, output_lang, pairslang1 = 'eng'
lang2 ='fra'input_lang, output_lang, pairs = readLangs(lang1, lang2)
print("input_lang:", input_lang)
print("output_lang:", output_lang)
print("pairs[:5]:",pairs[:5])

pairs[:5]: [[‘go .’, ‘va !’], [‘run !’, ‘cours !’], [‘run !’, ‘courez !’], [‘wow !’, ‘ca alors !’], [‘fire !’, ‘au feu !’]]

2.4、过滤出符合我们要求的语言对

#设置组成句子中单词或标点的最多个数
MAX_LENGTH =10#选择带有指定前缀的英文源语言的语句作为训练数据
eng_prefixes =("i am ","i m","he is","he s","she is ","she s","you are ","you re","they are ","they re"
)#过滤语言对的具体逻辑函数
def filterPair(pair):return len(pair[0].split(' '))<MAX_LENGTH and \pair[0].startswith(eng_prefixes) and \len(pair[1].split(' ')) < MAX_LENGTH#过滤语言对的函数
def filterPairs(pairs):return [pair for pair in pairs if filterPair(pair)]fpairs = filterPairs(pairs)
print("fpairs[:5]:",fpairs[:5])

fpairs[:5]: [[‘i m .’, ‘j ai ans .’], [‘i m ok .’, ‘je vais bien .’], [‘i m ok .’, ‘ca va .’], [‘i m fat .’, ‘je suis gras .’], [‘i m fat .’, ‘je suis gros .’]]

2.5、对以上数据准备函数进行整合,并使用类Lang对语言对进行数值映射

#整合数据预处理的函数
def prepareData(lang1,lang2):#lang1:代表源语言的名字,英文#lang2:代表目标语言的名字,法文#通过调用readlangs()函数得到两个类对象,并得到字符串类型的语言对的列表input_lang,output_lang,pairs = readLangs(lang1,lang2)#对字符串类型的列表进行过滤操作pairs = filterPairs(pairs)#对过滤后的语言对列表进行遍历操作,添加进类对象中for pair in pairs:input_lang.addSentence(pair[0])output_lang.addSentence(pair[1])#返回数值映射后的类对象,以及过滤后的语言对列表return input_lang,output_lang,pairsinput_lang,output_lang,pairs=prepareData('eng','fra')
print("input_n_words:",input_lang.n_words)
print("output_n_words:",output_lang.n_words)
print(random.choice(pairs))

input_n_words: 3082

output_n_words: 4552

[‘you re going to ruin your eyes .’, ‘vous allez vous bousiller les yeux .’]

2.6、将语言对转化维模型输入需要的张量

#将语言对转化为模型输入需要的张量
def tensorFromSentence(lang,sentence):indexes = [lang.word2index[word] for word in sentence.split(' ')]indexes.append(EOS_token)return torch.tensor(indexes,dtype=torch.long,device=device).view(-1,1)def tensorsFromPair(pair):input_tensor = tensorFromSentence(input_lang,pair[0])output_tensor = tensorFromSentence(output_lang,pair[1])return (input_tensor,output_tensor)pair = pairs[0]
pair_tensor = tensorsFromPair(pairs[0])
print(pair_tensor)

(tensor([[2],
[3],
[4],
[1]]), tensor([[2],
[3],
[4],
[5],
[1]]))

3、构建基于GRU的编码器和解码器
# 3、构建基于GRU的编码器和解码器
#编码器
class EncoderRNN(nn.Module):def __init__(self,input_size,hidden_size):#input_size:代表编码器输入尺寸,就是英文的词表大小#hidden_size:代表GRU的隐藏层神经单元数,同时也是词嵌入的维度super(EncoderRNN, self).__init__()#将参数传入类中self.input_size = input_sizeself.hidden_size = hidden_size#实例化Embedding层,输入参数分别是词表单词总数,和词嵌入的维度self.embedding = nn.Embedding(input_size,hidden_size)#实例化GRU,参数也是hidden_sizeself.gru = nn.GRU(hidden_size,hidden_size)def forward(self,input,hidden):#input:代表源语言中的输入张量#hidden:代表初始化的隐藏层张量#注意:经过Embedding处理后,张量是一个二维张量,但是GRU要求输入是三维张量#所以要对结果进行扩展维度 view(),同时让任意单词映射后的尺寸是(1,Embedding)output =self.embedding(input).view(1,1,-1)output,hidden = self.gru(output,hidden)return output,hiddendef initHidden(self):#将隐藏层张量初始化为1*1*self.hidden_size大小的张量return torch.zeros(1,1,self.hidden_size,device=device)hidden_size =25
input_size =20input = pair_tensor[0][0]
hidden = torch.zeros(1,1,hidden_size)encoder = EncoderRNN(input_size,hidden_size)
encoder_output,hidden = encoder(input,hidden)
print(encoder_output)

tensor([[[-2.8290e-01, -9.6259e-02, 2.5239e-01, -5.4805e-01, 1.4647e-01,
-4.3992e-02, 1.9509e-01, 2.4348e-01, 3.6683e-01, -5.5452e-02,
4.6634e-02, 1.5199e-01, 2.5359e-02, 3.4754e-01, 7.4054e-02,
8.3258e-02, 1.8888e-01, 3.2992e-01, 1.1495e-01, -2.5253e-01,
-4.0492e-02, 8.2203e-02, 4.5562e-04, 8.7427e-02, 1.9541e-01]]],
grad_fn=)

#解码器
class DecoderRNN(nn.Module):def __init__(self,hidden_size,output_size):#hidden_size:代表隐藏层的神经元个数,同时也是解码器的输入尺寸#output_size:代表整个解码器的输出尺寸,指定的尺寸也就是目标语言的单词总数super(DecoderRNN,self).__init__()#将参数传入类中self.hidden_size = hidden_sizeself.output_size = output_size#实例化Embedding对象,输入参数分别是目标语言的单词总数,和词嵌入的维度self.embedding = nn.Embedding(output_size,hidden_size)#实例化GRU对象self.gru = nn.GRU(hidden_size,hidden_size)#实例化线性层的对象,对GRU的输出做线性变换,得到希望的输出尺寸output_sizeself.out = nn.Linear(hidden_size,output_size)#最后进入softmax的处理self.softmax=nn.LogSoftmax(dim=1)def forward(self,input,hidden):#input:代表目标语言的输入张量#hidden:代表初始化的GRU隐藏层张量#经历了Embedding层处理后,要将张量形状改变为三维张量output = self.embedding(input).view(1,1,-1)#适用relu函数对输出进行处理,使得Embedding矩阵更稀疏,防止过拟合output=F.relu(output)#将张量传入GRU解码器output,hidden = self.gru(output,hidden)#经历GRU处理后的张量是三维张量,但是全连接层需要二位张量,利用output[0]来降维output=self.softmax(self.out(output[0]))return output,hiddendef initHidden(self):#初始化隐藏层张量,形状为1*1*self.hidden_sizereturn torch.zeros(1,1,self.hidden_size,device=device)hidden_size=25
output_size =10input1 = pair_tensor[1][0]
hidden=torch.zeros(1,1,hidden_size)decoder = DecoderRNN(hidden_size,output_size)
output,hidden = decoder(input1,hidden)
print(output)
print(output.shape)

tensor([[-2.3544, -2.3464, -2.1223, -2.2558, -2.2278, -2.4300, -2.5363, -2.3480,
-2.3790, -2.1068]], grad_fn=)
torch.Size([1, 10])

构建基于GRU和Attention的解码器

#构建基于GRU和Attention的解码器class AttnDecoderRNN(nn.Module):def __init__(self,hidden_size,output_size,dropout_p=0.1,max_length=MAX_LENGTH):#hidden_size:代表解码器的GRU输出尺寸,就是隐藏层神经元个数#output_size:指定的网络输出尺寸,代表目标语言的词汇总数#dropout_p:使用dropout层的置零比例#max_length:代表句子的最大长度super(AttnDecoderRNN, self).__init__()#将参数传入类中self.hidden_size = hidden_sizeself.output_size = output_sizeself.dropout_p = dropout_pself.max_length=max_length#实例化一个Embedding对象,参数是目标语言的词汇总数和词嵌入的维度self.embedding = nn.Embedding(output_size,hidden_size)#实例化第一个注意力层,注意输入是两个张量的合并self.attn=nn.Linear(self.hidden_size * 2,self.max_length)#实例化第二个注意力层,注意输入也是两个张量的合并,同时输出要进入GRU中self.attn_combine = nn.Linear(self.hidden_size * 2 ,self.hidden_size)#实例化一个nn.Dropout(self.dropout_p)self.dropout = nn.Dropout(self.dropout_p)#实例化GRU单元self.gru = nn.GRU(self.hidden_size,self.hidden_size)#实例化GRU之后的线性层,作为整个解码器的输出self.out =nn.Linear(self.hidden_size,self.output_size)def forward(self,input1,hidden,encoder_output):#input1:源数据的输入张量#hidden:初始化的隐藏层张量#encoder_output:代表编码器的输出张量#对输入input1 进行词嵌入处理,并扩展维度embedded = self.embedding(input1).view(1,1,-1)#紧接着将其输入dropout层,防止过拟合embedded=self.dropout(embedded)#在进行第一个注意力层处理前,要将Q,K进行纵轴拼接attn_weights = F.softmax(self.attn(torch.cat((embedded[0],hidden[0]),1)),dim=1)#进行bmm操作,注意将二位张量扩展成三维张量attn_applied = torch.bmm(attn_weights.unsqueeze(0),encoder_output.unsqueeze(0))#再次进行拼接,顺便要进行一次降维output = torch.cat((embedded[0],attn_applied[0]),1)#将output输入第二个注意力层output=self.attn_combine(output).unsqueeze(0)#使用relu进行激活层处理output=F.relu(output)#将激活后的张量,连同隐藏层张量,一起传入GRU中output,hidden = self.gru(output,hidden)#最后将结果先降维,然后线性层梳理成指定的输出维度,最后经过softmax处理output=F.log_softmax(self.out(output[0]),dim=1)#返回解码器的最终输出结果,最后的隐藏层张量,注意力权重张量return output,hidden,attn_weightsdef initHidden(self):#初始化一个全零的隐藏层张量,形状为1*1*self.hidden_sizereturn torch.zeros(1,1,self.hidden_size,device=device)#实例化参数
hidden_size=25
output_size=10#输入参数
input1= pair_tensor[1][0]
hidden = torch.zeros(1,1,hidden_size)
encoder_output = torch.randn(10,25)#调用
decoder= AttnDecoderRNN(hidden_size,output_size)
output,hidden,attn_weights = decoder(input1,hidden,encoder_output)
print(output)
print(output.shape)
print(hidden.shape)
print(attn_weights)
print(attn_weights.shape)

tensor([[-2.3155, -2.0316, -2.4451, -2.2536, -2.5503, -2.3917, -2.0801, -2.4474,
-2.2222, -2.4182]], grad_fn=)
torch.Size([1, 10])
torch.Size([1, 1, 25])
tensor([[0.0789, 0.0532, 0.1400, 0.0623, 0.3510, 0.1217, 0.0299, 0.0812, 0.0376,
0.0441]], grad_fn=)
torch.Size([1, 10])

4、构建模型训练函数,并进行训练

什么是teacher_forcing:它是一种用于序列生成任务的训练技巧,在seq2seq架构中,根据循环神经网络,解码器每次应该使用上一步的结果作为输入的一部分,但是训练过程中,一旦上一步的结果是错误的,就会导致这种错误被累积,无法达到训练效果。因此,我们需要一种机制改变上一步出错的情况。因为训练时我们是已知争取的输出应该是什么,因此可以强制将上一步结果设置成正确的输出,这种方式叫做teacher_forcing

teacher_forcing作用:能够在训练的时候矫正模型的预测,避免在序列生成的过程中误差进一步放大。teacher_forcing能够极大的加快模型的收敛速度,令训练过程更快更平稳

构建训练函数train

构建时间计算函数timesince

调用训练函数并打印日志和制图

损失曲线分析:一直下降的损失曲线,说明模型正在收敛,能够从数据中找到一些规律应用于数据

# 4、构建模型训练函数,并进行训练
#设定teacher_forcing的比率,在多大的概率下使用这个策略进行训练
teacher_forcing_ratio =0.5def train(input_tensor,target_tensor,encoder,decoder,encoder_optimizer,decoder_optimizer,criterion,max_length=MAX_LENGTH):#input_tensor:源语言的输入张量#target_tensor:目标语言的输入张量#encoder:编码器的实例化对象  decoder:解码器的实例化对象#encoder_optimizer 编码器优化器   decoder_optimizer :解码器优化器#criterion:损失函数    max_length:代表句子的最大长度#初始化编码器的隐藏层张量encoder_hidden=encoder.initHidden()#训练前将编码器和解码器的优化器梯度归零encoder_optimizer.zero_grad()decoder_optimizer.zero_grad()#根据源文本和目标文本张量获得对应的长度input_length = input_tensor.size(0)target_length = target_tensor.size(0)#初始化编码器的输出矩阵张量,形状是max_length*encoder.hidden_sizeencoder_outputs = torch.zeros(max_length,encoder.hidden_size,device=device)#设置初始损失值loss =0#遍历输入张量for ei in range(input_length):encoder_output,encoder_hidden = encoder(input_tensor[ei],encoder_hidden)#每一个轮次的输出encoder_output是三维张量,使用[0,0]进行降维到一维列表,赋值给输出张量encoder_outputs[ei]=encoder_output[0,0]#初始化解码器的第一个输入字符decoder_input = torch.tensor([[SOS_token]],device=device)#初始化解码器的隐藏层张量,赋值给最后一次编码器的隐藏层张量decoder_hidden = encoder_hidden#判断是否使用teacher_forcinguse_teacher_forcing = True if random.random() < teacher_forcing_ratio else False#如果使用teacher_forcingif use_teacher_forcing:#遍历目标张量,进行解码for di in range(target_length):decoder_output,decoder_hidden,decoder_attention = decoder(decoder_input,decoder_hidden,encoder_outputs)#使用损失函数计算损失值,并进行累加loss +=criterion(decoder_output,target_tensor[di])#因为使用了teacher_forcing,所以将下一步的解码器输入强制设定为“正确的答案”decoder_input=target_tensor[di]#如果不适用teacher_forcingelse:#遍历目标张量,进行解码for di in range(target_length):decoder_output,decoder_hidden,decoder_attention = decoder(decoder_input,decoder_hidden,encoder_outputs)#预测值变成输出张量中概率最大的那一个topv,topi = decoder_output.topk(1)#使用损失函数计算损失值,并进行累加loss+=criterion(decoder_output,target_tensor[di])#如果某一步的解码结果是句子终止符号,则解码直接结束,跳出循环if topi.squeeze().item()==EOS_token:break#下一步解码器的输入要设定为当前步最大概率值的那一个decoder_input=topi.squeeze().detach()#应用反向传播进行梯度计算loss.backward()#利用编码器和解码器的优化器进行参数的更新encoder_optimizer.step()decoder_optimizer.step()#返回平均损失return loss.item()/target_length#构建时间函数
import time
import mathdef timeSince(since):now = time.time()s = now - sincem=math.floor(s/60)s-=m*60return '%dm %ds' % (m,s)since = time.time()-10*60period = timeSince(since)
print(period)#调用训练函数并打印日志和制图
import matplotlib.pyplot as plt
def trainIters(encoder,decoder,n_iters,print_every=1000,plot_every=100,learning_rate =0.01):#encoder:编码器实例化对象# decoder:解码器实例化对象# n_iters:训练总迭代步数# print_every:每隔多少轮次进行一次训练日志的打印# plot_every :每隔多少轮次进行一次损失值的添加,为了后续绘制损失曲线# learning_rate :学习率#获取训练开始时间start = time.time()#初始化存放平均损失值的列表plot_losses =[]#每隔打印间隔的总损失值print_loss_total =0#每个绘制曲线损失值的列表plot_loss_total =0#定义编码器和解码器的优化器encoder_optimizer = optim.SGD(encoder.parameters(),lr=learning_rate)decoder_optimizer = optim.SGD(decoder.parameters(),lr=learning_rate)#定义损失函数criterion = nn.NLLLoss()#按照设定的总迭代次数进行迭代训练for iter in range(1,n_iters+1):#每次从语言对的列表中随机抽取一条样本作为本轮迭代的训练数据training_pair = tensorsFromPair(random.choice(pairs))#依次将选取出来的语句对作为输入张量,和输出张量input_tensor = training_pair[0]target_tensor = training_pair[1]#调用train()函数获得本轮迭代的损失值loss = train(input_tensor,target_tensor,encoder,decoder,encoder_optimizer,decoder_optimizer,criterion)#将本轮迭代的损失值进行累加print_loss_total += lossplot_loss_total += loss#如果到达了打印的轮次if iter % print_every == 0:#首先获取本次打印的平均损失值print_loss_avg = print_loss_total/print_every#为了下一个打印间隔的累加,这里将累加器清零print_loss_total = 0#打印若干信息print('%s (%d %d%%) %.4f' % (timeSince(start),iter,iter / n_iters * 100, print_loss_avg))#如果到达了绘制损失曲线的轮次if iter % plot_every == 0:#首先获取本次损失添加的平均损失值plot_loss_avg = plot_loss_total / plot_every#将平均损失值添加进最后的列表plot_losses.append(plot_loss_avg)#为了下一个添加损失值的累计,这里将累加器清零plot_loss_total = 0#绘制损失曲线plt.figure()plt.plot(plot_losses)#plt.savefig("D:\data\s2s.png")#输入参数
hidden_size=256
encoder1 = EncoderRNN(input_lang.n_words,hidden_size).to(device)
attn_decoder1 = AttnDecoderRNN(hidden_size,output_lang.n_words,dropout_p=0.1).to(device)
#attn_decoder1 = AttnDecoderRNN(hidden_size,output_lang.n_words).to(device)n_iters = 5000
print_every = 500if __name__ == '__main__':trainIters(encoder1,attn_decoder1,n_iters,print_every=print_every)#trainIters(encoder1,attn_decoder1,n_iters)

0m 35s (500 10%) 4.4319
1m 12s (1000 20%) 4.0590
1m 49s (1500 30%) 3.7745
2m 28s (2000 40%) 3.6969
3m 5s (2500 50%) 3.5634
3m 44s (3000 60%) 3.4102
4m 21s (3500 70%) 3.4046
5m 0s (4000 80%) 3.3699
5m 38s (4500 90%) 3.2801
6m 17s (5000 100%) 3.1754

5、构建模型评估函数,并进行测试以及Attention效果分析

5.1、构建模型评估函数evaluate

def evaluate(encoder,decoder,sentence,max_length=MAX_LENGTH):#encoder:编码器#decoder:解码器#sentence:待评估的源语句#max_length:句子最大长度with torch.no_grad():#对输入语句进行张量表示input_tensor = tensorFromSentence(input_lang,sentence)#获得输入句子长度input_length = input_tensor.size(0)#初始化编码器的隐藏层张量encoder_hidden = encoder.initHidden()#初始化编码器的输出张量,矩阵的形状max_length * hidden_sizeencoder_outputs= torch.zeros(max_length,encoder.hidden_size,device=device)#遍历输入张量for ei in range(input_length):#循环进入编码器的处理encoder_output,encoder_hidden = encoder(input_tensor[ei],encoder_hidden)#将三维张量的输出先进行降维到一维,然后赋值给encoder_outputencoder_outputs[ei] = encoder_output[0,0]#初始化解码器的第一个输入,就是起始字符decoder_input = torch.tensor([[SOS_token]],device=device)#初始化解码器的隐藏层输入decoder_hidden = encoder_hidden#初始化预测词汇的列表decoded_words =[]#初始化一个attention张量decoder_attentions = torch.zeros(max_length,max_length)#遍历解码for di in range(max_length):#将张量送入解码器处理decoder_output,decoder_hidden,decoder_attention = decoder(decoder_input,decoder_hidden,encoder_outputs)#首先将注意力张量保存decoder_attentions[di] = decoder_attention.data#topv,topi = decoder_output.data.topk(1)#如果解析出的是结束字符if topi.item()== EOS_token:#将结束字符添加到结果列表中,并退出解码循环decoded_words.append('<EOS>')breakelse:#要根据索引去将真实的字符添加进结果列表中decoded_words.append(output_lang.index2word[topi.item()])#最后一步将预测的标签赋值给下一步解码器的输入decoder_input = topi.squeeze().detach()return decoded_words,decoder_attentions[:di + 1]

5.2、随机选择指定数量的数据进行评估

def evaluateRandomly(encoder,decoder,n=6):for i in range(n):pair = random.choice(pairs)print('>', pair[0])print('=', pair[1])output_words ,attentions = evaluate(encoder,decoder,pair[0])output_sentence = ' '.join(output_words)print('<',output_sentence)print(' ')if __name__ == '__main__':evaluateRandomly(encoder1,attn_decoder1)

5.3、进行了Attention可视化分析

sentence="we re both teachers ."
output_words,attention = evaluate(encoder1,attn_decoder1,sentence)
print(output_words)
plt.figure()
plt.matshow(attention.numpy())

he saved us all .
= il nous a toutes sauvees .
< il a a de . .

they are russian .
= ils sont russes .
< ils sont en .

they re babies .
= ce sont des bebes .
< ils sont sont .

i m very strict .
= je suis tres strict .
< je suis tres en . .

she s eating for two .
= elle mange comme deux .
< elle est en train .

i m concentrating .
= je suis en train de me concentrer .
< je suis en .

[‘tu’, ‘es’, ‘vraiment’, ‘de’, ‘.’, ‘’]

分析:

Attention图像的纵坐标代表输入的源语言各个词汇对应的索引,0-6分别对应[“we”, “re”," both", “teachers”, “.”,“”],纵坐标代表生成的目标语言各个词汇对应的索引,0-7代表[‘nous’,‘sommes’,‘toutes’,‘deux’,‘enseignantes’,‘.’,"],图中浅色小方块(颜色越浅说明影响越大)代表词汇之间的影响关系,比如源语言的第1个词汇对生成目标语言的第1个词汇影响最大,源语言的第4、5个词对生成目标语言的第5个词会影响最大,通过这样的可视化图形,我们可以知道Attention的效果好坏,与我们人为去判定到底还有多大的差距,进而衡量我们训练模型的可用性。

seq2seq模型架构分析

从图中可知,seq2seq模型架构,包括两部分分别是encoder(编码器)和decoder(解码器)。编码器和解码器的内部实现都使用了GRU模型,这里它要完成的是一个中文到英文的翻译:欢迎 来 北京 —>welcome to beijing 。编码器首先处理中文输入"欢迎来北京",通过GRU模型获得每个时间步的输出张量,最后将它们拼接成一个中间语义张量C,接着解码器将使用这个中间语义张量c以及每一个时间步的隐层张量,逐个生成对应的翻译语言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/762392.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

户外水质检测显示屏用于检测并显示各种水质数据

水质检测一直是环境保护和公共卫生领域的重要课题。随着科技的不断进步&#xff0c;水质检测设备也在不断更新换代。其中&#xff0c;水质检测显示屏作为一种新型的检测设备&#xff0c;为监测和显示各种水质数据提供了便利和高效的手段。 水质检测显示屏是一种集成了传感器、数…

CSS 让元素根据内容自适应宽度

一、需求 点击链接跳转&#xff0c;只点击标红区域才跳转&#xff0c;右侧空白区域不要跳转 二、实现 宽度太宽&#xff0c;导致右侧空白区域也加了跳转效果&#xff0c;修改为 将元素的最大宽度设置为其内容所需的宽度。 方法一&#xff1a;建议方式 使用 display: inline…

Excel的数据分析工具

Excel的数据分析工具 会生成新的工作簿 全选--数据透视表 插入切片器 使用作图工具 可以继续插入条件切片

数据结构:图的拓扑排序与关键路径

目录 一、拓扑排序 1.1、算法的基本步骤 1.2、算法实现 1.3、习题思考 1.4、DFS生成逆拓扑序 二、关键路径 1.1、关键路径的原理 1.2、算法的基本步骤 1.3、算法实现 1.4、习题思考 一、拓扑排序 ➢ AOV网:在 有向图中&#xff0c; 顶点表示活动&#xff08;或任务&a…

Android ViewPager不支持wrap_content的原因

文章目录 Android ViewPager不支持wrap_content的原因问题源码分析解决 Android ViewPager不支持wrap_content的原因 问题 <androidx.viewpager.widget.ViewPagerandroid:id"id/wrap_view_pager"android:layout_width"match_parent"android:layout_he…

【氮化镓】利用Ga2O3缓冲层改善SiC衬底AlN/GaN/AlGaN HEMT器件性能

Micro and Nanostructures 189 (2024) 207815文献于阅读总结。 本文是关于使用SiC衬底AlN/GaN/AlGaN高电子迁移率晶体管&#xff08;HEMT&#xff09;的研究&#xff0c;特别是探讨了不同缓冲层对器件性能的影响&#xff0c;以应用于高速射频&#xff08;RF&#xff09;应用。…

ClickHouse01-什么是ClickHouse

什么是ClickHouse&#xff1f; 关于发展历史存在的优势与劣势什么是它风靡的原因&#xff1f; 什么是ClickHouse&#xff1f; 官方给出的回答是&#xff0c;它是一个高性能、列式存储、基于SQL、供在线分析处理的数据库管理系统 当然这边不得不提到OLAP(Online Analytical Pr…

《Java开发实战》课程

1、按以下要求编写程序 (1) 创建一个Rectangle类,添加width和height两个成员变量; (2) 在Rectangle中添加两种方法分别计算矩形的周长和面积; (3) 编程利用Rectangle输出一个矩形的周长和面积(长和宽由用户从键盘输入); import java.util.Scanner;public class Recta…

信息学奥赛之MAC端VSCode C++环境配置

前提 安装 Visual Studio CodeVSCode 中安装 C/C扩展确保 Clang 已经安装&#xff08;在终端中输入命令&#xff1a;clang --version 来确认是否安装&#xff09;未安装&#xff0c;在命令行执行xcode-select --install 命令&#xff0c;会自行安装&#xff0c;安装文件有点大…

ideaSSM博物馆网站系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea 开发 SSM 博物馆网站系统是一套完善的信息管理系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c…

爬虫分析-基于Python的空气质量数据分析与实践

概要 本篇文章利用了Python爬虫技术对空气质量网站的数据进行获取&#xff0c;获取之后把数据生成CSV格式的文件&#xff0c;然后再存入数据库方便保存。再从之前24小时的AQI&#xff08;空气质量指数&#xff09;的平均值中进行分析,把数据取出来后&#xff0c;对数据进行数据…

android 实现息屏亮屏 Runtime.getRuntime().exec不执行

公司想实现远程息屏亮屏。试了下PowerManager&#xff0c;对我这个广告屏来讲是没有效果的。 import android.content.Context; import android.os.PowerManager;public class ScreenStateHelper {private PowerManager powerManager;private WakeLock wakeLock;public Screen…

第12篇:4线-2线普通编码器

Q&#xff1a;在数字系统中&#xff0c;用一个二进制代码表示特定信息称为编码&#xff0c;而具有编码功能的逻辑电路就称为编码器。本期我们学习实现4线-2线普通编码器。 A&#xff1a;基本原理&#xff1a;二进制编码器有n位输出&#xff0c;与个输入相对应。4线-2线普通编码…

前端与后端具备能力的区别

前端与后端具备能力的区别 在软件开发领域&#xff0c;前端和后端是两个至关重要的部分&#xff0c;它们各自承担着不同的职责和任务。前端主要负责与用户交互的界面设计和实现&#xff0c;而后端则负责处理数据和业务逻辑。因此&#xff0c;前端和后端开发者需要具备不同的技…

mysql 如何设计分库分表

在MySQL中设计分库分表的方法通常涉及到水平拆分与垂直拆分两种主要方式。 水平拆分&#xff1a; 按照某一列进行水平拆分&#xff1a; 可以根据某一列&#xff08;如用户ID、时间等&#xff09;的取值范围将数据拆分到不同的数据库或表中。基于哈希值的水平拆分&#xff1a;…

银行OA系统|基于SpringBoot架构+ Mysql+Java+ B/S结构的银行OA系统设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

Orange3数据预处理(行选择组件)

选择行 根据数据特征的条件选择数据实例。 输入 数据&#xff1a;输入数据集 输出 匹配数据&#xff1a;满足条件的实例 不匹配数据&#xff1a;不满足条件的实例 数据&#xff1a;带有额外列的数据&#xff0c;显示实例是否被选中 这个小部件根据用户…

每日一题:C语言经典例题之实数的整数部分

题目描述 输入一个实数&#xff0c;输出实数的整数部分。注意该实数的位数不超过100位。输入的整数部分可能含有不必要的前导0&#xff0c;输出时应去掉&#xff0c;当然&#xff0c;若整数部分为0&#xff0c;则该0不能去掉。如输入0023.56732&#xff0c;输出应为23&#xff…

java零钱兑换 II(力扣Leetcode518)

零钱兑换 II 力扣原题链接 问题描述 给定一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0。假设每一种面额的硬币有无限个。 示例 示…