BERT问答模型回答问题

在数据准备阶段,确保您有一个高质量的问答对数据集非常重要。这个数据集应该包含问题和对应的答案,以及答案在上下文中的位置(起始和结束索引)。

预处理数据时,清洗数据、去除无用信息、分词、转换为小写等操作可以帮助提高模型的性能。

在选择模型架构阶段,使用预训练的BERT模型作为基础是一个很好的选择。在BERT模型之上添加一个问答头部,通常是两个线性层,一个用于预测答案的起始位置,另一个用于预测答案的结束位置。

设置训练环境时,选择合适的损失函数和优化器非常重要。交叉熵损失通常用于训练起始和结束位置的预测,而Adam优化器是一种常用的优化器。学习率和学习率调度器也需要进行适当的设置。

在训练模型阶段,使用训练集数据训练模型,并在每个epoch结束后使用验证集评估模型性能。

使用早停来避免过拟合是一个好的做法。

在评估和测试阶段,使用测试集来评估模型性能,并使用评价指标如精确度、召回率、F1分数等来衡量模型的性能。

根据评估结果调整模型架构或超参数,可能需要进行更多的数据清洗或增强。

最后,将训练好的模型部署到生产环境中,以回答实际的问题。


import tensorflow as tf
import tensorflow_hub as hub
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.losses import SparseCategoricalCrossentropy

 

# 加载预训练的BERT模型
# trainable=True 表示在训练过程中BERT模型的参数也会被更新
bert_layer = hub.KerasLayer("https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/3",
                            trainable=True)

 

# 构建问答模型
# 定义模型的输入,这里需要三个输入:
# input_word_ids: 输入序列的token ids
# input_mask: 用于区分真实token和填充token的掩码
# segment_ids: 用于区分第一个句子和第二个句子的标记(对于问答任务通常不需要)


input_word_ids = tf.keras.layers.Input(shape=(None,), dtype=tf.int32, name='input_word_ids')
input_mask = tf.keras.layers.Input(shape=(None,), dtype=tf.int32, name='input_mask')


segment_ids = tf.keras.layers.Input(shape=(None,), dtype=tf.int32, name='segment_ids')

 

# 将输入传递给BERT模型
pooled_output, sequence_output = bert_layer([input_word_ids, input_mask, segment_ids])

# 添加问答头部
# 这里使用两个独立的线性层来预测答案的起始和结束位置
start_logits = tf.keras.layers.Dense(1, name="start_logit", use_bias=False)(sequence_output)


start_logits = tf.keras.layers.Flatten()(start_logits)

 

end_logits = tf.keras.layers.Dense(1, name="end_logit", use_bias=False)(sequence_output)


end_logits = tf.keras.layers.Flatten()(end_logits)

 

# 使用softmax激活函数将线性层的输出转换为概率分布
start_probs = tf.keras.layers.Activation(tf.keras.activations.softmax)(start_logits)


end_probs = tf.keras.layers.Activation(tf.keras.activations.softmax)(end_logits)

 

# 定义最终的模型
model = tf.keras.Model(inputs=[input_word_ids, input_mask, segment_ids], outputs=[start_probs, end_probs])

# 设置训练参数
# 使用Adam优化器和交叉熵损失函数
optimizer = Adam(learning_rate=5e-5)


loss = SparseCategoricalCrossentropy(from_logits=False)

model.compile(optimizer=optimizer, loss=[loss, loss])  

# 使用两个损失函数,一个用于起始位置,一个用于结束位置

# 准备数据
# 假设有一个数据集,其中包含编码后的输入ids、注意力掩码、起始位置和结束位置
# 这里没有提供数据集的具体实现,因为它将依赖于您的数据格式和预处理步骤
train_dataset = ...  # 包含编码后的输入ids、注意力掩码、起始位置和结束位置

# 训练模型
# 使用fit方法进行训练,指定训练集、训练轮数和批处理大小
model.fit(train_dataset, epochs=3, batch_size=8)

