基于Transformer实现机器翻译(日译中)

一、介绍

        1.定义

        Transformer是一种基于注意力机制的深度学习模型,最初由Google在2017年提出。主要用于机器翻译任务,但也被广泛应用于其他自然语言处理(NLP)领域,如文本摘要、语言理解、文本生成等。

        2.核心思想

        完全抛弃了传统的循环神经网络(RNN)和长短期记忆网络(LSTM)等序列模型的结构,而是通过自注意力机制(self-attention)实现了对序列数据的建模。Transformer模型通过编码器-解码器架构,结合多头注意力机制和前馈神经网络,能够更好地捕捉输入序列中不同位置的依赖关系,并实现在不同任务上的表现优异,尤其在机器翻译任务上取得了显著的性能提升。Transformer的创新思想和结构设计为当今自然语言处理领域带来了重大影响。

        3.特点及优势

        *并行计算能力强: 由于自注意力机制的引入,Transformer模型可以同时处理输入序列中所有位置的信息,而无需按顺序逐步计算,因此具有更好的并行计算能力,能够加快训练速度。

        *更好的捕捉长距离依赖关系: 自注意力机制允许模型在每个位置考虑到输入序列中所有位置的信息,有利于捕捉长距离依赖关系,更好地理解上下文信息。

        *易于扩展和改进: Transformer模型结构清晰简洁,易于理解和扩展,研究者可以根据具体任务对模型进行调整和改进,适用于各种自然语言处理任务。

         *消除了梯度传播的障碍: 由于残差连接和层归一化的应用,Transformer有助于缓解梯度消失和爆炸的问题,使得网络更易训练。

        *高性能的表现: Transformer模型在诸如机器翻译、文本生成和语言理解等任务上表现出色,取得了很多领域的最先进结果,证明了其有效性和实用性。

        4.应用

        除了机器翻译,Transformer模型也成功应用于其他多种NLP任务,例如:文本分类,情感分析,文本摘要,问答系统,语言建模。

二、实验代码

        1.环境和安装包

        首先,让我们确保我们的系统中安装了以下软件包

import math
import torchtext
import torch
import torch.nn as nn
from torch import Tensor
from torch.nn.utils.rnn import pad_sequence
from torch.utils.data import DataLoader
from collections import Counter
from torchtext.vocab import Vocab
from torch.nn import TransformerEncoder, TransformerDecoder, TransformerEncoderLayer, TransformerDecoderLayer
import io
import time
import pandas as pd
import numpy as np
import pickle
import tqdm
import sentencepiece as spm
torch.manual_seed(0)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# print(torch.cuda.get_device_name(0)) ## 如果你有GPU,请在你自己的电脑上尝试运行这一套代码
device

2.获取平行数据集

        在本教程中,我们将使用从JParaCrawl下载的日英并行数据集

df = pd.read_csv('./zh-ja/zh-ja.bicleaner05.txt', sep='\\t', engine='python', header=None)
trainen = df[2].values.tolist()#[:10000]
trainja = df[3].values.tolist()#[:10000]
# trainen.pop(5972)
# trainja.pop(5972)

        导入所有日语及其英文对应文本后,我删除了数据集中的最后一条数据,因为它有一个缺失值。总共,在trainen和trainja中的句子数量为5,973,071条,然而,为了学习目的,通常建议对数据进行抽样,并确保一切按预期工作正常,然后再一次使用所有数据,以节省时间。

        下面是数据集中包含的句子示例。

print(trainen[500])
print(trainja[500])

3.准备标记器

        与英语或其他按字母顺序排列的语言不同,日语句子不包含空格来分隔单词。我们可以使用JParaCrawl提供的标记器,该标记器是使用日语和英语的句子片段创建的,您可以访问JParaCrawl网站下载它们。

# 加载英文分词模型
en_tokenizer = spm.SentencePieceProcessor(model_file='enja_spm_models/spm.en.nopretok.model')

# 加载日文分词模型
ja_tokenizer = spm.SentencePieceProcessor(model_file='enja_spm_models/spm.ja.nopretok.model')

        在加载了标记器之后,可以测试它们,例如,通过执行以下代码。

en_tokenizer.encode("All residents aged 20 to 59 years who live in Japan must enroll in public pension system.", out_type='str')

ja_tokenizer.encode("年金 日本に住んでいる20歳~60歳の全ての人は、公的年金制度に加入しなければなりません。", out_type='str')

