TensorFlow 实战(五)(5)

本文涉及的产品
文档翻译,文档翻译 1千页
语种识别,语种识别 100万字符
文本翻译,文本翻译 100万字符
简介: TensorFlow 实战(五)

TensorFlow 实战(五)(4)https://developer.aliyun.com/article/1522833

让我们看看如何在 TensorFlow 中实现这一点。首先,我们将加载刚保存的模型:

model = tf.keras.models.load_model(save_path)

很容易获得编码器模型,因为我们将编码器封装为最终模型中的嵌套模型。可以通过调用 get_layer()函数来取出它。

en_model = model.get_layer("encoder")

之后,我们定义两个输入来表示解码器的两个输入:

d_inp = tf.keras.Input(shape=(1,), dtype=tf.string, name='d_infer_input')
d_state_inp = tf.keras.Input(shape=(256,), name='d_infer_state')

正如我们之前讨论的那样,我们定义了两个输入:一个表示解码器的输入(d_inp),另一个表示解码器 GRU 层的状态输入(d_state_inp)。分析形状,d_inp 接受一堆字符串的数组,就像之前一样。d_state_inp 表示 GRU 模型的状态向量,具有 256 个特征维度。

在定义输入后,我们将重现我们在训练模型中构建解码器时遵循的所有步骤。但是,我们将从训练模型中获取层,而不是创建新的随机初始化层。特别是,我们将有以下层来流输输入:

  • 解码器的向量化层(产生 d_vectorized_out)
  • 解码器的嵌入层(产生 d_emb_out)
  • 解码器的 GRU 层(产生 d_gru_out)
  • 解码器的完全连接的隐藏层(产生 d_dense1_out)
  • 最后的预测层(产生 d_final_out)

我们引入了一个重要的改变来介绍 GRU 模型。请注意,我们将 return_sequences 设置为 False,以确保解码器 GRU 仅返回最后一个输出(即不返回输出序列)。换句话说,GRU 层的输出是一个[None,256]大小的张量。这有助于我们将输出形状匹配到先前定义的 d_state_inp,使递归模型更容易构建。此外,GRU 层以 d_state_inp 作为模型中的 initial_state。这样,我们就可以将输出状态向量作为递归输入馈送到解码器:

# Generate the vectorized output of inp
d_vectorizer = model.get_layer('d_vectorizer')    
d_vectorized_out = d_vectorizer(d_inp)
# Generate the embeddings from the vectorized input
d_emb_out = model.get_layer('d_embedding')(d_vectorized_out)
# Get the GRU layer
d_gru_layer = model.get_layer("d_gru")
# Since we generate one word at a time, we will not need the return_sequences
d_gru_layer.return_sequences = False
# Get the GRU out while using d_state_inp from earlier, as the initial state
d_gru_out = d_gru_layer(d_emb_out, initial_state=d_state_inp) 
# Get the dense output
d_dense1_out = model.get_layer("d_dense_1")(d_gru_out) 
# Get the final output
d_final_out = model.get_layer("d_dense_final")(d_dense1_out) 

是时候定义最终的解码器模型了:

de_model = tf.keras.models.Model(
    inputs=[d_inp, d_state_inp], outputs=[d_final_out, d_gru_out]
)

模型接受 d_inp 和 d_state_inp 作为输入,并产生 d_final_out(即最终预测)和 d_gru_out(即 GRU 输出状态)作为输出。最后,让我们退后一步,并将我们所做的工作封装在一个名为 get_inference_model()的单个函数中,如下面的示例所示。

列出 11.11 号栏目中的机器翻译模型递归推理模型定义

