45 深度学习(九):transformer

news2024/11/20 18:43:54

文章目录

  • transformer
    • 原理
    • 代码的基础准备
    • 位置编码
    • Encoder block
      • multi-head attention
      • Feed Forward
      • 自定义encoder block
    • Deconder block
    • Encoder
    • Decoder
    • transformer
    • 自定义loss 和 学习率
    • mask生成函数
    • 训练
    • 翻译

transformer

这边讲一下这几年如日中天的新的seq2seq模式的transformer,这个模型解决了RNN训练时不能并行训练的慢,提出了self-attention机制,并关注到了注意力机制,也为之后的发展引领了新的时尚。

原理

我们首先看一下transformer这个的结构图,然后根据这个结构图进行实现代码

在这里插入图片描述

代码的基础准备

import numpy as np
import pandas as pd
import tensorflow as tf
import unicodedata
import re
from sklearn.model_selection import train_test_split
# 数据处理,主要和业务相关,当工作的时候绝大多数也就是将业务和代码相连接,这是十分重要的
# -----------------------------------------------------------------------------
# 数据预处理 去除重读的因子 和带空格以及特殊标点符号的东西
def preprocess_sentence(i):
  # NFD是转换方法,把每一个字节拆开,Mn是重音,所以去除
  i = ''.join(c for c in unicodedata.normalize('NFD',i) if unicodedata.category(c)!='Mn')
  # 把英文或者西班牙文变成纯小写,翻译与大写小写无关,降低影响,并且去掉头尾的空格
  i = i.lower().strip()
  # 在单词与跟在其后的标点符号之间插入一个空格
  i = re.sub(r"([?.!,¿])", r" \1 ", i)
  # 因为可能有多余空格,所以处理一下
  i = re.sub(r'[" "]+', " ", i)
  # 除了 (a-z, A-Z, ".", "?", "!", ","),将所有字符替换为空格
  i = re.sub(r"[^a-zA-Z?.!,¿]+", " ", i)
  i = i.rstrip().strip()
  i = '<start> ' + i + ' <end>'
  return i

def load_dataset(path, num_examples):
  # lines就是读取之后的每一行的数据列表
  lines = open(path, encoding='UTF-8').read().strip().split('\n')
  # i就是一个样本,一个英文样本或者一个西班牙的样本
  word_pairs = [[preprocess_sentence(i) for i in line.split('\t')]for line in lines[:num_examples]]
  # 我们这边想要拿英文翻译成西班牙文,而我们查看data当中发现英语在左侧 西班牙语在右侧,所以英语左边应该是input
  inputs,targets =zip(*word_pairs)
  # Tokenizer帮我们把词语式的转换为id式的,filters是黑名单 英语和西班牙语的需要额外自己分别训练
  inputs_tokenizer = tf.keras.preprocessing.text.Tokenizer(filters='')
  targets_tokenizer = tf.keras.preprocessing.text.Tokenizer(filters='')
  # 训练词袋
  inputs_tokenizer.fit_on_texts(inputs)
  targets_tokenizer.fit_on_texts(targets)
  # 把英文或西班牙文转化为数字 sparse
  inputs_tensor = inputs_tokenizer.texts_to_sequences(inputs)
  targets_tensor = targets_tokenizer.texts_to_sequences(targets)
  # 还需要补长或者截断 没有maxlen 就是自动取最长的进行补0
  inputs_tensor = tf.keras.preprocessing.sequence.pad_sequences(inputs_tensor, padding='post')
  targets_tensor = tf.keras.preprocessing.sequence.pad_sequences(targets_tensor, padding='post')
  return inputs_tensor, targets_tensor, inputs_tokenizer, targets_tokenizer

data_path = './data_spa_en/spa.txt'
# 需要训练的数据量 这边取全部,如果觉得训练太久,这边就选小一点
num_examples = 118964
# inp_lang targ_lang 是tokenizer
input_tensor, target_tensor, input_tokenizer, target_tokenizer = load_dataset(data_path, num_examples)
# 这边就不定义测试集了,对于nlp领域来说准确性一般没有什么作用
input_tensor_train, input_tensor_val, target_tensor_train, target_tensor_val = train_test_split(input_tensor, target_tensor, test_size=0.2)
batch_size = 64
embedding_dim = 256
units = 1024
# 训练集
dataset = tf.data.Dataset.from_tensor_slices((input_tensor_train,target_tensor_train)).shuffle(len(input_tensor_train))
dataset = dataset.batch(batch_size,drop_remainder=True)