4.构建TorchText Vocab对象并将句子转换为Torch张量

        利用标记器和原始文本数据,我们创建了一个来自TorchText的Vocab对象。这一过程可能耗时数秒至数分钟不等,具体时间取决于数据集的体积及处理能力。并且,选用的标记器种类也会对构建词汇表所花费的时间有所影响。在尝试了多种日语标记器之后,我发现SentencePiece既有效又高效,比较符合我的需求。

def build_vocab(sentences, tokenizer):
  counter = Counter()
  for sentence in sentences:
    counter.update(tokenizer.encode(sentence, out_type=str))
  return Vocab(counter, specials=['<unk>', '<pad>', '<bos>', '<eos>'])

# 使用trainja和ja_tokenizer构建日语词汇表
ja_vocab = build_vocab(trainja, ja_tokenizer)

# 使用trainen和en_tokenizer构建英语词汇表
en_vocab = build_vocab(trainen, en_tokenizer)

        在我们有了词汇表对象之后,我们可以使用vocab和标记器对象来为我们的训练数据构建张量。

def data_process(ja, en):
  data = []  # 创建一个空列表,用于存储处理后的数据
  for (raw_ja, raw_en) in zip(ja, en):  # 使用zip函数将ja和en两个列表中的元素一一对应地组合在一起
    # 对原始日语文本进行分词,并将每个分词转换为对应的词汇表中的索引值,然后创建一个张量(tensor)
    ja_tensor_ = torch.tensor([ja_vocab[token] for token in ja_tokenizer.encode(raw_ja.rstrip("\n"), out_type=str)],
                            dtype=torch.long)
    # 对原始英语文本进行分词,并将每个分词转换为对应的词汇表中的索引值,然后创建一个张量(tensor)
    en_tensor_ = torch.tensor([en_vocab[token] for token in en_tokenizer.encode(raw_en.rstrip("\n"), out_type=str)],
                            dtype=torch.long)
    data.append((ja_tensor_, en_tensor_))  # 将处理后的日语和英语张量添加到data列表中
  return data  # 返回处理后的数据列表

train_data = data_process(trainja, trainen)  # 调用data_process函数处理训练数据,并将结果存储在train_data变量中

5.创建要在训练期间迭代的DataLoader对象

        在这里,我们将BATCH_SIZE设置为16,以防止“cuda内存不足”,但这取决于各种因素,如机器内存容量、数据大小等,所以可以根据您的需要随意更改批量大小(注意:PyTorch的教程使用Multi30k德语-英语数据集将批量大小设置为128。)

# 定义一个常量,表示每个批次的大小
BATCH_SIZE = 8

# 定义一些词汇表中的特殊标记的索引值
PAD_IDX = ja_vocab['<pad>']
BOS_IDX = ja_vocab['<bos>']
EOS_IDX = ja_vocab['<eos>']

# 定义一个函数,用于生成批次数据
def generate_batch(data_batch):
  # 初始化两个空列表,用于存储日语和英语文本的批次数据
  ja_batch, en_batch = [], []
  
  # 遍历输入的数据批次
  for (ja_item, en_item) in data_batch:
    # 在日语文本的开头和结尾分别添加特殊标记,并将其添加到日语批次数据列表中
    ja_batch.append(torch.cat([torch.tensor([BOS_IDX]), ja_item, torch.tensor([EOS_IDX])], dim=0))
    # 在英语文本的开头和结尾分别添加特殊标记,并将其添加到英语批次数据列表中
    en_batch.append(torch.cat([torch.tensor([BOS_IDX]), en_item, torch.tensor([EOS_IDX])], dim=0))
  
  # 对日语批次数据进行填充,使其长度相同
  ja_batch = pad_sequence(ja_batch, padding_value=PAD_IDX)
  # 对英语批次数据进行填充,使其长度相同
  en_batch = pad_sequence(en_batch, padding_value=PAD_IDX)
  
  # 返回填充后的日语和英语批次数据
  return ja_batch, en_batch

# 使用DataLoader加载训练数据,并指定批次大小、是否打乱顺序以及如何生成批次数据
train_iter = DataLoader(train_data, batch_size=BATCH_SIZE,
                        shuffle=True, collate_fn=generate_batch)