import tensorflow.keras.backend as K
K.clear_session()
def get_inference_model(save_path):
    """ Load the saved model and create an inference model from that """
    model = tf.keras.models.load_model(save_path)                        ❶
    en_model = model.get_layer("encoder")                                ❷
    d_inp = tf.keras.Input(
        shape=(1,), dtype=tf.string, name='d_infer_input'
    )                                                                    ❸
    d_state_inp = tf.keras.Input(shape=(256,), name='d_infer_state')     ❹
    d_vectorizer = model.get_layer('d_vectorizer')                       ❺
    d_vectorized_out = d_vectorizer(d_inp)                               ❺
    d_emb_out = model.get_layer('d_embedding')(d_vectorized_out)         ❻
    d_gru_layer = model.get_layer("d_gru")                               ❼
    d_gru_layer.return_sequences = False                                 ❽
    d_gru_out = d_gru_layer(d_emb_out, initial_state=d_state_inp)        ❾
    d_dense1_out = model.get_layer("d_dense_1")(d_gru_out)               ❿
    d_final_out = model.get_layer("d_dense_final")(d_dense1_out)         ⓫
    de_model = tf.keras.models.Model(
        inputs=[d_inp, d_state_inp], outputs=[d_final_out, d_gru_out]    ⓬
    )
    return en_model, de_model

❶ 加载已保存的训练模型。

❷ 通过调用 get_layer()函数从加载的模型中获取编码器模型。

❸ 定义新推理解码器的第一个输入,一个输入层,以一批字符串为输入。

❹ 定义新推理解码器的第二个输入,一个输入层,以初始状态作为解码器 GRU 的输入状态传递。

❺ 生成解码器的字符串输入的向量化输出。

❻ 从矢量化输入生成嵌入。

❼ 获得解码器的 GRU 层。

❽ 由于我们一次生成一个单词,我们将不需要 return_sequences

❾ 在使用先前的 d_state_inp 作为初始状态时获得 GRU 输出。

❿ 获得密集输出。

⓫ 获得最终输出。

⓬ 定义最终的解码器。

然后,我们将定义一个函数来加载我们刚刚保存的词汇表。我们使用 JSON 格式保存了词汇表,加载词汇表所需的所有操作就是调用打开的词汇文件的 json.load()

def get_vocabularies(save_dir):
    """ Load the vocabulary files from a given path"""
    with open(os.path.join(save_dir, 'en_vocab.json'), 'r') as f:
        en_vocabulary = json.load(f)
    with open(os.path.join(save_dir, 'de_vocab.json'), 'r') as f:
        de_vocabulary = json.load(f)
    return en_vocabulary, de_vocabulary
print("Loading vocabularies")
en_vocabulary, de_vocabulary = get_vocabularies(
    os.path.join('models', 'seq2seq_vocab')
)
print("Loading weights and generating the inference model")
en_model, de_model = get_inference_model(os.path.join('models', 'seq2seq'))
print("\tDone")

接下来,我们已经拥有了生成新翻译所需的一切。如前所述,我们将创建一个输入英文句子(用 sample_en_text 表示)到编码器生成上下文向量的过程/函数。接下来,使用 SOS 标记和上下文向量进行预测,以获得第一个德语标记预测和下一个状态输出。最后,递归地将解码器的输出作为解码器的输入,直到预测的标记为 EOS。以下清单使用我们刚刚构建的推断模型描述了这一功能。

清单 11.12 使用新推断模型生成翻译

def generate_new_translation(en_model, de_model, de_vocabulary, sample_en_text):
    """ Generate a new translation """
    start_token = 'sos'    
    print("Input: {}".format(sample_en_text))                              ❶
    d_state = en_model.predict(np.array([sample_en_text]))                 ❷
    de_word = start_token                                                  ❸
    de_translation = []                                                    ❹
    while de_word != end_token:                                            ❺
        de_pred, d_state = de_model.predict([np.array([de_word]), d_state])❻
        de_word = de_vocabulary[np.argmax(de_pred[0])]                     ❼
        de_translation.append(de_word)                                     ❽
    print("Translation: {}\n".format(' '.join(de_translation)))

❶ 打印输入。

❷ 获取解码器的初始状态。

❸ 解码器的第一个输入词将始终是起始标记(即其值为 sos)。

❹ 我们在这个列表中收集翻译。

❺ 一直预测,直到我们获得结束标记(即它的值为 eos)。

❻ 使用新状态覆盖先前的状态输入。

