文章目录

  • 前言
  • 一、数据的预处理
  • 二、模型配置
    • 三.模型训练
  • 总结

前言

注意力机制是一种在深度学习中广泛使用的技术,它可以有效地处理输入序列和输出序列之间的对应关系。其中,Encoder-Decoder是一种常见的注意力机制,它主要用于序列到序列的任务,例如机器翻译、语音识别等。在Encoder-Decoder中,输入序列首先通过一个编码器进行编码,然后再通过一个解码器进行解码,最终生成输出序列。在这个过程中,注意力机制可以帮助模型更好地理解输入序列中的重要信息,并在生成输出序列的过程中更加准确地对其进行利用。由于其出色的性能和广泛的适用性,注意力机制的Encoder-Decoder已经成为自然语言处理和语音识别等领域中的重要技术之一。


要做一个中英互译的神经网络训练,我们需要有:
预:可供训练的数据集 数据集我已经上传数据集(免费)
1.数据的预处理
2.模型配置
3.模型训练
整个过程是在kaggle上进行的

一、数据的预处理

数据的预处理和有关数据集的简介,我上篇文章已经讲解,有需要的直接可以查阅机器翻译 深度学习预处理实战(中英文互译)一
在这里我直接附上代码:

import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from sklearn.model_selection import train_test_split
import unicodedata
import re
import numpy as np
import os
import io
import time
import pandas as pd
import numpy as np
import jieba
jieba.initialize() # 手动初始化jieba资源,提高分词效率。
jieba.enable_paddle() # 启动paddle模式。 0.40版之后开始支持,早期版本不支持# 判断是否包含中文
def is_chinese(string):"""检查整个字符串是否包含中文:param string: 需要检查的字符串:return: bool"""for ch in string:if u'\u4e00' <= ch <= u'\u9fa5':return Truereturn False# 中英文预处理
def preprocess_sentence(w):if not is_chinese(w):w = w.lower()# 除了 (a-z, A-Z, ".", "?", "!", ","),将所有字符替换为空格w = re.sub(r"[^a-zA-Z?.!,]+", " ", w)w = w.rstrip().strip()# 给句子加上开始和结束标记,以便模型知道每个句子开始和结束的位置w = '<start> ' + w + ' <end>'else:w = re.sub(r"[^\u4e00-\u9fa5,。?!]+", "", w)w = w.strip()# seg_list = jieba.cut(w,use_paddle=True) # 使用paddle模式分词# w=' '.join(list(seg_list))w = 分字(w)# 给句子加上开始和结束标记,以便模型知道每个句子开始和结束的位置w = '<start> ' + w + ' <end>'return wdef 分字(str):line = str.strip()pattern = re.compile('[^\u4e00-\u9fa5,。?!]')en = ' '.join(pattern.split(line)).strip()result=''for character in en:result+=character+' 'return result.strip()# 调用预处理方法,并返回这样格式的句子对:[english, chinese]
def create_dataset(path, num_examples):lines = io.open(path, encoding='UTF-8').read().strip().split('\n')word_pairs = [[preprocess_sentence(w) for w in l.split('\t')[0:2][::-1]] for l in lines[:num_examples]]return zip(*word_pairs)# 判断词序列长度
def max_length(tensor):return max(len(t) for t in tensor)# 词符化
def tokenize(lang):lang_tokenizer = tf.keras.preprocessing.text.Tokenizer(filters='')lang_tokenizer.fit_on_texts(lang)tensor = lang_tokenizer.texts_to_sequences(lang)tensor = tf.keras.preprocessing.sequence.pad_sequences(tensor,padding='post')return tensor, lang_tokenizer# 创建清理过的输入输出对
def load_dataset(path, num_examples=None):chs, en = create_dataset(path, num_examples)input_tensor, inp_lang_tokenizer = tokenize(en)target_tensor, targ_lang_tokenizer = tokenize(chs)return input_tensor, target_tensor, inp_lang_tokenizer, targ_lang_tokenizer# 格式化显示字典内容
def convert(lang, tensor):for t in tensor:if t!=0:print("%d ----> %s" % (t, lang.index_word[t]))if __name__=="__main__":num_examples = 100# 读取英中互译文件path_to_file = '/kaggle/input/tansantcmn/cmn.txt'input_tensor, target_tensor, inp_lang_tokenizer, targ_lang_tokenizer = load_dataset(path_to_file, num_examples)# 计算最大长度max_length_input, max_length_target = max_length(input_tensor), max_length(target_tensor)# 将数据集拆分为训练和验证集input_tensor_train, input_tensor_val, target_tensor_train, target_tensor_val = train_test_split(input_tensor, target_tensor, test_size=0.2)# 显示长度print("Max length of input:", max_length_input)print("Max length of target:", max_length_target)# 显示词典长度print("Input vocabulary size:", len(inp_lang_tokenizer.word_index))print("Target vocabulary size:", len(targ_lang_tokenizer.word_index))# 显示样例print("Example input sequence:")convert(inp_lang_tokenizer, input_tensor_train[0])print("Actual input sentence:")print(' '.join([inp_lang_tokenizer.index_word[i] for i in input_tensor_train[0] if i not in [0]]))print("\nExample target sequence:")convert(targ_lang_tokenizer, target_tensor_train[0])print("Actual target sentence:")print(' '.join([targ_lang_tokenizer.index_word[i] for i in target_tensor_train[0] if i not in [0]]))
print(len(input_tensor_train), len(target_tensor_train), len(input_tensor_val), len(target_tensor_val))# 显示编码后的源语言(中文)张量数据集示例
print('经过编码后的源语言(中文)张量数据集示例:')
print(input_tensor[:3])

