0.快递单信息抽取[三]:Ernie 1.0至ErnieGram + CRF改进算法

相关项目推荐:

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

Paddlenlp之UIE分类模型【以情感倾向分析新闻分类为例】含智能标注方案)

应用实践:分类模型大集成者[PaddleHub、Finetune、prompt]

Paddlenlp之UIE关系抽取模型【高管关系抽取为例】

1. 项目概述—技术难点

本项目主要介绍如何使用飞桨自然语言处理开发库PaddleNLP完成快递单信息抽取:从用户提供的快递单中,抽取姓名、电话、省、市、区、详细地址等内容,形成结构化信息,如 图1 所示,辅助物流行业从业者进行有效信息的提取,从而降低客户填单的成本。


图1:快递单信息收取示意

从物流信息中抽取想要的关键信息,实际上是自然语言处理中的实体抽取任务,这类任务在产业应用时通常会面临如下技术难点:

  • 实体类别多,任务复杂度高

同一名词可能对应多个实体类别,如“蜗牛”。
不少实体词与普通用语相同,尤其作品名。
此外,实体类别多,任务复杂度较高,如 图2 列举了部分实体类型。实际的实体类型依业务决定。


图2:实体示例
  • 实体词往往稀疏低频

人名在语料出现频次高,但不同人名出现频次有限
大多垂类实体词在通用语料出现频次低。

  • 特定业务场景中标注数据集较少,需要一定的成本标注,如果数据集质量差或样本量过少,精度会比较低。

2. 方案设计

2.1 模型选取

针对实体信息抽取技术,有如下三种方案:

  • 符号主义 —— 字符串匹配
    需要构建词典,穷举所有地址、姓名等信息,但无法发现新词、简称等。
  • 统计语言模型(Word-Based Generative Model)- n-gram概率/最大概率路径
    需要构建词典及词频,但无法发现新词、简称等。
  • 序列标注(Character-Based Discriminative Model)
    需要标注数据,效果好; 有两类实现方法:一是基于统计的模型:HMM、MEMM、CRF,这类方法需要关注特征工程;二是深度学习方法:RNN、LSTM、GRU、CRF、RNN+CRF…

本案例采用序列标注的方式,更加灵活、通用。

我们首先要定义好需要抽取哪些字段。

比如现在拿到一个快递单,可以作为我们的模型输入,例如“张三18625584663广东省深圳市南山区学府路东百度国际大厦”,那么序列标注模型的目的就是识别出其中的“张三”为人名(用符号 P 表示),“18625584663”为电话名(用符号 T 表示),“广东省深圳市南山区百度国际大厦”分别是 1-4 级的地址(分别用 A1~A4 表示,可以释义为省、市、区、街道)。

这是一个典型的命名实体识别(Named Entity Recognition,NER)场景,各实体类型及相应符号表示见下表:

抽取实体/字段符号抽取结果
姓名P张三
电话T18625584663
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广东省深圳市南山区百度国际大厦”,每个汉字及对应标签为:


图3:数据集标注示例

注意到“张“,”三”在这里表示成了“P-B” 和 “P-I”,“P-B”和“P-I”合并成“P” 这个标签。这样重新组合后可以得到以下信息抽取结果:

张三18625584663广东省深圳市南山区百度国际大厦
PTA1A2A3A4

2.2 模型介绍

2.2.1 循环神经网络 - 门控循环单元(GRU,Gate Recurrent Unit)

BIGRU是一种经典的循环神经网络(RNN,Recurrent Neural Network),用于对句子等序列信息进行建模。这里我们重点解释下其概念和相关原理。一个 RNN 的示意图如下所示,


图4:RNN示意图

左边是原始的 RNN,可以看到绿色的点代码输入 x,红色的点代表输出 y,中间的蓝色是 RNN 模型部分。橙色的箭头由自身指向自身,表示 RNN 的输入来自于上时刻的输出,这也是为什么名字中带有循环(Recurrent)这个词。

右边是按照时间序列展开的示意图,注意到蓝色的 RNN 模块是同一个,只不过在不同的时刻复用了。这时候能够清晰地表示序列标注模型的输入输出。

