怎样在 TensorFlow 和 Python 中使用 BERT 问答

介绍

Tensorflow 是一个开源的端到端平台,用于构建机器学习驱动的应用程序。 它包含一组用于各种任务的丰富工具和库,但主要侧重于神经网络的训练和推理。 Tensorflow 用于多种应用,包括:

  • 搜索引擎 – 用于为搜索排名部署深度神经网络,如 Google 的 RankBrain。

  • 汽车 – 构建专为自动驾驶设计的神经网络。

  • 教育 – 设计模型以过滤教室中的有害聊天消息。

  • Medicare – 用于构建神经网络以从患者数据中检测潜在的健康并发症。

  • 文本摘要和情感分析。

Transformers 的双向编码器表示 (BERT) 是一种自然语言模型,它使用基于 Transformer 的机器学习技术来完成几种常见的语言功能,包括:

  • 情感分析 – 情感推断,例如确定电影评测的极性。

  • 自然语言推理——确定一个假设是否从一个前提逻辑地推导出来。

  • 命名实体识别——从非结构化文本中提取信息到预定义的类别中,例如人名、位置和数量。

  • 问答 – 构建对话式问题和回答系统,例如聊天机器人。

  • 文本生成 – 生成与人类书写的文本无法区分的文本。

  • 文本预测 – 撰写电子邮件时的预测性文本建议,例如 Gmail 的提示性文本。

  • 文字总结。

BERT 使用来自 Wikipedia 的 25 亿个单词和来自 Google 的 BookCorpus 的 8 亿个单词进行了预训练。

本指南介绍了怎样使用 Python 在 TensorFlow 中使用 BERT 实现问答。

先决条件

  • Python的工作知识。

  • 正确安装和配置 python 工具链,包括 pip(Python 版本 >= 3.7)。

设置项目虚拟环境

为您的应用程序创建一个隔离的虚拟环境:

  1. 安装 virtualenv 蟒蛇包:

    $ pip install virtualenv
    
  2. 创建项目目录:

    $ mkdir bert_QA
    
  3. 导航到新目录:

    $ cd bert_QA
    
  4. 创建虚拟环境:

    $ python3 -m venv env
    

    这将创建一个名为 env 包含用于控制虚拟环境的脚本,包括程序库。

  5. 激活虚拟环境:

    $ source env/bin/activate
    

安装 TensorFlow

要安装 TensorFlow,请输入以下命令:

$ pip install tensorflow

Tflite 模型制作者

Tflite 模型生成器是一个库,可简化使用自定义数据集训练 Tensorflow Lite 模型的过程。 它使用迁移学习来减少所需的训练数据量和时间。

tflite 模型生成器库降低了在为设备上的 ML 应用程序部署时将 Tensorflow 神经网络模型转换和调整为特定输入数据的复杂性。 这些模型可以进行微调以在内存和 CPU 受限的设备(如智能手机)上运行,而不会牺牲在这些低功耗设备上运行时的大部分准确性。

本指南使用 tflite 模型生成器库来微调 BERT 模型以进行问答。

安装 Tflite 模型制作工具

要安装 tflite 模型制造商库:

  1. 克隆存储库:

    git clone https://github.com/tensorflow/examples
    
  2. 安装要求:

    pip install -r examples/tensorflow_examples/lite/model_maker/requirements.txt
    
  3. 安装包:

    pip install -e examples/tensorflow_examples/lite/model_maker/pip_package/
    

构建 Lite 模型

要创建负责问答的微调 lite 模型,请创建一个 lite_model_gen.py 工作目录中的文件:

touch lite_model_gen.py

导入库

通过将以下行添加到 lite_model_gen.py 文件:

import tensorflow as tf

from tflite_model_maker import model_spec

from tflite_model_maker import question_answer

from tflite_model_maker.question_answer import DataLoader

从 tflit 模型生成器库中导入的类具有以下功能:

  • model_spec:用于选择代表模型的模型规范。

  • question_answer:用于数据加载和模型训练以进行问答。

  • DataLoader:提供用于在模型再训练期间加载自定义数据的通用实用程序。

选择模型规格