先看运行结果

我们从数据集中随机抽取了一句话来进行翻译(grab tom.),可以看到翻译的结果(抓住汤姆)。此时效果还是不错的
我们这里是英译中的翻译,如果小伙伴想进行中译英,可以在(# 中英文预处理)函数中将not is_chinese(w):中的not去掉。
接下来我们来尝试使用注意力机制来进行深度学习训练

二、模型配置

要进行深度学习的训练,我们首先需要搭建模型
实现了一个基于注意力机制的Encoder-Decoder模型,
这里主要分为三个部分:
Encoder、
BahdanauAttention
Decoder。

Encoder部分
Encoder是一个继承自tf.keras.Model的类,用于对输入序列进行编码。其中,输入序列通过Embedding层进行嵌入后,再通过GRU层进行编码,最终输出编码器的编码结果和隐藏状态。

class Encoder(tf.keras.Model):def __init__(self, vocab_size, embedding_dim, enc_units, batch_sz):super(Encoder, self).__init__()self.batch_sz = batch_szself.enc_units = enc_unitsself.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)self.gru = tf.keras.layers.GRU(self.enc_units,return_sequences=True,return_state=True,recurrent_initializer='glorot_uniform')def call(self, x, hidden):x = self.embedding(x)output, state = self.gru(x, initial_state = hidden)return output, statedef initialize_hidden_state(self):return tf.zeros((self.batch_sz, self.enc_units))

BahdanauAttention
BahdanauAttention是一个继承自tf.keras.layers.Layer的类,用于计算注意力向量和注意力权重。其中,通过Dense层将解码器的隐状态和编码器的编码结果映射到同一维度,然后通过tanh函数和Dense层计算分数,再通过softmax函数计算注意力权重。最后,将注意力权重乘以编码器的编码结果得到注意力向量。

class BahdanauAttention(tf.keras.layers.Layer):def __init__(self, units):super(BahdanauAttention, self).__init__()self.W1 = tf.keras.layers.Dense(units)self.W2 = tf.keras.layers.Dense(units)self.V = tf.keras.layers.Dense(1)def call(self, query, values):# query为上次的GRU隐藏层,values为编码器的编码结果enc_output,隐藏层的形状 == (批大小,隐藏层大小)# hidden_with_time_axis 的形状 == (批大小,1,隐藏层大小)# 这样做是为了执行加法以计算分数  hidden_with_time_axis = tf.expand_dims(query, 1)# 分数的形状 == (批大小,最大长度,1)# 我们在最后一个轴上得到 1, 因为我们把分数应用于 self.V# 在应用 self.V 之前,张量的形状是(批大小,最大长度,单位)score = self.V(tf.nn.tanh(self.W1(values) + self.W2(hidden_with_time_axis)))# 注意力权重 (attention_weights) 的形状 == (批大小,最大长度,1)attention_weights = tf.nn.softmax(score, axis=1)# 上下文向量 (context_vector) 求和之后的形状 == (批大小,隐藏层大小)context_vector = attention_weights * values  # 使用注意力权重*编码器输出作为返回值,将来会作为解码器的输入context_vector = tf.reduce_sum(context_vector, axis=1)return context_vector, attention_weights