❼ 从预测的标记 ID 中获取实际的单词。

❽ 将其添加到翻译中。

让我们在数据集中对几个测试输入运行这个,看看我们得到了什么:

for i in range(5):
    sample_en_text = test_df["EN"].iloc[i]
    generate_new_translation(en_model, de_model, de_vocabulary, sample_en_text)

这将输出

Input: The pleasure's all mine.
Translation: die [UNK] [UNK] mir eos
Input: Tom was asking for it.
Translation: tom sprach es zu tun eos
Input: He denied having been involved in the affair.
Translation: er [UNK] sich auf das [UNK] [UNK] eos
Input: Is there something in particular that you want to drink?
Translation: gibt es etwas [UNK] wenn du etwas [UNK] eos
Input: Don't run. Walk slowly.
Translation: [UNK] nicht zu fuß eos

你可以将这些英文短语/句子与谷歌翻译进行比较,看看我们的模型是如何接近它们的。对于在相对简单和小的数据集上训练的模型,我们的模型表现非常好。翻译中存在 [UNK] 标记,因为在语料库中所有不太频繁的词都被替换为 [UNK]。因此,当模型不确定应该在某个位置填充哪个单词时,它可能会输出 [UNK]。

练习 4

您决定使用 LSTM 模型而不是 GRU 模型。正如您所知,LSTM 模型有两个状态:细胞状态和输出状态。您已经构建了编码器,现在正在构建解码器。您计划调整以下代码以使用 LSTM 模型:

d_inp = tf.keras.Input(shape=(1,), dtype=tf.string)       
d_state_inp = tf.keras.Input(shape=(256,))                
d_vectorized_out = de_vectorizer(d_inp)
d_emb_out = tf.keras.layers.Embedding(de_vocab+2, 128, mask_zero=True)(d_vectorized_out)
d_gru_out = tf.keras.layers.GRU(256)(d_emb_out, initial_state=d_state_inp)
d_final_out = tf.keras.layers.Dense(
    de_vocab+2, activation='softmax'
)(d_gru_out)                    
de_model = tf.keras.models.Model(
    inputs=[d_inp, d_state_inp], outputs=[d_final_out, d_gru_out]
)

如果你在 LSTM 层中设置 return_state=True 并在某些兼容输入 x 上调用它,则输出如下

lstm_out, state_h, state_c = tf.keras.layers.LSTM(256, return_state=True)(x)

state_hstate_c 分别代表输出状态和细胞状态。

我们已经使用序列到序列架构训练了一个机器翻译模型。在下一章中,我们将探讨如何使用一种称为注意力的技术进一步改进这个模型。

摘要

  • 编码器-解码器模式在序列到序列任务中很常见,比如机器翻译。
  • 编码器接收源语言输入并生成上下文向量。
  • 上下文向量由解码器用于生成目标语言输出(即翻译)。
  • tf.keras.layers.experimental.preprocessing.TextVectorization 层允许您将标记化(即将字符串转换为标记列表,然后转换为标记 ID)集成到模型中。这使得模型可以接受字符串而不是数值。
  • 在序列到序列任务上训练模型时,可以使用教师强制训练:
  • 在教师强制训练中,编码器像往常一样接收源语言输入并生成上下文向量。然后,解码器消耗并预测翻译中的单词。换句话说,解码器在训练时以这样的方式进行,以便在给定翻译中的前一个单词(或多个单词)的情况下预测下一个单词。
  • 机器翻译模型产生的翻译质量使用 BLEU 分数进行衡量:
  • BLEU 分数使用修改后的精确度指标以及测量翻译的不同 n-gram 上的精确度来计算得分。
  • 使用教师强制训练模型后,需要定义一个单独的推理模型,使用训练后的权重:
  • 此推理模型具有相同的编码器,但解码器将以先前预测的单词作为下一步的输入,并递归预测单词,直到满足预定义的结束条件为止。

练习答案

练习 1

def vocab_size(ser):
    cnt = Counter(ser.sum())
    return len(cnt)