6.顺序到顺序变压器

        Transformer模型,如“注意力就是你所需要的”论文所述,是一种Seq2Seq模型,专门用于解决机器翻译问题。该模型由编码器和解码器模块组成,每个模块都包含若干层。

        编码器负责处理输入序列,它通过一系列的多头注意力机制和前馈网络层来传递和转换输入数据。编码器的输出(通常被称为存储器)随后被送入解码器,与目标张量一起处理。在训练过程中,编码器和解码器采用教师强制(teacher forcing)技术进行端到端的学习。

from torch.nn import (TransformerEncoder, TransformerDecoder,
                      TransformerEncoderLayer, TransformerDecoderLayer)

class Seq2SeqTransformer(nn.Module):
    def __init__(self, num_encoder_layers: int, num_decoder_layers: int,
                 emb_size: int, src_vocab_size: int, tgt_vocab_size: int,
                 dim_feedforward:int = 512, dropout:float = 0.1):
        super(Seq2SeqTransformer, self).__init__()
        # 定义编码器层
        encoder_layer = TransformerEncoderLayer(d_model=emb_size, nhead=NHEAD,
                                                dim_feedforward=dim_feedforward)
        # 创建编码器
        self.transformer_encoder = TransformerEncoder(encoder_layer, num_layers=num_encoder_layers)
        # 定义解码器层
        decoder_layer = TransformerDecoderLayer(d_model=emb_size, nhead=NHEAD,
                                                dim_feedforward=dim_feedforward)
        # 创建解码器
        self.transformer_decoder = TransformerDecoder(decoder_layer, num_layers=num_decoder_layers)

        # 定义生成器
        self.generator = nn.Linear(emb_size, tgt_vocab_size)
        # 创建源语言词嵌入层
        self.src_tok_emb = TokenEmbedding(src_vocab_size, emb_size)
        # 创建目标语言词嵌入层
        self.tgt_tok_emb = TokenEmbedding(tgt_vocab_size, emb_size)
        # 创建位置编码层
        self.positional_encoding = PositionalEncoding(emb_size, dropout=dropout)

    def forward(self, src: Tensor, trg: Tensor, src_mask: Tensor,
                tgt_mask: Tensor, src_padding_mask: Tensor,
                tgt_padding_mask: Tensor, memory_key_padding_mask: Tensor):
        # 对源语言序列进行词嵌入和位置编码
        src_emb = self.positional_encoding(self.src_tok_emb(src))
        # 对目标语言序列进行词嵌入和位置编码
        tgt_emb = self.positional_encoding(self.tgt_tok_emb(trg))
        # 通过编码器得到记忆矩阵
        memory = self.transformer_encoder(src_emb, src_mask, src_padding_mask)
        # 通过解码器得到输出序列
        outs = self.transformer_decoder(tgt_emb, memory, tgt_mask, None,
                                        tgt_padding_mask, memory_key_padding_mask)
        # 通过生成器得到最终的输出结果
        return self.generator(outs)

    def encode(self, src: Tensor, src_mask: Tensor):
        # 对源语言序列进行编码
        return self.transformer_encoder(self.positional_encoding(
                            self.src_tok_emb(src)), src_mask)

    def decode(self, tgt: Tensor, memory: Tensor, tgt_mask: Tensor):
        # 对目标语言序列进行解码
        return self.transformer_decoder(self.positional_encoding(
                          self.tgt_tok_emb(tgt)), memory,
                          tgt_mask)

        文本标记通过使用标记嵌入来表示。位置编码被添加到标记嵌入中,以引入单词顺序的概念。

class PositionalEncoding(nn.Module):
    def __init__(self, emb_size: int, dropout, maxlen: int = 5000):
        super(PositionalEncoding, self).__init__()

        # 计算位置编码的分母
        den = torch.exp(- torch.arange(0, emb_size, 2) * math.log(10000) / emb_size)

        # 生成最多包含 'maxlen' 个令牌的位置
        pos = torch.arange(0, maxlen).reshape(maxlen, 1)
        
        # 初始化一个全零的位置编码矩阵
        pos_embedding = torch.zeros((maxlen, emb_size))

        # 使用正弦和余弦值填充位置编码矩阵
        pos_embedding[:, 0::2] = torch.sin(pos * den)
        pos_embedding[:, 1::2] = torch.cos(pos * den)

        # 给位置编码矩阵增加一个维度
        pos_embedding = pos_embedding.unsqueeze(-2)

        self.dropout = nn.Dropout(dropout)
        # 将位置编码注册为模型的缓冲区
        self.register_buffer('pos_embedding', pos_embedding)

    def forward(self, token_embedding: Tensor):
        # 将位置编码添加到令牌嵌入中并应用dropout
        return self.dropout(token_embedding + self.pos_embedding[:token_embedding.size(0),:])


