要查看图文版教程,请移步到:http://studyai.com/pytorch-1.4/beginner/torchtext_translation_tutorial.html

本教程介绍如何使用 torchtext 提供的几个便利的类来预处理包含英语和德语句子的知名数据集中的数据, 并使用它来训练一个带有注意力机制的序列到序列的模型,将德语句子翻译成英语。

本教程是基于PyTorch社区成员 Ben Trevett 创作的 这个教程

在本教程结束时,你将能够:

使用以下 torchtext 提供的类将句子预处理为NLP建模的常用格式:TranslationDatasetFieldBucketIterator

Field 和 TranslationDataset

torchtext 有用于创建数据集的实用程序,这些数据集可以很容易地迭代以创建语言翻译模型。 一个关键类是 Field, 它指定每个句子的预处理方式, 另一个是 TranslationDataset ; torchtext 有几个这样的数据集;在本教程中,我们将使用 Multi30k dataset , 它包含大约30000个英语和德语句子(平均长度约13个单词)。

请注意: 本教程的词语切分标记(tokenization)需要 Spacy 。 我们使用Spacy是因为它在英语以外的语言中为词语切分标记提供了强大的支持。 torchtext 提供了一个基本的英语标记器,并支持其他英语标记器 (例如 Moses ), 但对于语言翻译-则需要多种语言-而Spacy是最好的选择。

要运行此教程,首先要使用 pip 或 conda 安装 spacy 。 接着, 下载 English 和 German 原始数据的 Spacy tokenizers:

python -m spacy download en
python -m spacy download de

安装好 Spacy 之后, 下面的代码将基于 Field 中定义的标记器(tokenizer)标记 TranslationDataset 中的每个句子

from torchtext.datasets import Multi30k
from torchtext.data import Field, BucketIteratorSRC = Field(tokenize = "spacy",tokenizer_language="de",init_token = '<sos>',eos_token = '<eos>',lower = True)TRG = Field(tokenize = "spacy",tokenizer_language="en",init_token = '<sos>',eos_token = '<eos>',lower = True)train_data, valid_data, test_data = Multi30k.splits(exts = ('.de', '.en'),fields = (SRC, TRG))

现在我们已经定义了 train_data ,我们可以看到 torchtext 的 Field 的一个非常有用的功能: build_vocab 方法现在允许我们创建与每种语言相关联的词汇表(vocabulary)

SRC.build_vocab(train_data, min_freq = 2)
TRG.build_vocab(train_data, min_freq = 2)

一旦运行上面这些代码行后, SRC.vocab.stoi 将是一个字典,其中词汇表中的标记为键,其相应索引为值; SRC.vocab.itos 将是同一个字典,只是其中的键和值被交换了。 在本教程中,我们不会广泛地使用这个事实,但是在您将遇到的其他NLP任务中,这可能会很有用。

BucketIterator

我们将要使用 torchtext 的最后一个特别的功能是 BucketIterator, 因为它接受一个 TranslationDataset 作为其第一个参数,所以非常简单易用。 就像文档中描述的那样: 定义一个迭代器,用于将相似长度的样本组织到同一个batch中。 在为每个新的回合(new epoch)生产新的随机batch时,最小化所需的填充量(padding)。

import torchdevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')BATCH_SIZE = 128train_iterator, valid_iterator, test_iterator = BucketIterator.splits((train_data, valid_data, test_data),batch_size = BATCH_SIZE,device = device)

这些迭代器(iterators)可以被调用,就像调用 DataLoader 的迭代器一样; 下面, 在 函数 train 和 evaluate 中, 可以简单地使用以下方式来调用:

for i, batch in enumerate(iterator):

每一个 batch 都有 src 和 trg 属性:

src = batch.src
trg = batch.trg

定义 nn.Module 和 Optimizer

从 torchtext 的角度来看:随着数据集的构建和迭代器(iterator)的定义, 本教程的其余部分只是将我们的模型定义为 nn.Module 以及创建一个 Optimizer,然后对其进行训练。

具体来说,我们的模型遵循了 这里 描述的架构(您可以在 这里 找到一个更具注释性的版本)。

注意: 这个模型只是一个可用于语言翻译的示例模型;我们选择它是因为它是该任务的一个标准模型, 而不是因为它是被强烈推荐用于翻译任务的模型。正如您可能知道的,最先进的模型当前基于Transformers; 您可以在 这里 看到PyTorch实现 Transformer layers 的能力; 特别是,下面模型中使用的 “attention” 不同于Transformer模型中的多头自我注意(multi-headed self-attention)。