# 保存模型
# 训练完成后,保存模型以便将来使用或部署
model.save('./my_qa_model')

 

在这个例子中,我们使用TensorFlow和TensorFlow Hub来构建和训练一个问答模型。我们从TensorFlow Hub加载了一个预训练的BERT模型,并在其基础上添加了一个简单的问答头部,该头部由两个线性层组成,用于预测答案的起始和结束位置。

 

然后,我们编译模型,指定优化器和损失函数,并在准备好的数据集上进行训练。最后,我们保存了训练好的模型。

这个例子假设您已经有了一个适当格式的训练数据集,其中包含了编码后的输入ids、注意力掩码、以及答案的起始和结束位置。

 

在实际应用中,需要根据自己的数据集来实现数据加载和预处理的逻辑。建议参考下面的公开数据集。

 

问答(QA)模型通常使用的数据集包含了一系列的问题、上下文(问题的答案所在的文本段落)以及答案在上下文中的确切位置。一个典型的QA数据集条目可能包括以下字段:

 context : 一个文本段落,其中包含了一个或多个问题的答案。
 question : 针对上下文的一个问题。
 answer : 上下文中的一个文本片段,是对问题的答案。
 start_position : 答案在上下文中的起始字符索引。
 end_position : 答案在上下文中的结束字符索引。

以下是一个简化的QA数据集的模拟例子:

 
[
  {
    "context": "TensorFlow is an open source software library for high performance numerical computation.",
    "question": "What is TensorFlow?",
    "answer": "an open source software library for high performance numerical computation",
    "start_position": 13,
    "end_position": 80
  },
  {
    "context": "Paris is the capital and most populous city of France.",
    "question": "What is the capital of France?",
    "answer": "Paris",
    "start_position": 0,
    "end_position": 5
  },
  {
    "context": "The mitochondrion is the powerhouse of the cell.",
    "question": "What is referred to as the powerhouse of the cell?",
    "answer": "The mitochondrion",
    "start_position": 0,
    "end_position": 17
  }
]
 

在实际的训练过程中,您需要将这些数据转换为模型可以理解的格式。这通常涉及以下步骤:

使用BERT的tokenizer将 context 和 question 文本转换为token ids。
创建 attention_mask 以区分真实的token和填充的token。
创建 token_type_ids (也称为 segment_ids )以区分问题和上下文。
将答案的 start_position 和 end_position 转换为token级别的索引。
Hugging Face的Transformers库来准备数据的示例代码:
from transformers import BertTokenizer


# 初始化tokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

# 模拟的数据集
dataset = [
  {
    "context": "TensorFlow is an open source software library for high performance numerical computation.",
    "question": "What is TensorFlow?",
    "answer": "an open source software library for high performance numerical computation",
    "start_position": 13,
    "end_position": 80
  },
  # ... 其他数据条目
]

# 准备模型输入
inputs = []
for item in dataset:
    # 对context和question进行编码
    encoded = tokenizer.encode_plus(
        item['question'],
        item['context'],
        max_length=512,
        truncation=True,
        padding='max_length',
        return_tensors='tf'
    )
    # 找到答案的token级别的start和end位置
    start_position =

encoded.char_to_token(item['start_position'])
    end_position = encoded.char_to_token(item['end_position'] - 1)  # -1因为end_position是包含的
   
    # 如果答案的某部分被截断了,那么我们需要处理这种情况
    if start_position is None or end_position is None:
        start_position = tokenizer.model_max_length
        end_position = tokenizer.model_max_length
   
    inputs.append({
        'input_ids': encoded['input_ids'],
        'attention_mask': encoded['attention_mask'],
        'token_type_ids': encoded['token_type_ids'],
        'start_position': start_position,
        'end_position': end_position
    })