tflite 模型制作库支持 BERT-Base 和 MobileBERT 模型进行问答:

  • BERT 基础 – 这是广泛用于 NLP 任务的标准 BERT 模型。

  • 移动BERT – 是 BERT-Base 的紧凑版本,体积小约 4 倍,速度快近 6 倍。 尽管 MobileBERT 比 BERT-Base 小,但它取得了具有竞争力的结果,并且更适合智能手机等功率受限设备中的设备上用例。

  • MobileBERT-SQuAD – 该模型使用与 MobileBERT 相同的架构,但初始模型已经在 斯坦福问答数据集 (SQuAD) 1.1。 SQuAD 是一个阅读理解数据集,由群众工作者在一组维基百科文章中提出的问答对组成。 SQuAD 1.1 包含 500 多篇文章的 100,000 多个问答对。

要使用 MobileBERT-SQuAD 规范,请添加以下行:

# Model specification representing the model

spec = model_spec.get('mobilebert_qa_squad')

model_spec 有一个方法 – get,它将模型规范的名称作为参数。 对于使用 BERT 的问答任务,它可以将三个字符串中的任何一个作为参数:

  • mobilebert_qa_squad:指定 MobileBERT-SQuAD。

  • mobilebert_qa:指定 MobileBERT。

  • bert_qa:指定 BERT-Base。

获取训练数据

本指南使用 琐事QA 用于模型训练的数据集。 TriviaQA 是一个用于阅读理解和问答的大规模数据集,包含超过 65 万个问答证据三元组。

要加载数据集进行训练,应使用 TriviaQA 转换 python 脚本. 本指南将使用预先转换的数据集 训练验证.

要下载转换后的数据集,请添加以下行:

# Download archived version of already converted datasets

train_data_path = tf.keras.utils.get_file(

      fname="triviaqa-web-train-8000.json",

      origin='https://storage.googleapis.com/download.tensorflow.org/models/tflite/dataset/triviaqa-web-train-8000.json')



validation_data_path = tf.keras.utils.get_file(

      fname="triviaqa-verified-web-dev.json",

      origin='https://storage.googleapis.com/download.tensorflow.org/models/tflite/dataset/triviaqa-verified-web-dev.json')

tf.keras.utils.get_file 函数用于从给定 URL 下载文件,如果它尚未存在于缓存中。 名称 指定文件的名称,以及 起源 指定文件的原始 URL。 这将下载数据集并返回下载文件的路径。

加载数据集

通过添加以下行来加载数据集:

# Fetch the training and validation data

train_data = DataLoader.from_squad(train_data_path, spec, is_training=True)

validation_data = DataLoader.from_squad(validation_data_path, spec, is_training=False)

DataLoader.from_squad 以 SQuAD 格式加载传递的数据集并根据给定的文本预处理文本 型号规格. 此方法采用文件名和 型号规格 作为参数,可选参数包括 is_training– 一个布尔值,表示数据是否用于训练。

创建模型

创建 Tflite 模型:

# Create the model

model = question_answer.create(train_data, model_spec=spec)

question_answer.create class 方法加载数据并训练模型以进行问答。 它需要两个参数 – 训练数据和模型规范。 它还接受可选参数:

  • batch_size=None:训练的批量大小。

  • epochs=2: 训练的 epoch 数。

  • steps_per_epoch=None:在宣布一个时期完成并开始下一个时期之前的批次样本。 它默认运行,直到输入数据集用完为止。

  • shuffle=False: 采用布尔值确定输入数据是否应该被打乱。

此方法返回问答的模型实例。

评估模型

要使用验证数据集评估模型:

# Evaluate the model

model.evaluate(validation_data)

调用 evaluate 模型对象上的方法返回一个指标字典,包括 f1 得分和 exact_match.

导出模型

要导出 tflite 模型以用于设备上的问答:

# Export the model

model.export(export_dir=".")

这会将模型导出到默认的当前工作目录 TFLITE 格式。 其他导出格式包括 VOCABSAVED_MODEL.

模型生成代码

决赛 lite_model_gen.py 代码:

import tensorflow as tf

from tflite_model_maker import model_spec

from tflite_model_maker import question_answer

from tflite_model_maker.question_answer import DataLoader



# Model specification representing the model