Decoder
Decoder是一个继承自tf.keras.Model的类,用于对输出序列进行解码。其中,输入序列通过Embedding层进行嵌入后,再通过GRU层进行解码。在解码器中,首先使用BahdanauAttention计算注意力向量和注意力权重,然后将解码器的输入和注意力向量拼接在一起,通过Dense层计算输出单词的概率分布,最终输出预测的概率分布、解码器的隐藏状态和注意力权重。

class Decoder(tf.keras.Model):def __init__(self, vocab_size, embedding_dim, dec_units, batch_sz):super(Decoder, self).__init__()self.batch_sz = batch_szself.dec_units = dec_unitsself.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)self.gru = tf.keras.layers.GRU(self.dec_units,return_sequences=True,return_state=True,recurrent_initializer='glorot_uniform')self.fc = tf.keras.layers.Dense(vocab_size)# 第一步,使用注意力机制self.attention = BahdanauAttention(self.dec_units)def call(self, x, hidden, enc_output):# 第二步,用解码器的隐状态和编码器输出得到注意力向量和注意力权重# 其中(enc_output) 的形状 == (批大小,最大长度,隐藏层大小)context_vector, attention_weights = self.attention(hidden, enc_output)#  在通过嵌入层后的形状 == (批大小,1,嵌入维度)x = self.embedding(x)# 第三步,使用解码器的输入与注意力向量拼接,用于计算输出单词的概率分布# x 在拼接 (concatenation) 后的形状 == (批大小,1,嵌入维度 + 隐藏层大小)x = tf.concat([tf.expand_dims(context_vector, 1), x], axis=-1)#第四步:得到解码器的隐藏状态,用于计算下一步的注意力向量# 将合并后的向量传送到 GRUoutput, state = self.gru(x)# 输出的形状 == (批大小 * 1,隐藏层大小)output = tf.reshape(output, (-1, output.shape[2]))# 输出的形状 == (批大小,词典大小)x = self.fc(output)# 第五步,把x(预测词的概率分布)state(解码器GRU的参数快照(隐状态)),attention_weights(注意力权重)返回给调用者return x, state, attention_weights

这里附上模型配置的完整代码