import random
from typing import Tupleimport torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch import Tensorclass Encoder(nn.Module):def __init__(self,input_dim: int,emb_dim: int,enc_hid_dim: int,dec_hid_dim: int,dropout: float):super().__init__()self.input_dim = input_dimself.emb_dim = emb_dimself.enc_hid_dim = enc_hid_dimself.dec_hid_dim = dec_hid_dimself.dropout = dropoutself.embedding = nn.Embedding(input_dim, emb_dim)self.rnn = nn.GRU(emb_dim, enc_hid_dim, bidirectional = True)self.fc = nn.Linear(enc_hid_dim * 2, dec_hid_dim)self.dropout = nn.Dropout(dropout)def forward(self,src: Tensor) -> Tuple[Tensor]:embedded = self.dropout(self.embedding(src))outputs, hidden = self.rnn(embedded)hidden = torch.tanh(self.fc(torch.cat((hidden[-2,:,:], hidden[-1,:,:]), dim = 1)))return outputs, hiddenclass Attention(nn.Module):def __init__(self,enc_hid_dim: int,dec_hid_dim: int,attn_dim: int):super().__init__()self.enc_hid_dim = enc_hid_dimself.dec_hid_dim = dec_hid_dimself.attn_in = (enc_hid_dim * 2) + dec_hid_dimself.attn = nn.Linear(self.attn_in, attn_dim)def forward(self,decoder_hidden: Tensor,encoder_outputs: Tensor) -> Tensor:src_len = encoder_outputs.shape[0]repeated_decoder_hidden = decoder_hidden.unsqueeze(1).repeat(1, src_len, 1)encoder_outputs = encoder_outputs.permute(1, 0, 2)energy = torch.tanh(self.attn(torch.cat((repeated_decoder_hidden,encoder_outputs),dim = 2)))attention = torch.sum(energy, dim=2)return F.softmax(attention, dim=1)class Decoder(nn.Module):def __init__(self,output_dim: int,emb_dim: int,enc_hid_dim: int,dec_hid_dim: int,dropout: int,attention: nn.Module):super().__init__()self.emb_dim = emb_dimself.enc_hid_dim = enc_hid_dimself.dec_hid_dim = dec_hid_dimself.output_dim = output_dimself.dropout = dropoutself.attention = attentionself.embedding = nn.Embedding(output_dim, emb_dim)self.rnn = nn.GRU((enc_hid_dim * 2) + emb_dim, dec_hid_dim)self.out = nn.Linear(self.attention.attn_in + emb_dim, output_dim)self.dropout = nn.Dropout(dropout)def _weighted_encoder_rep(self,decoder_hidden: Tensor,encoder_outputs: Tensor) -> Tensor:a = self.attention(decoder_hidden, encoder_outputs)a = a.unsqueeze(1)encoder_outputs = encoder_outputs.permute(1, 0, 2)weighted_encoder_rep = torch.bmm(a, encoder_outputs)weighted_encoder_rep = weighted_encoder_rep.permute(1, 0, 2)return weighted_encoder_repdef forward(self,input: Tensor,decoder_hidden: Tensor,encoder_outputs: Tensor) -> Tuple[Tensor]:input = input.unsqueeze(0)embedded = self.dropout(self.embedding(input))weighted_encoder_rep = self._weighted_encoder_rep(decoder_hidden,encoder_outputs)rnn_input = torch.cat((embedded, weighted_encoder_rep), dim = 2)output, decoder_hidden = self.rnn(rnn_input, decoder_hidden.unsqueeze(0))embedded = embedded.squeeze(0)output = output.squeeze(0)weighted_encoder_rep = weighted_encoder_rep.squeeze(0)output = self.out(torch.cat((output,weighted_encoder_rep,embedded), dim = 1))return output, decoder_hidden.squeeze(0)class Seq2Seq(nn.Module):def __init__(self,encoder: nn.Module,decoder: nn.Module,device: torch.device):super().__init__()self.encoder = encoderself.decoder = decoderself.device = devicedef forward(self,src: Tensor,trg: Tensor,teacher_forcing_ratio: float = 0.5) -> Tensor:batch_size = src.shape[1]max_len = trg.shape[0]trg_vocab_size = self.decoder.output_dimoutputs = torch.zeros(max_len, batch_size, trg_vocab_size).to(self.device)encoder_outputs, hidden = self.encoder(src)# first input to the decoder is the <sos> tokenoutput = trg[0,:]for t in range(1, max_len):output, hidden = self.decoder(output, hidden, encoder_outputs)outputs[t] = outputteacher_force = random.random() < teacher_forcing_ratiotop1 = output.max(1)[1]output = (trg[t] if teacher_force else top1)return outputsINPUT_DIM = len(SRC.vocab)
OUTPUT_DIM = len(TRG.vocab)
# ENC_EMB_DIM = 256
# DEC_EMB_DIM = 256
# ENC_HID_DIM = 512
# DEC_HID_DIM = 512
# ATTN_DIM = 64
# ENC_DROPOUT = 0.5
# DEC_DROPOUT = 0.5ENC_EMB_DIM = 32
DEC_EMB_DIM = 32
ENC_HID_DIM = 64
DEC_HID_DIM = 64
ATTN_DIM = 8
ENC_DROPOUT = 0.5
DEC_DROPOUT = 0.5enc = Encoder(INPUT_DIM, ENC_EMB_DIM, ENC_HID_DIM, DEC_HID_DIM, ENC_DROPOUT)attn = Attention(ENC_HID_DIM, DEC_HID_DIM, ATTN_DIM)dec = Decoder(OUTPUT_DIM, DEC_EMB_DIM, ENC_HID_DIM, DEC_HID_DIM, DEC_DROPOUT, attn)model = Seq2Seq(enc, dec, device).to(device)def init_weights(m: nn.Module):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)optimizer = optim.Adam(model.parameters())def count_parameters(model: nn.Module):return sum(p.numel() for p in model.parameters() if p.requires_grad)print(f'The model has {count_parameters(model):,} trainable parameters')