# 将输入转换为TensorFlow的Dataset对象
def map_example_to_dict(input_ids, attention_mask, token_type_ids, start_position, end_position):
    return {
        "input_word_ids": input_ids,
        "input_mask": attention_mask,
        "segment_ids": token_type_ids,
    }, {
        "start_positions": start_position,
        "end_positions": end_position
    }

# 创建tf.data.Dataset
train_data = tf.data.Dataset.from_generator(
    lambda: inputs,
    output_types=({'input_ids': tf.int32, 'attention_mask': tf.int32, 'token_type_ids': tf.int32,
                   'start_position': tf.int32, 'end_position': tf.int32}),
    output_shapes=({'input_ids': (None,), 'attention_mask': (None,), 'token_type_ids': (None,),
                    'start_position': (), 'end_position': ()})
)

train_data = train_data.map(
    lambda x: map_example_to_dict(x['input_ids'], x['attention_mask'], x['token_type_ids'],
                                  x['start_position'], x['end_position'])
)
 

在这个例子中,首先使用tokenizer将文本转换为模型可以理解的格式,然后创建一个 tf.data.Dataset 对象,它可以被用来训练模型。

注意,需要处理可能由于截断而导致答案不完整的情况。

在这种情况下,将答案的位置设置为最大长度,这意味着答案不在输入中。

在实际训练时,需要确保这种情况得到妥善处理。


SQuAD (Stanford Question Answering Dataset): 由斯坦福大学发布的英文问答数据集,包含10万个问题-答案对,这些问题是基于维基百科文章提出的。


CoQA (Conversational Question Answering Challenge): 一个面向会话式问答的数据集,包含12万个问题-答案对,这些对话是基于多种文本来源构建的。


MS MARCO (Microsoft Machine Reading Comprehension): 微软发布的大规模问答数据集,旨在提供真实世界的机器阅读理解训练数据。


Natural Questions (NQ): 由谷歌发布的问答数据集,包含自然提出的问题和维基百科页面作为上下文的答案。


HotpotQA: 一个问答数据集,要求模型进行多跳推理,即从多个文档中收集信息以回答问题。


TriviaQA: 包含大量的问答对,这些问题是基于Trivia知识提出的,答案需要从相关的文档中找到。


DuReader: 是一个中文问答数据集,由百度发布,包含了大量的真实用户提出的问题和长文本答案。


CMRC (Chinese Machine Reading Comprehension): 中文阅读理解数据集,包含了大量的问答对,旨在评估机器对中文文本的理解能力。


XQuAD (Cross-lingual Question Answering Dataset): 一个跨语言问答数据集,包含多种语言的翻译版本,旨在评估跨语言问答模型的性能。


MLQA (Multilingual Question Answering): 一个多语言问答数据集,支持问答任务的跨语言评估。

1. **OMGEval**: 这是一个多语言开放式问答数据集,由北京语言大学、清华大学等高校组成的团队共同发布。它支持生成式评估基准测试,适用于基础模型的评价。数据集已在GitHub上开源,可供研究人员和开发者使用。
2. **XQA**: 针对跨语言OpenQA(开放领域问答),这个数据集专门设计来处理问题与文档之间的关系以及对整个文档的理解。它旨在填补现有数据集中对跨语言理解的空白。
3. **百度知道知识类数据集**: 这个数据集包含大约147万个样本,是百度知道平台上的知识类问答对,适合用来训练和测试中文问答系统。
4. **webtext2019zh知识类数据集**: 这个数据集拥有约425万个社区问答对,是一个大规模的知识类数据集,同样适用于中文问答系统的开发。

开放的数据集很多,多留意开源社区,这里提供一种极度方便的方案,那就是直接用谷歌的TensorFlow 

 

TensorFlow Datasets 提供了一个简单的API来下载和准备数据集,使得加载数据变得非常容易。

这些数据集涵盖了多种机器学习任务,包括图像分类、文本分类、翻译、问答等。

import tensorflow_datasets as tfds

# 加载数据集,例如SQuAD
dataset, info = tfds.load('squad', with_info=True)