max_input_length = max(len(t) for t in input_tensor)
max_target_length = max(len(t) for t in target_tensor)
input_tokenizer_length = len(input_tokenizer.word_index)
target_tokenizer_length = len(target_tokenizer.word_index)
# -----------------------------------------------------------------------------

这个和之前的那个seq2seq的实现是完全一致的,这边就不细说。

位置编码

在这里插入图片描述

然后我们先实现的是这个位置编码这一部分,首先我们知道的是,我们的inputs的输入会先经过embedding层形状变成(batch-size,num-steps,embedding-dim),然后我们需要加上一个关于位置的矩阵,这个位置矩阵,包含着就是位置的信息,我们这边采用比较常见的sin-cos的方法去构建:
在这里插入图片描述
pos的意思就是一句话当中的第几个字,而i代表的就是这个字我们不是经过了embedding之后的第几个维度,也就对应着我们上面的那个输入经过了embedding之后的形状,而这个位置编码实际上就是为了满足让后面的元素和前面的元素相构成关系,也就是前面几个元素的关系和可以推出下一个元素,这样的道理。

具体的数学证明见下:
在这里插入图片描述
这边就不细说了,这还是很简单的。

理解了上面,关于如何提取出位置编码,这边就需要有相关的小技巧,我们使用切片的方式进行进行调整。