练习 2

# The decoder
en_repeat_out = tf.keras.layers.RepeatVector(de_seq_length)(en_gru_out)
d_gru_layer = tf.keras.layers.GRU(256, return_sequences=True, name='d_gru')
d_gru_out = d_gru_layer(en_repeat_out, initial_state=gru_out)
d_dense_layer_1 = tf.keras.layers.Dense(512, activation='relu', name='d_dense_1')
d_dense1_out = d_dense_layer_1(d_gru_out)
d_dense_layer_final = tf.keras.layers.Dense(
    de_vocab+2, activation='softmax', name='d_dense_final'
)
d_final_out = d_dense_layer_final(d_dense1_out)
# Define the full model
model = tf.keras.models.Model(
    inputs=inp, outputs=d_final_out, name='final_seq2seq'
)

练习 3

prev_bleu = None
for epoch in range(epochs):
    bleu_log = []  
    n_train_batches = en_inputs_raw.shape[0]//batch_size
    for i in range(n_train_batches):
        print("Training batch {}/{}".format(i+1, n_train_batches), end='\r')
        x = [         
            en_inputs_raw[i*batch_size:(i+1)*batch_size],  
            de_inputs_raw[i*batch_size:(i+1)*batch_size]
        ]
        y = vectorizer(de_labels_raw[i*batch_size:(i+1)*batch_size])
        model.train_on_batch(x, y)
        pred_y = model.predict(x)
        bleu_log.append(bleu_metric.calculate_bleu_from_predictions(y, pred_y)) 
    mean_bleu = np.mean(bleu_log)
    # The termination criteria
    if prev_bleu and prev_bleu > mean_bleu:
        break
    prev_bleu = mean_bleu

练习 4

d_inp = tf.keras.Input(shape=(1,), dtype=tf.string)       
d_state_h_inp = tf.keras.Input(shape=(256,))                
d_state_c_inp = tf.keras.Input(shape=(256,))                
d_vectorized_out = de_vectorizer(d_inp)                                         
d_emb_out = tf.keras.layers.Embedding(
    de_vocab+2, 128, mask_zero=True
)(d_vectorized_out)                    
d_lstm_out, d_state_h, d_state_c = tf.keras.layers.LSTM(
 256, return_state=True
)(d_emb_out, initial_state=[d_state_h_inp, d_state_c_inp])
d_final_out = tf.keras.layers.Dense(
 de_vocab+2, activation='softmax'
)(d_lstm_out) 
de_model = tf.keras.models.Model(
    inputs=[d_inp, d_state_h_inp, d_state_c_inp], 
    outputs=[d_final_out, d_state_h, d_state_c]              
)
de_model.summary()