class TokenEmbedding(nn.Module):
    def __init__(self, vocab_size: int, emb_size):
        super(TokenEmbedding, self).__init__()
        # 初始化一个用于令牌嵌入的嵌入层
        self.embedding = nn.Embedding(vocab_size, emb_size)
        self.emb_size = emb_size

    def forward(self, tokens: Tensor):
        # 获取令牌嵌入并乘以 'emb_size' 的平方根进行缩放
        return self.embedding(tokens.long()) * math.sqrt(self.emb_size)

        我们创建一个后续单词掩码来阻止目标单词关注其后续单词。我们还创建掩码,用于掩码源和目标填充令牌

def generate_square_subsequent_mask(sz):
    # 生成一个方形的下三角矩阵作为掩码
    mask = (torch.triu(torch.ones((sz, sz), device=device)) == 1).transpose(0, 1)
    
    # 将掩码转换为浮点类型,并用负无穷和0来填充掩码
    mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))
    
    return mask

def create_mask(src, tgt):
    src_seq_len = src.shape[0]
    tgt_seq_len = tgt.shape[0]

    # 生成目标序列的掩码
    tgt_mask = generate_square_subsequent_mask(tgt_seq_len)
    
    # 创建源序列的全零掩码
    src_mask = torch.zeros((src_seq_len, src_seq_len), device=device).type(torch.bool)

    # 创建源序列和目标序列的填充掩码
    src_padding_mask = (src == PAD_IDX).transpose(0, 1)
    tgt_padding_mask = (tgt == PAD_IDX).transpose(0, 1)
    
    return src_mask, tgt_mask, src_padding_mask, tgt_padding_mask

        定义模型参数并实例化模型。这里我们服务器实在是计算能力有限,按照以下配置可以训练但是效果应该是不行的。如果想要看到训练的效果请使用你自己的带GPU的电脑运行这一套代码。

        当你使用自己的GPU的时候,NUM_ENCODER_LAYERS 和 NUM_DECODER_LAYERS 设置为3或者更高,NHEAD设置8,EMB_SIZE设置为512。

# 定义源语言词汇表大小和目标语言词汇表大小
SRC_VOCAB_SIZE = len(ja_vocab)
TGT_VOCAB_SIZE = len(en_vocab)

# 定义词嵌入维度
EMB_SIZE = 512
# 定义 Transformer 模型的头数
NHEAD = 8
# 定义前馈神经网络隐藏层维度
FFN_HID_DIM = 512
# 定义批量大小
BATCH_SIZE = 8
# 定义编码器层数
NUM_ENCODER_LAYERS = 3
# 定义解码器层数
NUM_DECODER_LAYERS = 3
# 定义训练周期数
NUM_EPOCHS = 16

# 初始化 Seq2SeqTransformer 模型
transformer = Seq2SeqTransformer(NUM_ENCODER_LAYERS, NUM_DECODER_LAYERS, EMB_SIZE, SRC_VOCAB_SIZE, TGT_VOCAB_SIZE, FFN_HID_DIM)

# 使用 Xavier 初始化模型的参数
for p in transformer.parameters():
    if p.dim() > 1:
        nn.init.xavier_uniform_(p)

# 将模型移动到指定设备(例如 GPU)
transformer = transformer.to(device)

# 定义损失函数为交叉熵损失函数,并忽略填充索引 PAD_IDX
loss_fn = torch.nn.CrossEntropyLoss(ignore_index=PAD_IDX)

# 定义 Adam 优化器,用于更新 Transformer 模型的参数
optimizer = torch.optim.Adam(transformer.parameters(), lr=0.0001, betas=(0.9, 0.98), eps=1e-9)

# 定义训练函数,处理一个训练周期的数据
def train_epoch(model, train_iter, optimizer):
    model.train()
    losses = 0
    for idx, (src, tgt) in  enumerate(train_iter):
        src = src.to(device)
        tgt = tgt.to(device)
        
        tgt_input = tgt[:-1, :]

        # 创建源序列掩码、目标序列掩码以及填充掩码
        src_mask, tgt_mask, src_padding_mask, tgt_padding_mask = create_mask(src, tgt_input)

        # 传入模型进行前向传播
        logits = model(src, tgt_input, src_mask, tgt_mask,
                       src_padding_mask, tgt_padding_mask, src_padding_mask)

        # 梯度清零
        optimizer.zero_grad()

        tgt_out = tgt[1:,:]
        loss = loss_fn(logits.reshape(-1, logits.shape[-1]), tgt_out.reshape(-1))
        loss.backward()

        # 更新参数
        optimizer.step()
        
        losses += loss.item()
    
    return losses / len(train_iter)

