赞
踩
本文使用飞桨(PaddlePaddle)训练机器翻译模型,实现将英文翻译成中文的神经网络翻译机。
本人全部文章请参见:博客文章导航目录
本文归属于:自然语言处理系列
本系列实践代码请参见:我的GitHub
前文:BERT与ERNIE
本文使用Sequence-to-Sequence模型原理一文中所述Seq2Seq模型实现机器翻译。其中RNN使用长短期记忆网络(LSTM)原理与实战一文中所述LSTM模型结构,同时结合注意力机制(Attention):Seq2Seq模型的改进一文中所述注意力机制改进Seq2Seq模型,提升机器翻译效果。
本文代码部分参考了PaddlePaddle官方应用实践教程,对代码结构进行了修改,并调整了部分处理逻辑,使得该深度学习实践与本系列讲解的方法原理一致。
本文讲解的机器翻译实践使用http://www.manythings.org/anki/提供的中英文句子对作为训练数据集。对于英文,先将其全部变成小写,然后仅保留英文单词及句子末尾标点符号。对于中文,直接按字进行切分,不采用分词操作。同时设定MAX_LEN = 20
,得到一个包含29077个中英句子对的训练数据集。
对数据集进行进一步处理,生成中英文词表。在英文句子后添加<eos>
符号,在中文句子前后分别添加<bos>
和<eos>
符号,
并使用<pad>
符号将短句子填充成统一长度。最后根据中文句子创建Decoder每个时刻标签对应的句子,并将训练句子转换成词的ID构成的序列。具体代码如下:
# -*- coding: utf-8 -*- # @Time : 2021/8/1 19:16 # @Author : He Ruizhi # @File : machine_translation.py # @Software: PyCharm import paddle import paddle.nn.functional as F import re import numpy as np import time import warnings warnings.filterwarnings('ignore') print(paddle.__version__) # 2.1.0 # 设置训练句子最大长度,用于筛选数据集中的部分数据 MAX_LEN = 20 def create_dataset(file_path): """ 构建机器翻译训练数据集 :param file_path: 训练数据路径 :return: train_en_sents:由数字ID组成的英文句子 train_cn_sents:由数字ID组成的中文句子 train_cn_label_sents:由数字ID组成的中文词汇标签 en_vocab:英文词表 cn_vocab:中文词表 """ with open(file_path, 'rt', encoding='utf-8') as f: lines = f.read().strip().split('\n') # 设置正则匹配模板,用于从英文句子中提取单词 words_re = re.compile(r'\w+') # 将训练数据文件中的中文和英文句子全部提取出来 pairs = [] for line in lines: en_sent, cn_sent, _ = line.split('\t') pairs.append((words_re.findall(en_sent.lower())+[en_sent[-1]], list(cn_sent))) # 从原始训练数据中筛选出一部分数据用来训练模型 # 实际训练神经网络翻译机时数据量肯定是越多越好,不过本文只选取长度小于10的句子 filtered_pairs = [] for pair in pairs: if len(pair[0]) < MAX_LEN and len(pair[1]) < MAX_LEN: filtered_pairs.append(pair) # 创建中英文词表,将中文和因为句子转换成词的ID构成的序列 # 此外须在词表中添加三个特殊词:<pad>用来对短句子进行填充;<bos>表示解码时的起始符号;<eos>表示解码时的终止符号 # 在实际任务中,一般还会需要指定<unk>符号表示在词表中未出现过的词,并在构造训练集时有意识地添加<unk>符号,使模型能够处理相应情况 en_vocab = {} cn_vocab = {} en_vocab['<pad>'], en_vocab['<bos>'], en_vocab['<eos>'] = 0, 1, 2 cn_vocab['<pad>'], cn_vocab['<bos>'], cn_vocab['<eos>'] = 0, 1, 2 en_idx, cn_idx = 3, 3 for en, cn in filtered_pairs: for w in en: if w not in en_vocab: en_vocab[w] = en_idx en_idx += 1 for w in cn: if w not in cn_vocab: cn_vocab[w] = cn_idx cn_idx += 1 # 使用<pad>符号将短句子填充成长度一致的句子,便于使用批量数据训练模型 # 同时根据词表,创建一份实际的用于训练的用numpy array组织起来的数据集 padded_en_sents = [] padded_cn_sents = [] # 训练过程中的预测的目标,即每个中文的当前词去预测下一个词是什么词 padded_cn_label_sents = [] for en, cn in filtered_pairs: padded_en_sent = en + ['<eos>'] + ['<pad>'] * (MAX_LEN - len(en)) padded_cn_sent = ['<bos>'] + cn + ['<eos>'] + ['<pad>'] * (MAX_LEN - len(cn)) padded_cn_label_sent = cn + ['<eos>'] + ['<pad>'] * (MAX_LEN - len(cn) + 1) # 根据词表,将相应的单词转换成数字ID padded_en_sents.append([en_vocab[w] for w in padded_en_sent]) padded_cn_sents.append([cn_vocab[w] for w in padded_cn_sent]) padded_cn_label_sents.append([cn_vocab[w] for w in padded_cn_label_sent]) # 将训练数据用numpy array组织起来 train_en_sents = np.array(padded_en_sents, dtype='int64') train_cn_sents = np.array(padded_cn_sents, dtype='int64') train_cn_label_sents = np.array(padded_cn_label_sents, dtype='int64') return train_en_sents, train_cn_sents, train_cn_label_sents, en_vocab, cn_vocab
本文讲解的机器翻译实践采用Encoder-AttentionDecoder架构,Encoder采用LSTM模型,Decoder采用Attention+LSTM模型。虽然在注意力机制(Attention):Seq2Seq模型的改进一文中为了讲解简便,使用的是SimpleRNN+Attention,而不是LSTM+Attention。但是使用不同的RNN结构,本质均为Decoder RNN初始状态等于Encoder RNN最后时刻状态,Decoder RNN t t t时刻输入为 x t ′ x_t^\prime xt′和Context Vector c t − 1 c_{t-1} ct−1拼接而成的向量。
在Encoder部分,输入英文句子,通过查找完Embedding之后接一个LSTM的方式构建一个对英文句子编码的网络。具体代码如下:
class Encoder(paddle.nn.Layer):
"""Seq2Seq模型Encoder,采用LSTM结构"""
def __init__(self, en_vocab_size, en_embedding_dim, lstm_hidden_size, lstm_num_layers):
super(Encoder, self).__init__()
self.emb = paddle.nn.Embedding(num_embeddings=en_vocab_size, embedding_dim=en_embedding_dim)
self.lstm = paddle.nn.LSTM(input_size=en_embedding_dim, hidden_size=lstm_hidden_size,
num_layers=lstm_num_layers)
def forward(self, x):
x = self.emb(x)
x, (h, c) = self.lstm(x)
return x, h, c
在Decoder部分,通过一个带有Attention的LSTM来完成解码。
Decoder的forward
函数每次调用只让LSTM往前计算一次,即对只生成当前时刻的输出,而不是生成整个输出序列。整体的recurrent
部分,是在训练循环内完成的。
本文讲解的机器翻译实践Attention中权重计算采用注意力机制(Attention):Seq2Seq模型的改进一文3.2部分所述方法一。即将Decoder
t
t
t时刻输出状态向量
s
t
s_t
st分别与Encoder各个时刻状态向量
h
1
h_1
h1至
h
m
h_m
hm拼接,依次通过一个tanh函数激活的全连接层,和一个线性加和层(Linear Layer)。
具体代码如下:
class AttentionDecoder(paddle.nn.Layer): """Seq2Seq模型解码器,采用带有注意力机制的LSTM结构""" def __init__(self, cn_vocab_size, cn_embedding_dim, lstm_hidden_size, v_dim): super(AttentionDecoder, self).__init__() self.emb = paddle.nn.Embedding(num_embeddings=cn_vocab_size, embedding_dim=cn_embedding_dim) # lstm层输入为x'_t和Context Vector拼接而成的向量,Context Vector的维度与lstm_hidden_size一致 self.lstm = paddle.nn.LSTM(input_size=cn_embedding_dim + lstm_hidden_size, hidden_size=lstm_hidden_size) # 用于计算Attention权重 self.attention_linear1 = paddle.nn.Linear(lstm_hidden_size * 2, v_dim) self.attention_linear2 = paddle.nn.Linear(v_dim, 1) # 用于根据lstm状态计算输出 self.out_linear = paddle.nn.Linear(lstm_hidden_size, cn_vocab_size) # forward函数每次往前计算一次。整体的recurrent部分,是在训练循环内完成的。 def forward(self, x, previous_hidden, previous_cell, encoder_outputs): x = self.emb(x) # 对previous_hidden进行数据重排 hidden_transpose = paddle.transpose(previous_hidden, [1, 0, 2]) # attention输入:Decoder当前状态和Encoder所有状态 # 总共需计算encoder_outputs.shape[1]个权重(这是因为会在输入句子后面加上一个<eos>符号) attention_inputs = paddle.concat( (encoder_outputs, paddle.tile(hidden_transpose, repeat_times=[1, encoder_outputs.shape[1], 1])), axis=-1 ) attention_hidden = self.attention_linear1(attention_inputs) attention_hidden = F.tanh(attention_hidden) attention_logits = self.attention_linear2(attention_hidden) attention_logits = paddle.squeeze(attention_logits) # 计算得到所有encoder_outputs.shape[1]个权重 attention_weights = F.softmax(attention_logits) attention_weights = paddle.expand_as(paddle.unsqueeze(attention_weights, -1), encoder_outputs) # 计算Context Vector context_vector = paddle.multiply(encoder_outputs, attention_weights) context_vector = paddle.sum(context_vector, 1) context_vector = paddle.unsqueeze(context_vector, 1) lstm_input = paddle.concat((x, context_vector), axis=-1) x, (hidden, cell) = self.lstm(lstm_input, (previous_hidden, previous_cell)) output = self.out_linear(hidden) output = paddle.squeeze(output, axis=0) return output, (hidden, cell)
定义trian
函数,创建Encoder
和AttentionDecoder
对象,创建Adam
优化器,设定学习率和优化参数。
在每个epoch
内,随机打乱训练数据,在每个batch
内,通过多次调用atten_decoder
,实现解码时的recurrent
循环。在每次解码下一个词时,给定了训练数据当中的真实词作为了预测下一个词时的输入。
具体代码如下:
def train(train_en_sents, train_cn_sents, train_cn_label_sents, epochs, learning_rate, batch_size, en_vocab_size, en_embedding_dim, lstm_hidden_size, lstm_num_layers, cn_vocab_size, cn_embedding_dim, v_dim): encoder = Encoder(en_vocab_size, en_embedding_dim, lstm_hidden_size, lstm_num_layers) atten_decoder = AttentionDecoder(cn_vocab_size, cn_embedding_dim, lstm_hidden_size, v_dim) opt = paddle.optimizer.Adam(learning_rate=learning_rate, parameters=encoder.parameters()+atten_decoder.parameters()) for epoch in range(epochs): print("epoch:{}".format(epoch)) # 将训练数据集打乱 perm = np.random.permutation(len(train_en_sents)) train_en_sents_shuffled = train_en_sents[perm] train_cn_sents_shuffled = train_cn_sents[perm] train_cn_label_sents_shuffled = train_cn_label_sents[perm] for iteration in range(train_en_sents_shuffled.shape[0] // batch_size): # 获取一个batch的英文句子训练数据 x_data = train_en_sents_shuffled[(batch_size * iteration):(batch_size * (iteration + 1))] # 将数据转换成paddle内置tensor sent = paddle.to_tensor(x_data) # 经过encoder得到对输入数据的编码 en_repr, hidden, cell = encoder(sent) # 获取一个batch的对应的中文句子数据 x_cn_data = train_cn_sents_shuffled[(batch_size * iteration):(batch_size * (iteration + 1))] x_cn_label_data = train_cn_label_sents_shuffled[(batch_size * iteration):(batch_size * (iteration + 1))] # 损失 loss = paddle.zeros([1]) # 解码器循环,计算总损失 for i in range(MAX_LEN + 2): # 获得当前输入atten_decoder的输入元素及标签 cn_word = paddle.to_tensor(x_cn_data[:, i:i + 1]) cn_word_label = paddle.to_tensor(x_cn_label_data[:, i]) logits, (hidden, cell) = atten_decoder(cn_word, hidden, cell, en_repr) step_loss = F.cross_entropy(logits, cn_word_label) loss += step_loss # 计算平均损失 loss = loss / (MAX_LEN + 2) if iteration % 200 == 0: print("iter {}, loss:{}".format(iteration, loss.numpy())) # 后向传播 loss.backward() # 参数更新 opt.step() # 清除梯度 opt.clear_grad() # 训练完成保存模型参数 paddle.save(encoder.state_dict(), 'models/encoder.pdparams') paddle.save(atten_decoder.state_dict(), 'models/atten_decoder.pdparams')
调用create_dataset
函数生成训练数据。设置超参数epochs = 20
,batch_size = 64
,learning_rate = 0.001
,en_embedding_dim = 128
,cn_embedding_dim = 128
,lstm_hidden_size = 256
,lstm_num_layers = 1
以及v_dim = 256
,调用train
函数开启训练。代码如下:
if __name__ == '__main__': train_en_sents, train_cn_sents, train_cn_label_sents, en_vocab, cn_vocab = create_dataset('datasets/cmn.txt') # 设置超参数 epochs = 20 batch_size = 64 learning_rate = 0.001 en_vocab_size = len(en_vocab) cn_vocab_size = len(cn_vocab) en_embedding_dim = 128 cn_embedding_dim = 128 lstm_hidden_size = 256 lstm_num_layers = 1 v_dim = 256 start_time = time.time() train(train_en_sents, train_cn_sents, train_cn_label_sents, epochs, learning_rate, batch_size, en_vocab_size, en_embedding_dim, lstm_hidden_size, lstm_num_layers, cn_vocab_size, cn_embedding_dim, v_dim) finish_time = time.time() print('训练用时:{:.2f}分钟'.format((finish_time-start_time)/60.0))
使用GPU训练模型,用时共7.59分钟。如果使用CPU,预计训练所用时间至少翻一倍。其中训练过程打印的信息如下:
2.1.0 W0803 22:08:31.521724 16684 device_context.cc:404] Please NOTE: device: 0, GPU Compute Capability: 6.1, Driver API Version: 11.2, Runtime API Version: 10.1 W0803 22:08:31.536396 16684 device_context.cc:422] device: 0, cuDNN Version: 7.6. epoch:0 iter 0, loss:[8.066058] iter 200, loss:[3.3313792] epoch:1 iter 0, loss:[3.0832756] iter 200, loss:[2.9235165] epoch:2 iter 0, loss:[2.5026035] iter 200, loss:[2.6165113] epoch:3 iter 0, loss:[2.511048] iter 200, loss:[2.173079] epoch:4 iter 0, loss:[2.342031] iter 200, loss:[2.179213] epoch:5 iter 0, loss:[1.9800943] iter 200, loss:[1.9754598] epoch:6 iter 0, loss:[2.1824288] iter 200, loss:[2.0068507] epoch:7 iter 0, loss:[1.8755927] iter 200, loss:[1.7782102] epoch:8 iter 0, loss:[1.6492431] iter 200, loss:[1.7164807] epoch:9 iter 0, loss:[1.5739967] iter 200, loss:[1.5312105] epoch:10 iter 0, loss:[1.6726758] iter 200, loss:[1.5393445] epoch:11 iter 0, loss:[1.391438] iter 200, loss:[1.3156104] epoch:12 iter 0, loss:[1.328358] iter 200, loss:[1.0773911] epoch:13 iter 0, loss:[1.1689429] iter 200, loss:[1.2644379] epoch:14 iter 0, loss:[1.0560603] iter 200, loss:[1.1911696] epoch:15 iter 0, loss:[1.1562344] iter 200, loss:[1.0733411] epoch:16 iter 0, loss:[1.0015976] iter 200, loss:[0.9953356] epoch:17 iter 0, loss:[0.78453755] iter 200, loss:[1.0062006] epoch:18 iter 0, loss:[0.8454544] iter 200, loss:[1.0099177] epoch:19 iter 0, loss:[0.8389757] iter 200, loss:[0.74120027] 训练用时:7.59分钟
训练完成后,从训练集中随机抽取部分句子演示机器翻译效果。定义translate_test
函数,从训练集中随机抽取部分句子,经过encoder
编码,再使用atten_decoder
解码,并将结果输出。具体代码如下:
def translate_test(num_of_exampels_to_evaluate, encoder, atten_decoder, en_vocab, cn_vocab): """ 展示机器翻译效果,用训练集中部分数据查看机器的翻译的结果 :param num_of_exampels_to_evaluate: 指定从训练多少句子 :param encoder: 训练好的encoder :param atten_decoder: 训练好的atten_decoder :param en_vocab: 英文词汇表 :param cn_vocab: 中文词汇表 :return: None """ # 将模型设置为eval模式 encoder.eval() atten_decoder.eval() # 从训练数据中随机选择部分英语句子展示翻译效果 indices = np.random.choice(len(train_en_sents), num_of_exampels_to_evaluate, replace=False) x_data = train_en_sents[indices] sent = paddle.to_tensor(x_data) en_repr, hidden, cell = encoder(sent) # 获取随机选择到的英语句子和对应的中文翻译 en_vocab_list = list(en_vocab) cn_vocab_list = list(cn_vocab) en_sents = [] cn_sents = [] for i in range(num_of_exampels_to_evaluate): this_en_sents = [] this_cn_sents = [] for en_vocab_id in train_en_sents[indices[i]]: # 0,1,2是三个特殊符号的ID if en_vocab_id not in [0, 1, 2]: this_en_sents.append(en_vocab_list[en_vocab_id]) for cn_vocab_id in train_cn_sents[indices[i]]: if cn_vocab_id not in [0, 1, 2]: this_cn_sents.append(cn_vocab_list[cn_vocab_id]) en_sents.append(this_en_sents) cn_sents.append(this_cn_sents) # Decoder解码时输入的第一个符号为<bos> word = np.array([[cn_vocab['<bos>']]] * num_of_exampels_to_evaluate) word = paddle.to_tensor(word) decoded_sent = [] for i in range(MAX_LEN + 2): logits, (hidden, cell) = atten_decoder(word, hidden, cell, en_repr) word = paddle.argmax(logits, axis=1) decoded_sent.append(word.numpy()) word = paddle.unsqueeze(word, axis=-1) results = np.stack(decoded_sent, axis=1) for i in range(num_of_exampels_to_evaluate): en_input = " ".join(en_sents[i][:-1]) + en_sents[i][-1] ground_truth_translate = "".join(cn_sents[i][:-1]) + cn_sents[i][-1] model_translate = "" for k in results[i]: w = list(cn_vocab)[k] if w != '<pad>' and w != '<eos>': model_translate += w print(en_input) print("true: {}".format(ground_truth_translate)) print("pred: {}".format(model_translate))
创建encoder
和atten_decoder
对象,并加载训练好的模型参数,调用translate
函数查看机器翻译效果。具体代码如下:
# 用训练好的模型来预测
# 首先创建encoder和atten_decoder对象,并加载训练好的参数
encoder = Encoder(en_vocab_size, en_embedding_dim, lstm_hidden_size, lstm_num_layers)
atten_decoder = AttentionDecoder(cn_vocab_size, cn_embedding_dim, lstm_hidden_size, v_dim)
encoder_state_dict = paddle.load('models/encoder.pdparams')
atten_decoder_state_dict = paddle.load('models/atten_decoder.pdparams')
encoder.set_state_dict(encoder_state_dict)
atten_decoder.set_state_dict(atten_decoder_state_dict)
# 调用translate_test函数实现机器翻译——英译中
translate_test(10, encoder, atten_decoder, en_vocab, cn_vocab)
运行上述代码,打印如下结果:
one hundred years is called a century. true: 一百年被叫做一个世纪。 pred: 一个人都在10岁了。 how long would it take? true: 要多长时间? pred: 要多久? i m waiting for this store to open. true: 我正等著這家店開門。 pred: 我在等我去那裡。 why do you need this money? true: 你為什麼需要這筆錢? pred: 你為什麼需要这种錢? i m free now. true: 我现在有空了。 pred: 我现在有点了。 he said that it was nine o clock. true: 他说九点了。 pred: 他說他很快就了。 you ve got a lot of willpower. true: 你的意志力很強。 pred: 你的朋友很好。 i ve got something i want to show you. true: 我有东西想给你看看。 pred: 我有些事要我想要你。 that hurts. true: 真疼。 pred: 真疼。 the top of mt fuji was covered with snow. true: 富士山顶盖满了雪。 pred: 富士山被山顶盖了。
定义translate_self
函数,将输入的英文句子经过encoder
编码,再使用atten_decoder
解码,将输入的英文句子翻译成中文。具体代码如下:
def translate_self(encoder, atten_decoder, en_vocab, cn_vocab, max_translation_length, use_pad=True): """根据输入的英文句子,完成机器翻译——英译中 Tips: 1> 当前程序并未在训练数据中添加'<unk>',当输入语料中包含不在英文词表中的词,使用'<pad>'符号进行替换 Args: max_translation_length: 翻译的中文句子的最长长度,超过该长度直接截断 use_pad: 是否将输入的长度小于MAX_LEN的英文句子使用'<pad>'字符填充 True: 该模式会将输入的英文句子长度填充至MAX_LEN。由于训练时使用了'<pad>'字符填充,翻译效果会好很多 False: 不对输入的英文句子进行填充。该模式更贴近实际应用场景,但是在当前数据量下,效果预计会比较差 """ # 将模型设置为eval模式 encoder.eval() atten_decoder.eval() while True: input_en = input("Please enter the English sentence to be translated: ") print(f"Your English sentence: {input_en}") # 将英文句子转换成token words_re = re.compile(r'\w+') words_en = words_re.findall(input_en) if input_en[-1] in [".", "?", "!"]: words_en += [input_en[-1]] words_en += ["<eos>"] words_en = [word.lower() if word.lower() in en_vocab else "<pad>" for word in words_en] if use_pad and len(words_en) < MAX_LEN + 1: words_en += ["<pad>"] * (MAX_LEN - len(words_en) + 1) tokens_en = [[en_vocab[word] for word in words_en]] print(f"Sentence for translator: {' '.join(words_en)}") sent = paddle.to_tensor(tokens_en, dtype="int64") en_repr, hidden, cell = encoder(sent) # Decoder解码时输入的第一个符号为<bos> word = np.array([[cn_vocab['<bos>']]]) word = paddle.to_tensor(word) print("Translated Chinese sentences: ", end="") for i in range(max_translation_length): logits, (hidden, cell) = atten_decoder(word, hidden, cell, en_repr) word = paddle.argmax(logits, axis=1) word_id = word.numpy() if word_id != 2: print(list(cn_vocab)[int(word_id)], end="") else: break word = paddle.unsqueeze(word, axis=-1) print("\n==============================================")
调用translate_self
函数,输入英文句子,查看训练好的机器翻译模型效果:
# 调用translate_self函数,翻译自定义英文输入
translate_self(encoder, atten_decoder, en_vocab, cn_vocab, 25, use_pad=True)
运行上述代码,多次输入自定义英文句子,打印结果如下:
Please enter the English sentence to be translated: How old are you? Your English sentence: How old are you? Sentence for translator: how old are you ? <eos> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> Translated Chinese sentences: 你幾歲? ============================================== Please enter the English sentence to be translated: What's your name? Your English sentence: What's your name? Sentence for translator: what s your name ? <eos> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> Translated Chinese sentences: 你叫什么? ============================================== Please enter the English sentence to be translated: I love you forever. Your English sentence: I love you forever. Sentence for translator: i love you forever . <eos> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> Translated Chinese sentences: 我喜欢你们的第一。 ============================================== Please enter the English sentence to be translated: I'm fine, thanks. And you? Your English sentence: I'm fine, thanks. And you? Sentence for translator: i m fine thanks and you ? <eos> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> Translated Chinese sentences: 我又你的感覺,不是嗎? ============================================== Please enter the English sentence to be translated: Never give up! Your English sentence: Never give up! Sentence for translator: never give up ! <eos> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> <pad> Translated Chinese sentences: 别来。
本文着重综合NLP模型原理与应用系列内容,讲述机器翻译基本原理和深度学习实践流程,离产业化机器翻译模型还比较遥远。在工业界,主流使用BERT+Transform模型,而不是文本所采用的模型。同时工业训练神经网络翻译机,训练数据量级不可同日而语。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。