写点什么

医疗领域实体抽取:UIE Slim 最新升级版含数据标注、serving 部署、模型蒸馏等教学,助力工业应用场景快速落地

  • 2023-05-30
    浙江
  • 本文字数:25434 字

    阅读完需:约 83 分钟

医疗领域实体抽取:UIE Slim最新升级版含数据标注、serving部署、模型蒸馏等教学,助力工业应用场景快速落地

医疗领域实体抽取:UIE Slim 最新升级版含数据标注、serving 部署、模型蒸馏等教学,助力工业应用场景快速落地

本项目为 UIE 框架升级版本实体关系抽取,详细讲解了数据标注,以及医疗领域 NER 微调,同时完成基于 SimpleServing 的快速服务化部署,并考虑了在一些工业应用场景中对性能的要求较高,若不能有效压缩则无法实际应用。因此,将 UIE 模型的知识迁移到封闭域信息抽取小模型,同时使用 FasterTokenizer 进行文本预处理加速,整体提速 7.6x 倍。


UIE(Universal Information Extraction):Yaojie Lu 等人在 ACL-2022 中提出了通用信息抽取统一框架 UIE。该框架实现了实体抽取、关系抽取、事件抽取、情感分析等任务的统一建模,并使得不同任务间具备良好的迁移和泛化能力。为了方便大家使用 UIE 的强大能力,PaddleNLP 借鉴该论文的方法,基于 ERNIE 3.0 知识增强预训练模型,训练并开源了首个中文通用信息抽取模型 UIE。该模型可以支持不限定行业领域和抽取目标的关键信息抽取,实现零样本快速冷启动,并具备优秀的小样本微调能力,快速适配特定的抽取目标。



  • 框架升级:预训练模型参数配置统一,自定义参数配置的保存和加载无需额外开发:

  • Trainer API 新增 BF16 训练、Recompute 重计算、Sharding 等多项分布式能力,通过简单配置即可进行超大规模预训练模型训练;

  • 模型压缩 API 支持量化训练、词表压缩等功能,压缩后的模型精度损失更小,模型部署的内存占用大大降低;

  • 数据增强 API 全面升级,支持字、词、句子三种粒度数据增强策略,可轻松定制数据增强策略

相关链接以及码源见文末

1.通用信息抽取案例展示

paddlenlp.Taskflow 提供通用信息抽取、评价观点抽取等能力,可抽取多种类型的信息,包括但不限于命名实体识别(如人名、地名、机构名等)、关系(如电影的导演、歌曲的发行时间等)、事件(如某路口发生车祸、某地发生地震等)、以及评价维度、观点词、情感倾向等信息。用户可以使用自然语言自定义抽取目标,无需训练即可统一抽取输入文本中的对应信息。


1.1 实体抽取

命名实体识别(Named Entity Recognition,简称 NER),是指识别文本中具有特定意义的实体。在开放域信息抽取中,抽取的类别没有限制,用户可以自己定义。


#使用最新版本paddlenlp!pip install -U paddlenlp
复制代码


#中文案例from pprint import pprintfrom paddlenlp import Taskflow
schema = ['肿瘤的大小', '肿瘤的个数', '肝癌级别', '脉管内癌栓分级']ie = Taskflow('information_extraction', schema=schema)pprint(ie("(右肝肿瘤)肝细胞性肝癌(II-III级,梁索型和假腺管型),肿瘤包膜不完整,紧邻肝被膜,侵及周围肝组织,未见脉管内癌栓(MVI分级:M0级)及卫星子灶形成。(肿物1个,大小4.2×4.0×2.8cm)。"))
复制代码


[2023-05-26 16:55:28,241] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load '/home/aistudio/.paddlenlp/taskflow/information_extraction/uie-base'.

[{'肝癌级别': [{'end': 20, 'probability': 0.9246461700957553, 'start': 13, 'text': 'II-III级'}], '肿瘤的个数': [{'end': 84, 'probability': 0.7917904385206498, 'start': 82, 'text': '1个'}], '肿瘤的大小': [{'end': 100, 'probability': 0.8300156430113255, 'start': 87, 'text': '4.2×4.0×2.8cm'}], '脉管内癌栓分级': [{'end': 70, 'probability': 0.9117306589152285, 'start': 67, 'text': 'M0级'}]}]
复制代码


#英文案例from pprint import pprintfrom paddlenlp import Taskflowschema = ['Person', 'Organization']ie_en = Taskflow('information_extraction', schema=schema, model='uie-base-en')pprint(ie_en('In 1997, Steve was excited to become the CEO of Apple.'))
复制代码


[2023-05-26 16:55:49,194] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load '/home/aistudio/.paddlenlp/taskflow/information_extraction/uie-base-en'.

[{'Organization': [{'end': 53, 'probability': 0.9997953278247742, 'start': 48, 'text': 'Apple'}], 'Person': [{'end': 14, 'probability': 0.9991742882141885, 'start': 9, 'text': 'Steve'}]}]
复制代码

1.2 关系抽取

关系抽取(Relation Extraction,简称 RE),是指从文本中识别实体并抽取实体之间的语义关系,进而获取三元组信息,即<主体,谓语,客体


from pprint import pprintfrom paddlenlp import Taskflowschema = {'竞赛名称': ['主办方', '承办方', '已举办次数']} ie = Taskflow('information_extraction', schema=schema)pprint(ie('2022语言与智能技术竞赛由中国中文信息学会和中国计算机学会联合主办,百度公司、中国中文信息学会评测工作委员会和中国计算机学会自然语言处理专委会承办,已连续举办4届,成为全球最热门的中文NLP赛事之一。'))
复制代码


[2023-05-26 17:00:58,587] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load '/home/aistudio/.paddlenlp/taskflow/information_extraction/uie-base'.

[{'竞赛名称': [{'end': 13, 'probability': 0.7825916894634872, 'relations': {'主办方': [{'end': 22, 'probability': 0.8421433086170715, 'start': 14, 'text': '中国中文信息学会'}, {'end': 30, 'probability': 0.758231755824518, 'start': 23, 'text': '中国计算机学会'}], '已举办次数': [{'end': 82, 'probability': 0.4663388767270149, 'start': 80, 'text': '4届'}], '承办方': [{'end': 39, 'probability': 0.8290383514873625, 'start': 35, 'text': '百度公司'}, {'end': 72, 'probability': 0.6189110006367571, 'start': 56, 'text': '中国计算机学会自然语言处理专委会'}, {'end': 55, 'probability': 0.6996860429707326, 'start': 40, 'text': '中国中文信息学会评测工作委员会'}]}, 'start': 0, 'text': '2022语言与智能技术竞赛'}]}]
复制代码


#英文案例schema = [{'Person': ['Company', 'Position']}]ie_en = Taskflow('information_extraction', schema=schema, model='uie-base-en')pprint(ie_en('In 1997, Steve was excited to become the CEO of Apple.'))
复制代码


[2023-05-26 17:02:06,079] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load '/home/aistudio/.paddlenlp/taskflow/information_extraction/uie-base-en'.

[{'Person': [{'end': 14, 'probability': 0.998905056612891, 'relations': {'Company': [{'end': 53, 'probability': 0.9975869289012067, 'start': 48, 'text': 'Apple'}], 'Position': [{'end': 44, 'probability': 0.9019888473388775, 'start': 41, 'text': 'CEO'}]}, 'start': 9, 'text': 'Steve'}]}]
复制代码

1.3 混合任务抽取

例如在法律场景同时对文本进行实体抽取和关系抽取,schema 可按照如下方式进行构造:


schema = ['法院', {'原告': '委托代理人'}, {'被告': '委托代理人'}]ie.set_schema(schema)pprint(ie("北京市海淀区人民法院\n民事判决书\n(199x)建初字第xxx号\n原告:张三。\n委托代理人李四,北京市 A律师事务所律师。\n被告:B公司,法定代表人王五,开发公司总经理。\n委托代理人赵六,北京市 C律师事务所律师。")) # Better print results using pprint
复制代码


[{'原告': [{'end': 37,          'probability': 0.9949732561990032,          'relations': {'委托代理人': [{'end': 46,                                   'probability': 0.7957008469207665,                                   'start': 44,                                   'text': '李四'}]},          'start': 35,          'text': '张三'}],  '法院': [{'end': 10,          'probability': 0.922022839827882,          'start': 0,          'text': '北京市海淀区人民法院'}],  '被告': [{'end': 67,          'probability': 0.8437379661680566,          'relations': {'委托代理人': [{'end': 92,                                   'probability': 0.7265425929861387,                                   'start': 90,                                   'text': '赵六'}]},          'start': 64,          'text': 'B公司'}]}]
复制代码

1.4 更多模型配置选择


from paddlenlp import Taskflowie = Taskflow('information_extraction',                  schema="",                  schema_lang="zh",                  batch_size=1,                  model='uie-base',                  position_prob=0.5,                  precision='fp32',                  use_fast=False)
复制代码


  • schema:定义任务抽取目标,可参考开箱即用中不同任务的调用示例进行配置。

  • schema_lang:设置 schema 的语言,默认为zh, 可选有zhen。因为中英 schema 的构造有所不同,因此需要指定 schema 的语言。该参数只对uie-m-baseuie-m-large模型有效。

  • batch_size:批处理大小,请结合机器情况进行调整,默认为 1。

  • model:选择任务使用的模型,默认为uie-base,可选有uie-base, uie-medium, uie-mini, uie-micro, uie-nanouie-medical-base, uie-base-en

  • position_prob:模型对于 span 的起始位置/终止位置的结果概率在 0~1 之间,返回结果去掉小于这个阈值的结果,默认为 0.5,span 的最终概率输出为起始位置概率和终止位置概率的乘积。

  • precision:选择模型精度,默认为fp32,可选有fp16fp32fp16推理速度更快,支持 GPU 和 NPU 硬件环境。如果选择fp16,在 GPU 硬件环境下,请先确保机器正确安装 NVIDIA 相关驱动和基础软件,确保 CUDA>=11.2,cuDNN>=8.1.1,初次使用需按照提示安装相关依赖。其次,需要确保 GPU 设备的 CUDA 计算能力(CUDA Compute Capability)大于 7.0,典型的设备包括 V100、T4、A10、A100、GTX 20 系列和 30 系列显卡等。更多关于 CUDA Compute Capability 和精度支持情况请参考 NVIDIA 文档:GPU硬件与支持精度对照表

  • use_fast: 使用 C++实现的高性能分词算子 FastTokenizer 进行文本预处理加速。需要通过pip install fast-tokenizer-python安装 FastTokenizer 库后方可使用。默认为False。更多使用说明可参考


# #中英文混合抽取# from pprint import pprint# from paddlenlp import Taskflow
# schema = ['Time', 'Player', 'Competition', 'Score']# ie = Taskflow('information_extraction', schema=schema, model="uie-m-base", schema_lang="en")# pprint(ie(["2月8日上午北京冬奥会自由式滑雪女子大跳台决赛中中国选手谷爱凌以188.25分获得金牌!", "Rafael Nadal wins French Open Final!"]))
复制代码


[2023-05-26 17:05:25,736] [    INFO] - We are using <class 'paddlenlp.transformers.ernie_m.tokenizer.ErnieMTokenizer'> to load '/home/aistudio/.paddlenlp/taskflow/information_extraction/uie-m-base'.

[{'Competition': [{'end': 23, 'probability': 0.9372359354800146, 'start': 6, 'text': '北京冬奥会自由式滑雪女子大跳台决赛'}], 'Player': [{'end': 31, 'probability': 0.6994761471998885, 'start': 28, 'text': '谷爱凌'}], 'Score': [{'end': 39, 'probability': 0.9887921351112396, 'start': 32, 'text': '188.25分'}], 'Time': [{'end': 6, 'probability': 0.9783122597547802, 'start': 0, 'text': '2月8日上午'}]}, {'Competition': [{'end': 35, 'probability': 0.985105301913876, 'start': 18, 'text': 'French Open Final'}], 'Player': [{'end': 12, 'probability': 0.9374054078857128, 'start': 0, 'text': 'Rafael Nadal'}]}]
复制代码

2.数据标注教学

2.1 基于 Label Studio 数据标注

2.1.1 Label Studio 安装

以下标注示例用到的环境配置:


  • Python 3.8+

  • label-studio == 1.7.0

  • paddleocr >= 2.6.0.1


在终端(terminal)使用 pip 安装 label-studio:


pip install label-studio==1.7.0
复制代码


安装完成后,运行以下命令行:


label-studio start
复制代码


在浏览器打开http://localhost:8080/,输入用户名和密码登录,开始使用 label-studio 进行标注。

2.1.2 文本抽取标注教学

  • 项目创建