# 定义评估函数,用于在验证集上评估模型性能
def evaluate(model, val_iter):
    model.eval()
    losses = 0
    for idx, (src, tgt) in (enumerate(val_iter)):
        src = src.to(device)
        tgt = tgt.to(device)

        tgt_input = tgt[:-1, :]

        src_mask, tgt_mask, src_padding_mask, tgt_padding_mask = create_mask(src, tgt_input)

        logits = model(src, tgt_input, src_mask, tgt_mask,
                       src_padding_mask, tgt_padding_mask, src_padding_mask)
        
        tgt_out = tgt[1:,:]
        loss = loss_fn(logits.reshape(-1, logits.shape[-1]), tgt_out.reshape(-1))
        
        losses += loss.item()
    
    return losses / len(val_iter)

7.开始训练

        终于,在准备好必要的课程和功能之后,我们准备好训练我们的模型了。毋庸置疑,但训练所需的时间可能会因许多因素而大不相同,比如计算能力、参数和数据集的大小。

        我使用了来自JParaCrawl的完整句子列表来训练模型,该列表每种语言约有590万个句子,使用单个NVIDIA GeForce RTX 3070 GPU每个时代大约需要5个小时。

try:
    for epoch in tqdm.tqdm(range(1, NUM_EPOCHS+1)):
      start_time = time.time()
      train_loss = train_epoch(transformer, tqdm.tqdm(train_iter, mininterval=10), optimizer)
      end_time = time.time()
      print((f"Epoch: {epoch}, Train loss: {train_loss:.3f}, "
              f"Epoch time = {(end_time - start_time):.3f}s"))
except KeyboardInterrupt:
    print("Exiting loop")

8.尝试使用经过训练的模型翻译日语句子

        首先,我们创建翻译新句子的功能,包括获取日语句子、标记化、转换为张量、推理,然后将结果解码回句子等步骤,但这次是用英语。

def greedy_decode(model, src, src_mask, max_len, start_symbol):
    # 将输入数据移动到指定设备
    src = src.to(device)
    src_mask = src_mask.to(device)
    
    # 编码源序列
    memory = model.encode(src, src_mask)
    
    # 初始化目标序列的起始符号
    ys = torch.ones(1, 1).fill_(start_symbol).type(torch.long).to(device)
    
    # 生成目标序列直到达到最大长度或遇到终止符号
    for i in range(max_len-1):
        memory = memory.to(device)
        
        # 创建目标序列掩码
        memory_mask = torch.zeros(ys.shape[0], memory.shape[0]).to(device).type(torch.bool)
        tgt_mask = (generate_square_subsequent_mask(ys.size(0)).type(torch.bool)).to(device)
        
        # 解码当前目标序列
        out = model.decode(ys, memory, tgt_mask)
        out = out.transpose(0, 1)
        
        # 预测下一个词
        prob = model.generator(out[:, -1])
        _, next_word = torch.max(prob, dim = 1)
        next_word = next_word.item()
        
        # 更新目标序列
        ys = torch.cat([ys, torch.ones(1, 1).type_as(src.data).fill_(next_word)], dim=0)
        
        # 如果预测到终止符号,终止解码
        if next_word == EOS_IDX:
            break
    
    return ys

def translate(model, src, src_vocab, tgt_vocab, src_tokenizer):
    # 将模型设置为评估模式
    model.eval()
    
    # 对源文本进行分词和编码
    tokens = [BOS_IDX] + [src_vocab.stoi[tok] for tok in src_tokenizer.encode(src, out_type=str)] + [EOS_IDX]
    num_tokens = len(tokens)
    src = (torch.LongTensor(tokens).reshape(num_tokens, 1))
    src_mask = (torch.zeros(num_tokens, num_tokens)).type(torch.bool)
    
    # 使用贪婪解码方法生成目标序列
    tgt_tokens = greedy_decode(model, src, src_mask, max_len=num_tokens + 5, start_symbol=BOS_IDX).flatten()
    
    # 将目标序列转换为文本并去除特殊标记符号
    return " ".join([tgt_vocab.itos[tok] for tok in tgt_tokens]).replace("<bos>", "").replace("<eos>", "")

        接着,我们可以直接调用translate函数并传递所需的参数。

