赞
踩
相关项目推荐:
Paddlenlp之UIE模型实战实体抽取任务【打车数据、快递单】
Paddlenlp之UIE分类模型【以情感倾向分析新闻分类为例】含智能标注方案)
应用实践:分类模型大集成者[PaddleHub、Finetune、prompt]
本项目主要介绍如何使用飞桨自然语言处理开发库PaddleNLP完成快递单信息抽取:从用户提供的快递单中,抽取姓名、电话、省、市、区、详细地址等内容,形成结构化信息,如 图1 所示,辅助物流行业从业者进行有效信息的提取,从而降低客户填单的成本。
从物流信息中抽取想要的关键信息,实际上是自然语言处理中的实体抽取任务,这类任务在产业应用时通常会面临如下技术难点:
同一名词可能对应多个实体类别,如“蜗牛”。
不少实体词与普通用语相同,尤其作品名。
此外,实体类别多,任务复杂度较高,如 图2 列举了部分实体类型。实际的实体类型依业务决定。
人名在语料出现频次高,但不同人名出现频次有限
大多垂类实体词在通用语料出现频次低。
针对实体信息抽取技术,有如下三种方案:
本案例采用序列标注的方式,更加灵活、通用。
我们首先要定义好需要抽取哪些字段。
比如现在拿到一个快递单,可以作为我们的模型输入,例如“张三18625584663广东省深圳市南山区学府路东百度国际大厦”,那么序列标注模型的目的就是识别出其中的“张三”为人名(用符号 P 表示),“18625584663”为电话名(用符号 T 表示),“广东省深圳市南山区百度国际大厦”分别是 1-4 级的地址(分别用 A1~A4 表示,可以释义为省、市、区、街道)。
这是一个典型的命名实体识别(Named Entity Recognition,NER)场景,各实体类型及相应符号表示见下表:
抽取实体/字段 | 符号 | 抽取结果 |
---|---|---|
姓名 | P | 张三 |
电话 | T | 18625584663 |
省 | A1 | 广东省 |
市 | A2 | 深圳市 |
区 | A3 | 南山区 |
详细地址 | A4 | 百度国际大厦 |
在序列标注任务中,一般会定义一个标签集合,来表示所以可能取到的预测结果。在本案例中,针对需要被抽取的“姓名、电话、省、市、区、详细地址”等实体,标签集合可以定义为:
label = {P-B, P-I, T-B, T-I, A1-B, A1-I, A2-B, A2-I, A3-B, A3-I, A4-B, A4-I, O}
每个标签的定义分别为:
标签 | 定义 |
---|---|
P-B | 姓名起始位置 |
P-I | 姓名中间位置或结束位置 |
T-B | 电话起始位置 |
T-I | 电话中间位置或结束位置 |
A1-B | 省份起始位置 |
A1-I | 省份中间位置或结束位置 |
A2-B | 城市起始位置 |
A2-I | 城市中间位置或结束位置 |
A3-B | 县区起始位置 |
A3-I | 县区中间位置或结束位置 |
A4-B | 详细地址起始位置 |
A4-I | 详细地址中间位置或结束位置 |
O | 无关字符 |
注意每个标签的结果只有 B、I、O 三种,这种标签的定义方式叫做 BIO 体系,也有稍麻烦一点的 BIESO 体系,这里不做展开。其中 B 表示一个标签类别的开头,比如 P-B 指的是姓名的开头;相应的,I 表示一个标签的延续。
对于句子“张三18625584663广东省深圳市南山区百度国际大厦”,每个汉字及对应标签为:
注意到“张“,”三”在这里表示成了“P-B” 和 “P-I”,“P-B”和“P-I”合并成“P” 这个标签。这样重新组合后可以得到以下信息抽取结果:
张三 | 18625584663 | 广东省 | 深圳市 | 南山区 | 百度国际大厦 |
---|---|---|---|---|---|
P | T | A1 | A2 | A3 | A4 |
BIGRU是一种经典的循环神经网络(RNN,Recurrent Neural Network),用于对句子等序列信息进行建模。这里我们重点解释下其概念和相关原理。一个 RNN 的示意图如下所示,
左边是原始的 RNN,可以看到绿色的点代码输入 x,红色的点代表输出 y,中间的蓝色是 RNN 模型部分。橙色的箭头由自身指向自身,表示 RNN 的输入来自于上时刻的输出,这也是为什么名字中带有循环(Recurrent)这个词。
右边是按照时间序列展开的示意图,注意到蓝色的 RNN 模块是同一个,只不过在不同的时刻复用了。这时候能够清晰地表示序列标注模型的输入输出。
GRU为了解决长期记忆和反向传播中梯度问题而提出来的,和LSTM一样能够有效对长序列建模,且GRU训练效率更高。
长句子的问题解决了,序列标注任务的另外一个问题也亟待解决,即标签之间的依赖性。举个例子,我们预测的标签一般不会出现 P-B,T-I 并列的情况,因为这样的标签不合理,也无法解析。无论是 RNN 还是 LSTM 都只能尽量不出现,却无法从原理上避免这个问题。下面要提到的条件随机场(CRF,Conditional Random Field)却很好的解决了这个问题。
条件随机场这个模型属于概率图模型中的无向图模型,这里我们不做展开,只直观解释下该模型背后考量的思想。一个经典的链式 CRF 如下图所示,
CRF 本质是一个无向图,其中绿色点表示输入,红色点表示输出。点与点之间的边可以分成两类,一类是 x x x 与 y y y 之间的连线,表示其相关性;另一类是相邻时刻的 y y y 之间的相关性。也就是说,在预测某时刻 y y y 时,同时要考虑相邻的标签解决。当 CRF 模型收敛时,就会学到类似 P-B 和 T-I 作为相邻标签的概率非常低。
除了GRU+CRF方案外,我们也可以使用预训练模型,将序列信息抽取问题,建模成字符级分类问题。这里我们采用强大的语义模型ERNIE,完成字符级分类任务。
信息抽取的通用评测指标:Precision、Recall、F1值。
例子:希望抽取10个信息,实际抽取12个,其中有9个是对的
采取的是快递单数据集,这份数据除姓名、人名、地名之外,无其他信息。采用BIO方式标注训练集,由于仅含实体信息,所以数据集无“O”(非实体)标识。训练集中除第一行是 text_a\tlabel
,后面的每行数据都是由两列组成,以制表符分隔,第一列是 utf-8 编码的中文文本,以 \002
分割,第二列是对应序列标注的结果,以 \002
分割。
!wc -l ./express_ner/train.txt
!wc -l ./express_ner/dev.txt
!wc -l ./express_ner/test.txt
!head -10 ./express_ner/train.txt
1601 ./express_ner/train.txt
201 ./express_ner/dev.txt
201 ./express_ner/test.txt
text_a label
16620200077宣荣嗣甘肃省白银市会宁县河畔镇十字街金海超市西行50米 T-BT-IT-IT-IT-IT-IT-IT-IT-IT-IT-IP-BP-IP-IA1-BA1-IA1-IA2-BA2-IA2-IA3-BA3-IA3-IA4-BA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-I
13552664307姜骏炜云南省德宏傣族景颇族自治州盈江县平原镇蜜回路下段 T-BT-IT-IT-IT-IT-IT-IT-IT-IT-IT-IP-BP-IP-IA1-BA1-IA1-IA2-BA2-IA2-IA2-IA2-IA2-IA2-IA2-IA2-IA2-IA3-BA3-IA3-IA4-BA4-IA4-IA4-IA4-IA4-IA4-IA4-I
内蒙古自治区赤峰市阿鲁科尔沁旗汉林西街路南13701085390那峥 A1-BA1-IA1-IA1-IA1-IA1-IA2-BA2-IA2-IA3-BA3-IA3-IA3-IA3-IA3-IA4-BA4-IA4-IA4-IA4-IA4-IT-BT-IT-IT-IT-IT-IT-IT-IT-IT-IT-IP-BP-I
广东省梅州市大埔县茶阳镇胜利路13601328173张铱 A1-BA1-IA1-IA2-BA2-IA2-IA3-BA3-IA3-IA4-BA4-IA4-IA4-IA4-IA4-IT-BT-IT-IT-IT-IT-IT-IT-IT-IT-IT-IP-BP-I
新疆维吾尔自治区阿克苏地区阿克苏市步行街10号15810789378慕东霖 A1-BA1-IA1-IA1-IA1-IA1-IA1-IA1-IA2-BA2-IA2-IA2-IA2-IA3-BA3-IA3-IA3-IA4-BA4-IA4-IA4-IA4-IA4-IT-BT-IT-IT-IT-IT-IT-IT-IT-IT-IT-IP-BP-IP-I
18511138255福建省泉州市丰泽区普济路168号宓文会 T-BT-IT-IT-IT-IT-IT-IT-IT-IT-IT-IA1-BA1-IA1-IA2-BA2-IA2-IA3-BA3-IA3-IA4-BA4-IA4-IA4-IA4-IA4-IA4-IP-BP-IP-I
16601146030伊乡净湖南省邵阳市双清区黔道soho大厦 T-BT-IT-IT-IT-IT-IT-IT-IT-IT-IT-IP-BP-IP-IA1-BA1-IA1-IA2-BA2-IA2-IA3-BA3-IA3-IA4-BA4-IA4-IA4-IA4-IA4-IA4-IA4-I
甘肃省张掖市山丹县甘新北路9号18610656643谢剑铿 A1-BA1-IA1-IA2-BA2-IA2-IA3-BA3-IA3-IA4-BA4-IA4-IA4-IA4-IA4-IT-BT-IT-IT-IT-IT-IT-IT-IT-IT-IT-IP-BP-IP-I
13240063339宿卓贵州省遵义市仁怀市端午路罗家坝160-63号 T-BT-IT-IT-IT-IT-IT-IT-IT-IT-IT-IP-BP-IA1-BA1-IA1-IA2-BA2-IA2-IA3-BA3-IA3-IA4-BA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-IA4-I
# 实体标签
!cat ./conf/tag.dic
P-B
P-I
T-B
T-I
A1-B
A1-I
A2-B
A2-I
A3-B
A3-I
A4-B
A4-I
O
本项目基于PaddleNLP NER example的代码进行修改,分别基于基本组网单元GRU、CRF和预训练模型,实现了多个方案。
我们以快递单信息抽取为例,介绍如何使用PaddleNLP搭建网络。
AI Studio平台默认安装了Paddle和PaddleNLP,并定期更新版本。 如需手动更新Paddle,可参考飞桨安装说明,安装相应环境下最新版飞桨框架。
使用如下命令确保安装最新版PaddleNLP:
!pip install --upgrade paddlenlp
!python run_bigru_crf.py #部分结果展示 ''' Eval begin... Eval samples: 192 save checkpoint at /home/aistudio/gru_results/final Eval begin... step 1/6 - loss: 0.0000e+00 - precision: 0.9592 - recall: 0.9843 - f1: 0.9716 - 98ms/step step 2/6 - loss: 0.0000e+00 - precision: 0.9668 - recall: 0.9869 - f1: 0.9767 - 101ms/step step 3/6 - loss: 24.7474 - precision: 0.9724 - recall: 0.9843 - f1: 0.9783 - 100ms/step step 4/6 - loss: 0.0000e+00 - precision: 0.9703 - recall: 0.9830 - f1: 0.9766 - 100ms/step step 5/6 - loss: 0.0000e+00 - precision: 0.9700 - recall: 0.9822 - f1: 0.9761 - 99ms/step step 6/6 - loss: 0.0000e+00 - precision: 0.9614 - recall: 0.9773 - f1: 0.9693 - 100ms/step Eval samples: 192 Predict begin... step 6/6 [==============================] - 74ms/step Predict samples: 192 192 ('黑龙江省', 'A1')('双鸭山市', 'A2')('尖山区', 'A3')('八马路与东平行路交叉口北40米', 'A4')('韦业涛', 'P')('18600009172', 'T') ('广西壮族自治区', 'A1')('桂林市', 'A2')('雁山区', 'A3')('雁山镇西龙村老年活动中心', 'A4')('17610348888', 'T')('羊卓卫', 'P') ('15652864561', 'T')('河南省', 'A1')('开封市', 'A2')('顺河回族区', 'A3')('顺河区公园路32号', 'A4')('赵本山', 'P') ('河北省', 'A1')('唐山市', 'A2')('玉田县', 'A3')('无终大街159号', 'A4')('18614253058', 'T')('尚汉生', 'P') ('台湾', 'A1')('台中市', 'A2')('北区', 'A3')('北区锦新街18号', 'A4')('18511226708', 'T')('蓟丽', 'P') Eval samples: 192 '''
"\nEval begin...\nEval samples: 192\nsave checkpoint at /home/aistudio/gru_results/final\nEval begin...\nstep 1/6 - loss: 0.0000e+00 - precision: 0.9592 - recall: 0.9843 - f1: 0.9716 - 98ms/step\nstep 2/6 - loss: 0.0000e+00 - precision: 0.9668 - recall: 0.9869 - f1: 0.9767 - 101ms/step\nstep 3/6 - loss: 24.7474 - precision: 0.9724 - recall: 0.9843 - f1: 0.9783 - 100ms/step\nstep 4/6 - loss: 0.0000e+00 - precision: 0.9703 - recall: 0.9830 - f1: 0.9766 - 100ms/step\nstep 5/6 - loss: 0.0000e+00 - precision: 0.9700 - recall: 0.9822 - f1: 0.9761 - 99ms/step\nstep 6/6 - loss: 0.0000e+00 - precision: 0.9614 - recall: 0.9773 - f1: 0.9693 - 100ms/step\nEval samples: 192\nPredict begin...\nstep 6/6 [==============================] - 74ms/step \nPredict samples: 192\n192\n('黑龙江省', 'A1')('双鸭山市', 'A2')('尖山区', 'A3')('八马路与东平行路交叉口北40米', 'A4')('韦业涛', 'P')('18600009172', 'T')\n('广西壮族自治区', 'A1')('桂林市', 'A2')('雁山区', 'A3')('雁山镇西龙村老年活动中心', 'A4')('17610348888', 'T')('羊卓卫', 'P')\n('15652864561', 'T')('河南省', 'A1')('开封市', 'A2')('顺河回族区', 'A3')('顺河区公园路32号', 'A4')('赵本山', 'P')\n('河北省', 'A1')('唐山市', 'A2')('玉田县', 'A3')('无终大街159号', 'A4')('18614253058', 'T')('尚汉生', 'P')\n('台湾', 'A1')('台中市', 'A2')('北区', 'A3')('北区锦新街18号', 'A4')('18511226708', 'T')('蓟丽', 'P')\nEval samples: 192\n"
!python run_ernie.py
#部分结果展示
'''
epoch:8 - step:72 - loss: 0.038532
eval precision: 0.974124 - recall: 0.981497 - f1: 0.977796
epoch:9 - step:73 - loss: 0.031000
epoch:9 - step:74 - loss: 0.033214
epoch:9 - step:75 - loss: 0.034606
epoch:9 - step:76 - loss: 0.038763
epoch:9 - step:77 - loss: 0.033273
epoch:9 - step:78 - loss: 0.031058
epoch:9 - step:79 - loss: 0.028151
epoch:9 - step:80 - loss: 0.030707
eval precision: 0.976608 - recall: 0.983179 - f1: 0.979883
'''
!python run_ernie_gram.py #部分结果展示 ''' epoch:8 - step:72 - loss: 0.030066 eval precision: 0.990764 - recall: 0.992431 - f1: 0.991597 epoch:9 - step:73 - loss: 0.023607 epoch:9 - step:74 - loss: 0.023326 epoch:9 - step:75 - loss: 0.022730 epoch:9 - step:76 - loss: 0.033801 epoch:9 - step:77 - loss: 0.026398 epoch:9 - step:78 - loss: 0.026028 epoch:9 - step:79 - loss: 0.021799 epoch:9 - step:80 - loss: 0.025259 eval precision: 0.990764 - recall: 0.992431 - f1: 0.991597 '''
!python run_ernie_crf.py
#部分结果展示
'''
[EVAL] Precision: 0.975793 - Recall: 0.983179 - F1: 0.979472
[TRAIN] Epoch:9 - Step:73 - Loss: 0.111980
[TRAIN] Epoch:9 - Step:74 - Loss: 0.152896
[TRAIN] Epoch:9 - Step:75 - Loss: 0.274099
[TRAIN] Epoch:9 - Step:76 - Loss: 0.294602
[TRAIN] Epoch:9 - Step:77 - Loss: 0.231813
[TRAIN] Epoch:9 - Step:78 - Loss: 0.225045
[TRAIN] Epoch:9 - Step:79 - Loss: 0.180734
[TRAIN] Epoch:9 - Step:80 - Loss: 0.171899
[EVAL] Precision: 0.975000 - Recall: 0.984020 - F1: 0.979489
'''
!python run_erniegram_crf.py
#部分结果展示
'''
[EVAL] Precision: 0.992437 - Recall: 0.993272 - F1: 0.992854
[TRAIN] Epoch:9 - Step:73 - Loss: 0.100207
[TRAIN] Epoch:9 - Step:74 - Loss: 0.189141
[TRAIN] Epoch:9 - Step:75 - Loss: 0.051093
[TRAIN] Epoch:9 - Step:76 - Loss: 0.230366
[TRAIN] Epoch:9 - Step:77 - Loss: 0.271885
[TRAIN] Epoch:9 - Step:78 - Loss: 0.342371
[TRAIN] Epoch:9 - Step:79 - Loss: 0.050146
[TRAIN] Epoch:9 - Step:80 - Loss: 0.257951
[EVAL] Precision: 0.990764 - Recall: 0.992431 - F1: 0.991597
'''
import os import paddle import paddlenlp from utils import load_dict label_vocab = load_dict('./conf/tag.dic') model = paddlenlp.transformers.ErnieForTokenClassification.from_pretrained("ernie-1.0", num_classes=len(label_vocab)) params_path = './erniegram_crf_result/model_80.pdparams' state_dict = paddle.load(params_path) model.set_dict(state_dict) print("Loaded parameters from %s" % params_path) model.eval() model = paddle.jit.to_static( model, input_spec=[ paddle.static.InputSpec( shape=[None, None], dtype="int64"), # input_ids paddle.static.InputSpec( shape=[None, None], dtype="int64") # segment_ids ]) output_path = './erniegram_crf_result_new' save_path = os.path.join(output_path, "inference") paddle.jit.save(model, save_path)
[2022-06-02 10:50:12,568] [ INFO] - Already cached /home/aistudio/.paddlenlp/models/ernie-1.0/ernie_v1_chn_base.pdparams
Loaded parameters from ./erniegram_crf_result/model_80.pdparams
获得静态图模型之后,我们使用Paddle Inference进行预测部署。Paddle Inference是飞桨的原生推理库,作用于服务器端和云端,提供高性能的推理能力。
Paddle Inference 采用 Predictor 进行预测。Predictor 是一个高性能预测引擎,该引擎通过对计算图的分析,完成对计算图的一系列的优化(如OP的融合、内存/显存的优化、 MKLDNN,TensorRT 等底层加速库的支持等),能够大大提升预测性能。另外Paddle Inference提供了Python、C++、GO等多语言的API,可以根据实际环境需要进行选择,例如使用 Paddle Inference 开发 Python 预测程序可参考示例,相关API已安装在Paddle包,直接使用即可。
结果展示:
模型 | precision | recall | F1 |
---|---|---|---|
GRU+CRF | 0.9614 | 0.9773 | 0.9693 |
Ernie | 0.9766 | 0.983179 | 0.9798 |
ErnieGram | 0.9907 | 0.9924 | 0.9915 |
Ernie +CRF | 0.9750 | 0.9840 | 0.9794 |
ErnieGram +CRF | 0.99076 | 0.9924 | 0.9916 |
结论:CRF在ERNIE上体现作用不大,主要是在传统处理nlp语言上有显著作用,可以避免标注偏置问题。同时可以看出ErnieGram>Ernie>>GRU+CRF 的性能
在文章:
ERNIE-Gram: Pre-Training with Explicitly N-Gram Masked Language Modeling for Natural Language Understanding
粗粒度的语言信息,例如命名实体或短语,有助于在预训练中充分进行表征学习。以前的工作主要集中在将 BERT 的掩码语言建模 (MLM) 的目标从掩码单个令牌扩展到 n 个令牌的连续序列。我们认为这种连续掩蔽方法忽略了对粗粒度语言信息的内部依赖和相互关系进行建模。作为替代方案,我们提出了 ERNIE-Gram,这是一种明确的 n-gram 掩码方法,用于增强粗粒度信息与预训练的集成。在 ERNIE-Gram 中,n-gram 被屏蔽并直接使用显式 n-gram 身份而不是 n 个标记的连续序列进行预测。此外,ERNIE-Gram 使用生成器模型将似是而非的 n-gram 标识作为可选的 n-gram 掩码进行采样,并以粗粒度和细粒度方式预测它们,以实现全面的 n-gram 预测和关系建模。我们在英文和中文文本语料库上预训练 ERNIE-Gram,并对 19 个下游任务进行微调。实验结果表明,ERNIE-Gram 大大优于以前的预训练模型,如 XLNet 和 RoBERTa,并且与最先进的方法取得了可比的结果。源代码和预训练模型已在此 https URL 上发布。
最终结论:
ERNIE-Gram 大大优于以前的预训练模型!!
项目链接:
Paddlenlp之UIE模型实战实体抽取任务【打车数据、快递单】
Paddlenlp之UIE分类模型【以情感倾向分析新闻分类为例】含智能标注方案)
应用实践:分类模型大集成者[PaddleHub、Finetune、prompt]
此文仅为搬运,原作链接:https://aistudio.baidu.com/aistudio/projectdetail/4159638
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。