点击创建(Create)开始创建一个新的项目,填写项目名称、描述,然后选择Object Detection with Bounding Boxes


  • 填写项目名称、描述


  • 命名实体识别、关系抽取、事件抽取、实体/评价维度分类任务选择``Relation Extraction`。


  • 添加标签(也可跳过后续在 Setting/Labeling Interface 中配置)



图中展示了实体类型标签的构建,其他类型标签的构建可参考


  • 数据上传


先从本地上传 txt 格式文件,选择List of tasks,然后选择导入本项目。



  • 标签构建


  • Span 类型标签



  • Relation 类型标签



Relation XML 模板:


  <Relations>    <Relation value="歌手"/>    <Relation value="发行时间"/>    <Relation value="所属专辑"/>  </Relations>
复制代码


  • 任务标注


  • 实体抽取


标注示例:



该标注示例对应的 schema 为:


schema = [    '时间',    '选手',    '赛事名称',    '得分']
复制代码


  • 关系抽取



对于关系抽取,其 P 的类型设置十分重要,需要遵循以下原则


“{S}的{P}为{O}”需要能够构成语义合理的短语。比如对于三元组(S, 父子, O),关系类别为父子是没有问题的。但按照 UIE 当前关系类型 prompt 的构造方式,“S 的父子为 O”这个表达不是很通顺,因此 P 改成孩子更好,即“S 的孩子为 O”。合理的 P 类型设置,将显著提升零样本效果


该标注示例对应的 schema 为:


schema = {    '作品名': [        '歌手',        '发行时间',        '所属专辑'    ]}
复制代码


该标注示例对应的 schema 为:


schema = '情感倾向[正向,负向]'
复制代码


  • 数据导出


勾选已标注文本 ID,选择导出的文件类型为JSON,导出数据:



  • 数据转换


将导出的文件重命名为label_studio.json后,放入./data目录下。通过label_studio.py脚本可转为 UIE 的数据格式。


  • 抽取式任务


python label_studio.py \    --label_studio_file ./data/label_studio.json \    --save_dir ./data \    --splits 0.8 0.1 0.1 \    --task_type ext
复制代码


  • 更多配置


  • label_studio_file: 从 label studio 导出的数据标注文件。

  • save_dir: 训练数据的保存目录,默认存储在data目录下。

  • negative_ratio: 最大负例比例,该参数只对抽取类型任务有效,适当构造负例可提升模型效果。负例数量和实际的标签数量有关,最大负例数量 = negative_ratio * 正例数量。该参数只对训练集有效,默认为 5。为了保证评估指标的准确性,验证集和测试集默认构造全负例。

  • splits: 划分数据集时训练集、验证集所占的比例。默认为[0.8, 0.1, 0.1]表示按照8:1:1的比例将数据划分为训练集、验证集和测试集。

  • task_type: 选择任务类型,可选有抽取和分类两种类型的任务。

  • options: 指定分类任务的类别标签,该参数只对分类类型任务有效。默认为["正向", "负向"]。

  • prompt_prefix: 声明分类任务的 prompt 前缀信息,该参数只对分类类型任务有效。默认为"情感倾向"。

  • is_shuffle: 是否对数据集进行随机打散,默认为 True。

  • seed: 随机种子,默认为 1000.

  • schema_lang:选择 schema 的语言,将会应该训练数据 prompt 的构造方式,可选有chen。默认为ch

  • separator: 实体类别/评价维度与分类标签的分隔符,该参数只对实体/评价维度分类任务有效。默认为"##"。


备注:


  • 默认情况下 label_studio.py 脚本会按照比例将数据划分为 train/dev/test 数据集

  • 每次执行 label_studio.py 脚本,将会覆盖已有的同名数据文件

  • 在模型训练阶段我们推荐构造一些负例以提升模型效果,在数据转换阶段我们内置了这一功能。可通过negative_ratio控制自动构造的负样本比例;负样本数量 = negative_ratio * 正样本数量。

  • 对于从 label_studio 导出的文件,默认文件中的每条数据都是经过人工正确标注的。


  • References


2.2 基于 doccano 数据标注

2.2.1 doccano 安装

以下标注示例用到的环境配置:


  • doccano 1.6.2


Step 1. 本地安装doccano($ pip install doccano
Step 2. 初始化数据库和账户(用户名和密码可替换为自定义值)#初始化,设置用户名= admin,密码=passdoccano initdoccano createuser --username admin --password pass -------------------------个人设置---------------------------$ doccano init $ doccano createuser --username my_admin_name --password my_password

Step 3. 启动doccano
在一个窗口启动doccano的WebServer,保持窗口$ doccano webserver --port 8000
在另一个窗口启动doccano的任务队列$ doccano task
打开浏览器(推荐Chrome),在地址栏中输入http://127.0.0.1:8000/后回车即得以下界面。
复制代码


更多详细内容见:A.1[数据标注]:强烈推荐数据标注平台doccano----简介、安装、使用、踩坑记录

2.2.2 标注教学

  • 抽取式任务项目创建


创建项目时选择序列标注任务,并勾选 Allow overlapping entity Use relation Labeling。适配命名实体识别、关系抽取、事件抽取、评价观点抽取等任务。



  • 数据上传


上传的文件为 txt 格式,每一行为一条待标注文本,示例:


2月8日上午北京冬奥会自由式滑雪女子大跳台决赛中中国选手谷爱凌以188.25分获得金牌第十四届全运会在西安举办
复制代码


上传数据类型选择 TextLine:



NOTE:doccano 支持TextFileTextLineJSONLCoNLL四种数据上传格式,UIE 定制训练中统一使用 TextLine 这一文件格式,即上传的文件需要为 txt 格式,且在数据标注时,该文件的每一行待标注文本显示为一页内容。


  • 构建抽取式任务标签


抽取式任务包含 Span Relation 两种标签类型,Span 指原文本中的目标信息片段,如实体识别中某个类型的实体,事件抽取中的触发词和论元;Relation 指原文本中 Span 之间的关系,如关系抽取中两个实体(Subject&Object)之间的关系,事件抽取中论元和触发词之间的关系。


Span 类型标签构建示例:



Relation 类型标签构建示例:



  • 任务标注

  • 命名实体识别


命名实体识别(Named Entity Recognition,简称 NER),是指识别文本中具有特定意义的实体。在开放域信息抽取中,抽取的类别没有限制,用户可以自己定义


标注示例:



示例中定义了时间选手赛事名称得分四种 Span 类型标签。


schema = [    '时间',    '选手',    '赛事名称',    '得分']
复制代码


  • 关系抽取


关系抽取(Relation Extraction,简称 RE),是指从文本中识别实体并抽取实体之间的语义关系,即抽取三元组(实体一,关系类型,实体二)。


标注示例:



示例中定义了作品名人物名时间三种 Span 类型标签,以及歌手发行时间所属专辑三种 Relation 标签。Relation 标签由 Subject 对应实体指向 Object 对应实体


该标注示例对应的 schema 为:


schema = {    '作品名': [        '歌手',        '发行时间',        '所属专辑'    ]}
复制代码


  • 数据导出

  • 导出抽取式和实体/评价维度级分类任务数据


选择导出的文件类型为JSONL(relation),导出数据示例:


{    "id": 38,    "text": "百科名片你知道我要什么,是歌手高明骏演唱的一首歌曲,1989年发行,收录于个人专辑《丛林男孩》中",    "relations": [        {            "id": 20,            "from_id": 51,            "to_id": 53,            "type": "歌手"        },        {            "id": 21,            "from_id": 51,            "to_id": 55,            "type": "发行时间"        },        {            "id": 22,            "from_id": 51,            "to_id": 54,            "type": "所属专辑"        }    ],    "entities": [        {            "id": 51,            "start_offset": 4,            "end_offset": 11,            "label": "作品名"        },        {            "id": 53,            "start_offset": 15,            "end_offset": 18,            "label": "人物名"        },        {            "id": 54,            "start_offset": 42,            "end_offset": 46,            "label": "作品名"        },        {            "id": 55,            "start_offset": 26,            "end_offset": 31,            "label": "时间"        }    ]}
复制代码


标注数据保存在同一个文本文件中,每条样例占一行且存储为json格式,其包含以下字段


  • id: 样本在数据集中的唯一标识 ID。

  • text: 原始文本数据。

  • entities: 数据中包含的 Span 标签,每个 Span 标签包含四个字段:

  • id: Span 在数据集中的唯一标识 ID。

  • start_offset: Span 的起始 token 在文本中的下标。

  • end_offset: Span 的结束 token 在文本中下标的下一个位置。

  • label: Span 类型。

  • relations: 数据中包含的 Relation 标签,每个 Relation 标签包含四个字段:

  • id: (Span1, Relation, Span2)三元组在数据集中的唯一标识 ID,不同样本中的相同三元组对应同一个 ID。

  • from_id: Span1 对应的标识 ID。

  • to_id: Span2 对应的标识 ID。

  • type: Relation 类型。


  • 数据转换


该章节详细说明如何通过doccano.py脚本对 doccano 平台导出的标注数据进行转换,一键生成训练/验证/测试集。


  • 抽取式任务数据转换


  • 当标注完成后,在 doccano 平台上导出 JSONL(relation) 形式的文件,并将其重命名为 doccano_ext.json 后,放入 ./data 目录下。

  • 通过 doccano.py 脚本进行数据形式转换,然后便可以开始进行相应模型训练。


python doccano.py \    --doccano_file ./data/doccano_ext.json \    --task_type "ext" \    --save_dir ./data \    --negative_ratio 5
复制代码


备注:


  • 默认情况下 doccano.py 脚本会按照比例将数据划分为 train/dev/test 数据集

  • 每次执行 doccano.py 脚本,将会覆盖已有的同名数据文件

  • 在模型训练阶段我们推荐构造一些负例以提升模型效果,在数据转换阶段我们内置了这一功能。可通过negative_ratio控制自动构造的负样本比例;负样本数量 = negative_ratio * 正样本数量。

  • 对于从 doccano 导出的文件,默认文件中的每条数据都是经过人工正确标注的。


  • References


3.基于医疗领域 NER 微调

3.1 加载数据数据标注

#加载数据集!wget https://bj.bcebos.com/paddlenlp/datasets/uie/data_distill/data.zip && unzip data.zip -d ./data
复制代码


--2023-05-26 17:35:27--  https://bj.bcebos.com/paddlenlp/datasets/uie/data_distill/data.zip正在解析主机 bj.bcebos.com (bj.bcebos.com)... 182.61.200.195, 182.61.200.229, 2409:8c04:1001:1002:0:ff:b001:368a正在连接 bj.bcebos.com (bj.bcebos.com)|182.61.200.195|:443... 已连接。已发出 HTTP 请求,正在等待回应... 200 OK长度: 135105 (132K) [application/zip]正在保存至: “data.zip.1”
data.zip.1 100%[===================>] 131.94K 774KB/s in 0.2s
2023-05-26 17:35:27 (774 KB/s) - 已保存 “data.zip.1” [135105/135105])
Archive: data.zip creating: ./data/data/ inflating: ./data/data/unlabeled_data.txt inflating: ./data/data/doccano_ext.json
复制代码


!python doccano.py \    --doccano_file ./data/data/doccano_ext.json \    --task_type ext \    --save_dir ./data \    --splits 0.8 0.15 0.05 \    --schema_lang ch
复制代码


[2023-05-26 17:46:51,321] [    INFO] - Converting doccano data...100%|██████████████████████████████████████| 160/160 [00:00<00:00, 35084.10it/s][2023-05-26 17:46:51,327] [    INFO] - Adding negative samples for first stage prompt...100%|█████████████████████████████████████| 160/160 [00:00<00:00, 311989.14it/s][2023-05-26 17:46:51,328] [    INFO] - Adding negative samples for second stage prompt...100%|███████████████████████████████████████| 160/160 [00:00<00:00, 1928.84it/s][2023-05-26 17:46:51,411] [    INFO] - Converting doccano data...100%|████████████████████████████████████████| 30/30 [00:00<00:00, 44259.28it/s][2023-05-26 17:46:51,412] [    INFO] - Adding negative samples for first stage prompt...100%|███████████████████████████████████████| 30/30 [00:00<00:00, 284681.27it/s][2023-05-26 17:46:51,413] [    INFO] - Adding negative samples for second stage prompt...100%|███████████████████████████████████████| 30/30 [00:00<00:00, 370085.65it/s][2023-05-26 17:46:51,413] [    INFO] - Converting doccano data...100%|████████████████████████████████████████| 10/10 [00:00<00:00, 46091.25it/s][2023-05-26 17:46:51,414] [    INFO] - Adding negative samples for first stage prompt...100%|███████████████████████████████████████| 10/10 [00:00<00:00, 194180.74it/s][2023-05-26 17:46:51,414] [    INFO] - Adding negative samples for second stage prompt...100%|███████████████████████████████████████| 10/10 [00:00<00:00, 252668.92it/s][2023-05-26 17:46:51,425] [    INFO] - Save 1566 examples to ./data/train.txt.[2023-05-26 17:46:51,427] [    INFO] - Save 186 examples to ./data/dev.txt.[2023-05-26 17:46:51,427] [    INFO] - Save 60 examples to ./data/test.txt.[2023-05-26 17:46:51,427] [    INFO] - Finished! It takes 0.11 seconds
复制代码


可配置参数说明:


  • doccano_file: 从 doccano 导出的数据标注文件。

  • save_dir: 训练数据的保存目录,默认存储在data目录下。

  • negative_ratio: 最大负例比例,该参数只对抽取类型任务有效,适当构造负例可提升模型效果。负例数量和实际的标签数量有关,最大负例数量 = negative_ratio * 正例数量。该参数只对训练集有效,默认为 5。为了保证评估指标的准确性,验证集和测试集默认构造全负例。

  • splits: 划分数据集时训练集、验证集所占的比例。默认为[0.8, 0.1, 0.1]表示按照8:1:1的比例将数据划分为训练集、验证集和测试集。

  • task_type: 选择任务类型,可选有抽取和分类两种类型的任务。

  • options: 指定分类任务的类别标签,该参数只对分类类型任务有效。默认为["正向", "负向"]。

  • prompt_prefix: 声明分类任务的 prompt 前缀信息,该参数只对分类类型任务有效。默认为"情感倾向"。

  • is_shuffle: 是否对数据集进行随机打散,默认为 True。

  • seed: 随机种子,默认为 1000.

  • separator: 实体类别/评价维度与分类标签的分隔符,该参数只对实体/评价维度级分类任务有效。默认为"##"。

  • schema_lang: 选择 schema 的语言,可选有chen。默认为ch,英文数据集请选择en


备注:


  • 默认情况下 doccano.py 脚本会按照比例将数据划分为 train/dev/test 数据集

  • 每次执行 doccano.py 脚本,将会覆盖已有的同名数据文件

  • 在模型训练阶段我们推荐构造一些负例以提升模型效果,在数据转换阶段我们内置了这一功能。可通过negative_ratio控制自动构造的负样本比例;负样本数量 = negative_ratio * 正样本数量。

  • 对于从 doccano 导出的文件,默认文件中的每条数据都是经过人工正确标注的。


此外,也可以通过数据标注平台 Label Studio 进行数据标注。本示例提供了 labelstudio2doccano.py 脚本,将 label studio 导出的 JSON 数据文件格式转换成 doccano 导出的数据文件格式,后续的数据转换与模型微调等操作不变。


python labelstudio2doccano.py --labelstudio_file label-studio.json
复制代码


可配置参数说明:


  • labelstudio_file: label studio 的导出文件路径(仅支持 JSON 格式)。

  • doccano_file: doccano 格式的数据文件保存路径,默认为 "doccano_ext.jsonl"。

  • task_type: 任务类型,可选有抽取("ext")和分类("cls")两种类型的任务,默认为 "ext"。

3.2 模型微调

推荐使用 Trainer API 对模型进行微调。只需输入模型、数据集等就可以使用 Trainer API 高效快速地进行预训练、微调和模型压缩等任务,可以一键启动多卡训练、混合精度训练、梯度累积、断点重启、日志显示等功能,Trainer API 还针对训练过程的通用训练配置做了封装,比如:优化器、学习率调度等。


使用下面的命令,使用 uie-base 作为预训练模型进行模型微调,将微调后的模型保存至 $finetuned_model:


单卡启动:


#单卡训练!python finetune.py  \    --device gpu \    --logging_steps 10 \    --save_steps 100 \    --eval_steps 100 \    --seed 42 \    --model_name_or_path uie-base \    --output_dir ./checkpoint/model_best \    --train_path data/train.txt \    --dev_path data/dev.txt  \    --max_seq_length 512  \    --per_device_eval_batch_size 16 \    --per_device_train_batch_size  16 \    --num_train_epochs 20 \    --learning_rate 1e-5 \    --label_names "start_positions" "end_positions" \    --do_train \    --do_eval \    --do_export \    --export_model_dir ./checkpoint/model_best \    --overwrite_output_dir \    --disable_tqdm True \    --metric_for_best_model eval_f1 \    --load_best_model_at_end  True \    --save_total_limit 1
复制代码


部分结果展示:


[2023-05-26 17:57:40,257] [    INFO] - eval_loss: 0.0049851336516439915, eval_precision: 0.6474820143884892, eval_recall: 0.72, eval_f1: 0.6818181818181818, eval_runtime: 1.4021, eval_samples_per_second: 132.655, eval_steps_per_second: 8.558, epoch: 20.0[2023-05-26 17:57:40,257] [    INFO] - ***** eval metrics *****[2023-05-26 17:57:40,257] [    INFO] -   epoch                   =       20.0[2023-05-26 17:57:40,257] [    INFO] -   eval_f1                 =     0.6818[2023-05-26 17:57:40,257] [    INFO] -   eval_loss               =      0.005[2023-05-26 17:57:40,257] [    INFO] -   eval_precision          =     0.6475[2023-05-26 17:57:40,257] [    INFO] -   eval_recall             =       0.72[2023-05-26 17:57:40,257] [    INFO] -   eval_runtime            = 0:00:01.40[2023-05-26 17:57:40,257] [    INFO] -   eval_samples_per_second =    132.655[2023-05-26 17:57:40,257] [    INFO] -   eval_steps_per_second   =      8.558
复制代码


#多卡训练:GPU环境中使用,可以指定gpus参数进行多卡训练:# !export finetuned_model=./checkpoint/model_best# !python -u -m paddle.distributed.launch --gpus "0,1" finetune.py \#     --device gpu \#     --logging_steps 10 \#     --save_steps 100 \#     --eval_steps 100 \#     --seed 42 \#     --model_name_or_path uie-base \#     --output_dir $finetuned_model \#     --train_path data/train.txt \#     --dev_path data/dev.txt  \#     --max_seq_length 512  \#     --per_device_eval_batch_size 16 \#     --per_device_train_batch_size  16 \#     --num_train_epochs 100 \#     --learning_rate 1e-5 \#     --do_train \#     --do_eval \#     --do_export \#     --export_model_dir $finetuned_model \#     --label_names "start_positions" "end_positions" \#     --overwrite_output_dir \#     --disable_tqdm True \#     --metric_for_best_model eval_f1 \#     --load_best_model_at_end  True \#     --save_total_limit 1 \
复制代码


注意:如果模型是跨语言模型 UIE-M,还需设置 --multilingual


可配置参数说明:


  • model_name_or_path:必须,进行 few shot 训练使用的预训练模型。可选择的有 "uie-base"、 "uie-medium", "uie-mini", "uie-micro", "uie-nano", "uie-m-base", "uie-m-large"。

  • multilingual:是否是跨语言模型,用 "uie-m-base", "uie-m-large" 等模型进微调得到的模型也是多语言模型,需要设置为 True;默认为 False。

  • output_dir:必须,模型训练或压缩后保存的模型目录;默认为 None

  • device: 训练设备,可选择 'cpu'、'gpu' 、'npu'其中的一种;默认为 GPU 训练。

  • per_device_train_batch_size:训练集训练过程批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为 32。

  • per_device_eval_batch_size:开发集评测过程批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为 32。

  • learning_rate:训练最大学习率,UIE 推荐设置为 1e-5;默认值为 3e-5。

  • num_train_epochs: 训练轮次,使用早停法时可以选择 100;默认为 10。

  • logging_steps: 训练过程中日志打印的间隔 steps 数,默认 100。

  • save_steps: 训练过程中保存模型 checkpoint 的间隔 steps 数,默认 100。

  • seed:全局随机种子,默认为 42。

  • weight_decay:除了所有 bias 和 LayerNorm 权重之外,应用于所有层的权重衰减数值。可选;默认为 0.0;

  • do_train:是否进行微调训练,设置该参数表示进行微调训练,默认不设置。

  • do_eval:是否进行评估,设置该参数表示进行评估。

3.3 模型评估

评估方式说明:采用单阶段评价的方式,即关系抽取、事件抽取等需要分阶段预测的任务对每一阶段的预测结果进行分别评价。验证/测试集默认会利用同一层级的所有标签来构造出全部负例。


可开启 debug 模式对每个正例类别分别进行评估,该模式仅用于模型调试:


!python evaluate.py \    --model_path ./checkpoint/model_best \    --test_path ./data/dev.txt \    --batch_size 16 \    --max_seq_len 512

复制代码


#对 UIE-M 进行模型评估:# !python evaluate.py \#     --model_path ./checkpoint/model_best \#     --test_path ./data/dev.txt \#     --batch_size 16 \#     --max_seq_len 512 \#     --multilingual
复制代码


#debug!python evaluate.py \    --model_path ./checkpoint/model_best \    --test_path ./data/dev.txt \    --debug
复制代码


部分结果展示:


#[2023-05-26 17:59:33,311] [    INFO] - Class Name: all_classes# [2023-05-26 17:59:33,311] [    INFO] - Evaluation Precision: 0.64748 | Recall: 0.72000 | F1: 0.68182


[2023-05-26 18:00:38,849] [ INFO] - -----------------------------[2023-05-26 18:00:38,849] [ INFO] - Class Name: 疾病[2023-05-26 18:00:38,849] [ INFO] - Evaluation Precision: 0.90000 | Recall: 0.84375 | F1: 0.87097[2023-05-26 18:00:38,953] [ INFO] - -----------------------------[2023-05-26 18:00:38,953] [ INFO] - Class Name: 手术治疗[2023-05-26 18:00:38,953] [ INFO] - Evaluation Precision: 0.73333 | Recall: 0.84615 | F1: 0.78571[2023-05-26 18:00:39,100] [ INFO] - -----------------------------[2023-05-26 18:00:39,101] [ INFO] - Class Name: 检查[2023-05-26 18:00:39,101] [ INFO] - Evaluation Precision: 0.65625 | Recall: 0.63636 | F1: 0.64615[2023-05-26 18:00:39,200] [ INFO] - -----------------------------[2023-05-26 18:00:39,200] [ INFO] - Class Name: X的手术治疗[2023-05-26 18:00:39,200] [ INFO] - Evaluation Precision: 0.84615 | Recall: 0.84615 | F1: 0.84615[2023-05-26 18:00:39,291] [ INFO] - -----------------------------[2023-05-26 18:00:39,291] [ INFO] - Class Name: X的实验室检查[2023-05-26 18:00:39,291] [ INFO] - Evaluation Precision: 0.66667 | Recall: 0.62500 | F1: 0.64516[2023-05-26 18:00:39,371] [ INFO] - -----------------------------[2023-05-26 18:00:39,371] [ INFO] - Class Name: X的影像学检查[2023-05-26 18:00:39,371] [ INFO] - Evaluation Precision: 0.66667 | Recall: 0.55556 | F1: 0.60606
复制代码


可配置参数说明:


  • model_path: 进行评估的模型文件夹路径,路径下需包含模型权重文件model_state.pdparams及配置文件model_config.json

  • test_path: 进行评估的测试集文件。

  • batch_size: 批处理大小,请结合机器情况进行调整,默认为 16。

  • max_seq_len: 文本最大切分长度,输入超过最大长度时会对输入文本进行自动切分,默认为 512。

  • debug: 是否开启 debug 模式对每个正例类别分别进行评估,该模式仅用于模型调试,默认关闭。

  • multilingual: 是否是跨语言模型,默认关闭。

  • schema_lang: 选择 schema 的语言,可选有chen。默认为ch,英文数据集请选择en

3.4 模型预测

paddlenlp.Taskflow 装载定制模型,通过 task_path 指定模型权重文件的路径,路径下需要包含训练好的模型权重文件 model_state.pdparams。


相关 bug:KeyError: 'sentencepiece_model_file'


同一个脚本先加载 uie-x,再加载 uie,报错 KeyError: 'sentencepiece_model_file':https://github.com/PaddlePaddle/PaddleNLP/issues/5795


#加载过 uiem 之后不能加载 uie 模型:https://github.com/PaddlePaddle/PaddleNLP/issues/5615


  1. 修复加载最新版本 paddlenlp 重启内核即可

  2. 重启项目,先加载 uie,再加在 uie-x 则不出错


!pip install --pre --upgrade paddlenlp -f https://www.paddlepaddle.org.cn/whl/paddlenlp.html
复制代码


from pprint import pprintfrom paddlenlp import Taskflow
schema = {"疾病": ["手术治疗", "实验室检查", "影像学检查"]}my_ie = Taskflow("information_extraction", schema=schema, task_path='./checkpoint/model_best')pprint(my_ie("关于脑膜膨出或脑脑膜膨出的诊断,根据囊性包块的部位、大小和外观,透光试验阳性,加上相应的病史及临床表现,一般作出正确诊断并不难。头颅CT平扫可显示颅骨缺损及由此向外膨出具有脑脊液同样密度的囊性肿物,如合并脑脑膜膨出则可见囊内有脑组织密度影。"))
复制代码


[2023-05-29 10:12:14,567] [    INFO] - loading configuration file ./checkpoint/model_best/config.json[2023-05-29 10:12:14,571] [    INFO] - Model config ErnieConfig {  "architectures": [    "UIE"  ],  "attention_probs_dropout_prob": 0.1,  "dtype": "float32",  "enable_recompute": false,  "fuse": false,  "hidden_act": "gelu",  "hidden_dropout_prob": 0.1,  "hidden_size": 768,  "initializer_range": 0.02,  "intermediate_size": 3072,  "layer_norm_eps": 1e-12,  "max_position_embeddings": 2048,  "model_type": "ernie",  "num_attention_heads": 12,  "num_hidden_layers": 12,  "pad_token_id": 0,  "paddlenlp_version": null,  "pool_act": "tanh",  "task_id": 0,  "task_type_vocab_size": 3,  "type_vocab_size": 4,  "use_task_id": true,  "vocab_size": 40000}
[2023-05-29 10:12:16,072] [ INFO] - All model checkpoint weights were used when initializing UIE.
[2023-05-29 10:12:16,074] [ INFO] - All the weights of UIE were initialized from the model checkpoint at ./checkpoint/model_best.If your task is similar to the task the model of the checkpoint was trained on, you can already use UIE for predictions without further training.[2023-05-29 10:12:16,078] [ INFO] - Converting to the inference model cost a little time.[2023-05-29 10:12:23,647] [ INFO] - The inference model save in the path:./checkpoint/model_best/static/inference[2023-05-29 10:12:25,616] [ INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load './checkpoint/model_best'.

[{'疾病': [{'end': 6, 'probability': 0.9975638704756875, 'relations': {'实验室检查': [{'end': 36, 'probability': 0.9964935361743485, 'start': 32, 'text': '透光试验'}], '影像学检查': [{'end': 70, 'probability': 0.9986574055854476, 'start': 64, 'text': '头颅CT平扫'}]}, 'start': 2, 'text': '脑膜膨出'}]}]
复制代码

4.基于 SimpleServing 的模型快速服务化部署

在 UIE 的服务化能力中提供基于 PaddleNLP SimpleServing 来搭建服务化能力,通过几行代码即可搭建服务化部署能力。


  • 环境准备


使用有 SimpleServing 功能的 PaddleNLP 版本(或者最新的 develop 版本)


pip install paddlenlp >= 2.5.0
复制代码


  • Server 服务启动


进入文件当前所在路径


paddlenlp server server:app --workers 1 --host 0.0.0.0 --port 8190
复制代码


  • Client 请求启动


python client.py
复制代码


  • 服务化自定义参数

  • Server 自定义参数

  • schema 替换


# Default schemaschema = 
复制代码


* 设置模型路径
复制代码


# Default task_pathuie = Taskflow('information_extraction', task_path='./checkpoint/model_best/', schema=schema)
复制代码


* 多卡服务化预测
复制代码


PaddleNLP SimpleServing 支持多卡负载均衡预测,主要在服务化注册的时候,注册两个 Taskflow 的 task 即可,下面是示例代码


uie1 = Taskflow('information_extraction', task_path='../../../checkpoint/model_best/', schema=schema, device_id=0)uie2 = Taskflow('information_extraction', task_path='../../../checkpoint/model_best/', schema=schema, device_id=1)service.register_taskflow('uie', [uie1, uie2])
复制代码


  • 更多配置


from paddlenlp import Taskflowschema = uie = Taskflow("zero_shot_text_classification",                   schema=schema,                   model="uie-base",                   max_seq_len=512,                   batch_size=1,                   pred_threshold=0.5,                   precision="fp32")
复制代码


  • schema:定义任务标签候选集合。

  • model:选择任务使用的模型,默认为utc-base, 可选有utc-xbase, utc-base, utc-medium, utc-micro, utc-mini, utc-nano, utc-pico

  • max_seq_len:最长输入长度,包括所有标签的长度,默认为 512。

  • batch_size:批处理大小,请结合机器情况进行调整,默认为 1。

  • pred_threshold:模型对标签预测的概率在 0~1 之间,返回结果去掉小于这个阈值的结果,默认为 0.5。

  • precision:选择模型精度,默认为fp32,可选有fp16fp32fp16推理速度更快。如果选择fp16,请先确保机器正确安装 NVIDIA 相关驱动和基础软件,确保 CUDA>=11.2,cuDNN>=8.1.1,初次使用需按照提示安装相关依赖。其次,需要确保 GPU 设备的 CUDA 计算能力(CUDA Compute Capability)大于 7.0,典型的设备包括 V100、T4、A10、A100、GTX 20 系列和 30 系列显卡等。更多关于 CUDA Compute Capability 和精度支持情况请参考 NVIDIA 文档:GPU硬件与支持精度对照表

  • Client 自定义参数


# Changed to input texts you wantedtexts = ['麻疹感染@### 诊断性检查 最常使用的诊断试验是麻疹特异性IgM抗体检测。麻疹感染@出疹后3-14天敏感性最高']
复制代码


%cd /home/aistudio/deploy!paddlenlp server server:app --workers 1 --host 0.0.0.0 --port 8190#Error loading ASGI app. Could not import module "server".#去终端执行即可
复制代码


# %cd /home/aistudio/deploy!python client.py
复制代码


在 notebook 如果不行,可以直接进入终端进行调试,需要注意的是要在同一个路径下不然会报错:




import json
import requests
url = "http://0.0.0.0:8190/taskflow/uie"headers = {"Content-Type": "application/json"}texts = ["麻疹感染@### 诊断性检查 最常使用的诊断试验是麻疹特异性IgM抗体检测。麻疹感染@出疹后3-14天敏感性最高"]data = { "data": { "text": texts, }}r = requests.post(url=url, headers=headers, data=json.dumps(data))datas = json.loads(r.text)print(datas)

from paddlenlp import SimpleServer, Taskflow
# The schema changed to your defined schemaschema = {"疾病": ["手术治疗", "实验室检查", "影像学检查"]}# The task path changed to your best model pathuie = Taskflow("information_extraction", schema=schema, task_path="/home/aistudio/checkpoint/model_best")# If you want to define the finetuned uie serviceapp = SimpleServer()app.register_taskflow("taskflow/uie", uie)
复制代码

5.UIE Slim 数据蒸馏

在 UIE 强大的抽取能力背后,同样需要较大的算力支持计算。在一些工业应用场景中对性能的要求较高,若不能有效压缩则无法实际应用。因此,我们基于数据蒸馏技术构建了 UIE Slim 数据蒸馏系统。其原理是通过数据作为桥梁,将 UIE 模型的知识迁移到封闭域信息抽取小模型,以达到精度损失较小的情况下却能达到大幅度预测速度提升的效果。


  • Step 1: 使用 UIE 模型对标注数据进行 finetune,得到 Teacher Model。

  • Step 2: 用户提供大规模无标注数据,需与标注数据同源。使用 Taskflow UIE 对无监督数据进行预测。

  • Step 3: 使用标注数据以及步骤 2 得到的合成数据训练出封闭域 Student Model。


  • 数据集介绍


示例数据包含以下两部分:


5.1 离线蒸馏

  • 通过训练好的 UIE 定制模型预测无监督数据的标签


可配置参数说明:


  • data_path: 标注数据(doccano_ext.json)及无监督文本(unlabeled_data.txt)路径。

  • model_path: 训练好的 UIE 定制模型路径。

  • save_dir: 学生模型训练数据保存路径。

  • synthetic_ratio: 控制合成数据的比例。最大合成数据数量=synthetic_ratio*标注数据数量。

  • task_type: 选择任务类型,可选有entity_extractionrelation_extractionevent_extractionopinion_extraction。因为是封闭域信息抽取,需指定任务类型。

  • seed: 随机种子,默认为 1000。


!unzip data.zip -d ./data
复制代码


!python doccano.py \    --doccano_file ./data/data/doccano_ext.json \    --task_type ext \    --save_dir ./data \    --splits 0.8 0.15 0.05 \    --schema_lang ch
复制代码


!cp /home/aistudio/data/sample_index.json /home/aistudio/data/data
复制代码


# %cd data_distill!python data_distill.py \    --data_path /home/aistudio/data/data \    --save_dir student_data \    --task_type relation_extraction \    --synthetic_ratio 10 \    --model_path /home/aistudio/checkpoint/model_best #已经训练好的模型
复制代码


[2023-05-29 10:59:49,601] [    INFO] - loading configuration file /home/aistudio/checkpoint/model_best/config.json[2023-05-29 10:59:49,603] [    INFO] - Model config ErnieConfig {  "architectures": [    "UIE"  ],  "attention_probs_dropout_prob": 0.1,  "dtype": "float32",  "enable_recompute": false,  "fuse": false,  "hidden_act": "gelu",  "hidden_dropout_prob": 0.1,  "hidden_size": 768,  "initializer_range": 0.02,  "intermediate_size": 3072,  "layer_norm_eps": 1e-12,  "max_position_embeddings": 2048,  "model_type": "ernie",  "num_attention_heads": 12,  "num_hidden_layers": 12,  "pad_token_id": 0,  "paddlenlp_version": null,  "pool_act": "tanh",  "task_id": 0,  "task_type_vocab_size": 3,  "type_vocab_size": 4,  "use_task_id": true,  "vocab_size": 40000}
W0529 10:59:50.154482 28097 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 8.0, Driver API Version: 11.2, Runtime API Version: 11.2W0529 10:59:50.157151 28097 gpu_resources.cc:91] device: 0, cuDNN Version: 8.2.[2023-05-29 10:59:51,054] [ INFO] - All model checkpoint weights were used when initializing UIE.
[2023-05-29 10:59:51,054] [ INFO] - All the weights of UIE were initialized from the model checkpoint at /home/aistudio/checkpoint/model_best.If your task is similar to the task the model of the checkpoint was trained on, you can already use UIE for predictions without further training.[2023-05-29 10:59:51,056] [ INFO] - Converting to the inference model cost a little time.[2023-05-29 10:59:57,485] [ INFO] - The inference model save in the path:/home/aistudio/checkpoint/model_best/static/inference[2023-05-29 10:59:59,538] [ INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load '/home/aistudio/checkpoint/model_best'.[2023-05-29 11:00:46,880] [ INFO] - Save 1437 examples to student_data/train_data.json.[2023-05-29 11:00:46,881] [ INFO] - Save 30 examples to student_data/dev_data.json.[2023-05-29 11:00:46,881] [ INFO] - Save 10 examples to student_data/test_data.json.
复制代码

5.2 老师模型评估

UIE 微调阶段针对 UIE 训练格式数据评估模型效果(该评估方式非端到端评估,不适合关系、事件等任务),可通过以下评估脚本针对原始标注格式数据评估模型效果


可配置参数说明:


  • model_path: 训练好的 UIE 定制模型路径。

  • test_path: 测试数据集路径。

  • label_maps_path: 学生模型标签字典。

  • batch_size: 批处理大小,默认为 8。

  • max_seq_len: 最大文本长度,默认为 256。

  • task_type: 选择任务类型,可选有entity_extractionrelation_extractionevent_extractionopinion_extraction。因为是封闭域信息抽取的评估,需指定任务类型。


!python evaluate_teacher.py \    --task_type relation_extraction \    --test_path ./student_data/dev_data.json \    --label_maps_path ./student_data/label_maps.json \    --model_path /home/aistudio/checkpoint/model_best
复制代码


[2023-05-29 11:02:20,600] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load '/home/aistudio/checkpoint/model_best'.[2023-05-29 11:02:20,623] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load 'ernie-3.0-base-zh'.[2023-05-29 11:02:20,623] [    INFO] - Downloading https://bj.bcebos.com/paddlenlp/models/transformers/ernie_3.0/ernie_3.0_base_zh_vocab.txt and saved to /home/aistudio/.paddlenlp/models/ernie-3.0-base-zh[2023-05-29 11:02:20,758] [    INFO] - Downloading ernie_3.0_base_zh_vocab.txt from https://bj.bcebos.com/paddlenlp/models/transformers/ernie_3.0/ernie_3.0_base_zh_vocab.txt100%|█████████████████████████████████████████| 182k/182k [00:00<00:00, 469kB/s][2023-05-29 11:02:21,289] [    INFO] - tokenizer config file saved in /home/aistudio/.paddlenlp/models/ernie-3.0-base-zh/tokenizer_config.json[2023-05-29 11:02:21,289] [    INFO] - Special tokens file saved in /home/aistudio/.paddlenlp/models/ernie-3.0-base-zh/special_tokens_map.json[2023-05-29 11:02:24,414] [    INFO]                                             - Evaluation precision: {'entity_f1': 0.75497, 'entity_precision': 0.78082, 'entity_recall': 0.73077, 'relation_f1': 0.54902, 'relation_precision': 0.50909, 'relation_recall': 0.59574}
复制代码

5.3 学生模型训练

可配置参数说明:


  • train_path: 训练集文件路径。

  • dev_path: 验证集文件路径。

  • batch_size: 批处理大小,默认为 16。

  • learning_rate: 学习率,默认为 3e-5。

  • save_dir: 模型存储路径,默认为./checkpoint

  • max_seq_len: 最大文本长度,默认为 256。

  • weight_decay: 表示 AdamW 优化器中使用的 weight_decay 的系数。

  • warmup_proportion: 学习率 warmup 策略的比例,如果 0.1,则学习率会在前 10%训练 step 的过程中从 0 慢慢增长到 learning_rate, 而后再缓慢衰减,默认为 0.0。

  • num_epochs: 训练轮数,默认为 100。

  • seed: 随机种子,默认为 1000。

  • encoder: 选择学生模型的模型底座,默认为ernie-3.0-mini-zh

  • task_type: 选择任务类型,可选有entity_extractionrelation_extractionevent_extractionopinion_extraction。因为是封闭域信息抽取,需指定任务类型。

  • logging_steps: 日志打印的间隔 steps 数,默认 10。

  • valid_steps: evaluate 的间隔 steps 数,默认 200。

  • device: 选用什么设备进行训练,可选 cpu 或 gpu。

  • init_from_ckpt: 可选,模型参数路径,热启动模型训练;默认为 None。


!python train.py \    --task_type relation_extraction \    --train_path student_data/train_data.json \    --dev_path student_data/dev_data.json \    --label_maps_path student_data/label_maps.json \    --num_epochs 200 \    --encoder ernie-3.0-mini-zh\    --device "gpu"\    --valid_steps 100\    --logging_steps 50\    --save_dir './checkpoint-mini'\    --batch_size 32
复制代码

5.4 Taskflow 部署学生模型

  • 通过 Taskflow 一键部署封闭域信息抽取模型,task_path为学生模型路径。


from pprint import pprintfrom paddlenlp import Taskflowie = Taskflow("information_extraction",model="uie-data-distill-gp", task_path="/home/aistudio/data_distill/checkpoint-mini/model_best") # Schema is fixed in closed-domain information extractionpprint(ie("麻疹感染@### 诊断性检查 最常使用的诊断试验是麻疹特异性IgM抗体检测。麻疹感染@出疹后3-14天敏感性最高"))
复制代码


[2023-05-29 16:06:31,608] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load '/home/aistudio/data_distill/checkpoint-mini/model_best'.

[{'疾病': [{'end': 4, 'probability': 0.9999304, 'relations': {'实验室检查': [{'end': 37, 'probability': 0.9997897, 'relations': {}, 'start': 25, 'text': '麻疹特异性IgM抗体检测'}]}, 'start': 0, 'text': '麻疹感染'}]}]
复制代码

6.性能提升测评(重点)

对比原模型、SimpleServing、以及蒸馏后的模型推理速度

6.1 UIE-base+FasterTokenizer

from pprint import pprintimport jsonfrom paddlenlp import Taskflowimport pandas as pd#运行时间import time

def openreadtxt(file_name): data = [] file = open(file_name,'r',encoding='UTF-8') #打开文件 file_data = file.readlines() #读取所有行 for row in file_data: data.append(row) #将每行数据插入data中 return data
# 时间1old_time = time.time()data_input=openreadtxt('/home/aistudio/input/medical_data/data/unlabeled_data.txt')
schema = {'疾病': ['手术治疗', '实验室检查', '影像学检查']}
few_ie = Taskflow('information_extraction', schema=schema,use_faster=True,batch_size=32,task_path='/home/aistudio/checkpoint/model_best',)# 时间1current_time = time.time()print("数据模型载入运行时间为" + str(current_time - old_time) + "s")
#时间2old_time1 = time.time()results=few_ie(data_input)current_time1 = time.time()print("模型计算运行时间为" + str(current_time1 - old_time1) + "s")#时间2
#时间三old_time3 = time.time()test = pd.DataFrame(data=results)test.to_csv('/home/aistudio/output/reslut.txt', sep='\t', index=False,header=False) #本地
current_time3 = time.time()print("数据导出运行时间为" + str(current_time3 - old_time3) + "s")
print("数据结果已导出")
复制代码


[2023-05-29 15:36:15,515] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load '/home/aistudio/checkpoint/model_best'.

数据模型载入运行时间为6.07235050201416s模型计算运行时间为71.23507380485535s数据导出运行时间为0.025907278060913086s数据结果已导出
复制代码

6.2 UIE-base+Servering 推理

#%cd /home/aistudio/deploy#!paddlenlp server server:app --workers 1 --host 0.0.0.0 --port 8191
#!python client-test.py
复制代码



6.3 UIE-base Slim

#数据蒸馏模型from pprint import pprintimport jsonfrom paddlenlp.taskflow import Taskflowimport pandas as pd#运行时间import time
def openreadtxt(file_name): data = [] file = open(file_name,'r',encoding='UTF-8') #打开文件 file_data = file.readlines() #读取所有行 for row in file_data: data.append(row) #将每行数据插入data中 return data
# 时间1old_time = time.time()data_input=openreadtxt('/home/aistudio/input/medical_data/data/unlabeled_data.txt')

few_ie = Taskflow("information_extraction", model="uie-data-distill-gp", task_path="/home/aistudio/data_distill/checkpoint-mini/model_best",batch_size=32) # Schema 在闭域信息抽取中是固定的

# 时间1current_time = time.time()print("数据模型载入运行时间为" + str(current_time - old_time) + "s")
#时间2old_time1 = time.time()results=few_ie(data_input)current_time1 = time.time()print("模型计算运行时间为" + str(current_time1 - old_time1) + "s")#时间2
#时间三old_time3 = time.time()test = pd.DataFrame(data=results)test.to_csv('/home/aistudio/output/reslut.txt', sep='\t', index=False,header=False) #本地
# with open("/home/aistudio/output/reslut.txt", "w+",encoding='UTF-8') as f: #a : 写入文件,若文件不存在则会先创建再写入,但不会覆盖原文件,而是追加在文件末尾# for result in results:# line = json.dumps(result, ensure_ascii=False) #对中文默认使用的ascii编码.想输出真正的中文需要指定ensure_ascii=False# f.write(line + "\n")current_time3 = time.time()print("数据导出运行时间为" + str(current_time3 - old_time3) + "s")
print("数据结果已导出")
复制代码


[2023-05-29 15:37:26,883] [    INFO] - We are using <class 'paddlenlp.transformers.ernie.tokenizer.ErnieTokenizer'> to load '/home/aistudio/data_distill/checkpoint-mini/model_best'.

数据模型载入运行时间为1.5062384605407715s模型计算运行时间为9.325902938842773s数据导出运行时间为0.024837017059326172s数据结果已导出
复制代码

7.总结

7.1 方案对比总结


本项目为 UIE 框架升级版本实体关系抽取,详细讲解了数据标注,以及医疗领域 NER 微调,同时完成基于 SimpleServing 的快速服务化部署,并考虑了在一些工业应用场景中对性能的要求较高,若不能有效压缩则无法实际应用。因此,将 UIE 模型的知识迁移到封闭域信息抽取小模型,同时使用 FasterTokenizer 进行文本预处理加速,整体提速 7.6x 倍。

7.2 更多优质项目推荐

NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等:


  1. [小样本文本分类应用:基于 UTC 的医疗意图多分类,训练调优部署一条龙]

  2. [“中国法研杯”司法人工智能挑战赛:基于 UTC 的多标签/层次分类小样本文本应用]

  3. [Paddlenlp 之 UIE 模型实战实体抽取任务【打车数据、快递单】]

  4. [Paddlenlp 之 UIE 关系抽取模型【高管关系抽取为例】]

  5. [UIE Slim 满足工业应用场景,解决推理部署耗时问题,提升效能!]

  6. [基于 Labelstudio 的 UIE 半监督智能标注方案(本地版),赶快用起来啦!]

  7. [基于 Labelstudio 的 UIE 半监督深度学习的智能标注方案(云端版),提效!]

  8. [基于 ERNIELayout&PDFplumber-UIEX 多方案学术论文信息抽取]

  9. [基线提升至 96.45%:2022 司法杯犯罪事实实体识别+数据蒸馏+主动学习]

  10. [[信息抽取]基于 ERNIE3.0 的多对多信息抽取算法:属性关系抽取]

项目链接以及码源

码源链接在文章末跳转订阅可见


  • 参考链接



发布于: 2023-05-30阅读数: 2
用户头像

本博客将不定期更新关于NLP等领域相关知识 2022-01-06 加入

本博客将不定期更新关于机器学习、强化学习、数据挖掘以及NLP等领域相关知识,以及分享自己学习到的知识技能,感谢大家关注!

评论

发布
暂无评论
医疗领域实体抽取:UIE Slim最新升级版含数据标注、serving部署、模型蒸馏等教学,助力工业应用场景快速落地_人工智能_汀丶人工智能_InfoQ写作社区