class Encoder(tf.keras.Model):def __init__(self, vocab_size, embedding_dim, enc_units, batch_sz):super(Encoder, self).__init__()self.batch_sz = batch_szself.enc_units = enc_unitsself.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)self.gru = tf.keras.layers.GRU(self.enc_units,return_sequences=True,return_state=True,recurrent_initializer='glorot_uniform')def call(self, x, hidden):x = self.embedding(x)output, state = self.gru(x, initial_state = hidden)return output, statedef initialize_hidden_state(self):return tf.zeros((self.batch_sz, self.enc_units))
class BahdanauAttention(tf.keras.layers.Layer):def __init__(self, units):super(BahdanauAttention, self).__init__()self.W1 = tf.keras.layers.Dense(units)self.W2 = tf.keras.layers.Dense(units)self.V = tf.keras.layers.Dense(1)def call(self, query, values):# query为上次的GRU隐藏层,values为编码器的编码结果enc_output,隐藏层的形状 == (批大小,隐藏层大小)# hidden_with_time_axis 的形状 == (批大小,1,隐藏层大小)# 这样做是为了执行加法以计算分数  hidden_with_time_axis = tf.expand_dims(query, 1)# 分数的形状 == (批大小,最大长度,1)# 我们在最后一个轴上得到 1, 因为我们把分数应用于 self.V# 在应用 self.V 之前,张量的形状是(批大小,最大长度,单位)score = self.V(tf.nn.tanh(self.W1(values) + self.W2(hidden_with_time_axis)))# 注意力权重 (attention_weights) 的形状 == (批大小,最大长度,1)attention_weights = tf.nn.softmax(score, axis=1)# 上下文向量 (context_vector) 求和之后的形状 == (批大小,隐藏层大小)context_vector = attention_weights * values  # 使用注意力权重*编码器输出作为返回值,将来会作为解码器的输入context_vector = tf.reduce_sum(context_vector, axis=1)return context_vector, attention_weights
class Decoder(tf.keras.Model):def __init__(self, vocab_size, embedding_dim, dec_units, batch_sz):super(Decoder, self).__init__()self.batch_sz = batch_szself.dec_units = dec_unitsself.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)self.gru = tf.keras.layers.GRU(self.dec_units,return_sequences=True,return_state=True,recurrent_initializer='glorot_uniform')self.fc = tf.keras.layers.Dense(vocab_size)# 第一步,使用注意力机制self.attention = BahdanauAttention(self.dec_units)def call(self, x, hidden, enc_output):# 第二步,用解码器的隐状态和编码器输出得到注意力向量和注意力权重# 其中(enc_output) 的形状 == (批大小,最大长度,隐藏层大小)context_vector, attention_weights = self.attention(hidden, enc_output)#  在通过嵌入层后的形状 == (批大小,1,嵌入维度)x = self.embedding(x)# 第三步,使用解码器的输入与注意力向量拼接,用于计算输出单词的概率分布# x 在拼接 (concatenation) 后的形状 == (批大小,1,嵌入维度 + 隐藏层大小)x = tf.concat([tf.expand_dims(context_vector, 1), x], axis=-1)#第四步:得到解码器的隐藏状态,用于计算下一步的注意力向量# 将合并后的向量传送到 GRUoutput, state = self.gru(x)# 输出的形状 == (批大小 * 1,隐藏层大小)output = tf.reshape(output, (-1, output.shape[2]))# 输出的形状 == (批大小,词典大小)x = self.fc(output)# 第五步,把x(预测词的概率分布)state(解码器GRU的参数快照(隐状态)),attention_weights(注意力权重)返回给调用者return x, state, attention_weights
num_examples = 5000
BATCH_SIZE = 64
embedding_dim = 256
units = 1024
path_to_file = '/kaggle/input/tansantcmn/cmn.txt'
input_tensor, target_tensor, inp_lang, targ_lang = load_dataset(path_to_file, num_examples)
max_length_targ, max_length_inp = max_length(target_tensor),max_length(input_tensor)
input_tensor_train, input_tensor_val, target_tensor_train, target_tensor_val = train_test_split(input_tensor, target_tensor, test_size=0.2)
BUFFER_SIZE = len(input_tensor_train)steps_per_epoch = len(input_tensor_train)//BATCH_SIZEvocab_inp_size = len(inp_lang.word_index)+1
vocab_tar_size = len(targ_lang.word_index)+1
dataset = tf.data.Dataset.from_tensor_slices((input_tensor_train, target_tensor_train)).shuffle(BUFFER_SIZE)
dataset = dataset.batch(BATCH_SIZE, drop_remainder=True)
encoder = Encoder(vocab_inp_size, embedding_dim, units, BATCH_SIZE)
example_input_batch, example_target_batch = next(iter(dataset))
# 样本输入
sample_hidden = encoder.initialize_hidden_state()
sample_output, sample_hidden = encoder(example_input_batch, sample_hidden)
print ('Encoder(编码器层) 输出层参数: (一次训练所选取的样本数, 句子长度, 神经元数量) {}'.format(sample_output.shape))
print ('Encoder(编码器层) 隐藏层参数: (一次训练所选取的样本数, 神经元数量) {}'.format(sample_hidden.shape))
attention_layer = BahdanauAttention(10)
attention_result, attention_weights = attention_layer(sample_hidden, sample_output)
print("Attention(注意力层) 输出层参数: (一次训练所选取的样本数, 神经元数量) {}".format(attention_result.shape))
print("Attention(注意力层) 权值参数: (一次训练所选取的样本数, 句子长度, 1) {}".format(attention_weights.shape))
decoder = Decoder(vocab_tar_size, embedding_dim, units, BATCH_SIZE)
sample_decoder_output, _, _ = decoder(tf.random.uniform((64, 1)),sample_hidden, sample_output)
print ('Decoder(解码器层) 输出层参数: (一次训练所选取的样本数, 字典大小) {}'.format(sample_decoder_output.shape))

在看一下我们模型设置的参数

大家可以进行微调,本人尝试过,效果影响不大。

三.模型训练

