直接使用
请打开基于EasyNLP的中文信息抽取,并点击右上角 “ 在DSW中打开” 。
基于EasyNLP的信息抽取
EasyNLP是阿里云PAI算法团队基于PyTorch开发的易用且丰富的NLP算法框架( https://github.com/alibaba/EasyNLP ),支持常用的中文预训练模型和大模型落地技术,并且提供了从训练到部署的一站式NLP开发体验。EasyNLP提供多种模型的训练及预测功能,旨在帮助自然语言开发者方便快捷地构建模型并应用于生产。
本文以信息抽取任务为例,如何在EasyNLP框架中使⽤K-Global Pointer模型。
关于K-Global Pointer算法
Global Pointer模型是由苏剑林提出的解决命名实体识别任务的模型,其主要思想是构建一个\(n*n\)的矩阵\(A\)(\(n\)为序列长度),\(A[i,j]\)代表的是序列\(i\)到序列\(j\)组成的连续子串为对应实体类型的概率,通过设计门槛值\(B\)即可将文本中具有特定意义的实体识别出来。
K-Global Pointer模型是在Global Pointer模型的基础之上改进的。首先我们将仅支持命名实体识别的模型拓展成支持中文信息抽取三大任务的模型。然后,我们使用了MacBERT预训练语言模型来将文本序列转换成向量序列。最后我们针对不同的任务设计了一套prompt模板,其能帮助预训练语言模型“回忆”起自己在预训练时“学习”到的东西。接下来,我们将根据中文信息抽取三大任务分别进行阐述。
针对命名实体识别任务,我们有文本\(w_1,w_2,w_3,\ldots,w_n\)以及需要提取的实体类型\(entity\_type\),对应的prompt为“找到文章中所有【\(entity\_type\)】类型的实体?”,对应的输入模型的文本\(H\)为“找到文章中所有【\(entity\_type\)】类型的实体?文章:【\(w_1,w_2,w_3,\ldots,w_n\)】”,模型经过相应的处理即可输出文本中实体类型为\(entity\_type\)的实体。
关于信息抽取
信息抽取的三大任务是命名实体识别、关系抽取、事件抽取。命名实体识别是指识别文本中具有特定意义的实体,包括人名、地名、机构名、专有名词等;关系抽取是指识别文本中实体之间的关系;事件抽取是指识别文本中的事件信息并以结构化的形式呈现出来。信息抽取技术被广泛应用于知识图谱的构建、机器阅读理解、智能问答和信息检索系统中。信息抽取的三大任务不是相互独立的关系,而是相互依存、彼此依赖的关系。命名实体识别是关系抽取、事件抽取的基础,关系抽取是事件抽取的基础。同时,关系抽取、事件抽取对命名实体识别任务有帮助,事件抽取对关系抽取任务有帮助。但目前关于仅使用一个模型完成中文信息抽取三大任务的研究相对较少,因此,我们提出K-Global Pointer算法并集成进EasyNLP算法框架中,使用户可以使用自定义数据集训练中文信息抽取模型并使用。
运行环境要求
建议用户使用:Python 3.6,Pytorch 1.8镜像,GPU机型 P100 or V100,内存至少为 32G
EasyNLP安装
建议从GitHub下载EasyNLP源代码进行安装,命令如下:
! echo y | pip uninstall pai-easynlp easynlp ! git clone https://github.com/alibaba/EasyNLP.git ! pip install -r EasyNLP/requirements.txt -i http://mirrors.aliyun.com/pypi/simple ! cd EasyNLP && python setup.py install
安装完成easynlp之后,建议重启notebook,防止环境存在缓存,未更新
您可以使用如下命令验证是否安装成功:
import easynlp easynlp.__file__
如果您系统内已经安装完easynlp的CLI工具,则说明EasyNLP代码库已经安装。
数据准备
首先,您需要进入指定模型目录,下载用于本示例的训练和测试集,命令如下:
!wget http://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/ie/train.tsv !wget http://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/ie/train_part.tsv !wget http://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/ie/dev.tsv !wget http://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/ie/predict_input_EE.tsv !wget http://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/ie/predict_input_NER.tsv
训练和测试数据都是以\t隔开的.tsv文件,数据下载完成后,可以通过以下代码查看前5条数据。数据表示为train.tsv文件以及dev.tsv文件,这两个⽂件都包含以制表符\t分隔的五列,第一列是标签,第二列是上文K-Global Pointer模型详解中提到的\(H\),第三列是答案的开始,第四列是答案的的结束,第五列是答案。
print('Training data sample:') ! head -n 5 train.tsv print("&"*50) print('Development set data sample:') ! head -n 5 dev.tsv
初始化
在Python 3.6环境下,我们首先从刚刚安装好的EasyNLP中引入模型运行需要的各种库,并做一些初始化。在本教程中,我们使用hfl/macbert-large-zh。EasyNLP中集成了丰富的预训练模型库,如果想尝试其他预训练模型,如RoBERTa、albert等,也可以在user_defined_parameters中进行相应修改,具体的模型名称可见模型列表。这里只需要在user_defined_parameters中指定pretrain_model_name_or_path=hfl/macbert-large-zh,即可指定信息抽取任务的模型。
import torch.cuda from easynlp.appzoo import InformationExtractionDataset from easynlp.appzoo import get_application_predictor, get_application_model, get_application_evaluator, get_application_model_for_evaluation from easynlp.core import Trainer, PredictorManager from easynlp.utils import initialize_easynlp, get_args, get_pretrain_model_path from easynlp.utils.global_vars import parse_user_defined_parameters initialize_easynlp() args = get_args() args.user_defined_parameters = 'pretrain_model_name_or_path=hfl/macbert-large-zh' user_defined_parameters = parse_user_defined_parameters(args.user_defined_parameters) # 保存路径 args.checkpoint_dir = "./information_extraction_model/" args.sequence_length=512 args.micro_batch_size=16 args.weight_decay=0.0 args.save_checkpoint_steps=500 args.gradient_accumulation_steps=8 args.epoch_num=1 args.learning_rate=2e-05 args.random_seed=42 args.worker_gpu=4 args.app_name = "information_extraction" args.first_sequence= "sent"
注意:上述代码如果出现“Address already in use”错误,则需要运行以下代码清理端口上正在执行的程序。
netstat -tunlp|grep 6000
kill -9 PID (需要替换成上一行代码执行结果中对应的程序ID)
载入数据
我们使用EasyNLP中自带的InformationExtractionDataset,对训练和测试数据进行载入。主要参数如下:
- pretrained_model_name_or_path:预训练模型名称路径,这里我们使用封装好的get_pretrain_model_path函数,来处理模型名称"bert-base-uncased"以得到其路径,并自动下载模型
- data_file 训练或测试的数据文件
- max_seq_length:总输入文本的最大长度,超过将截断,不足将padding
- input_schema:输入tsv数据的格式,逗号分隔的每一项对应数据文件中每行以\t分隔的一项,每项开头为其字段标识,如question_text、answer_text、context_text等
- first_sequence、second_sequence:用于说明input_schema中哪些字段用于作为问句、描述,input_schema中其他字段名(qas_id、answer_name、start_position_name)将在user_defined_parameters中进行声明
- user_defined_parameters:任务特定的预声明参数。在机器阅读理解任务中,需要声明如下几种:
- pretrain_model_name_or_path:同上
- is_training:是否为训练过程,train_dataset为True,valid_dataset为False
args.label_name="label" args.outputs = "aug.tsv" args.data_threads=5 args.output_schema="augmented_data" args.tables = "train.tsv,dev.tsv" args.input_schema = "id:str:1,instruction:str:1,start:str:1,end:str:1,target:str:1" args.pretrained_model_name_or_path = user_defined_parameters.get('pretrain_model_name_or_path', None) args.pretrained_model_name_or_path = get_pretrain_model_path(args.pretrained_model_name_or_path) train_dataset = InformationExtractionDataset( pretrained_model_name_or_path=args.pretrained_model_name_or_path, data_file=args.tables.split(",")[0], input_schema=args.input_schema, max_seq_length=args.sequence_length, first_sequence=args.first_sequence, second_sequence=args.second_sequence, label_name=args.label_name, label_enumerate_values=args.label_enumerate_values, user_defined_parameters=user_defined_parameters, is_training=True) valid_dataset = InformationExtractionDataset( pretrained_model_name_or_path=args.pretrained_model_name_or_path, data_file=args.tables.split(",")[-1], max_seq_length=args.sequence_length, input_schema=args.input_schema, first_sequence=args.first_sequence, second_sequence=args.second_sequence, label_name=args.label_name, label_enumerate_values=args.label_enumerate_values, user_defined_parameters=user_defined_parameters, is_training=False)
由于之前我们选用了hfl/macbert-large-zh,因此这里也会对预训练模型进行自动下载并载入。
模型训练
处理好数据与模型载入后,我们开始训练模型。 我们使用EasyNLP中封装好的get_application_model函数进行训练时的模型构建,其参数如下:
- app_name:任务名称,这里选择机器阅读理解"information_extraction"
- pretrained_model_name_or_path:预训练模型名称路径,这里我们使用封装好的get_pretrain_model_path函数,来处理模型名称"bert-base-uncased"以得到其路径,并自动下载模型
- user_defined_parameters:用户自定义参数,直接填入刚刚处理好的自定义参数user_defined_parameters
model = get_application_model(app_name="information_extraction", pretrained_model_name_or_path=get_pretrain_model_path("hfl/macbert-large-zh"), user_defined_parameters=user_defined_parameters )
trainer = Trainer(model=model, train_dataset=train_dataset, evaluator=get_application_evaluator(app_name="information_extraction", valid_dataset=valid_dataset, eval_batch_size=16, pretrained_model_name_or_path=get_pretrain_model_path("hfl/macbert-large-zh"), user_defined_parameters=user_defined_parameters, few_shot_anchor_args=args )) trainer.train()
模型评估
训练过程结束后,train好的模型被我们保存在一开始指定好的checkpoint_dir中,本地路径为"./information_extraction_model/"。我们可以对train好的模型进行效果评估。我们同样先使用EasyNLP中的get_application_model_for_evaluation方法构建评估模型。
model = get_application_model_for_evaluation(app_name="information_extraction", pretrained_model_name_or_path="./information_extraction_model/", user_defined_parameters=user_defined_parameters )
evaluator = get_application_evaluator(app_name="information_extraction", valid_dataset=valid_dataset, eval_batch_size=32, user_defined_parameters=user_defined_parameters, few_shot_anchor_args=args ) model.to(torch.cuda.current_device()) evaluator.evaluate(model=model)
模型预测
我们同样可以使用训练好的模型进行信息抽取的预测。我们首先创建一个predictor,并据此实例化一个PredictorManager实例。我们指定预测好的结果输出在指定的tsv文件中。
命名实体识别
对于命名实体识别任务,数据表示为predict_input_NER.tsv文件,这个⽂件包含以制表符\t分隔的三列,第一列是标签,第二列是实体类型,第三列是文本。我们支持对同一个文本识别多种实体类型,仅需要在第二列中将不同的实体类型用;分隔开。
代码如下:
args.tables="predict_input_NER.tsv" args.outputs="predict_output_NER.tsv" args.input_schema="id:str:1,scheme:str:1,content:str:1" args.output_schema="id,content,q_and_a" args.worker_gpu=4 args.sequence_length=512 args.micro_batch_size=16 args.checkpoint_dir="./information_extraction_model/" args.data_threads=5 args.user_defined_parameters='task=NER' predictor = get_application_predictor( app_name=args.app_name, model_dir=args.checkpoint_dir, input_schema=args.input_schema, sequence_length=args.sequence_length, output_file=args.outputs, user_defined_parameters=parse_user_defined_parameters(args.user_defined_parameters)) predictor_manager = PredictorManager( predictor=predictor, input_file=args.tables.split(",")[0], skip_first_line=args.skip_first_line, input_schema=args.input_schema, output_file=args.outputs, output_schema=args.output_schema, append_cols=args.append_cols, batch_size=args.micro_batch_size ) predictor_manager.run() exit()
输入以下命令,可以展示通过训练后的模型预测出的内容。
print('Predicted results: id context q_and_a') ! head -n 5 predict_output_NER.tsv
事件抽取任务
对于关系抽取任务,数据表示为predict_input_RE.tsv文件,这个⽂件包含以制表符\t分隔的三列,第一列是标签,第二列是关系类型,第三列是文本。我们支持对同一个文本识别多种关系类型,仅需要在第二列中将不同的关系类型用;分隔开。对于一个关系类型relation_type(subject_type-predicate-object_type)表示为subject_type:predicate。
代码如下
args.tables="predict_input_EE.tsv" args.outputs="predict_output_EE.tsv" args.input_schema="id:str:1,scheme:str:1,content:str:1" args.output_schema="id,content,q_and_a" args.worker_gpu=4 args.sequence_length=512 args.micro_batch_size=16 args.checkpoint_dir="./information_extraction_model/" args.data_threads=5 args.user_defined_parameters='task=EE' predictor = get_application_predictor( app_name=args.app_name, model_dir=args.checkpoint_dir, input_schema=args.input_schema, sequence_length=args.sequence_length, output_file=args.outputs, user_defined_parameters=parse_user_defined_parameters(args.user_defined_parameters)) predictor_manager = PredictorManager( predictor=predictor, input_file=args.tables.split(",")[0], skip_first_line=args.skip_first_line, input_schema=args.input_schema, output_file=args.outputs, output_schema=args.output_schema, append_cols=args.append_cols, batch_size=args.micro_batch_size ) predictor_manager.run() exit()
print('Predicted results: id context q_and_a') ! head -n 5 predict_output_EE.tsv
Predicted results: id context q_and_a 1 2022语言与智能技术竞赛由中国中文信息学会和中国计算机学会联合主办,百度公司、中国中文信息学会评测工作委员会和中国计算机学会自然语言处理专委会承办,已连续举办4届,成为全球最热门的中文NLP赛事之一。 [['竞赛名称(2022语言与智能技术竞赛)-承办方', '百度公司', 0.69364333152771, 66, 70], ['竞赛名称(2022语言与智能技术竞赛)-已举办次数', '4届', 0.7212715744972229, 113, 115]]
一步执行
值得一提的是,上述所有训练/评估/预测代码,都已经被集成在EasyNLP/examples/information_extraction/main.py中,此外,我们也预先编写好了多种可供直接执行的脚本。用户可以通过带参数运行main.py中指令,或者直接使用bash文件命令行执行的方式,一步执行上述所有训练/评估/预测操作。
main文件一步执行
用户通过以下代码带参数执行main.py中的指令,可直接对模型进行训练/评估/预测操作。
训练代码指令如下。参数说明如“载入数据”小节中所示。在本示例中,预训练模型指定为bert-base-uncased。
! python EasyNLP/examples/information_extraction/main.py \ --mode train \ --tables=train.tsv,dev.tsv \ --input_schema=id:str:1,instruction:str:1,start:str:1,end:str:1,target:str:1 \ --worker_gpu=4 \ --app_name=information_extraction \ --sequence_length=512 \ --weight_decay=0.0 \ --micro_batch_size=2 \ --checkpoint_dir=./information_extraction_model/ \ --data_threads=5 \ --user_defined_parameters='pretrain_model_name_or_path=hfl/macbert-large-zh' \ --save_checkpoint_steps=500 \ --gradient_accumulation_steps=8 \ --epoch_num=3 \ --learning_rate=2e-05 \ --random_seed=42
评估代码如下,参数含义与训练是一致的
! python EasyNLP/examples/information_extraction/main.py \ --mode evaluate \ --tables=dev.tsv \ --input_schema=id:str:1,instruction:str:1,start:str:1,end:str:1,target:str:1 \ --worker_gpu=4 \ --app_name=information_extraction \ --sequence_length=512 \ --weight_decay=0.0 \ --micro_batch_size=2 \ --checkpoint_dir=./information_extraction_model/ \ --data_threads=5
预测代码、参数含义同样与上面保持一致,以命名实体识别和事件抽取任务为例,输入为predict_input_NER.tsv或者predict_input_EE.tsv,输出结果可在predict_output_EE.tsv或者predict_output_NER.tsv中查看。
## 命名实体识别任务预测 ! python EasyNLP/examples/information_extraction/main.py \ --mode predict \ --tables=predict_input_NER.tsv \ --outputs=predict_output_NER.tsv \ --input_schema=id:str:1,scheme:str:1,content:str:1 \ --output_schema=id,content,q_and_a \ --worker_gpu=4 \ --app_name=information_extraction \ --sequence_length=512 \ --weight_decay=0.0 \ --micro_batch_size=4 \ --checkpoint_dir=./information_extraction_model/ \ --data_threads=5 \ --user_defined_parameters='task=NER'
## 事件抽取任务预测 ! python EasyNLP/examples/information_extraction/main.py \ --mode predict \ --tables=predict_input_EE.tsv \ --outputs=predict_output_EE.tsv \ --input_schema=id:str:1,scheme:str:1,content:str:1 \ --output_schema=id,content,q_and_a \ --worker_gpu=4 \ --app_name=information_extraction \ --sequence_length=512 \ --weight_decay=0.0 \ --micro_batch_size=4 \ --checkpoint_dir=./information_extraction_model/ \ --data_threads=5 \ --user_defined_parameters='task=EE'
利用bash文件命令行执行
我们在EasyNLP/examples/information_extraction/文件夹下封装好了多种可直接执行的bash脚本,用户同样可以通过使用bash文件命令行执行的方式来一步完成特征的抽取。以下以run_train_eval_predict_user_defined_local.sh脚本为例。
模型训练:
! cd EasyNLP/examples/information_extraction/ && bash run_train_eval_predict_user_defined_local.sh 0 train
模型评估
! cd EasyNLP/examples/information_extraction/ && bash run_train_eval_predict_user_defined_local.sh 0 evaluate
模型预测:
! cd EasyNLP/examples/information_extraction/ && bash run_train_eval_predict_user_defined_local.sh 0 predict