spec = model_spec.get('mobilebert_qa_squad')



# Download archived version of already converted datasets

train_data_path = tf.keras.utils.get_file(

fname="triviaqa-web-train-8000.json", origin='https://storage.googleapis.com/download.tensorflow.org/models/tflite/dataset/triviaqa-web-train-8000.json')



validation_data_path = tf.keras.utils.get_file(

fname="triviaqa-verified-web-dev.json",

origin='https://storage.googleapis.com/download.tensorflow.org/models/tflite/dataset/triviaqa-verified-web-dev.json')



# Fetch the training and validation data

train_data = DataLoader.from_squad(train_data_path, spec, is_training=True)

validation_data = DataLoader.from_squad(validation_data_path, spec, is_training=False)



# Create the model

model = question_answer.create(train_data, model_spec=spec)



# Evaluate the model

model.evaluate(validation_data)



# Export the model

model.export(export_dir=".")

运行代码

运行代码:

$ python3 lite_model_gen.py

笔记:代码运行时间在一个小时到几个小时之间,具体取决于 CPU 性能或 GPU 的存在。

输出类似于:

…

….

Downloading data from https://storage.googleapis.com/download.tensorflow.org/models/tflite/dataset/triviaqa-web-train-8000.json

32571392/32570663 [==============================] - 0s 0us/step

32579584/32570663 [==============================] - 0s 0us/step

Downloading data from https://storage.googleapis.com/download.tensorflow.org/models/tflite/dataset/triviaqa-verified-web-dev.json

1171456/1167744 [==============================] - 0s 0us/step

1179648/1167744 [==============================] - 0s 0us/step



INFO:tensorflow:Retraining the models...

INFO:tensorflow:Retraining the models...

Epoch 1/2

1067/1067 [==============================] - 70867s 66s/step - loss: 1.1337 - start_positions_loss: 1.1310 - end_positions_loss: 1.1363

Epoch 2/2

1067/1067 [==============================] - 70983s 67s/step - loss: 0.7942 - start_positions_loss: 0.7934 - end_positions_loss: 0.7949



INFO:tensorflow:Made predictions for 200 records.

INFO:tensorflow:Made predictions for 200 records.

…

…

{'exact_match': 0.5986394557823129, 'final_f1': 0.6728435963129841}

…

…

INFO:tensorflow:TensorFlow Lite model exported successfully: ./model.tflite

运行成功后,将lite模型导出到当前项目目录。

建筑问答

为了集成导出的模型以进行问答,本指南使用了 TFlite Support 工具包。 该工具包带有强大的库,可将 TFLite 模型集成到不同的平台上。

安装:

$ pip install tflite-support

现在,创建问答脚本:

$ touch question_answer.py

导入库

导入 BertQuestionAnswerer 班级:

from tflite_support.task.text import BertQuestionAnswerer

伯特问答者 类对文本进行问答。

创建 BertQuestionAnswerer 对象

创建 伯特问答者 导出的 lite 模型中的对象:

# Create the BertQuestionAnswerer object from a TensorFlow lite model

question_answerer = BertQuestionAnswerer.create_from_file("./model.tflite")

这会返回一个 伯特问答者 从模型文件创建的对象。

创建问题答案上下文

问答需要上下文。 这个上下文可以是提出问题的段落或句子。 以下关于亚历山大大帝的文字来自 维基百科. 这将用作问答的上下文:

# Create context for question answering

context = "Alexander the Great was a king of the ancient Greek kingdom of Macedon. He succeeded his father Philip II to the throne in 336 BC at the age of 20, and spent most of his ruling years conducting a lengthy military campaign throughout Western Asia and Egypt. By the age of thirty, he had created one of the largest empires in history, stretching from Greece to northwestern India. He was undefeated in battle and is widely considered to be one of history's greatest and most successful military commanders. Until the age of 16, Alexander was tutored by Aristotle. In 335 BC, shortly after his assumption of kingship over Macedon, he campaigned in the Balkans and reasserted control over Thrace and Illyria before marching on the city of Thebes, which was subsequently destroyed in battle. Alexander then led the League of Corinth, and used his authority to launch the pan-Hellenic project envisaged by his father, assuming leadership over all Greeks in their conquest of Persia."