接下来有了模型,我们就可以进行训练了
简单来说训练注意力机制神经网络的步骤为:

  1. 定义编码器-解码器模型架构,其中编码器用于将输入序列编码成一个固定长度的向量,解码器用于生成输出序列。
    2.定义一个注意力机制,用于在每个时间步根据编码器的输出和解码器的当前状态,计算一个上下文向量,该向量可以提供给解码器作为额外的信息用于生成输出序列。
    3在训练过程中,对于每个时间步,首先通过编码器获得输入序列的编码结果,然后将该编码结果和解码器的当前状态作为注意力机制的输入,得到上下文向量,将上下文向量和解码器的当前输入拼接在一起,通过解码器生成输出序列的概率分布。
    4.定义损失函数,通常使用交叉熵损失函数或者自定义损失函数,用于评估模型输出和真实输出之间的差距。
    5.使用反向传播算法计算梯度,并使用优化算法更新模型参数,使得损失函数最小化。
    6.在测试过程中,对于每个输入序列,使用训练好的模型预测输出序列,得到最终的结果。
    完整代码:
num_examples = 20000
path_to_file = '/kaggle/input/tansantcmn/cmn.txt'
BATCH_SIZE = 70
input_tensor, target_tensor, inp_lang, targ_lang = load_dataset(path_to_file, num_examples)
max_length_targ, max_length_inp = max_length(target_tensor),max_length(input_tensor)
input_tensor_train, input_tensor_val, target_tensor_train, target_tensor_val = train_test_split(input_tensor, target_tensor, test_size=0.2)
BUFFER_SIZE = len(input_tensor_train)
steps_per_epoch = len(input_tensor_train)//BATCH_SIZE
EPOCHS = 15
embedding_dim = 256
units = 1024
vocab_inp_size = len(inp_lang.word_index)+1
vocab_tar_size = len(targ_lang.word_index)+1
dataset = tf.data.Dataset.from_tensor_slices((input_tensor_train, target_tensor_train)).shuffle(BUFFER_SIZE)
dataset = dataset.batch(BATCH_SIZE, drop_remainder=True)
encoder = Encoder(vocab_inp_size, embedding_dim, units, BATCH_SIZE)
attention_layer = BahdanauAttention(10)
decoder = Decoder(vocab_tar_size, embedding_dim, units, BATCH_SIZE)
optimizer = tf.keras.optimizers.Adam()
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True, reduction='none')
#定义优化器和损失函数
def loss_function(real, pred):mask = tf.math.logical_not(tf.math.equal(real, 0))loss_ = loss_object(real, pred)mask = tf.cast(mask, dtype=loss_.dtype)loss_ *= maskreturn tf.reduce_mean(loss_)
#定义保存点
checkpoint_dir = './training_checkpoints'
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")
checkpoint = tf.train.Checkpoint(optimizer=optimizer,encoder=encoder,decoder=decoder)
#TensorFlow 2.0引入的eager提高了代码的简洁性,但是性能略有损失。所以我们这里使用 @tf.function可以将eager模式转为高效的Graph模式,提高计算性能。
@tf.function
#定义一次训练中所要进行的工作:
def train_step(inp, targ, enc_hidden):#把损失初始化为0loss = 0with tf.GradientTape() as tape:# 把源语言(中文)输入编码器,并获得编码器的输出结果enc_output, enc_hidden = encoder(inp, enc_hidden)# 把编码器隐藏层数值,赋予解码器隐藏层,参与第一次的注意力计算dec_hidden = enc_hiddendec_input = tf.expand_dims([targ_lang.word_index['<start>']] * BATCH_SIZE, 1)#  循环目标句子中所有的词,将目标词作为下一个输入for t in range(1, targ.shape[1]):# 使用本单词、解码器的隐藏层、编码器的输出共同预测下一个单词。同时保留本次的解码器隐藏层,用于预测下一个词。predictions, dec_hidden, _ = decoder(dec_input, dec_hidden, enc_output)# 计算损失值,并累加。loss += loss_function(targ[:, t], predictions)# 使用teach_forcing# teach_forcing指的是,在训练时,每次解码器的输入并不是上次解码器的输出,而是样本目标语言对应单词。dec_input = tf.expand_dims(targ[:, t], 1)batch_loss = (loss / int(targ.shape[1]))# 需要训练参数是编码器的参数和解码的参数variables = encoder.trainable_variables + decoder.trainable_variables# 根据代价值计算下一次的参量值gradients = tape.gradient(loss, variables)# 将新的参量应用到模型optimizer.apply_gradients(zip(gradients, variables))return batch_lossdef evaluate(sentence):# 清空注意力图attention_plot = np.zeros((max_length_targ, max_length_inp))# 句子预处理sentence = preprocess_sentence(sentence)print(sentence)# 句子数字化inputs = [inp_lang.word_index[i] for i in sentence.split(' ')]# 按照最长句子长度补齐inputs = tf.keras.preprocessing.sequence.pad_sequences([inputs],maxlen=max_length_inp,padding='post')inputs = tf.convert_to_tensor(inputs)result = ''# 句子做编码hidden = [tf.zeros((1, units))]enc_out, enc_hidden = encoder(inputs, hidden)# 编码器隐藏层作为第一次解码器的隐藏层值dec_hidden = enc_hiddendec_input = tf.expand_dims([targ_lang.word_index['<start>']], 0)# 假设翻译结果不超过最长的样本句子for t in range(max_length_targ):# 逐个单词翻译predictions, dec_hidden, attention_weights = decoder(dec_input,dec_hidden,enc_out)# 存储注意力权重以便后面制图attention_weights = tf.reshape(attention_weights, (-1, ))attention_plot[t] = attention_weights.numpy()# 得到预测单词的字典编号predicted_id = tf.argmax(predictions[0]).numpy()# 从字典查到对应单词,用空格作分隔,与上一次结果进行拼接,组成翻译后的句子。result += targ_lang.index_word[predicted_id] + ' '# 如果是<end>表示翻译结束if targ_lang.index_word[predicted_id] == '<end>':return result, sentence, attention_plot# 预测的 ID 被保存起来,参与下一次预测。dec_input = tf.expand_dims([predicted_id], 0)return result, sentence, attention_plot
# 注意力权重制图函数
def plot_attention(attention, sentence, predicted_sentence):fig = plt.figure(figsize=(10,10))ax = fig.add_subplot(1, 1, 1)ax.matshow(attention, cmap='viridis')fontdict = {'fontsize': 14}ax.set_xticklabels([''] + sentence, fontdict=fontdict, rotation=90)ax.set_yticklabels([''] + predicted_sentence, fontdict=fontdict)ax.xaxis.set_major_locator(ticker.MultipleLocator(1))ax.yaxis.set_major_locator(ticker.MultipleLocator(1))plt.show()
#翻译一个句子。
def translate(sentence):result, sentence, attention_plot = evaluate(sentence)print('Input: %s' % (sentence))print('Predicted translation: {}'.format(result))attention_plot = attention_plot[:len(result.split(' ')), :len(sentence.split(' '))]plot_attention(attention_plot, sentence.split(' '), result.split(' '))if __name__=="__main__":# checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))for epoch in range(EPOCHS):start = time.time()# 初始化隐藏层和损失值enc_hidden = encoder.initialize_hidden_state()total_loss = 0# 一个批次的训练for (batch, (inp, targ)) in enumerate(dataset.take(steps_per_epoch)):
#            print("targ") 演示目标值张量,暂时注释掉
#            print(targ) 演示目标值张量,暂时注释掉batch_loss = train_step(inp, targ, enc_hidden)total_loss += batch_loss# 每100次显示一下模型损失值if batch % 100 == 0:print('Epoch {} Batch {} Loss {:.4f}'.format(epoch + 1,batch,batch_loss.numpy()))# 每 2 个周期(epoch),保存(检查点)一次模型if (epoch + 1) % 2 == 0:checkpoint.save(file_prefix = checkpoint_prefix)# 显示每次迭代的损失值和消耗时间print('Epoch {} Loss {:.4f}'.format(epoch + 1,total_loss / steps_per_epoch))print('Time taken for 1 epoch {} sec\n'.format(time.time() - start))#恢复检查点目录 (checkpoint_dir) 中最新的检查点checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))translate('book')

