机器翻译模型三Attention机制__Pytorch实现

目录

 

1.attention机制的引入

2.attention机制的计算方式

3.模型实现

3.1数据准备

3.2模型建立

3.3训练


1.attention机制的引入

在上一节的seq2seq模型中,为了在解码的时候,使得解码器以及线性分类层可以有直接获取更多信息,我们将原始上下文向量提供给每一个解码器,将原始上下文向量和词嵌入提供给每一个线性层,如下所示 :

 但是依然没能改变一个本质的地方,上下文向量被过度压缩了。即经过多个时间步的编码器压缩,之前的信息保留的越小越少。而解码器在翻译的时候,对之前信息获取很少,进一步导致模型质量下降。《NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE》提出attention机制,对每一个编码器和线性层输入的原始context向量进行了改进。所谓的上下文向量不再是最后经过编码器压缩以后的稠密向量,而是将每一个编码器的输出与当前解码器输入的隐藏状态进行一个“匹配”计算,为每个编码器的输出计算出一个“匹配”分数,然后将所有的匹配分数进行softmax计算转变为其权重概率,将权重概率与对应的编码器输出进行加权求和得到上下文向量,模型如下所示:

首先,s1输入的隐藏状态为原始上下文向量z(后面解码器则为s_t-1),将z与每一个编码器的输出[h1,h2,h3,h4]进行一个“匹配”计算(计算方式很多),得到一个匹配分数[score1,score2,score3,score4]。我们将其转变为权重形式,即对这个匹配分数进行softmax计算得到权重矩阵a[a1,a2,a3,a4]。然后计算其当前编码器对应注意力的上下文向量w=a1*h1+a2h2+a3h3+a4h4。这个注意力得出的上下文向量优势在于:(1)其没有经过过多压缩,降低了信息的损失。之前输入的context向量都是编码器最后的一个输出,经过编码器多重编码造成了之前有用信息的损失,而注意力向量是每一个编码器输出直接参与最后的上下文向量计算,每一个编码器信息的损失是根据解码器的实际需求来进行的。(2)每一个解码器都有其特有的注意力权重矩阵,因为每一个解码器输入的隐藏状态不同,其得到的权重矩阵也不相同。例如我们在解码第一个词的时候,其有用信息大概率与第一个编码器的输出有关系。之前的原始上下文向量对第一个编码器信息的保留很少,而注意力向量可以通过其权重矩阵,决定偏向哪一个编码器(权重越接近1,保留越多。越接近0保留越少)。

此外,我们考虑到LSTM偏向于最新的编码器,所以之前采用倒序的手段,这里介绍另一个新的技巧:双向LSTM,如下所示:

正序LSTM偏向句子的后半段,在反向LSTM偏向于句子的前半段。将两者的输出进行一个拼接得到双向LSTM的最终输出。切记双向LSTM不是双层,可以理解为两个独立的LSTM,一个将句子从左往右输入,另一个将句子从右往左输入,最终将二者的输出进行拼接得到最终输出,所以其输出的维度变为原来的两倍。最后编码器输出的隐状态之前可以直接用来作为原始上下文向量(假设编码器解码器的隐状态为一个维度),但是现在不可以了,将最后编码器输出的隐状态通过一个线性层降维到解码的维度,并经过一个tanh激活函数。

2.attention机制的计算方式

这里按照一般情况介绍attention机制:

attention机制的基本流程:对一个句子序列s,其由单词序列[w_1,w_2,...,w_n]构成。

(1)应用某种方法将s中的每个单词w_i编码为一个独特向量v_i

(2)解码时,使用学习到的注意力权重a_i对1中所得的所有向量做加权线性组合\sum_ia_iv_i

(3)在解码器进行下个词预测时,使用(2)中得到的线性组合。

 

       具体attention核心解释如下:

       我们的最终目标是要能够帮助decoder在生成词语时,有一个不同词语的权重参考。在训练时,对于decoder我们是有训练目标的,此时将decoder中的信息定义为一个Query(学习目标)。在encoder中包含了所有可能出现的词语,我们将其作为一个字典,该字典的key为所有encoder的序列信息。N个单词相当于当前字典中有n条记录,而字典的value通常也是所有encoder的序列信息。(一般情况下,KV相等)下一步是注意力权重计算,由于我们要让模型自己去学习应该对那些语素重点关注,因此我们要用学习目标Query来参与这个过程,因此对于Query的每个向量,通过一个函数来计算预测t时刻时候,注意力的权重。由于encoder序列长度为n,因此,应该是一个n维的向量,由于权重和为1,所以需要对该向量进行softmax归一化,让向量的每一维元素都是一个概率值。

 