# dataset是一个tf.data.Dataset对象,可以用于迭代和训练模型
train_dataset = dataset['train']
validation_dataset = dataset['validation']

# 例如,迭代训练数据集中的条目
for example in train_dataset.take(1):
    print(example)
 
TensorFlow Datasets 中的数据集通常已经预处理成了一种标准格式,但可以查看  info  对象来获取数据集的详细信息,包括特征描述、数据集大小、类别标签等。

查看 TensorFlow Datasets 中都有哪些可用的问答数据集,可以访问 TensorFlow Datasets 的官方目录:

https://www.tensorflow.org/datasets/catalog/overview

 

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

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

相关文章

基于二值化图像转GCode的斜向扫描实现

基于二值化图像转GCode的斜向扫描实现 什么是斜向扫描斜向扫描代码示例 基于二值化图像转GCode的斜向扫描实现 什么是斜向扫描 在激光雕刻中,斜向扫描(Diagonal Scanning)是一种雕刻技术,其中激光头沿着对角线方向来回移动&…

C++面试:表结构设计规范

目录 表结构设计规范 示例 第一个 第二个 1. 合理选择数据类型 2. 使用主键 3. 避免使用NULL 4. 规范命名 5. 规范化 6. 使用索引优化查询 7. 考虑关系完整性 8. 避免过宽的表 9. 预留扩展性 10. 安全性考虑 表结构设计是数据库设计的重要组成部分,它…

编译opencv4.6问题汇总,第三方软件包见我发的资源

win10系统 python3.8.2,cmake-3.15.5-win64-x64,opencv4.6 编译方式见:OpenCV的编译 - 知乎 本文主要总结问题。赠人玫瑰手留余香。 问题1 Problem with installing OpenCV using Visual Studio and CMake (error code: MSB3073) 解决方法…

c# textbox 提示文字

1. 定义提示文字内容 private readonly string RemarkText "最多输入100字"; // 提示文字 2. 添加textbox 焦点事件, 初始化textbox提示文字和字体颜色 public UserControl(){InitializeComponent();tb_Remark.Text RemarkText;tb_Remark.ForeColor…

R语言基础学习-01 (此语言用途小众 用于数学 生物领域 基因分析)

R 语言特点 R 语言环境软件属于 GNU 开源软件,兼容性好、使用免费语法十分有利于复杂的数学运算数据类型丰富,包括向量、矩阵、因子、数据集等常用数据结构代码风格好,可读性强 简单 虽然 R 主要用于统计分析或者开发统计相关的软件&#x…

微信小程序(二十六)列表渲染基础核心

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.列表渲染基础写法 2.外部索引和自身索引 源码&#xff1a; index.wxml <view class"students"><view class"item"><text>序号</text><text>姓名</text…

JUC并发编程

Java 并发编程&#xff08;Java Concurrency&#xff09;是指在 Java 程序中同时进行多个任务的一种编程方式。Java 提供了一套丰富的并发编程工具&#xff0c;其中包括 Java 并发包&#xff08;Java Concurrency Utilities&#xff0c;简称 JUC&#xff09;&#xff0c;用于简…

Unity2D_单向平台

类似空洞骑士 马里奥等各种2D游戏&#xff0c;其中都存在单向平台。 单向平台&#xff1a;角色可以从下穿过平台停在平台上&#xff0c;也可以从平台上按下或往下跳穿过平台 这里用Unity实现角色能跳上平台&#xff0c;也能按’下’穿过平台 平台需要使用Rigidbody2D Collid…

jQuery html的使用

jquery中的html方法可以获取和设置标签的html内容 var $div $("div")// 获取标签div的html内容alert($div.html())console.log($div.html()) .html: 设置标签的html内容&#xff0c;之前的内容会清除&#xff08;只会显示 CSDN&#xff09; // 设置标签的html内容&…

字符串中的单词反转【leetcode】