这里要说的是训练的epoch尽量在50个以上,否则效果不是很明显。
比如这里我训练了15个epoch loss=0.0928

可以看到把(book)翻译为了(在读书)

这个是我训练了30个epoch loss=0.02

同样是翻译 a book 结果居然出了繁体字 哈哈哈!


总结

当训练epoch在60个左右时,可以发现训练的效果有显著的提高,但还是会存在有测试翻译错误的现象,这里可能是因为所给的数据集只有13444条,数据太少的缘故,所以大家可以去换一个数据集。在文章中给的代码是英译中,只需要将预处理函数 if not is_chinese(w):中的not去掉,就可以为中译英了。
如果文章中有错误,欢迎读者指出共同进步。

机器翻译:引入注意力机制的Encoder-Decoder深度神经网络训练实战中英文互译(完结篇)相关推荐

  1. HAN:基于双层注意力机制的异质图深度神经网络

    「论文访谈间」是由 PaperWeekly 和中国中文信息学会社会媒体处理专委会(SMP)联合发起的论文报道栏目,旨在让国内优质论文得到更多关注和认可. 图神经网络是近年来图数据挖掘领域的热门研究方向 ...

  2. 在RNN模型中引入注意力机制(Attention)

    此前的文章介绍过Seq2seq模型,并将其用于机器翻译.Seq2seq模型的一个问题在于随着输入句子越来越长,更早输入的单词就很大可能会被忘掉.于是,随着输入句子中单词数变多,翻译质量就会很快劣化.改 ...

  3. 推荐系统CTR预估学习路线:引入注意力机制

    推荐系统CTR预估学习路线:从LR到FM/FFM探索二阶特征的高效实现 推荐系统CTR预估学习路线:利用树模型自动化特征工程 推荐系统CTR预估学习路线:深度模型 推荐系统CTR预估学习路线:引入注意 ...

  4. 注意力机制+软阈值化 = 深度残差收缩网络(Deep Residual Shrinkage Network)

    目录 1. 相关基础 1.1 残差网络 1.2 软阈值化 1.3 注意力机制 2. 深度残差收缩网络理论 2.1 动机 2.2 算法实现 2.3 优势 结论 顾名思义,深度残差收缩网络是由" ...

  5. 论文浅尝 | ​ADRL:一个基于注意力机制的知识图谱深度强化学习框架

    论文笔记整理:谭亦鸣,东南大学博士. 来源:Knowledge-Based Systems 197 (2020) 105910 链接:https://www.sciencedirect.com/sci ...

  6. 用注意力机制实现中英文互译

    用注意力机制实现中英文互译 [KEY: > input, = target, < output] il est en train de peindre un tableau . = he ...

  7. 不仅搞定“梯度消失”,还让CNN更具泛化性:港科大开源深度神经网络训练新方法

    原文链接:不仅搞定"梯度消失",还让CNN更具泛化性:港科大开源深度神经网络训练新方法 paper: https://arxiv.org/abs/2003.10739 code: ...

  8. 深度学习(二)---深度神经网络训练三部曲

    就像修炼武功一样,都有武林秘籍,按照步骤一步一步修炼,练好基础,然后再举一反三,最终就可修炼绝世武功.在深度学习领域进行学习的过程中也是一样,先把基础功训练扎实,深入理解原理及步骤,后面不管是各种算法 ...

  9. 【笔记3-7】CS224N课程笔记 - 神经网络机器翻译seq2seq注意力机制

    CS224N(七)Neural Machine Translation, Seq2seq and Attention seq2seq神经网络机器翻译 历史方法 seq2seq基础 seq2seq - ...