# 实例化Seq2SeqTransformer模型
transformer = Seq2SeqTransformer(NUM_ENCODER_LAYERS, NUM_DECODER_LAYERS,
                                 EMB_SIZE, SRC_VOCAB_SIZE, TGT_VOCAB_SIZE,
                                 FFN_HID_DIM)

# 加载预训练模型参数
state_dict = torch.load('model_256.pth')
transformer.load_state_dict(state_dict['model'])

# 将模型移动到指定设备
transformer.to(device)

# 调用翻译函数进行翻译
translation_result = translate(transformer, "HSコード 8515 はんだ付け用、ろう付け用又は溶接用の機器(電気式(電気加熱ガス式を含む。)", ja_vocab, en_vocab, ja_tokenizer)

# 返回翻译结果
print(translation_result)
trainen.pop(5)

trainja.pop(5)

9.保存Vocab对象和训练的模型

         最后, 培训完成后, 我们将首先使用Pickle保存Vocab对象(en_vocab和ja_vocab)

import pickle
# open a file, where you want to store the data
file = open('en_vocab.pkl', 'wb')
# dump information to that file
pickle.dump(en_vocab, file)
file.close()
file = open('ja_vocab.pkl', 'wb')
pickle.dump(ja_vocab, file)
file.close()

        最后,我们还可以使用PyTorch的保存和加载函数来保存模型以备以后使用。通常,根据我们以后想要使用模型的方式,有两种保存模型的方法。第一种是仅用于推断,可以稍后加载模型并将其用于从日语翻译成英语。

# save model for inference
torch.save(transformer.state_dict(), 'inference_model')

        第二个参数也用于推断,但是还用于当我们想要稍后加载模型并恢复训练时。

# save model + checkpoint to resume training later
torch.save({
  'epoch': NUM_EPOCHS,
  'model_state_dict': transformer.state_dict(),
  'optimizer_state_dict': optimizer.state_dict(),
  'loss': train_loss,
  }, 'model_checkpoint.tar')

三、总结与反思

        本次实验展示了基于Transformer的模型在日译中机器翻译任务上展现出的有效性和潜力。我们充满信心,通过持续的优化和改进,这一模型将在实际应用中取得更为令人满意的效果。                  

        Transformer架构的强大之处在于其能够捕捉输入序列中的长程依赖关系,并且通过自注意力机制有效地进行编码和解码,从而在翻译任务中取得显著的进展。未来的工作将着重于调整超参数、增加训练数据规模以及利用更先进的技术,以进一步提升模型性能,并拓展其应用范围,让机器翻译更加准确、流畅,服务于更广泛的用户群体。这个实验为我们揭示了前进的道路,激励我们不断努力探索,推动机器翻译技术不断进步,为实践和应用带来更大的推动力。

  • 16
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于Transformer实现机器翻译是一种先进的方法。在Pytorch,可以使用nn.Transformer实现英文到文的机器翻译任务\[1\]。如果想要深入了解nn.Transformer的使用,可以参考一篇博文《Pytorch nn.Transformer的使用详解与Transformer的黑盒讲解》\[1\]。在这篇博文,作者建议先学习CopyTask任务,然后再学习机器翻译任务,这样会更容易理解。 此外,谷歌翻译也在逐步将转换器编码器引入其翻译算法\[2\]。他们提供了一个即用型翻译界面,可以在谷歌翻译网站上使用\[2\]。另外,瓦斯瓦尼等人在2017年的研究发现,Transformer在WMT 2014英德翻译任务和WMT 2014英法翻译任务上取得了最先进的BLEU分数\[3\]。BLEU是一种用于评估机器翻译质量的指标,具体的评估方法可以在《Evaluating machine translation with BLEU》部分找到\[3\]。 综上所述,基于Transformer机器翻译方法在实践取得了很好的效果,并且在Pytorch有相应的实现。同时,谷歌翻译也在逐步引入转换器编码器,并且Transformer机器翻译任务取得了最先进的结果。 #### 引用[.reference_title] - *1* [Pytorch入门实战(5):基于nn.Transformer实现机器翻译(英译汉)](https://blog.csdn.net/zhaohongfei_358/article/details/126175328)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [【NLP】第6章 使用 Transformer 进行机器翻译](https://blog.csdn.net/sikh_0529/article/details/127037111)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值