# 这一步完成的是位置编码
# -----------------------------------------------------------------------------
# # PE(pos, 2i)   = sin(pos / 10000^(2i/d_model))
# # PE(pos, 2i+1)  = cos(pos / 10000^(2i/d_model))
def get_position_embedding(sentence_length, d_model):
  # sentense_length就是句子的长度num-step d_model就是embedding_dim
  # 首先我们知道位置编码生成之后需要和外面的embedding后的数据进行相加 形成带有位置信息的数据
  # 而外面的embedding的data的形状是(batch-size,num-step,embedding-dim)
  # 所以相对应的生成就可以得到

  # 先根据公式来写 pos就是对应的哪一个字 i对应的就是第几个embedding-dim dmodel就是embedding-dim
  # pos先不考虑batch-size那一维度,先扩展维度,从(num-step)变成(num-step,1)
  pos = np.arange(sentence_length).reshape(-1,1)
  i = np.arange(d_model).reshape(1,-1)
  x = pos / np.power(10000,(2 * (i // 2)) / np.float32(d_model))
  # 利用切片得到相对应的sin 和 cos
  sinx = np.sin(x[:, 0::2])
  cosx = np.cos(x[:, 1::2])
  # 凑成sin cos sin cos 的格式
  position_embedding = np.zeros((sentence_length,d_model))
  position_embedding[:, 0::2] = sinx
  position_embedding[:, 1::2] = cosx
  # 最后就是维度扩展,方便后续的相加
  position_embedding = position_embedding.reshape(1,sentence_length,d_model)
  return tf.cast(position_embedding, dtype=tf.float32)

position_embedding = get_position_embedding(5, 4)
print(position_embedding.shape)
print(position_embedding)
# -----------------------------------------------------------------------------

当然也可以封装到一个类当中,这边你们可以自己去实现一下

然后关于评价一下这个位置编码,我们这边使用绘制热力图进行展示:

import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline

# 评估位置编码
# -----------------------------------------------------------------------------
position_embedding = get_position_embedding(50, 256)
print(position_embedding.shape)
print(position_embedding)
def plot_position_embedding(position_embedding):
  plt.pcolormesh(position_embedding[0], cmap = 'RdBu')
  plt.xlabel('Depth')
  plt.xlim((0, 256))
  plt.ylabel('Position')
  plt.colorbar()
  plt.show()
# -----------------------------------------------------------------------------
plot_position_embedding(position_embedding)

输出:

(1, 50, 256)
图片1

图片1:
在这里插入图片描述
我们可以发现对于每一个字来说他的对应的值都是不一样的,这就很有效,不过对于sin cos 这种方式的实现来说,我们取的embedding的大小还会导致位置编码是否有效,这需要作为参数方程进行查看。

Encoder block

原理图:
在这里插入图片描述

multi-head attention

首先需要实现就是这个多头注意力机制,multi-head attention:

先看一下self-attention的数学实现方式:
在这里插入图片描述
在这里插入图片描述
总结:
在这里插入图片描述
而关于多头就是实现几次的样式:
在这里插入图片描述
这边的原理讲解有点复杂,之后会另开专栏进行讲解,这边理解数学即可,只需要理解我们这边的注意力机制计算的是我们的输入的词语与词语之间的关系。

# 多头注意力的实现
# -----------------------------------------------------------------------------
# 定义多头注意力机制
class MultiHeadAttention(keras.layers.Layer):
  def __init__(self,d_model,num_heads):
    super().__init__()
    self.d_model = d_model
    self.num_heads = num_heads
    self.WQ = keras.layers.Dense(self.d_model)
    self.WK = keras.layers.Dense(self.d_model)
    self.WV = keras.layers.Dense(self.d_model)
    self.dense = keras.layers.Dense(self.d_model)

    # 这边下面就需要进行分头计算 为了让头变多的同时 计算代价和参数代价不会随之增长,这边采用除法的操作
    assert self.d_model % self.num_heads == 0
    self.depth = self.d_model // self.num_heads


  def call(self,q,k,v,mask):
    # 输入的input实际上是embedding之后加上位置编码之后的数据,形状就是(batch-size,step-nums,embedding-dim)
    # 首先就是先生成q,k,v
    q = self.WQ(q)
    k = self.WK(k)
    v = self.WV(v)

    # 这边进行分头 然后已知qkv的形状是(batch-size,step-nums,d_model)
    # 然后将其形状都变成(batch-size,nums-head,step-nums,depth),也就是由于batch-size和step-num都有其含义,这边我们不能进行拆解,所以就把d_model拆解成一个代表第几个头 一个代表的就是参数
    # 而为什么需要拆解成(batch-size,nums-head,step-nums,depth) 而不是(batch-size,step-nums,nums-head,depth)
    # 原因就是我们后面的计算明显是要用相同的nums-head的情况下去运算,这样子方便
    # 还有这边需要使用轴滚动 不能直接使用reshape直接进行调换形状 二者的原理不一样
    q = tf.reshape(q,(tf.shape(q)[0],-1,self.num_heads,self.depth))
    q = tf.transpose(q,[0,2,1,3])
    k = tf.reshape(k, (tf.shape(k)[0], -1, self.num_heads, self.depth))
    k = tf.transpose(k, [0, 2, 1, 3])
    v = tf.reshape(v, (tf.shape(q)[0], -1, self.num_heads, self.depth))
    v = tf.transpose(v, [0, 2, 1, 3])

    # 开始计算缩放点积运算 此时q k 的形状(batch-size,nums-head,step-nums,depth)
    # 计算得到的Matrix_kq形状就是(batch-size,nums-head,step-nums,step-nums)
    Matrix_kq = tf.matmul(q,k,adjoint_b=True)
    if mask is not None:
      # 带有mask多头的注意力机制 后面再来解析
      Matrix_kq += (mask * (-1e9))

    # 然后这边两个数据相乘之后,数据太大了,这边可以做一个softmax 你用relu也可以
    # 不过需要注意的是,我们需要对于行做softmax,取决于我们对于k的理解
    Matrix_kq = tf.nn.softmax(Matrix_kq,axis=-1)
    output = tf.transpose(tf.matmul(Matrix_kq, v),[0,2,1,3])

    # 再对于注意力机制进行合并 生成的数据就是(batch-size,nums-step,d_model)的数据
    output = tf.reshape(output,(tf.shape(output)[0],-1,self.d_model))
    return output
# -----------------------------------------------------------------------------

Feed Forward

前馈网络:实际上就是两层全连接层,这边就只给出代码了

# 前馈网络
# -----------------------------------------------------------------------------
class FeedForward(keras.layers.Layer):
  def __init__(self,d_model, dim):
    super().__init__()
    self.dense1 = keras.layers.Dense(dim,activation='relu')
    self.dense2 = keras.layers.Dense(d_model)
  def call(self,x):
    return self.dense2(self.dense1(x))
# -----------------------------------------------------------------------------

自定义encoder block

在这里插入图片描述

# 自定义encoder block
# -----------------------------------------------------------------------------
class EncoderBlock(keras.layers.Layer):
  def __init__(self,d_model, num_heads, feed_dim, rate=0.1):
    super().__init__()
    self.attention = MultiHeadAttention(d_model,num_heads)
    self.feed = FeedForward(d_model, feed_dim)
    # 做的是layer的标准化和之前采用的batch标准化不一样,batch针对的是不同特征的,layer针对的是相同特征的
    self.layer_norm1 = keras.layers.LayerNormalization(epsilon=1e-6)
    self.layer_norm2 = keras.layers.LayerNormalization(epsilon=1e-6)
    # 下面两个层次用了做dropout,每次有10%的几率被drop掉
    self.dropout1 = keras.layers.Dropout(rate)
    self.dropout2 = keras.layers.Dropout(rate)

  def call(self,x,training,encoding_padding_mask):
    # x代表的就是训练的数据
    # training代表的是是否对于train状态下进行dropout,填入的是true or false
    # encoding_padding_mask代表的是将padding标识为不重要,避免注意力机制去关心那一块
    out1 = self.attention(x,x,x, encoding_padding_mask)
    out1 = self.dropout1(out1, training=training)
    # Resnet相加 很重要
    x = self.layer_norm1(x+out1)

    out2 = self.feed(x)
    out2 = self.dropout2(out2, training=training)
    output = self.layer_norm2(x+out2)
    return output
# -----------------------------------------------------------------------------
#来测试,结果和我们最初的输入维度一致,相当于做了两次残差连接
sample_encoder_layer = EncoderBlock(512, 8, 2048)
sample_input = tf.random.uniform((64, 50, 512))
sample_output = sample_encoder_layer(sample_input, False, None)
print(sample_output.shape)

Deconder block

在这里插入图片描述
代码见下:

# 自定义decoder block
# -----------------------------------------------------------------------------
class DecoderBlock(keras.layers.Layer):
  def __init__(self,d_model, num_heads, feed_dim, rate = 0.1):
    super().__init__()
    self.attention1 = MultiHeadAttention(d_model, num_heads)
    self.attention2 = MultiHeadAttention(d_model, num_heads)
    self.feed = FeedForward(d_model, feed_dim)
    self.layer_norm1 = keras.layers.LayerNormalization(epsilon=1e-6)
    self.layer_norm2 = keras.layers.LayerNormalization(epsilon=1e-6)
    self.layer_norm3 = keras.layers.LayerNormalization(epsilon=1e-6)
    self.dropout1 = keras.layers.Dropout(rate)
    self.dropout2 = keras.layers.Dropout(rate)
    self.dropout3 = keras.layers.Dropout(rate)

  def call(self, x, encoding_outputs, training, decoder_mask, encoder_decoder_padding_mask):
    # x就是下面传来的东西 encoding_outputs 就是encoding的输出 training同上
    # decoder_mask 就是遮住前面看过的东西和遮住padding的mask
    # encoder_decoder_padding_mask这个就是对应的mask
    out1 = self.attention1(x,x,x,decoder_mask)
    out1 = self.dropout1(out1,training=training)
    x = self.layer_norm1(x+out1)

    out2 = self.attention2(encoding_outputs,encoding_outputs,x, encoder_decoder_padding_mask)
    out2 = self.dropout2(out2, training=training)
    x = self.layer_norm2(x+out2)

    out3 = self.feed(x)
    out3 = self.dropout3(out3,training=training)
    output = self.layer_norm3(x+out3)
    return output
# -----------------------------------------------------------------------------

# 测试一下
sample_decoder_layer = DecoderBlock(512, 8, 2048)
sample_decoder_input = tf.random.uniform((64, 50, 512))
sample_decoder_output= sample_decoder_layer(sample_decoder_input, sample_output, False, None, None)
print(sample_decoder_output.shape)

Encoder

在这里插入图片描述
样例代码:

# 定义Encoder
# -----------------------------------------------------------------------------
class Encoder(keras.layers.Layer):
  def __init__(self,num_layers, input_vocab_size, max_length,d_model, num_heads, feed_dim, rate=0.1):
    super().__init__()
    self.d_model = d_model
    self.num_layers = num_layers
    self.max_length = max_length

    self.embedding = keras.layers.Embedding(input_vocab_size,self.d_model)
    self.position_embedding = get_position_embedding(max_length,self.d_model)
    self.dropout = keras.layers.Dropout(rate)
    self.encoder_blocks = [EncoderBlock(self.d_model,num_heads,feed_dim,rate) for _ in range(self.num_layers)]

  def call(self, x, training, encoder_padding_mask):
    # 一开始输入进去x的形状是(batch-size,num-step)
    embedding_x = self.embedding(x)
    # 因为位置编码值在-1和1之间,因此嵌入值乘以嵌入维度的平方根进行缩放,然后再与位置编码相加。
    embedding_x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
    # 因为x长度比position_embedding可能要小,因此embedding切片后和x相加
    posotion_and_embedding_x = embedding_x + self.position_embedding[:, :tf.shape(x)[1], :]
    posotion_and_embedding_x = self.dropout(posotion_and_embedding_x, training=training)
    
    # 得到的x不断作为下一层的输入
    for i in range(self.num_layers):
      posotion_and_embedding_x = self.encoder_blocks[i](posotion_and_embedding_x, training, encoder_padding_mask)
    # x最终shape如下
    # x.shape: (batch_size, input_seq_len, d_model)
    return posotion_and_embedding_x
# -----------------------------------------------------------------------------
# 测试
sample_encoder_model = Encoder(2,8500,50,512, 8, 2048)
sample_encoder_model_input = tf.random.uniform((64, 37))
sample_encoder_model_output = sample_encoder_model(
    sample_encoder_model_input, False, encoder_padding_mask = None)
print(sample_encoder_model_output.shape)

Decoder

在这里插入图片描述
样例代码:

# 定义Decoder
# -----------------------------------------------------------------------------
class Decoder(keras.layers.Layer):
  def __init__(self, num_layers, target_vocab_size, max_length,d_model, num_heads, feed_dim, rate=0.1):
    super().__init__()
    self.d_model = d_model
    self.num_layers = num_layers
    self.max_length = max_length

    self.embedding = keras.layers.Embedding(target_vocab_size, self.d_model)
    self.position_embedding = get_position_embedding(max_length, self.d_model)
    self.dropout = keras.layers.Dropout(rate)
    self.decoder_blocks = [DecoderBlock(self.d_model, num_heads, feed_dim, rate) for _ in range(self.num_layers)]

  def call(self, x, encoding_outputs, training,decoder_mask, encoder_decoder_padding_mask):
    embedding_x = self.embedding(x)
    embedding_x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
    posotion_and_embedding_x = embedding_x + self.position_embedding[:, :tf.shape(x)[1], :]
    posotion_and_embedding_x = self.dropout(posotion_and_embedding_x, training=training)
    for i in range(self.num_layers):
      posotion_and_embedding_x= self.decoder_blocks[i](posotion_and_embedding_x, encoding_outputs, training,decoder_mask, encoder_decoder_padding_mask)

    return posotion_and_embedding_x

# -----------------------------------------------------------------------------
# 测试
sample_decoder_model = Decoder(2, 8000,50,512, 8, 2048)
sample_decoder_model_input = tf.random.uniform((64, 37))
sample_decoder_model_output= sample_decoder_model(
    sample_decoder_model_input,
    sample_encoder_model_output,
    training = False, decoder_mask = None,
    encoder_decoder_padding_mask = None)

print(sample_decoder_model_output.shape)

transformer

在这里插入图片描述
样例代码:

# 定义transformer
# -----------------------------------------------------------------------------
class Transformer(keras.Model):
  def __init__(self,num_layers, input_vocab_size, target_vocab_size,max_length, d_model, num_heads, feed_dim, rate=0.1):
    super().__init__()
    self.encoder = Encoder(num_layers,input_vocab_size,max_length,d_model,num_heads,feed_dim,rate)
    self.decoder = Decoder(num_layers,target_vocab_size,max_length,d_model,num_heads,feed_dim,rate)
    self.final_layer = keras.layers.Dense(target_vocab_size)

  def call(self, input, target, training, encoder_padding_mask,decoder_mask, encoder_decoder_padding_mask):
    encoder_output = self.encoder(input,training,encoder_padding_mask)
    decoder_output = self.decoder(target,encoder_output,training,decoder_mask,encoder_decoder_padding_mask)

    predict = self.final_layer(decoder_output)
    return predict

# -----------------------------------------------------------------------------
# 测试
sample_transformer = Transformer(2, 8500, 8000, 50,512, 8, 2048, rate = 0.1)
temp_input = tf.random.uniform((64, 26))
temp_target = tf.random.uniform((64, 26))

# 得到输出
predictions = sample_transformer(
    temp_input, temp_target, training = False,
    encoder_padding_mask = None,
    decoder_mask = None,
    encoder_decoder_padding_mask = None)
# 输出shape
print(predictions.shape)

自定义loss 和 学习率

# 自定义的学习率调整设计实现
# -----------------------------------------------------------------------------
class CustomizedSchedule(keras.optimizers.schedules.LearningRateSchedule):
  def __init__(self, d_model, warmup_steps=4000):
    super().__init__()
    self.d_model = tf.cast(d_model, tf.float32)
    self.warmup_steps = warmup_steps

  def __call__(self, step):
    step = tf.cast(step,tf.float32)
    arg1 = tf.math.rsqrt(step)
    arg2 = step * (self.warmup_steps ** (-1.5))
    arg3 = tf.math.rsqrt(self.d_model)
    return arg3 * tf.math.minimum(arg1, arg2)

learning_rate = CustomizedSchedule(d_model)
optimizer = keras.optimizers.Adam(learning_rate,beta_1=0.9,beta_2=0.98,epsilon=1e-9)

loss_object = keras.losses.SparseCategoricalCrossentropy(from_logits=True, reduction='none')
def loss_function(real, pred):
  # 损失做了掩码处理,是padding的地方不计算损失
  mask = tf.math.logical_not(tf.math.equal(real, 0))
  loss_ = loss_object(real, pred)
  mask = tf.cast(mask, dtype=loss_.dtype)
  loss_ *= mask

  return tf.reduce_mean(loss_)
# -----------------------------------------------------------------------------

mask生成函数

def create_mask(input,target):
  encoder_padding_mask = tf.cast(tf.math.equal(input, 0), tf.float32)[:, tf.newaxis, tf.newaxis, :]
  encoder_decoder_padding_mask = encoder_padding_mask

  # 创建下三角型
  look_ahead_mask = (1 - tf.linalg.band_part(tf.ones((tf.shape(target)[1], tf.shape(target)[1])), -1, 0))
  decoder_padding_mask = tf.cast(tf.math.equal(target, 0), tf.float32)[:, tf.newaxis, tf.newaxis, :]
  decoder_mask = tf.maximum(look_ahead_mask, decoder_padding_mask)

  return encoder_padding_mask, decoder_mask, encoder_decoder_padding_mask

训练

# 训练
# -----------------------------------------------------------------------------
train_loss = keras.metrics.Mean(name = 'train_loss')
train_accuracy = keras.metrics.SparseCategoricalAccuracy(name = 'train_accuracy')
@tf.function
def train_step(input, target):
  tar_inp = target[:, :-1]  # 没带end
  tar_real = target[:, 1:]  # 没有start

  encoder_padding_mask, decoder_mask, encoder_decoder_padding_mask = create_mask(input, tar_inp)

  with tf.GradientTape() as tape:
    predictions = transformer(input, tar_inp, True,encoder_padding_mask,decoder_mask,encoder_decoder_padding_mask)
    loss = loss_function(tar_real, predictions)

  gradients = tape.gradient(loss, transformer.trainable_variables)
  optimizer.apply_gradients(zip(gradients, transformer.trainable_variables))

  train_loss(loss)
  train_accuracy(tar_real, predictions)



epochs = 200
for epoch in range(epochs):
  start = time.time()
  # reset后就会从零开始累计
  train_loss.reset_states()
  train_accuracy.reset_states()

  for (batch, (input, target)) in enumerate(dataset.take(batch_size)):
    train_step(input, target)
    if batch % 100 == 0:
      print('Epoch {} Batch {} Loss {:.4f} Accuracy {:.4f}'.format(epoch + 1, batch, train_loss.result(),train_accuracy.result()))

  print('Epoch {} Loss {:.4f} Accuracy {:.4f}'.format(epoch + 1, train_loss.result(), train_accuracy.result()))
  print('Time take for 1 epoch: {} secs\n'.format(time.time() - start))

# loss是一个正常的指标,accuracy只是机器翻译的一个参考指标,可以看趋势
# -----------------------------------------------------------------------------

翻译

# 预测
# -----------------------------------------------------------------------------
def translate(inp_sentence):
  # 对输入的语言做和训练时同样的预处理后,再进行word转id
  sentence = preprocess_sentence(inp_sentence)
  # text到id的转换
  inputs = [input_tokenizer.word_index[i] for i in sentence.split(' ')]
  # 加padding
  inputs = keras.preprocessing.sequence.pad_sequences([inputs], maxlen=50, padding='post')
  # 转换为tf张量
  encoder_input = tf.convert_to_tensor(inputs)
  decoder_input = tf.expand_dims([target_tokenizer.word_index['<start>']], 1)
  result = ''

  for i in range(max_length):
    # 产生mask并传给transformer
    encoder_padding_mask, decoder_mask, encoder_decoder_padding_mask = create_mask(encoder_input, decoder_input)
    predictions= transformer(encoder_input,decoder_input,False,encoder_padding_mask,decoder_mask,encoder_decoder_padding_mask)
    # print('-'*20)
    # print(predictions)
    # 预测值就是概率最大的那个的索引,那最后一个维度中最大的那个值
    predicted_id = tf.argmax(predictions[0][0]).numpy()
    result += target_tokenizer.index_word[predicted_id] + ' '
    # 如果等于end id,预测结束
    if target_tokenizer.index_word[predicted_id] == '<end>':
      break
    # 如果predicted_id不是end id,添加到新的decoder_input中
    decoder_input = tf.expand_dims([predicted_id], 1)

  print('Input: %s' % (sentence))
  print('Predicted translation: {}'.format(result))

translate(u'happy')
# -----------------------------------------------------------------------------

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1203931.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CMake中的字符串操作

如果使用set进行字符串拼接&#xff0c;对应的命令格式如下&#xff1a; set(变量名1 ${变量名1} ${变量名2} ...) 关于上面的命令其实就是将从第二个参数开始往后所有的字符串进行拼接&#xff0c;最后将结果存储到第一个参数中&#xff0c;如果第一个参数中原来有数据会对原…

ESP32-DHT11温湿度数据上传MQTT服务器

ESP32-DHT11温湿度数据上传MQTT服务器 简介ESP32DHT11 实验实验说明接线MQTT服务器建立连接添加订阅 ESP32驱动DHT11ESP32向MQTT服务器发送数据上传温湿度数据实验结果 简介 ESP32 点击图片购买 ESP32 系列模组集成 Wi-Fi、传统蓝牙和低功耗蓝牙功能&#xff0c;具有广泛的用途…

玩转硬件之C51的玩法(一)——破解“口红糖”中的电路

智能玩具&#xff1a;玩具行业的新风口 玩具是儿童的好伙伴&#xff0c;也是成人的乐趣来源。 随着科技的进步和消费的升级&#xff0c;玩具的形式和功能也在不断创新&#xff0c;智能玩具作为玩具行业的新风口&#xff0c;正受到越来越多的关注和喜爱。 什么是智能玩具&…

美颜与性能的平衡:视频直播美颜SDK集成与性能优化指南

目前美颜SDK所遇到的挑战是如何在追求美颜效果的同时保持系统性能的稳定。本文将深入探讨视频直播美颜SDK的集成以及性能优化的关键指南&#xff0c;以帮助开发者找到合适的平衡点。 一、美颜SDK的集成 1.选择适用于直播的美颜SDK 在美颜SDK的众多选择中&#xff0c;要考虑…

redis之org.springframework.data.redis.RedisSystemException: Error in execution

背景 在运行某系统时&#xff0c;在测试类向redis中存入某值&#xff0c;然后取出。 一、遇到的问题 报错&#xff1a; org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: …

【ruoyi】微服务关闭登录验证码

登录本地的nacos服务&#xff0c;修改&#xff1a;配置管理-配置列表-ruoyi-gateway-dev.yml 将验证码的enabled设置成false&#xff0c;即可

【SpringBoot】SpringBoot自动配置底层源码解析

概述 EnableAutoConfiguration源码解析SpringBoot常用条件注解源码解析SpringBoot之Mybatis自动配置源码解析SpringBoot之AOP自动配置源码解析SpringBoot Jar包启动过程源码解析 DeferredImportSelector接口 DeferredImportSelector和ImportSelector的区别在于&#xff1a; …

Python语言:经典案例分析讲解2

例题1&#xff1a;文件的操作 例题2&#xff1a;调用函数求偶数之和 例题3&#xff1a;调用函数并使用递归的方法求斐波那契数前N项之和 题1: 以只写的模式打开文件test.txt&#xff0c;写入"Python"&#xff0c;关闭文件。 代码如下&#xff1a; f open("E:/…

长江存储诉讼镁光侵权的8个专利是什么?

1.事件背景回顾 据《环球时报》周日从美国加州北区地方法院官方网站获悉&#xff0c;中国领先的存储芯片生产商长江存储科技股份有限公司&#xff08;YMTC&#xff09;周四对美国美光科技及其全资子公司美光消费品集团提起诉讼&#xff0c;指控其侵犯了长江存储的八项专利。 …

Hosts File Editor 实用工具

我一般手工编辑hosts文件&#xff0c;我想给hosts文件加一个开关&#xff0c;本想自己实现&#xff0c;但是忽然发现微软已经提供了官方的解决方案&#xff0c;感觉有能人。 对文件的行的修改被抽象成了一个开关。腻害&#xff01;&#xff01;&#xff01;

Hbuilder介绍,uniapp框架

Hbuilder对程序前端页面进行开发&#xff08;包括android&#xff0c;ios&#xff0c;小程序&#xff0c;web等等&#xff09;,其实也就是相当于把android开发进行前后端分离了。方便分工协作。提高开发效率。 用前端框架开发可以实现一次编码&#xff0c;多平台运行。 &…

酷柚易汛ERP - 序列号状态表操作指南

1、应用场景 序列表状态表统计商品的每个序列号目前的状态&#xff08;在库、已出库&#xff09;&#xff0c;每个序列号仅会显示一条记录。 2、主要操作 打开【仓库】-【序列号状态表】&#xff0c;可勾选序列号在库/已出库两种状态查询&#xff0c;其它筛选操作与上文其它…

学会这个样生成性能测试报告,涨薪5k轻轻松松

[文章末尾给大家留下了大量的福利] JMeter 执⾏原理   JMerer 通过线程组来驱动多个&#xff08;也可以理解为LR⼯具⾥⾯的虚拟⽤户&#xff09;运⾏测试脚本对⽬标服务器发起⼤量的⽹络请求&#xff0c;在每个客户端上可以运⾏多个线程组&#xff0c;也就是说⼀个测试计划⾥…

ObRegisterCallbacks()返回0xC0000022(拒绝访问)解决办法

在开发测试环境下&#xff0c;没有打签名的驱动调用ObRegisterCallbacks会返回0xC0000022&#xff08;拒绝访问&#xff09;的错误码。这是由于该函数内部会进行驱动的签名校验。 具体位置在 因此可以用以下代码绕过该检查 // 以下代码放在DriverEntry中 ULONG_PTR pDrvSectio…

微信公众号制作的资源及网站分享!

微信公众号的出现丰富了我们的网络世界&#xff0c;一篇又一篇的或长或短的文章&#xff0c;让我们碎片化的时间有了去处。而且&#xff0c;我们每个人也可以运营一个微信公众号&#xff0c;人人都可以创建属于自己的微信公众号&#xff0c;无论是记录生活还是分享文章或者想要…

使用代理IP时有哪些小技巧?大数据技术人员必看

很多大数据行业和跨境行业的用户都会使用到一个工具&#xff0c;就是代理IP工具&#xff0c;不过很多人对它的研究不深&#xff0c;其实在使用它时是有一些小技巧的&#xff0c;它不仅可以帮助我们隐蔽我们的真实IP地址&#xff0c;实现多账号矩阵运营&#xff0c;同时还能让我…

找工作去哪个网站比较好

吉鹿力招聘网是一个专注于互联网岗位求职招聘的网站&#xff0c;提供海量的互联网人才储备。它主要覆盖了互联网类招聘&#xff0c;包括技术、产品、设计、运营、市场、销售等。吉鹿力招聘网的特点是用户量大&#xff0c;需求旺盛。如果你希望找工作&#xff0c;吉鹿力招聘网是…

关于我在配置zookeeper出现,启动成功,进程存在,但是查看状态却没有出现Mode:xxxxx的问题和我的解决方案

在我输入:zkServer.sh status 之后出现报错码. 报错码&#xff1a; ZooKeeper JMX enabled by default Using config: /opt/software/zookeeper/bin/../conf/zoo.cfgClient port found: 2181. Client address: localhost. Error contacting service. It is probably not runni…

EXIT(1)

EXTI介绍 EXTI是片上外设 NVIC是cpu内的外设 回忆起之前的GPIO和AFIO 我们是如何检测按键按下的 我们是一直用while循环读取IDR寄存器的对应位置的值 一直检测判断按键是否被按下 那么是否有第二种方式检测按键是否被按下了呢&#xff1f; 通过EXTI 当EXTI检测到按键的电平发生…

找工作的网站都有哪些

吉鹿力招聘网作为一家知名的招聘网站&#xff0c;因其功能完善和用户隐私保护而备受用户青睐。它不仅可以与企业直接沟通&#xff0c;还可以提供在线聊工作的机会。通过吉鹿力招聘网&#xff0c;用户可以自主选择工作地点、时间和工作类型&#xff0c;大大提高了找到合适工作的…