写点什么

如何利用 TensorFlow Hub 让 BERT 开发更简单?

  • 2021-01-14
  • 本文字数:3818 字

    阅读完需:约 13 分钟

如何利用TensorFlow Hub 让BERT开发更简单?

在自然语言处理领域,BERT 和其他 Transformer 编码器架构都非常成功,无论是推进学术基准的技术水平,还是在 Google Search 这样的大规模应用中,均是如此。BERT 自 TensorFlow 创建以来一直可用,但它最初依赖于非 TensorFlow 的 Python 代码,以将原始文本转换为模型输入。

 

如今,在 TensorFlow 中构建 BERT 会更加简单。开发者可在 TensorFlow Hub 上使用预训练编码器和匹配的文本预处理模型。在 TensorFlow 中运行 BERT 对文本输入的操作只需要几行代码:

 

# Load BERT and the preprocessing model from TF Hub.preprocess = hub.load('https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/1')encoder = hub.load('https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/3')

# Use BERT on a batch of raw text inputs.input = preprocess(['Batch of inputs', 'TF Hub makes BERT easy!', 'More text.'])pooled_output = encoder(input)["pooled_output"]print(pooled_output)

tf.Tensor([[-0.8384154 -0.26902363 -0.3839138 ... -0.3949695 -0.58442086 0.8058556 ] [-0.8223734 -0.2883956 -0.09359277 ... -0.13833837 -0.6251748 0.88950026] [-0.9045408 -0.37877116 -0.7714909 ... -0.5112085 -0.70791864 0.92950743]],shape=(3, 768), dtype=float32
复制代码

 

这些编码器和预处理模型已经用 TensorFlow Model Garden 的 NLP 库构建,并以 SavedModel 格式导出到 TensorFlow Hub。实际上,预处理使用 TF.text 库中的 TensorFlow ops 输入文本进行标记化:允许开发者建立自己的 TensorFlow 模型,将原始文本输入到预测输出,而无需使用 Python 的循环。这样可以提高计算速度,去除样板代码,减少出错的可能性,并且可以将整个文本序列化为输出模型,使得 BERT 在生产环境中更容易使用。

 

为了详细说明这些模型的具体作用,我们发布了两个新的教程:

 

  • 初级教程:解决一项情感分析任务,不需要任何特殊定制,就能得到很好的模型质量。这是最简单的使用 BERT 和预处理模型的方法。

  • 高级教程:解决了在 TPU 上运行 GLUE 基准中的自然语言处理分类任务。它还说明了如何在需要多段输入的情况下使用预处理模型。

 

选择 BERT 模型

 

BERT 模型是在大型文本语料库(例如,Wikipedia 文章的归档)上使用自我监督任务进行预训练的,比如根据上下文预测句子中的单词。这种类型的训练使模型能够在没有标记数据的情况下学习文本语义的强大表示。但是训练它需要大量的计算:在 16 个 TPU 上花费 4 天的时间(如 2018 年 BERT 论文所报道的)。所幸的是,在这种昂贵的预训练完成一次后,我们就可以为许多不同的任务高效地重用这种丰富的表示了。

 

  • 八个 BERT 模型是与 BERT 原始作者发布的训练权重一起提供的。

  • 24 个 Small BERT 具有相同的通用架构,但 Transformer 会更少或更小,这让你可以探索速度、尺寸和质量之间的权衡。

  • ALBERT:这是四种不同大小的“A Lite Bert”,通过在层之间共享参数来减少模型大小(但不是计算时间)。

  • 8 个 BERT Experts 都具有相同的 BERT 架构和大小,但是为预训练域和中间微调任务提供了不同的选择,以便更好地配合目标任务。

  • Electra 具有与 BERT 相同的架构(有三种不同的大小),但在预训练时作为判别器,类似于生成对抗网络(Generative Adversarial Network,GAN)。

  • BERT 与 Talking-Heads Attention 和 Gated GELU [base, large] 对 Transformer 架构的核心进行了两个改进。

  • Lambert 已经接受了一些由 LAMB 优化器和 Roberta 提供的技术训练。

  • .......

 

这些模型是 BERT 编码器。上述链接将可以访问 TF Hub 上的文档,其中提到了各自所使用的正确的预处理模型。我们建议开发者访问这些模型页面,以便了解更多关于每个模型所针对的不同应用场景。基于其通用界面,通过更改编码器模型及其预处理的 URL,可以方便地对不同编码器进行特定任务的性能实验和比较。

预处理模型

 

对于每个 BERT 编码器,都有一个匹配的预处理模型。它使用 TF.text 库提供的 TensorFlow ops,它可以将原始文本转换为编码器所期望的数字输入时序。不像纯 Python 的预处理那样,这些操作可以作为 TensorFlow 模型的一部分,用于直接从文本输入中提供服务。每个 TF Hub 的预处理模型都已经配置了词汇表及其相关的文本归一化逻辑,无需进行进一步的设置。

 

前面我们已经介绍了最简单的预处理模型的使用方法,接下来让我们仔细看看。


preprocess = hub.load('https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/1')input = preprocess(["This is an amazing movie!"]) {'input_word_ids': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=  array([[ 101, 2023, 2003, 2019, 6429, 3185,  999,  102,    0,  ...]])>, 'input_mask': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=  array([[   1,    1,    1,    1,    1,    1,    1,    1,    0,  ...,]])>, 'input_type_ids': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=  array([[   0,    0,    0,    0,    0,    0,    0,    0,    0,  ...,]])>}
复制代码

 

像这样调用 preprocess() 可以将原始文本输入转换为固定长度的 BERT 编码器输入序列。你可以看到,它由一个张量 input_word_ids 组成,其中包含了每个标记化输入的数字 id,包括开始、结束和填充标记,再加上两个辅助张量:一个 input_mask(用于区分非填充和填充标记)和每个标记的 input_type_ids(可以区分每个输入的多个文本段,我们将在下面讨论)。

 

相同的预处理 SavedModel 还提供了更细粒度的 API,支持在编码器的一个输入序列中使用一个或两个不同的文本段。下面我们来看一个句子蕴含任务:

 

text_premises = ["The fox jumped over the lazy dog.",                 "Good day."]tokenized_premises = preprocess.tokenize(text_premises) <tf.RaggedTensor  [[[1996], [4419], [5598], [2058], [1996], [13971], [3899], [1012]],  [[2204], [2154], [1012]]]> text_hypotheses = ["The dog was lazy.",  # Entailed.                   "Axe handle!"]        # Not entailed.tokenized_hypotheses = preprocess.tokenize(text_hypotheses) <tf.RaggedTensor  [[[1996], [3899], [2001], [13971], [1012]],  [[12946], [5047], [999]]]>
复制代码

 

每个标记化的结果是一个数字 token idRaggedTensor,完整地表示每一个文本输入。如果某些前提和假设对太长,无法在下一步用于 BERT 输入的 seq_length 内适应,则可以在这里进行额外的预处理,比如修剪文本段或将其分割成多个编码器输入。

 

然后,将标记化的输入打包为用于 BERT 编码器的固定长度的输入序列:

 

encoder_inputs = preprocess.bert_pack_inputs(   [tokenized_premises, tokenized_hypotheses],   seq_length=18)  # Optional argument, defaults to 128. {'input_word_ids': <tf.Tensor: shape=(2, 18), dtype=int32, numpy=  array([[  101,  1996,  4419,  5598,  2058,  1996, 13971,  3899,  1012,            102,  1996,  3899,  2001, 13971,  1012,   102,     0,     0],         [  101,  2204,  2154,  1012,   102, 12946,  5047,   999,   102,              0,     0,     0,     0,     0,     0,     0,     0,     0]])>, 'input_mask': <tf.Tensor: shape=(2, 18), dtype=int32, numpy=  array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],         [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]])>, 'input_type_ids': <tf.Tensor: shape=(2, 18), dtype=int32, numpy=  array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0],         [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]])>}
复制代码

 

打包的结果是已经熟悉的 input_word_idsinput_maskinput_type_ids(第一个和第二个输入分别为 0 和 1)。所有输出都有一个公共的 seq_length(默认为 128)。在打包过程中,超过 seq_length 的输入被截断为大致相等的大小。 

加速模型训练

 

TensorFlow Hub 将 BERT 编码器和预处理模型作为独立的部分,用于加速训练,特别是在 TPU 上。

 

张量处理单元(Tensor Processing Units,TPU)是 Google 定制开发的加速器硬件,它擅长于大规模机器学习计算,比如对 BERT 所需的计算进行微调。TPU 工作在密集的张量上,并期望像字符串这样的可变长度数据,已由主机 CPU 转换为固定大小的张量。

 

由于 BERT 编码器模型与其相关的预处理模型之间的解耦,可以将编码器微调计算作为模型训练的一部分分配给 TPU,而预处理模型则在主机 CPU 上执行。通过使用 tf.data.Dataset.map(),可以在数据集中异步运行预处理计算,并且 TPU 上的编码器模型可以消耗密集的输出。这种异步预处理还可以改善其他加速器的性能。

 

我们的高级 BERT 教程可以在使用 TPU 工作器的 Colab 运行时中运行,并演示了这种端到端的方式。

总结

 

在 TensorFlow 中使用 BERT 和类似的模型已经变得更加简单了。TensorFlow Hub 提供了大量预训练 BERT 编码器文本预处理模型,只需几行代码就能很容易地使用。

 

作者介绍:

 

Arno Eigenwillig,软件工程师。 Luiz GUStavo Martins,开发技术推广工程师。

 

原文链接:

 

https://blog.tensorflow.org/2020/12/making-bert-easier-with-preprocessing-models-from-tensorflow-hub.html

2021-01-14 09:522447
用户头像
赵钰莹 极客邦科技 总编辑

发布了 894 篇内容, 共 677.8 次阅读, 收获喜欢 2694 次。

关注

评论

发布
暂无评论
发现更多内容

2021高级Android笔试总结,Android系列学习进阶视频

欢喜学安卓

android 程序员 面试 移动开发

GitHub标星15k+的Java编程思想最新中文版,肝了一周整理成1539页的PDF文档免费分享!

Java架构之路

Java 程序员 架构 编程语言

拍乐云将亮相 QCon 大会,揭秘音视频“两高一低”体验背后的技术

拍乐云Pano

推特视频怎么保存: 免费下载Twitter视频教程

科技猫

twitter 分享 经验分享 教程 视频处理

2021金三银四Android大厂面试题来袭!高级面试题+解析

欢喜学安卓

android 程序员 面试 移动开发

阿里架构师478页Java工程师面试知识解析笔记pdf,一份2021年通往阿里的面试指南

Java架构之路

Java 程序员 架构 面试 编程语言

超详细!看完阿里大师的Java成长笔记后,差距真不是一点点

Java 程序员 架构 面试

逻辑回归 - DAY 11

Qien Z.

线性回归 逻辑回归 5月日更 逻辑函数

【LeetCode】将句子排序Java题解

Albert

算法 LeetCode 5月日更

多租户如何独立进行开发测试?

paraboy1

从根上理解用户态与内核态

程序猿阿星

系统上下文 用户空间 内核空间 指令集

量化策略交易软件,马丁倍投智能交易机器人

只需三步,开启 API 文档简洁之美

CODING DevOps

API

CODING CD + Nginx Ingress 实现蓝绿发布

CODING DevOps

DevOps 敏捷开发 研发管理 CODING 研发团队

打破固有思维(十五)

Changing Lin

5月日更

融合创新,降低门槛,飞桨推动人工智能走通工业大生产之路

百度大脑

人工智能 飞桨

边缘计算应用领域

lenka

5月日更

11 步完美排查服务器! 是否已经被入侵

Thrash

安全

牛!大佬都在用。Ngrok + Metasploit = 暂时性隐蔽C2

Thrash

安全

拍照被嫌弃,他用分布式技术开发了一款自拍神器

科技汇

CODING 首届金融科技技术交流闭门会议顺利召开

CODING DevOps

DevOps DevSecOps 代码安全

专访新腾数致研发总监金涛:新思想、新工具与新效率

CODING DevOps

敏捷开发 研发团队

CODING 增强安全漏洞扫描能力,助力团队“安全左移”

CODING DevOps

代码扫描 CODING 代码安全

图扑软件正式加入腾讯智维生态发展计划,聚焦智能IDC

一只数据鲸鱼

数据中心 数据可视化 机房管理 智能IDC

java中的Stream实践

林一

Lambda stream java8

网络攻防学习笔记 Day21

穿过生命散发芬芳

5月日更 网络攻防

来自一个DBA的肺腑之言

BinTools图尔兹

数据库 运维自动化 数据安全 dba

支付网关整体架构图

try catch

支付 支付网关

GitHub收藏最高的10个Java练手项目推荐

北游学Java

Java spring 项目实战

Alibaba技术专家必知必会的Java技术知识点,掌握这些理论+实践+技术是你通往阿里的路

Java架构之路

Java 程序员 架构 面试 编程语言

招行票付通对接总体流程

try catch

支付 商业票据

如何利用TensorFlow Hub 让BERT开发更简单?_AI&大模型_Arno Eigenwillig_InfoQ精选文章