本题选自leetcode图解算法数据结构一书 你在与一位习惯从右往左阅读的朋友发消息&#xff0c;他发出的文字顺序都与正常相反但单词内容正确&#xff0c;为了和他顺利交流你决定写一个转换程序&#xff0c;把他所发的消息 message 转换为正常语序。 注意&#xff1a;输入字符串…

java学习笔记:java所有关键字汇总、解析及应用

文章目录 一、java的所有关键字汇总、解析及应用1. abstract2. assert3. boolean4. break5. byte6. case7. catch8. char9. class10. const11. continue12. default13. do14. double15. else16. enum17. extends18. final19. finally20. float21. for22. goto23. if24. impleme…

走迷宫-bfs

package Test;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;public class Main {static int N 110,hh 0,tt -1,n,m;static int[][] g new int[N][N]; //用来存储迷宫static int[][] d new int[N][N]; //用来存储d[i…

【C/Python】Gtk部件ListStore的使用

一、C语言 在GTK中&#xff0c;Gtk.ListStore是一个实现了Gtk.TreeModel接口的存储模型&#xff0c;用于在如Gtk.TreeView这样的控件中存储数据。以下是一个简单的使用Gtk.ListStore的C语言示例&#xff0c;该示例创建了一个列表&#xff0c;并在图形界面中显示&#xff1a; …

EasyExcel实现Excel文件导入导出

1 EasyExcel简介 EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。 github地址: https://github.com/alibaba/easyexcel 官方文档: https://www.yuque.com/easyexcel/doc/easyexcel Excel解析流程图: EasyExcel读取…

TensorFlow2实战-系列教程11:RNN文本分类3

&#x1f9e1;&#x1f49b;&#x1f49a;TensorFlow2实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Jupyter Notebook中进行 本篇文章配套的代码资源已经上传 6、构建训练数据 所有的输入样本必须都是相同shape&#xff08;文本长度&#xff0c;…

视网膜长尾数据

视网膜长尾数据 问题&#xff1a;视网膜疾病分类&#xff0c;解法&#xff1a;深度学习模型问题&#xff1a;数据复杂性处理&#xff0c;解法&#xff1a;多任务框架&#xff08;同时处理多种疾病&#xff09;和少量样本学习&#xff08;提高对罕见疾病的识别&#xff09;问题&…

记录解决报错--vue前后端分离,接口401(Unauthorized)

1.场景 前端访问不了后端接口。报错401。 2.解决步骤 ①在页面console.log(111)查看走到代码的位置没有。&#xff08;走到了&#xff0c;没问题&#xff09; ②查看vue.config.js配置。这段配置就是vue访问api的url。&#xff08;没问题&#xff09; devServer: {port: 80…

【Delphi】IDE 工具栏错乱恢复

由于经常会在4K和2K显示器上切换Delphi开发环境(IDE)&#xff0c;导致IDE工具栏错乱&#xff0c;咋样设置都无法恢复&#xff0c;后来看到红鱼儿的博客&#xff0c;说是通过操作注册表的方法&#xff0c;能解决&#xff0c;试了一下&#xff0c;果真好用&#xff0c;非常感谢分…

Java面试架构篇【一览众山小】

文章目录 &#x1f6a1; 简介☀️ Spring&#x1f425; 体系结构&#x1f420; 生命周期 &#x1f341; SpringMVC&#x1f330; 执行流程 &#x1f31c; SpringBoot&#x1f30d; 核心组件&#x1f38d; 自动装配&#x1f391; 3.0升级 &#x1f505; spring Cloud Alibaba&am…

获取依赖aar包的两种方式-在android studio里引入 如:glide

背景&#xff1a;我需要获取aar依赖到内网开发&#xff0c;内网几乎代表没网。 一、 如何需要获取依赖aar包 方式一&#xff1a;在官方的github中下载,耗时不建议 要从开发者网站、GitHub 存储库或其他来源获取 ‘com.github.bumptech.glide:glide:4.12.0’ AAR 包&#xff…