Transformer 模型,特别是 BERT 模型,彻底改变了 NLP,并在诸如情感分析、实体抽取或问答等任务上开辟了新的天地。BERT 模型允许数据科学家站在巨人的肩膀上。当企业用这些模型在大型语料库中进预训练时,数据科学家可以将迁移学习应用到这些多用途的 transformer 模型中,并针对其领域特定的问题取得突破性的结果。
在 SAP 的 Concur 实验室,研究人员希望使用 BERT 解决差旅费领域的新问题。他们想简化 BERT 的推论。但不幸的是,他们一直没找到完美的解决方案。
通过与 TensorFlow 团队合作,并使用他们的最新成果,Concur 实验室最终实现了一致、简单、快速的 BERT 模型推断,可以在几毫秒内实现从原始文本的分类预测。
那么,各种 TensorFlow 库和组件如何帮助研究人员达到这个里程碑?作为 SAP Concur 实验室的高级机器学习工程师,Hannes Hapke 写了一篇博文分享了他们的做法。TFX 团队的研究人员也参与了这篇博文的编辑。
这篇博客文章将向你概述如何使用 TensorFlow 生态系统来实现可伸缩、快速、高效的 BERT 部署。全文编译如下。
本文讨论的方法将允许开发人员使用 TensorFlow Extended(TFX)v0.21 或更高版本来训练 TensorFlow 模型。但是,对 tf.text 操作的支持尚未包含在 TensorFlow Service(v2.1)的当前版本中,而是包含在nightly docker版本中,并将包含在 v2.2 版本中。
如果你想查看完整的示例,请查看 Colab notebook。它展示了整个 TensorFlow 扩展(TFX)管道以生成可部署的 BERT 模型,并将预处理步骤作为模型图的一部分。
BERT 部署的现状
transformer 模型的最新进展令人吃惊。但不幸的是,将这些模型用在生产中却并不简单或者完美。理想情况下,我们希望将原始文本发送到服务器,但是 BERT 模型需要对输入文本进行预处理,然后才能从实际模型中获得预测。
有一些解决方案通过在客户端对文本进行预处理来解决这个问题,还有的解决方案是,在服务器端实现了一个中间步骤来处理输入数据。这两个方法都不太正确,因为它们需要额外的部署协调,降低了推理的效率。
图 1:当前的 BERT 部署
什么是最佳部署?
在部署模型时,方法越简单越好。我们希望部署 transformer 模型,并将预处理作为模型图的一部分。由于预处理被集成到模型图中,我们可以简单地将单个模型部署到模型服务器,删除其他部署依赖项,并充分利用模型服务器的优点。例如,我们可以批处理预测请求,以优化推理硬件的使用。
利用 TensorFlow 生态系统部署 BERT
TensorFlow 对我们来说是一个非常高效的框架,因为它不仅是一个机器学习框架,而且还提供了一个具有广泛的支持包和工具的生态系统。TensorFlow Serving 对我们来说非常有用。它提供了简单、一致、可伸缩的模型部署。
我们密切关注的另一个系统项目是 TensorFlow Transform。它为我们提供了一个将模型预处理步骤构建为图的机会,然后,我们可以将这些图与实际的深度学习模型一起导出。TensorFlow Transform 要求所有预处理步骤都表示为 TensorFlow 操作。正因为如此,TensorFlow 文本的最新发展对我们来说也非常有帮助。RaggedTensors 的实现不仅开启了新的应用,而且,其库还提供了实现自然语言预处理步骤所需的功能。
在 TensorFlowWorld 2019 上展示了 TensorFlow Text 的一个新功能,那就是完全实现一个 BERT 标记器。因此,我们可以用几行 TensorFlow 代码来表示预处理步骤。我们还通过使用另一个 TensorFlow 工具:TensorFlow Extended(TFX),实现了模型管道和部署一致的目标。TFX 允许我们以可重复的方式表达整个 ML 管道,因此有助于我们部署一致的机器学习模型。
图 2:附 tf.Text 的 TFX 管道
用 TensorFlow ops 编写预处理步骤
理想的模型部署接受原始文本作为模型的输入,并提供模型预测作为结果。简化 BERT 部署的关键是将预处理步骤表示为 TensorFlow ops。BERT 模型要求将原始输入文本标记为标记 id、输入掩码的伴随数据结构和生成的输入类型 id。借助 TensorFlow Text,我们现在可以用更少的代码来实现这一点。在接下来的文章中,我们将讨论从原始文本到特定于 BERT 的数据结构转换的细节,包括添加特定于 BERT 的标记。
vocab_file_path = load_bert_layer().resolved_object.vocab_file.asset_path
bert_tokenizer = text.BertTokenizer(vocab_lookup_table=vocab_file_path,
token_out_type=tf.int64,
lower_case=do_lower_case)...
input_word_ids = tokenize_text(text)
input_mask = tf.cast(input_word_ids > 0, tf.int64)
input_mask = tf.reshape(input_mask, [-1, MAX_SEQ_LEN])
zeros_dims = tf.stack(tf.shape(input_mask))
input_type_ids = tf.fill(zeros_dims, 0)
input_type_ids = tf.cast(input_type_ids, tf.int64)
图 3:BERT 标记器
利用 TensorFlow Transform 和上述代码,可以将预处理图与训练好的 TensorFlow 模型一起导出。随着 TensorFlow Serving 的最新更新,我们部署的 BERT 模型现在可以接受原始文本作为输入。在这里,没有其他部署依赖项!
使用 TensorFlow Transform 为我们提供了一些实际的好处。一方面,我们可以在组织上划分数据预处理和模型架构工作之间的职责。另一方面,我们可以方便地调试、测试和生成预处理输出的统计信息。transform 组件输出转换后的训练集,作为 TFRecords,这些训练集易于检查。
在 Transform 输出的「调试」过程中,我们发现了一些小错误,这些错误不会导致模型的训练失败,但可能会影响其性能。例如,[SEP] 标记中的偏移量。从技术上来讲,这里不需要 TensorFlow Transform。由于每个示例的预处理独立于整个语料库进行,我们可以很容易地将其直接构建到模型图中。但是,我们发现用这种方法构建和调试管道会更容易。
图 4:BERT 层
理想的部署?
简化开发
通过使用各种 TensorFlow 工具,我们能够以简单而简洁的方式部署 BERT 模型。将预处理步骤集成到模型图中可以减少训练数据和推理数据之间的倾斜风险。部署的模型不需要额外的客户机或服务器依赖项,这进一步降低了模型错误的风险。我们可以将我们的 BERT 模型与 TensorFlow Serving 一致地部署,同时还可以利用模型优化——如批处理推断。
推理性能
我们最初的性能测试看起来很有希望。在我们的演示 BERT 模型图上的推论,包含预处理步骤和每个预测模型。这些模型平均约 15.5 ms,它们是在单个 V100 GPU、最多 128 个标记、gRPC 请求上测量的,由 GPU 的非优化 TensorFlow 服务构建的无基础 BERT 模型。这和以前在客户端使用 BERT 标记化的部署以及使用 TensorFlow Serving 托管的分类模型的平均推断时间大致相同。当然,根据你的机器及其型号的不同,你可能会看到不同的结果。
了解更多信息
如果你想深入了解代码,请查看 Colab notebook,其中有一个使用预先训练的 BERT 模型实现情感分类模型的示例。如果你想试用我们的演示部署,请查看 Concur 实验室的演示页面,上面展示了我们的情感分类项目。
如果你对 TensorFlow Extended(TFX)和 TensorFlow Transform 的内部工作感兴趣,请进入 TFX 用户指南并查看即将出版的 O'Reilly 出版物「Building Machine Learning Pipelines, Automating Model Life Cycles With TensorFlow」。
要了解有关 TFX 的更多信息,请访问 TFX 网站,加入 TFX 讨论组,浏览 TFX 博客中的其他文章,或者在 YouTube 上观看我们的 TFX 播放列表,并订阅 TensorFlow 频道。
TFX 讨论小组:https://groups.google.com/a/tensorflow.org/forum/#!forum/tfx
YouTube TFX 播放列表:https://www.youtube.com/playlist?list=PLQY2H8rRoyvxR15n04JiW0ezF5HQRs_8F
TensorFlow 频道:https://goo.gle/2WtM7Ak
雷锋网雷锋网雷锋网