权重注意力计算方式:

(1)多层感知机方法(常用)

a(q,k)=W_1^Ttanh(W_1[q;k])

主要是先将query和key进行拼接,然后接一个激活函数tanh的全连接(本文就到这一步),然后再与一个网络定义的权重矩阵做乘积。这种方法据说对于大规模的数据特别有效。

(2)Bilinear方法

a(q,k)=q^TWk

通过一个句子句子中直接建立q和k的映射关系,比较直接,且计算速度较快。

 

(3)Dot Product

a(q,k)=q^Tk

这个方法更直接,连权重矩阵都省了,直接建立q和k的关系映射,优点是计算速度更快了,且不需要参数,降低了模型的复杂度。但是需要q和k的维度要相同。

 

(4)scaled-dot Product(常用,self-attention也用到了)

上面的点积方法有一个问题,就是随着向量维度的增加,最后计算得到的分数会很大,softmax得到改了后,在反向传播时在进行softmax计算等反向求导的时候,梯度会很小(趋近于0)。因此对其进行归一化:(可以参考资料)

a(q,k)=\frac{q^Tk}{\sqrt{d_k}}

d_k表示q,k的维度。

3.模型实现

3.1数据准备

工具:Jupyter

数据依然和前面的一样,处理过程也是一样的。

import torch
import spacy

from torchtext.data import Field,BucketIterator
from torchtext.datasets import Multi30k
de_seq=spacy.load("de_core_news_sm")
en_seq=spacy.load("en_core_web_sm")

def src_token(text):
    return [word.text for word in de_seq.tokenizer(text)]

def trg_token(text):
    return [word.text for word in en_seq.tokenizer(text)]

SRC=Field(tokenize=src_token,
         init_token="<sos>",
         eos_token="<eos>",
         lower=True)

TRG=Field(tokenize=trg_token,
         init_token="<sos>",
         eos_token="<eos>",
         lower=True)
train_data,val_data,test_data=Multi30k.splits(exts=(".de",".en"),
                                             fields=(SRC,TRG))

SRC.build_vocab(train_data,min_freq=2)
TRG.build_vocab(train_data,min_freq=2)
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
batch_size=128

train_iter,val_iter,test_iter=BucketIterator.splits(
    (train_data,val_data,test_data),
    batch_size=batch_size,
    device=device
)

测试:

for example in train_iter:
    print(example.src.shape,example.trg.shape)
    break

结果:

torch.Size([37, 128]) torch.Size([35, 128])

提前将测试的batch放前面:

src=example.src.permute(1,0)
trg=example.trg.permute(1,0)

3.2模型建立

import torch.nn as nn
class Encoder(nn.Module):
    def __init__(self,src_vocab_size,emb_size,enc_hidden_size,dec_hidden_size,dropout=0.5):
        super(Encoder,self).__init__()
        self.embeding=nn.Embedding(src_vocab_size,emb_size,padding_idx=0)
        self.rnn=nn.GRU(emb_size,enc_hidden_size,bidirectional=True,batch_first=True)
        self.fc=nn.Linear(2*enc_hidden_size,dec_hidden_size)
        self.dropout=nn.Dropout(dropout)
    
    def forward(self,src):
        #src[bactch src_len]
        src=self.dropout(self.embeding(src))
        #src[batch src_len  emb_size]
        outputs,f_n=self.rnn(src)
        #outputs[batch src_len enc_hidden_size*2]
        #f_n[2 batch enc_hidden_size]
        forward_hidden=f_n[-2,:,:]
        backward_hidden=f_n[-1,:,:]
        #forward_hidden[batch enc_hidden_size]
        #backward_hidden[batch enc_hidden_size]
        f_b_hidden=torch.cat((forward_hidden,backward_hidden),dim=1)
        #f_b_hidden[batch enc_hidden_size*2]
        f_n=self.fc(f_b_hidden).unsqueeze(0)
        #f_b_hidden[1 batch dec_hidden_size]
        return outputs,f_n
src_vocab_size=len(SRC.vocab)
trg_vocab_size=len(TRG.vocab)