最新文章

  1. html dom createevent,js 中 document.createEvent的用法
  2. JSDoc --JS API文档生成器
  3. view技术简单了解
  4. MySQL-5.5.33主从复制
  5. 烟台大学计算机与控制工程学院研究生导师,烟台大学计算机与控制工程学院欢迎大家...
  6. Spring boot与Quartz实现任务定时提醒
  7. 下班前网上搜集的方法哈哈
  8. python TCP通信,主从服务设计(通过json进行数据通信)
  9. java if case when_【SQL学习笔记4】case when 和if的用法
  10. Can't open /dev/sdb1 exclusively. Mounted filesystem?
  11. MyEclipse 使用教程
  12. ubuntu下载BT种子安装qBittorrent
  13. replaceAll()如何同时替换多个不同的字符串(或多个符号)
  14. C语言之用循环来打印各种各样的图案
  15. C++Programming Guidelines
  16. Monte Carlo Counterfactual Regret Minimization
  17. matlab 方差计算
  18. placement new 讲解
  19. 路由器静态路由配置及连通性测试
  20. 数组_二维数组的初始化方式

热门文章

  1. windows的powershell讲解
  2. Eureka服务治理 - 自我保护机制
  3. 语言争霸VS魔兽争霸 :: IT世界VS魔兽世界
  4. 【RPG Maker MZ】独立游戏制作日志①
  5. 某数字藏品监控网站HMAC
  6. 安装office2010后桌面右键“共享文件夹同步”怎么删除?
  7. html手机打不开是什么,手机打不开路由器网址_手机打不开路由器设置页面怎么办? - 192路由网...
  8. 中M22春C、Java入门练习-7.11
  9. iOS 图标、图形尺寸?
  10. 腾讯关闭游戏币回兑Q币 Q币疯狂交易受到冲击