GRU为了解决长期记忆和反向传播中梯度问题而提出来的,和LSTM一样能够有效对长序列建模,且GRU训练效率更高。

2.2.2 条件随机场(CRF,Conditional Random Fields)

长句子的问题解决了,序列标注任务的另外一个问题也亟待解决,即标签之间的依赖性。举个例子,我们预测的标签一般不会出现 P-B,T-I 并列的情况,因为这样的标签不合理,也无法解析。无论是 RNN 还是 LSTM 都只能尽量不出现,却无法从原理上避免这个问题。下面要提到的条件随机场(CRF,Conditional Random Field)却很好的解决了这个问题。

条件随机场这个模型属于概率图模型中的无向图模型,这里我们不做展开,只直观解释下该模型背后考量的思想。一个经典的链式 CRF 如下图所示,


图5:CRF示意图

CRF 本质是一个无向图,其中绿色点表示输入,红色点表示输出。点与点之间的边可以分成两类,一类是 x x x y y y 之间的连线,表示其相关性;另一类是相邻时刻的 y y y 之间的相关性。也就是说,在预测某时刻 y y y 时,同时要考虑相邻的标签解决。当 CRF 模型收敛时,就会学到类似 P-B 和 T-I 作为相邻标签的概率非常低。

2.2.3 预训练模型 (Ernie、Ernie-Gram)

除了GRU+CRF方案外,我们也可以使用预训练模型,将序列信息抽取问题,建模成字符级分类问题。这里我们采用强大的语义模型ERNIE,完成字符级分类任务。



图6:ERNIE模型示意图

2.3 评估指标

信息抽取的通用评测指标:Precision、Recall、F1值。
例子:希望抽取10个信息,实际抽取12个,其中有9个是对的


图7:评估指标

3. 代码实现

3.1 数据准备

采取的是快递单数据集,这份数据除姓名、人名、地名之外,无其他信息。采用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

3.2 模型组网、训练、评估、预测

本项目基于PaddleNLP NER example的代码进行修改,分别基于基本组网单元GRU、CRF和预训练模型,实现了多个方案。

我们以快递单信息抽取为例,介绍如何使用PaddleNLP搭建网络。

  • 方案1: RNN类网络BiGRU、CRF、ViterbiDecoder。
  • 方案2: Ernie
  • 方案3:Ernie+CRF
  • 方案4:Ernie-Gram
  • 方案5:Ernie-Gram+CRF

AI Studio平台默认安装了Paddle和PaddleNLP,并定期更新版本。 如需手动更新Paddle,可参考飞桨安装说明,安装相应环境下最新版飞桨框架。

使用如下命令确保安装最新版PaddleNLP:

!pip install --upgrade paddlenlp

GRU + CRF

!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"

Ernie

!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
'''

ErnieGram

!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
'''

ERNIE + CRF

!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
'''

ErnieGram + CRF

!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
'''

4. 部署

4.1 动转静导出模型

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

4.2 使用推理库预测

获得静态图模型之后,我们使用Paddle Inference进行预测部署。Paddle Inference是飞桨的原生推理库,作用于服务器端和云端,提供高性能的推理能力。

在这里插入图片描述

Paddle Inference 采用 Predictor 进行预测。Predictor 是一个高性能预测引擎,该引擎通过对计算图的分析,完成对计算图的一系列的优化(如OP的融合、内存/显存的优化、 MKLDNN,TensorRT 等底层加速库的支持等),能够大大提升预测性能。另外Paddle Inference提供了Python、C++、GO等多语言的API,可以根据实际环境需要进行选择,例如使用 Paddle Inference 开发 Python 预测程序可参考示例,相关API已安装在Paddle包,直接使用即可。

5.总结

结果展示:

模型precisionrecallF1
GRU+CRF0.96140.97730.9693
Ernie0.97660.9831790.9798
ErnieGram0.99070.99240.9915
Ernie +CRF0.97500.98400.9794
ErnieGram +CRF0.990760.99240.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]

Paddlenlp之UIE关系抽取模型【高管关系抽取为例】

此文仅为搬运,原作链接:https://aistudio.baidu.com/aistudio/projectdetail/4159638

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