emb_size=256
enc_hidden_size=512
dec_hidden_size=512

测试:

enModel=Encoder(src_vocab_size,emb_size,enc_hidden_size,dec_hidden_size).to(device)
enOutputs,h_n=enModel(src)
print(enOutputs.shape,h_n.shape)

结果:

torch.Size([128, 37, 1024]) torch.Size([1, 128, 512])
class Attention(nn.Module):
    def __init__(self,enc_hidden_size,dec_hidden_size):
        super(Attention,self).__init__()
        self.attn=nn.Linear(enc_hidden_size*2+dec_hidden_size,dec_hidden_size)
        self.v=nn.Linear(dec_hidden_size,1,bias=False)
    
    def forward(self,encode_outputs,h_n):
        #encode_outputs[batch src_len 2*enc_hidden_size]
        #h_n[1 batch dec_hidden_size]
        src_len=encode_outputs.shape[1]
        
        h_n=h_n.permute(1,0,2).repeat(1,src_len,1)#复制src_len隐状态分别于encoder输出进行attn
        #h_n[batch src_len  dec_hidden_size]
        inputs=torch.cat((encode_outputs,h_n),dim=2)
        #inputs[batch src_len  2*enc_hidden_size+dec_hidden_size]
        energy=self.attn(inputs)
        #energy[batch sec_len dec_hidden_size]
        scores=self.v(energy).squeeze()
        #score[batch sec_len]
        return nn.functional.softmax(scores,dim=1)

测试:

attnModel=Attention(enc_hidden_size,dec_hidden_size).to(device)
a=attnModel(enOutputs,h_n)
print(a.shape,a.sum(dim=1))

结果:

torch.Size([128, 37]) tensor([1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
        1.0000, 1.0000], device='cuda:0', grad_fn=<SumBackward1>)
class Decoder(nn.Module):
    def  __init__(self,trg_vocab_size,emb_size,en_hidden_size,dec_hidden_size,attention,dropout=0.5):
        super(Decoder,self).__init__()
        self.attn=attention
        
        self.emb=nn.Embedding(trg_vocab_size,emb_size)
        self.rnn=nn.GRU(emb_size+en_hidden_size*2,dec_hidden_size,batch_first=True)
        self.fn=nn.Linear(emb_size+en_hidden_size*2+dec_hidden_size,trg_vocab_size)
        self.dropout=nn.Dropout(dropout)
    
    def forward(self,input_trg,h_n,en_outputs):
        #input_trg[batch]
        #h_n[batch dec_hidden_size]
        #en_outputs[batch src_len en_hidden_size*2]
        
        input_trg=input_trg.unsqueeze(1)
        #input_trg[batch 1]
        input_trg=self.dropout(self.emb(input_trg))
        #input_trg[batch 1 emb_size]
        
        a=self.attn(en_outputs,h_n)
        #a[batch src_len]
        a=a.unsqueeze(1)
        #a[batch 1 src_len]
        weighted=torch.bmm(a,en_outputs)
        #weighted[batch 1 en_hidden_size*2]
        
        concat=torch.cat((input_trg,weighted),dim=2)
        #concat[batch 1 en_hidden_size*2+emb_size]
        h_n=h_n.unsqueeze(0)
        #h_n[1 batch de_hidden_size]
        output,h_n=self.rnn(concat,h_n)
        #output[batch 1 dec_hidden_size],h_n[1 batch de_hidden_size]
        
        concat=torch.cat((concat,output),dim=2)
        #concat[batch 1 en_hidden_size*2+emb_size+de_hidden_size]
        concat=concat.squeeze()
        #concat[batch  en_hidden_size*2+emb_size+de_hidden_size]
        output=self.fn(concat)
        #output[batch trg_vocab_size]
        return output,h_n.squeeze()

测试:

trg_i=trg[:,1]
deModel=Decoder(trg_vocab_size,emb_size,enc_hidden_size,dec_hidden_size,attnModel).to(device)
deOutputs,h_n=deModel(trg_i,h_n,enOutputs)
print(deOutputs.shape,h_n.shape)

结果:

(torch.Size([128, 5893]), torch.Size([1, 128, 512]))
import random
class Seq2Seq(nn.Module):
    def __init__(self,encoder,decoder):
        super(Seq2Seq,self).__init__()
        self.encoder=encoder
        self.decoder=decoder
    
    def forward(self,src,trg,teach_threshold=0.5):
        #src[batch src_len]
        #trg[batch trg_len]
        en_outputs,h_n=self.encoder(src)
        #en_outputs[batch src_len enc_hidden_size*2]
        #h_n[1 batch dec_hidden_size]
        
        batch=trg.shape[0]
        trg_len=trg.shape[1]
        
        #保存输出
        outputs=torch.zeros(batch,trg_len,trg_vocab_size).to(device)
        inputs=trg[:,0]
        for t in range(1,trg_len):
            output,h_n=self.decoder(inputs,h_n,en_outputs)
            #output[batch  trg_vocab_size]
            #h_n[1 batch dec_hidden_size]
            outputs[:,t,:]=output
            
            probabilty=random.random()
            inputs=trg[:,t] if probabilty<teach_threshold else output.argmax(1)
        return outputs

测试:

model=Seq2Seq(enModel,deModel).to(device)
outputs=model(src,trg)
outputs[0,0,:],outputs[0,1,:]

结果:

(tensor([0., 0., 0.,  ..., 0., 0., 0.], device='cuda:0',
        grad_fn=<SliceBackward>),
 tensor([-0.0026,  0.5602, -0.0122,  ...,  0.2537, -0.6007, -0.0582],
        device='cuda:0', grad_fn=<SliceBackward>))

3.3训练

import time,math
from torch.optim import Adam
epochs=10
optim=Adam(model.parameters())
criterion=nn.CrossEntropyLoss(ignore_index=1)
def init_weights(m):
    for name, param in m.named_parameters():
        if 'weight' in name:
            nn.init.normal_(param.data, mean=0, std=0.01)
        else:
            nn.init.constant_(param.data, 0)
            
model.apply(init_weights)
def epoch_time(start_time, end_time):
    elapsed_time = end_time - start_time
    elapsed_mins = int(elapsed_time / 60)
    elapsed_secs = int(elapsed_time - (elapsed_mins * 60))
    return elapsed_mins, elapsed_secs
def train(model,data_iter,optim,criterion,clip):
    model.train()
    lossAll=0
    
    for example in data_iter:
        src=example.src.permute(1,0)
        trg=example.trg.permute(1,0)
        
        output=model(src,trg)
        optim.zero_grad()
        #output[batch trg_len trg_vocab_size]
        output=output[:,1:,:].reshape(-1,trg_vocab_size)
        trg=trg[:,1:].reshape(-1)
        loss=criterion(output,trg)
        loss.backward()
        #截断梯度,对梯度高于1的直接设置为1
        nn.utils.clip_grad_norm_(model.parameters(),clip)
        optim.step()
        lossAll+=loss.item()
    return lossAll/len(data_iter)
def evaluate(model,data_iter,criterion):
    model.eval()
    lossAll=0
    
    with torch.no_grad():
        for example in data_iter:
            src=example.src.permute(1,0)
            trg=example.trg.permute(1,0)

            output=model(src,trg)
            #output[batch trg_len trg_vocab_size]
            output=output[:,1:,:].reshape(-1,trg_vocab_size)
            trg=trg[:,1:].reshape(-1)
            loss=criterion(output,trg)
            lossAll+=loss.item()
    return lossAll/len(data_iter)
for epoch in range(epochs):
    start_time = time.time()
    train_loss = train(model,train_iter, optim, criterion,clip=1)
    valid_loss = evaluate(model,val_iter,criterion)
    end_time = time.time()
    epoch_mins, epoch_secs = epoch_time(start_time, end_time)
        
    print(f'Epoch: {epoch+1:02} | Time: {epoch_mins}m {epoch_secs}s')
    print(f'\tTrain Loss: {train_loss:.3f} | Train PPL: {math.exp(train_loss):7.3f}')
    print(f'\t Val. Loss: {valid_loss:.3f} |  Val. PPL: {math.exp(valid_loss):7.3f}')

