乐趣区

关于人工智能:医疗领域实体抽取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 pprint
from 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 pprint
from paddlenlp import Taskflow
schema = ['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 pprint
from paddlenlp import Taskflow
schema = {'比赛名称': ['主办方', '承办方', '已举办次数']} 
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 更多模型配置抉择

| 模型 | 构造 | 语言 |
| :—: | :——–: | :——–: |
| uie-base (默认)| 12-layers, 768-hidden, 12-heads | 中文 |
| uie-base-en | 12-layers, 768-hidden, 12-heads | 英文 |
| uie-medical-base | 12-layers, 768-hidden, 12-heads | 中文 |
| uie-medium| 6-layers, 768-hidden, 12-heads | 中文 |
| uie-mini| 6-layers, 384-hidden, 12-heads | 中文 |
| uie-micro| 4-layers, 384-hidden, 12-heads | 中文 |
| uie-nano| 4-layers, 312-hidden, 12-heads | 中文 |
| uie-m-large| 24-layers, 1024-hidden, 16-heads | 中、英文 |
| uie-m-base| 12-layers, 768-hidden, 12-heads | 中、英文 |

from paddlenlp import Taskflow
ie = 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

  • 填写项目名称、形容

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/199661377-d9664165-61aa-4462-927d-225118b8535b.png height=230 width=1200 />

</div>

  • 命名实体辨认、关系抽取、事件抽取、实体 / 评估维度分类 工作抉择`Relation Extraction

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/212617773-34534e68-4544-4b24-8f39-ae7f9573d397.png height=420 width=1200 />

</div>

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

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/199662737-ed996a2c-7a24-4077-8a36-239c4bfb0a16.png height=380 width=1200 />

</div>

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

  • 数据上传

先从本地上传 txt 格式文件,抉择List of tasks,而后抉择导入本我的项目。

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/199667670-1b8f6755-b41f-41c4-8afc-06bb051690b6.png height=210 width=1200 />

</div>

  • 标签构建
  • Span 类型标签

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/199667941-04e300c5-3cd7-4b8e-aaf5-561415414891.png height=480 width=1200 />

</div>

  • Relation 类型标签

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/199725229-f5e998bf-367c-4449-b83a-c799f1e3de00.png height=620 width=1200 />

</div>

Relation XML 模板:

  <Relations>
    <Relation value="歌手"/>
    <Relation value="发行工夫"/>
    <Relation value="所属专辑"/>
  </Relations>
  • 工作标注
  • 实体抽取

标注示例:

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/199879957-aeec9d17-d342-4ea0-a840-457b49f6066e.png height=140 width=1000 />

</div>

该标注示例对应的 schema 为:

schema = [
    '工夫',
    '选手',
    '赛事名称',
    '得分'
]
  • 关系抽取

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/199879866-03c1ecac-1828-4f35-af70-9ae61701c303.png height=230 width=1200 />

</div>

对于关系抽取,其 P 的类型设置非常重要,须要遵循以下准则

“{S}的 {P} 为{O}”须要可能形成语义正当的短语。比方对于三元组 (S, 父子, O),关系类别为父子是没有问题的。但依照 UIE 以后关系类型 prompt 的结构形式,“S 的父子为 O”这个表白不是很通顺,因而 P 改成孩子更好,即“S 的孩子为 O”。 正当的 P 类型设置,将显著晋升零样本成果

该标注示例对应的 schema 为:

schema = {
    '作品名': [
        '歌手',
        '发行工夫',
        '所属专辑'
    ]
}

该标注示例对应的 schema 为:

schema = '情感偏向[正向,负向]'
  • 数据导出

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

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/199891344-023736e2-6f9d-454b-b72a-dec6689f8436.png height=180 width=1200 />

</div>

  • 数据转换

将导出的文件重命名为 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
  • Label Studio

2.2 基于 doccano 数据标注

2.2.1 doccano 装置

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

  • doccano 1.6.2
Step 1. 本地装置 doccano($ pip install doccano

Step 2. 初始化数据库和账户(用户名和明码可替换为自定义值)#初始化,设置用户名 = admin, 明码 =pass
doccano init
doccano 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—- 简介、装置、应用、踩坑记录](https://blog.csdn.net/sinat_39620217/article/details/125167926)

2.2.2 标注教学

  • 抽取式工作我的项目创立

创立我的项目时抉择 序列标注 工作,并勾选 Allow overlapping entityUse relation Labeling。适配 命名实体辨认、关系抽取、事件抽取、评估观点抽取 等工作。

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/167249142-44885510-51dc-4359-8054-9c89c9633700.png height=230 hspace='15'/>

</div>

  • 数据上传

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

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

上传数据类型 抉择 TextLine:

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/167247061-d5795c26-7a6f-4cdb-88ad-107a3cae5446.png height=300 hspace='15'/>

</div>

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

  • 构建抽取式工作标签

抽取式工作蕴含 SpanRelation两种标签类型,Span 指 原文本中的指标信息片段 ,如实体辨认中某个类型的实体,事件抽取中的触发词和论元;Relation 指 原文本中 Span 之间的关系,如关系抽取中两个实体(Subject&Object)之间的关系,事件抽取中论元和触发词之间的关系。

Span 类型标签构建示例:

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/167248034-afa3f637-65c5-4038-ada0-344ffbd776a2.png height=300 hspace='15'/>

</div>

Relation 类型标签构建示例:

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/167248307-916c77f6-bf80-4d6b-aa71-30c719f68257.png height=260 hspace='16'/>

</div>

  • 工作标注
  • 命名实体辨认

命名实体辨认(Named Entity Recognition,简称 NER),是指辨认文本中具备特定意义的实体。在凋谢域信息抽取中,抽取的类别没有限度,用户能够本人定义

标注示例:

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/167248557-f1da3694-1063-465a-be9a-1bb811949530.png height=200 hspace='20'/>

</div>

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

schema = [
    '工夫',
    '选手',
    '赛事名称',
    '得分'
]
  • 关系抽取

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

标注示例:

<div align=”center”>

<img src=https://user-images.githubusercontent.com/40840292/167248502-16a87902-3878-4432-b5b8-9808bd8d4de5.png height=200 hspace='20'/>

</div>

示例中定义了 作品名 人物名 工夫 三种 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
  • doccano

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 pprint
from 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 schema
schema = 
* 设置模型门路
# Default task_path
uie = 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 Taskflow
schema = 
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 wanted
texts = ['麻疹感化 @### 诊断性查看 最常应用的诊断试验是麻疹特异性 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 schema
schema = {"疾病": ["手术医治", "实验室查看", "影像学查看"]}
# The task path changed to your best model path
uie = Taskflow("information_extraction", schema=schema, task_path="/home/aistudio/checkpoint/model_best")
# If you want to define the finetuned uie service
app = 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。
  • 数据集介绍

示例数据蕴含以下两局部:

名称 数量
doccano 格局标注数据(doccano_ext.json) 200
无标注数据(unlabeled_data.txt) 1277

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.2
W0529 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.txt
100%|█████████████████████████████████████████| 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 pprint
from paddlenlp import Taskflow
ie = 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 extraction
pprint(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 pprint
import json
from paddlenlp import Taskflow
import 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

# 工夫 1
old_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',)
# 工夫 1
current_time = time.time()
print("数据模型载入运行工夫为" + str(current_time - old_time) + "s")

#工夫 2
old_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 pprint
import json
from paddlenlp.taskflow import Taskflow
import 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

# 工夫 1
old_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 在闭域信息抽取中是固定的


# 工夫 1
current_time = time.time()
print("数据模型载入运行工夫为" + str(current_time - old_time) + "s")

#工夫 2
old_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+faster 71.23 1
uie+servering 70.56 1+
UIE Slim 9.32 7.6

本我的项目为 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 的多对多信息抽取算法:属性关系抽取]

我的项目链接以及码源

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

  • 参考链接
  • GlobalPointer
  • GPLinker
  • JunnYu/GPLinker_pytorch
  • CBLUE
退出移动版