注意:在对语言翻译模型的性能进行评分时,我们必须告诉 nn.CrossEntropyLoss 函数忽略目标只是填充的索引 (ignore the indices where the target is simply padding.)。

PAD_IDX = TRG.vocab.stoi['<pad>']criterion = nn.CrossEntropyLoss(ignore_index=PAD_IDX)

最后,我们可以训练和评估这个模型:

import math
import timedef train(model: nn.Module,iterator: BucketIterator,optimizer: optim.Optimizer,criterion: nn.Module,clip: float):model.train()epoch_loss = 0for _, batch in enumerate(iterator):src = batch.srctrg = batch.trgoptimizer.zero_grad()output = model(src, trg)output = output[1:].view(-1, output.shape[-1])trg = trg[1:].view(-1)loss = criterion(output, trg)loss.backward()torch.nn.utils.clip_grad_norm_(model.parameters(), clip)optimizer.step()epoch_loss += loss.item()return epoch_loss / len(iterator)def evaluate(model: nn.Module,iterator: BucketIterator,criterion: nn.Module):model.eval()epoch_loss = 0with torch.no_grad():for _, batch in enumerate(iterator):src = batch.srctrg = batch.trgoutput = model(src, trg, 0) #turn off teacher forcingoutput = output[1:].view(-1, output.shape[-1])trg = trg[1:].view(-1)loss = criterion(output, trg)epoch_loss += loss.item()return epoch_loss / len(iterator)def epoch_time(start_time: int,end_time: int):elapsed_time = end_time - start_timeelapsed_mins = int(elapsed_time / 60)elapsed_secs = int(elapsed_time - (elapsed_mins * 60))return elapsed_mins, elapsed_secsN_EPOCHS = 10
CLIP = 1best_valid_loss = float('inf')for epoch in range(N_EPOCHS):start_time = time.time()train_loss = train(model, train_iterator, optimizer, criterion, CLIP)valid_loss = evaluate(model, valid_iterator, 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}')test_loss = evaluate(model, test_iterator, criterion)print(f'| Test Loss: {test_loss:.3f} | Test PPL: {math.exp(test_loss):7.3f} |')

下一步

使用 torchtext 继续学习 Ben Trevett 的教程的剩余部分—- 在这里
请继续关注使用其他 torchtext 功能特性以及 nn.Transformer 的教程,以便学习通过预测下一个单词进行语言建模!