实验结果:

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用PyTorch实现机器翻译的步骤: 1.读取和预处理数据 2.定义编码器和解码器模型 3.定义注意力机制 4.定义损失函数和优化器 5.训练模型 6.使用模型进行翻译 具体实现细节可以参考以下代码: ```python import os import zipfile import collections import time import torch import torch.nn as nn import torch.nn.functional as F from torch.utils import data from torch import optim from d2l.data.base import Vocab import d2l # 读取和预处理数据 def read_data_nmt(): data_dir = '/home/kesci/input/fraeng6506/fra-eng' with zipfile.ZipFile(os.path.join(data_dir, 'fra-eng.zip'), 'r') as f: raw_text = f.read('fra.txt').decode("utf-8") return raw_text raw_text = read_data_nmt() print(raw_text[:100]) def preprocess_nmt(text): text = text.replace('\u202f', ' ').replace('\xa0', ' ') no_space = lambda char, prev_char: ( True if char in (',', '!', '.') and prev_char != ' ' else False) out = [' '+char if i > 0 and no_space(char, text[i-1]) else char for i, char in enumerate(text.lower())] return ''.join(out) text = preprocess_nmt(raw_text) print(text[:100]) def tokenize_nmt(text, num_examples=None): source, target = [], [] for i, line in enumerate(text.split('\n')): if num_examples and i > num_examples: break parts = line.split('\t') if len(parts) == 2: source.append(parts[0].split(' ')) target.append(parts[1].split(' ')) return source, target source, target = tokenize_nmt(text) print(source[:3], target[:3]) # 建立词典 def build_vocab_nmt(tokens): tokens = [token for line in tokens for token in line] return Vocab(tokens, min_freq=3, use_special_tokens=True) src_vocab = build_vocab_nmt(source) print(list(src_vocab.token_to_idx.items())[:10]) tgt_vocab = build_vocab_nmt(target) print(list(tgt_vocab.token_to_idx.items())[:10]) # 将文本转换为数字序列 def encode_nmt(src_tokens, tgt_tokens, src_vocab, tgt_vocab): src_encoded = [[src_vocab[token] for token in line] for line in src_tokens] tgt_encoded = [[tgt_vocab[token] for token in line] for line in tgt_tokens] return src_encoded, tgt_encoded src_encoded, tgt_encoded = encode_nmt(source, target, src_vocab, tgt_vocab) print(src_encoded[:3], tgt_encoded[:3]) # 定义编码器和解码器模型 class Encoder(nn.Module): def __init__(self, vocab_size, embed_size, num_hiddens, num_layers, drop_prob=0): super(Encoder, self).__init__() self.embedding = nn.Embedding(vocab_size, embed_size) self.rnn = nn.LSTM(embed_size, num_hiddens, num_layers, dropout=drop_prob, bidirectional=True) def forward(self, inputs, state=None): # inputs shape: (batch_size, seq_len) # outputs shape: (seq_len, batch_size, 2*num_hiddens) embeddings = self.embedding(inputs) outputs, state = self.rnn(embeddings.permute([1, 0, 2]), state) return outputs.permute([1, 0, 2]), state class Decoder(nn.Module): def __init__(self, vocab_size, embed_size, num_hiddens, num_layers, attention_size, drop_prob=0): super(Decoder, self).__init__() self.embedding = nn.Embedding(vocab_size, embed_size) self.attention = Attention(num_hiddens, attention_size, drop_prob) self.rnn = nn.LSTM(num_hiddens + embed_size, num_hiddens, num_layers, dropout=drop_prob) self.out = nn.Linear(num_hiddens, vocab_size) def forward(self, cur_input, state, enc_outputs): # cur_input shape: (batch_size,) # state: the hidden state of the last time step # outputs shape: (batch_size, vocab_size) embeddings = self.embedding(cur_input).unsqueeze(0) context = self.attention(state[0][-1], enc_outputs) rnn_input = torch.cat([embeddings, context.unsqueeze(0)], dim=2) outputs, state = self.rnn(rnn_input, state) outputs = self.out(outputs).squeeze(0) return outputs, state class Attention(nn.Module): def __init__(self, enc_num_hiddens, dec_num_hiddens, attention_size, drop_prob=0): super(Attention, self).__init__() self.enc_attention = nn.Linear(enc_num_hiddens, attention_size, bias=False) self.dec_attention = nn.Linear(dec_num_hiddens, attention_size, bias=False) self.combined_attention = nn.Linear(attention_size, 1, bias=True) self.dropout = nn.Dropout(drop_prob) def forward(self, dec_state, enc_outputs): # dec_state shape: (batch_size, dec_num_hiddens) # enc_outputs shape: (batch_size, seq_len, enc_num_hiddens) dec_attention = self.dec_attention(dec_state).unsqueeze(1) enc_attention = self.enc_attention(enc_outputs) combined_attention = self.combined_attention(torch.tanh( enc_attention + dec_attention)) attention_weights = F.softmax(combined_attention.squeeze(2), dim=1) return torch.bmm(attention_weights.unsqueeze(1), enc_outputs).squeeze(1) # 定义损失函数和优化器 def sequence_mask(X, valid_len, value=0): maxlen = X.size(1) mask = torch.arange(maxlen)[None, :] < valid_len[:, None] X[~mask] = value return X class MaskedSoftmaxCELoss(nn.CrossEntropyLoss): def forward(self, pred, target, valid_len): weights = torch.ones_like(target) weights = sequence_mask(weights, valid_len).float() self.reduction = 'none' output = super(MaskedSoftmaxCELoss, self).forward(pred.transpose(1, 2), target) return (output * weights).mean(dim=1) def train_epoch_ch8(net, data_iter, lr, optimizer, device, use_random_iter): loss_sum, n = 0.0, 0 for batch in data_iter: optimizer.zero_grad() X, X_vlen, Y, Y_vlen = [x.to(device) for x in batch] bos = torch.tensor([tgt_vocab['<bos>']] * Y.shape[0], device=device).reshape(-1, 1) dec_input = torch.cat([bos, Y[:, :-1]], 1) # Teacher forcing Y_hat, _ = net(X, dec_input, X_vlen) loss = MaskedSoftmaxCELoss()(Y_hat, Y, Y_vlen) loss.sum().backward() d2l.grad_clipping(net, 1) num_tokens = Y_vlen.sum() optimizer.step() loss_sum += loss.sum().item() n += num_tokens.item() return loss_sum / n def train_ch8(net, train_iter, lr, num_epochs, device, use_random_iter=False): def init_weights(m): if type(m) == nn.Linear: nn.init.xavier_uniform_(m.weight) if type(m) == nn.LSTM: for param in m._flat_weights_names: if "weight" in param: nn.init.xavier_uniform_(m._parameters[param]) net.apply(init_weights) net.to(device) optimizer = torch.optim.Adam(net.parameters(), lr=lr) loss = MaskedSoftmaxCELoss() animator = d2l.Animator(xlabel='epoch', ylabel='loss', xlim=[1, num_epochs]) for epoch in range(num_epochs): timer = d2l.Timer() loss_avg = train_epoch_ch8(net, train_iter, lr, optimizer, device, use_random_iter) animator.add(epoch+1, loss_avg) print(f'epoch {epoch + 1}, loss {loss_avg:.3f}, ' f'time {timer.stop():.1f} sec') return net # 训练模型 embed_size, num_hiddens, num_layers = 64, 128, 2 attention_size, drop_prob, lr, batch_size, num_epochs = 10, 0.5, 0.01, 64, 300 train_iter = d2l.load_data_nmt(batch_size, num_examples=1000) encoder = Encoder(len(src_vocab), embed_size, num_hiddens, num_layers, drop_prob) decoder = Decoder(len(tgt_vocab), embed_size, num_hiddens, num_layers, attention_size, drop_prob) net = d2l.EncoderDecoder(encoder, decoder) device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') net = train_ch8(net, train_iter, lr, num_epochs, device) # 使用模型进行翻译 def predict_ch8(net, src_sentence, src_vocab, tgt_vocab, num_steps, device): src_tokens = src_vocab[src_sentence.lower().split(' ')] enc_valid_len = torch.tensor([len(src_tokens)], device=device) src_tokens = d2l.truncate_pad(src_tokens, num_steps, src_vocab['<pad>']) enc_X = torch.tensor(src_tokens, dtype=torch.long, device=device) enc_outputs, enc_state = net.encoder(enc_X.unsqueeze(0), enc_valid_len) dec_state = enc_state dec_X = torch.tensor([tgt_vocab['<bos>']], dtype=torch.long, device=device).reshape(1, 1) output_seq = [] for _ in range(num_steps): Y, dec_state = net.decoder(dec_X, dec_state, enc_outputs) dec_X = Y.argmax(dim=1).reshape(1, 1) pred = dec_X.squeeze(dim=0).type(torch.int32).item() if pred == tgt_vocab['<eos>']: break output_seq.append(pred) return ' '.join(tgt_vocab.to_tokens(output_seq)) src_sentence = 'They are watching.' print(predict_ch8(net, src_sentence, src_vocab, tgt_vocab, num_steps=10, device=device)) --相关问题--:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值