创建问题

根据上述上下文创建一个字典来保存问答对:

# Create questions

questions = {

    "Who is Alexander the Great": None,

    "Until the age of 16, who tutored Alexander": None,

}

回答问题

回答字典中的问题:

# Answer questions

for question in questions.keys():

   answer = question_answerer.answer(context, question)

   questions[question] = answer



print(questions)

answer 方法有两个参数,一个上下文和一个问题。 它根据上下文回答问题并返回一个 QuestionAnswererResult. 问题回答者结果 是由 伯特问答者.

最终问答代码

完整的 question_answer.py 代码:

from tflite_support.task.text import BertQuestionAnswerer



# Create the BertQuestionAnswerer object from a TensorFlow lite model

question_answerer = BertQuestionAnswerer.create_from_file("./model.tflite")



# Create context for question answering

context = "Alexander the Great was a king of the ancient Greek kingdom of Macedon. He succeeded his father Philip II to the throne in 336 BC at the age of 20, and spent most of his ruling years conducting a lengthy military campaign throughout Western Asia and Egypt. By the age of thirty, he had created one of the largest empires in history, stretching from Greece to northwestern India. He was undefeated in battle and is widely considered to be one of history's greatest and most successful military commanders. Until the age of 16, Alexander was tutored by Aristotle. In 335 BC, shortly after his assumption of kingship over Macedon, he campaigned in the Balkans and reasserted control over Thrace and Illyria before marching on the city of Thebes, which was subsequently destroyed in battle. Alexander then led the League of Corinth, and used his authority to launch the pan-Hellenic project envisaged by his father, assuming leadership over all Greeks in their conquest of Persia."



# Create questions

questions = {

    "Who is Alexander the Great": None,

    "Until the age of 16, who tutored Alexander": None,

}



# Answer questions

for question in questions.keys():

   answer = question_answerer.answer(context, question)

   questions[question] = answer



print(questions)

运行代码

运行上面的代码:

$ python3 question_answer.py

这会产生以下结果:

{

  'Who is Alexander the Great': QuestionAnswererResult(answers=[

      QaAnswer(pos=Pos(start=12, end=20, logit=-1.621170163154602), text="king of the ancient Greek kingdom of Macedon."), 

      QaAnswer(pos=Pos(start=12, end=27, logit=-2.1207242012023926), text="king of the ancient Greek kingdom of Macedon. He succeeded his father Philip II"),

      QaAnswer(pos=Pos(start=19, end=20, logit=-3.1698760986328125), text="Macedon."), 

      QaAnswer(pos=Pos(start=26, end=27, logit=-3.3418025970458984), text="Philip II"),

      QaAnswer(pos=Pos(start=12, end=12, logit=-3.3852314949035645), text="king")]), 



  'Until the age of 16, who tutored Alexander': QuestionAnswererResult(answers=[

      QaAnswer(pos=Pos(start=121, end=121, logit=7.933090686798096), text="Aristotle."), 

      QaAnswer(pos=Pos(start=118, end=121, logit=1.3499608039855957), text="tutored by Aristotle."), 

      QaAnswer(pos=Pos(start=121, end=122, logit=1.0493016242980957), text="Aristotle."), 

      QaAnswer(pos=Pos(start=110, end=121, logit=0.37497782707214355), text="Until the age of 16, Alexander was tutored by Aristotle."), 

      QaAnswer(pos=Pos(start=118, end=119, logit=-5.260964870452881), text="tutored")])

}

返回的 问题回答者结果 对象包含一个列表 QaAnswer代表对所提出问题的可能答案。 pos 标记答案在上下文中的相对位置,而 text 代表答案文本。

在第一个问题中,返回了五个可能的答案,其中两个是正确的,而在第二个问题中 – 5 个可能的答案中有 4 个是正确的。

结论

本指南介绍了怎样在 TensorFlow 中使用 BERT,方法是构建一个用于问答的精简模型并使用 Tflite 支持 用于在上下文中回答问题的库。

文章标题 名称(可选) 电子邮件(可选) 描述

发送建议

注:本教程在Vultr VPS上测试通过,如需部署请前往Vultr.com