PyTorch 使用Torchtext进行语言翻译(德语到英语)相关推荐

  1. PyTorch-18 使用Torchtext进行语言翻译(德语到英语)

    要查看图文版教程,请移步到:http://studyai.com/pytorch-1.4/beginner/torchtext_translation_tutorial.html 本教程介绍如何使用 ...

  2. CANoe11.0 语言设置 德语到英语切换

    在candb++出现德语界面切换至英语 1.file 2.tools 3.DBC file editor candb++ 下选择Vector CANoe 11.0\Exec32\candb.exe

  3. 【PyTorch】8 语言翻译Torchtext实战——英语和德语翻译、Attention模型、 Pytorch 1.8 安装

    torchtext 语言翻译 1. 数据处理 2. DataLoader 3. 定义nn.Module和Optimizer 4. 训练 4.1 Pytorch 1.8 安装 4.2 训练网络 5. 测 ...

  4. Facebook新AI模型实现直接从非英语语言翻译到另一种非英语语言

    据外媒报道,机器翻译技术自诞生以来走过了漫长的道路.虽然像谷歌这样的翻译曾经粗糙.不可靠,而且只对最基本的翻译有用,但如今,由于AI的力量,它们可以实现惊人的准确.然而一些古老的翻译方法仍然存在. 比 ...

  5. 语言 班费管理系统源代码_固定资产管理系统开源的各种语言翻译

    固定资产管理系统开源指的是将固定资产管理系统源代码进行开发,进而得到可以免费使用的固定资产管理系统,即是开源的固定资产管理系统.固定资产管理系统简单来说就是利用现代信息技术智能化管理企业资产的管理系统 ...

  6. 网络资产管理系统_固定资产管理系统网络版的各种语言翻译

    固定资产管理系统网络版指的是固定资产管理系统项目的联网版本,适合需要远程操作及多人同时操作的用户,各个版本都提供相应的网络版.固定资产管理系统网络版系统稳定.功能强大,支持局域网内用户联网操作软件,适 ...

  7. (六)多语言人工智能语言翻译

    目录 介绍 翻译多种语言 下一步 下载源文件 - 3.5 KB 介绍 谷歌翻译工作得如此之好,它通常看起来很神奇.但这不是魔法--这是深度学习! 在本系列文章中,我们将向您展示如何使用深度学习来创建自 ...

  8. (三)用于构建AI语言翻译系统的工具

    目录 介绍 工具和版本 TensorFlow Keras Pandas Word2Vec 下一步 下载源文件 - 3.5 KB 介绍 谷歌翻译工作得如此之好,它通常看起来很神奇.但这不是魔法--这是深 ...

  9. asset计算机语言,资产管理软件的各种语言翻译

    原标题:资产管理软件的各种语言翻译 资产管理软件是以实物管理为特点,以计算机为操作平台,以快捷.精准和功能全面为优势的管理类软件.软件采用先进成熟的条码(RFID)技术对资产实物从购置.领用.清理.盘 ...

最新文章

  1. ewebeditor 上传大内容文本注意点
  2. VMware Workstation 10装Mac OS X 10.9
  3. 三种ajax解析模式!
  4. php.ini-dist和php.ini区别,php.ini-dist 和 php.ini-recommended 的区别介绍(方便开发与安全的朋友)...
  5. 一种用css实现图片在父框中等比缩放并垂直居中的办法
  6. jstack Dump日志文件中的线程状态
  7. 为什么本地硬盘无法启动计算机,win10专业版系统本地磁盘打不开怎么办?
  8. JZ The First Day 总结
  9. codeforces 1220E
  10. 181022词霸有道扇贝每日一句
  11. 非越狱iPad实现外接键盘全APP五笔输入(IOS14已自带五笔)
  12. Norton AntiVirus (诺顿杀毒)v9.0 简体中文企业版
  13. Creator 3.0中摄像机调整技巧: 1.旋转:Cmd+右键 移动:空格+右键 放缩:滚轮
  14. Spring AOP不进入before和业务方法,却进入其他切面的问题
  15. 小技巧 - 如何在线下载 Google Play 里面的应用?
  16. 819A - 如何成为一名职业程序员
  17. Windows 7 更新补丁大包子
  18. swagger首页空白
  19. php和java做网站_java与php哪个做网站简单
  20. 常用的RS-485总线,详细讲解来啦!

热门文章

  1. Windows 10运行HarmonyOS项目
  2. 拒绝死板,明暗交界线这样过渡更显自然
  3. notepad++如何在运行里面添加打开方式
  4. 15.OpenWrt-U盘和TF卡存储
  5. Linux常规问题总结
  6. 「州晖」工业管道工程中管径尺寸设计研究
  7. request请求讲解
  8. 《Java编程思想》读后总结(一)
  9. 小东吖 之 java 运算符
  10. 最小生成树的拓展应用