相关文章
|
7月前
|
机器学习/深度学习 TensorFlow API
TensorFlow与Keras实战:构建深度学习模型
本文探讨了TensorFlow和其高级API Keras在深度学习中的应用。TensorFlow是Google开发的高性能开源框架,支持分布式计算,而Keras以其用户友好和模块化设计简化了神经网络构建。通过一个手写数字识别的实战案例,展示了如何使用Keras加载MNIST数据集、构建CNN模型、训练及评估模型,并进行预测。案例详述了数据预处理、模型构建、训练过程和预测新图像的步骤,为读者提供TensorFlow和Keras的基础实践指导。
499 59
|
2月前
|
机器学习/深度学习 TensorFlow API
机器学习实战:TensorFlow在图像识别中的应用探索
【10月更文挑战第28天】随着深度学习技术的发展,图像识别取得了显著进步。TensorFlow作为Google开源的机器学习框架,凭借其强大的功能和灵活的API,在图像识别任务中广泛应用。本文通过实战案例,探讨TensorFlow在图像识别中的优势与挑战,展示如何使用TensorFlow构建和训练卷积神经网络(CNN),并评估模型的性能。尽管面临学习曲线和资源消耗等挑战,TensorFlow仍展现出广阔的应用前景。
81 5
|
2月前
|
机器学习/深度学习 人工智能 TensorFlow
基于TensorFlow的深度学习模型训练与优化实战
基于TensorFlow的深度学习模型训练与优化实战
110 0
|
5月前
|
机器学习/深度学习 存储 前端开发
实战揭秘:如何借助TensorFlow.js的强大力量,轻松将高效能的机器学习模型无缝集成到Web浏览器中,从而打造智能化的前端应用并优化用户体验
【8月更文挑战第31天】将机器学习模型集成到Web应用中,可让用户在浏览器内体验智能化功能。TensorFlow.js作为在客户端浏览器中运行的库,提供了强大支持。本文通过问答形式详细介绍如何使用TensorFlow.js将机器学习模型带入Web浏览器,并通过具体示例代码展示最佳实践。首先,需在HTML文件中引入TensorFlow.js库;接着,可通过加载预训练模型如MobileNet实现图像分类;然后,编写代码处理图像识别并显示结果;此外,还介绍了如何训练自定义模型及优化模型性能的方法,包括模型量化、剪枝和压缩等。
85 1
|
5月前
|
机器学习/深度学习 数据采集 TensorFlow
使用TensorFlow进行模型训练:一次实战探索
【8月更文挑战第22天】本文通过实战案例详解使用TensorFlow进行模型训练的过程。首先确保已安装TensorFlow,接着预处理数据,包括加载、增强及归一化。然后利用`tf.keras`构建卷积神经网络模型,并配置训练参数。最后通过回调机制训练模型,并对模型性能进行评估。此流程为机器学习项目提供了一个实用指南。
|
4月前
|
机器学习/深度学习 数据挖掘 TensorFlow
解锁Python数据分析新技能,TensorFlow&PyTorch双引擎驱动深度学习实战盛宴
在数据驱动时代,Python凭借简洁的语法和强大的库支持,成为数据分析与机器学习的首选语言。Pandas和NumPy是Python数据分析的基础,前者提供高效的数据处理工具,后者则支持科学计算。TensorFlow与PyTorch作为深度学习领域的两大框架,助力数据科学家构建复杂神经网络,挖掘数据深层价值。通过Python打下的坚实基础,结合TensorFlow和PyTorch的强大功能,我们能在数据科学领域探索无限可能,解决复杂问题并推动科研进步。
77 0
|
5月前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
98 0
|
5月前
|
安全 Apache 数据安全/隐私保护
你的Wicket应用安全吗?揭秘在Apache Wicket中实现坚不可摧的安全认证策略
【8月更文挑战第31天】在当前的网络环境中,安全性是任何应用程序的关键考量。Apache Wicket 是一个强大的 Java Web 框架,提供了丰富的工具和组件,帮助开发者构建安全的 Web 应用程序。本文介绍了如何在 Wicket 中实现安全认证,
54 0
|
5月前
|
机器学习/深度学习 数据采集 TensorFlow
从零到精通:TensorFlow与卷积神经网络(CNN)助你成为图像识别高手的终极指南——深入浅出教你搭建首个猫狗分类器,附带实战代码与训练技巧揭秘
【8月更文挑战第31天】本文通过杂文形式介绍了如何利用 TensorFlow 和卷积神经网络(CNN)构建图像识别系统,详细演示了从数据准备、模型构建到训练与评估的全过程。通过具体示例代码,展示了使用 Keras API 训练猫狗分类器的步骤,旨在帮助读者掌握图像识别的核心技术。此外,还探讨了图像识别在物体检测、语义分割等领域的广泛应用前景。
49 0
|
6月前
|
机器学习/深度学习 数据挖掘 TensorFlow
解锁Python数据分析新技能,TensorFlow&PyTorch双引擎驱动深度学习实战盛宴
【7月更文挑战第31天】在数据驱动时代,Python凭借其简洁性与强大的库支持,成为数据分析与机器学习的首选语言。**数据分析基础**从Pandas和NumPy开始,Pandas简化了数据处理和清洗,NumPy支持高效的数学运算。例如,加载并清洗CSV数据、计算总销售额等。
67 2