Are you sure you want to delete this task? Once this task is deleted, it cannot be recovered.
汀丶人工智能 14cb169e2b | 1 year ago | |
---|---|---|
data | 1 year ago | |
deploy/python | 1 year ago | |
input | 1 year ago | |
output | 1 year ago | |
src | 1 year ago | |
1.png | 1 year ago | |
2.jpg | 1 year ago | |
README.md | 1 year ago | |
copy_cudnn.py | 1 year ago | |
doccano.md | 1 year ago | |
doccano.py | 1 year ago | |
evaluate.py | 1 year ago | |
finetune.py | 1 year ago | |
labelstudio2doccano.py | 1 year ago | |
main.py | 1 year ago | |
main.sh | 1 year ago | |
main_new.ipynb | 1 year ago | |
utils.py | 1 year ago |
个人原项目链接:https://aistudio.baidu.com/aistudio/projectdetail/4321385?contributionType=1
下面展示在调试环境下应该如何操作,更多内容查看main_new.ipynb文件即可,已经调通可自行调试。
目前所有程序已在云脑调试成功,云脑环境选择
dockerhub.pcl.ac.cn:5000/user-images/openi:PaddleGPU2.4.2_CUDA10.2_Python3.7_PaddleNLP2.5.2
已公开
本项目将演示如何通过小样本样本进行模型微调,快速且准确抽取快递单中的目的地、出发地、时间、打车费用等内容,形成结构化信息。辅助物流行业从业者进行有效信息的提取,从而降低客户填单的成本。
数据集情况:
waybill.jsonl文件是快递单信息数据集:
{"id": 57, "text": "昌胜远黑龙江省哈尔滨市南岗区宽桥街28号18618391296", "relations": [], "entities": [{"id": 111, "start_offset": 0, "end_offset": 3, "label": "姓名"}, {"id": 112, "start_offset": 3, "end_offset": 7, "label": "省份"}, {"id": 113, "start_offset": 7, "end_offset": 11, "label": "城市"}, {"id": 114, "start_offset": 11, "end_offset": 14, "label": "县区"}, {"id": 115, "start_offset": 14, "end_offset": 20, "label": "详细地址"}, {"id": 116, "start_offset": 20, "end_offset": 31, "label": "电话"}]}
{"id": 58, "text": "易颖18500308469山东省烟台市莱阳市富水南路1号", "relations": [], "entities": [{"id": 118, "start_offset": 0, "end_offset": 2, "label": "姓名"}, {"id": 119, "start_offset": 2, "end_offset": 13, "label": "电话"}, {"id": 120, "start_offset": 13, "end_offset": 16, "label": "省份"}, {"id": 121, "start_offset": 16, "end_offset": 19, "label": "城市"}, {"id": 122, "start_offset": 19, "end_offset": 22, "label": "县区"}, {"id": 123, "start_offset": 22, "end_offset": 28, "label": "详细地址"}]}
doccano_ext.jsonl是打车数据集:
{"id": 1, "text": "昨天晚上十点加班打车回家58元", "relations": [], "entities": [{"id": 0, "start_offset": 0, "end_offset": 6, "label": "时间"}, {"id": 1, "start_offset": 11, "end_offset": 12, "label": "目的地"}, {"id": 2, "start_offset": 12, "end_offset": 14, "label": "费用"}]}
{"id": 2, "text": "三月三号早上12点46加班,到公司54", "relations": [], "entities": [{"id": 3, "start_offset": 0, "end_offset": 11, "label": "时间"}, {"id": 4, "start_offset": 15, "end_offset": 17, "label": "目的地"}, {"id": 5, "start_offset": 17, "end_offset": 19, "label": "费用"}]}
{"id": 3, "text": "8月31号十一点零四工作加班五十块钱", "relations": [], "entities": [{"id": 6, "start_offset": 0, "end_offset": 10, "label": "时间"}, {"id": 7, "start_offset": 14, "end_offset": 16, "label": "费用"}]}
{"id": 4, "text": "5月17号晚上10点35分加班打车回家,36块五", "relations": [], "entities": [{"id": 8, "start_offset": 0, "end_offset": 13, "label": "时间"}, {"id": 1, "start_offset": 18, "end_offset": 19, "label": "目的地"}, {"id": 9, "start_offset": 20, "end_offset": 24, "label": "费用"}]}
{"id": 5, "text": "2009年1月份通讯费一百元", "relations": [], "entities": [{"id": 10, "start_offset": 0, "end_offset": 7, "label": "时间"}, {"id": 11, "start_offset": 11, "end_offset": 13, "label": "费用"}]}
输入:
城市内交通费7月5日金额114广州至佛山
从百度大厦到龙泽苑东区打车费二十元
上海虹桥高铁到杭州时间是9月24日费用是73元
上周末坐动车从北京到上海花费五十块五毛
昨天北京飞上海话费一百元
输出:
{"出发地": [{"text": "广州", "start": 15, "end": 17, "probability": 0.9073772252165782}], "目的地": [{"text": "佛山", "start": 18, "end": 20, "probability": 0.9927365183877761}], "时间": [{"text": "7月5日", "start": 6, "end": 10, "probability": 0.9978010396512218}]}
{"出发地": [{"text": "百度大厦", "start": 1, "end": 5, "probability": 0.968825147409472}], "目的地": [{"text": "龙泽苑东区", "start": 6, "end": 11, "probability": 0.9877913072493669}]}
{"目的地": [{"text": "杭州", "start": 7, "end": 9, "probability": 0.9929172180094881}], "时间": [{"text": "9月24日", "start": 12, "end": 17, "probability": 0.9953342057701597}]}
{#"出发地": [{"text": "北京", "start": 7, "end": 9, "probability": 0.973048366717471}], "目的地": [{"text": "上海", "start": 10, "end": 12, "probability": 0.988486130309397}], "时间": [{"text": "上周末", "start": 0, "end": 3, "probability": 0.9977407699595275}]}
{"出发地": [{"text": "北京", "start": 2, "end": 4, "probability": 0.974188953533556}], "目的地": [{"text": "上海", "start": 5, "end": 7, "probability": 0.9928200521486445}], "时间": [{"text": "昨天", "start": 0, "end": 2, "probability": 0.9731559534465504}]}
下面展示在调试环境下应该如何操作,更多内容查看main_new.ipynb文件即可,已经调通可自行调试。
!python doccano.py \
--doccano_file ./data/doccano_ext.jsonl \
--task_type 'ext' \
--save_dir ./data \
--splits 0.8 0.2 0 \
--negative_ratio 5
doccano_file: 从doccano导出的数据标注文件。
save_dir: 训练数据的保存目录,默认存储在data目录下。
negative_ratio: 最大负例比例,该参数只对抽取类型任务有效,适当构造负例可提升模型效果。负例数量和实际的标签数量有关,最大负例数量 = negative_ratio * 正例数量。该参数只对训练集有效,默认为5。为了保证评估指标的准确性,验证集和测试集默认构造全负例。
splits: 划分数据集时训练集、验证集所占的比例。默认为[0.8, 0.1, 0.1]表示按照81的比例将数据划分为训练集、验证集和测试集。
task_type: 选择任务类型,可选有抽取和分类两种类型的任务。
options: 指定分类任务的类别标签,该参数只对分类类型任务有效。默认为["正向", "负向"]。
prompt_prefix: 声明分类任务的prompt前缀信息,该参数只对分类类型任务有效。默认为"情感倾向"。
is_shuffle: 是否对数据集进行随机打散,默认为True。
seed: 随机种子,默认为1000.
*separator: 实体类别/评价维度与分类标签的分隔符,该参数只对实体/评价维度级分类任务有效。默认为"##"。
输出部分展示:
{"content": "上海到北京机票1320元", "result_list": [{"text": "上海", "start": 0, "end": 2}], "prompt": "出发地"}
{"content": "上海到北京机票1320元", "result_list": [{"text": "北京", "start": 3, "end": 5}], "prompt": "目的地"}
{"content": "上海到北京机票1320元", "result_list": [{"text": "1320", "start": 7, "end": 11}], "prompt": "费用"}
{"content": "上海虹桥到杭州东站高铁g7555共73元时间是10月14日", "result_list": [{"text": "上海虹桥", "start": 0, "end": 4}], "prompt": "出发地"}
{"content": "上海虹桥到杭州东站高铁g7555共73元时间是10月14日", "result_list": [{"text": "杭州东站", "start": 5, "end": 9}], "prompt": "目的地"}
{"content": "上海虹桥到杭州东站高铁g7555共73元时间是10月14日", "result_list": [{"text": "73", "start": 17, "end": 19}], "prompt": "费用"}
{"content": "上海虹桥到杭州东站高铁g7555共73元时间是10月14日", "result_list": [{"text": "10月14日", "start": 23, "end": 29}], "prompt": "时间"}
{"content": "昨天晚上十点加班打车回家58元", "result_list": [{"text": "昨天晚上十点", "start": 0, "end": 6}], "prompt": "时间"}
{"content": "昨天晚上十点加班打车回家58元", "result_list": [{"text": "家", "start": 11, "end": 12}], "prompt": "目的地"}
{"content": "昨天晚上十点加班打车回家58元", "result_list": [{"text": "58", "start": 12, "end": 14}], "prompt": "费用"}
{"content": "2月20号从南山到光明二十元", "result_list": [{"text": "2月20号", "start": 0, "end": 5}], "prompt": "时间"}
!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-03-20 15:09:47,643] [ INFO] - global step 250, epoch: 13, loss: 0.00045, speed: 3.90 step/s
[2023-03-20 15:09:47,910] [ INFO] - Evaluation precision: 1.00000, recall: 1.00000, F1: 1.00000
[2023-03-20 15:09:50,399] [ INFO] - global step 260, epoch: 13, loss: 0.00043, speed: 4.02 step/s
[2023-03-20 15:09:52,966] [ INFO] - global step 270, epoch: 14, loss: 0.00042, speed: 3.90 step/s
[2023-03-20 15:09:55,464] [ INFO] - global step 280, epoch: 14, loss: 0.00040, speed: 4.00 step/s
推荐使用GPU环境,否则可能会内存溢出。CPU环境下,可以修改model为uie-tiny,适当调下batch_size。
增加准确率的话:--num_epochs 设置大点多训练训练
可配置参数说明:
train_path: 训练集文件路径。
dev_path: 验证集文件路径。
save_dir: 模型存储路径,默认为./checkpoint。
learning_rate: 学习率,默认为1e-5。
batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数,默认为16。
max_seq_len: 文本最大切分长度,输入超过最大长度时会对输入文本进行自动切分,默认为512。
num_epochs: 训练轮数,默认为100。
model 选择模型,程序会基于选择的模型进行模型微调,可选有uie-base和uie-tiny,默认为uie-base。
seed: 随机种子,默认为1000.
logging_steps: 日志打印的间隔steps数,默认10。
valid_steps: evaluate的间隔steps数,默认100。
device: 选用什么设备进行训练,可选cpu或gpu。
!python evaluate.py \
--model_path ./checkpoint/model_best \
--test_path ./data/dev.txt \
--batch_size 16 \
--max_seq_len 512
2023-03-20 16:16:51,795] [ INFO] - -----------------------------
[2023-03-20 16:16:51,795] [ INFO] - Class Name: all_classes
[2023-03-20 16:16:51,795] [ INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000
!python evaluate.py \
--model_path ./checkpoint/model_best \
--test_path ./data/dev.txt \
--debug
[2023-03-20 16:17:12,312] [ INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000
[2023-03-20 16:17:12,349] [ INFO] - -----------------------------
[2023-03-20 16:17:12,349] [ INFO] - Class Name: X的地
[2023-03-20 16:17:12,349] [ INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000
model_path: 进行评估的模型文件夹路径,路径下需包含模型权重文件model_state.pdparams及配置文件model_config.json。
test_path: 进行评估的测试集文件。
batch_size: 批处理大小,请结合机器情况进行调整,默认为16。
max_seq_len: 文本最大切分长度,输入超过最大长度时会对输入文本进行自动切分,默认为512。
model: 选择所使用的模型,可选有uie-base, uie-medium, uie-mini, uie-micro和uie-nano,默认为uie-base。
debug: 是否开启debug模式对每个正例类别分别进行评估,该模式仅用于模型调试,默认关闭。
from pprint import pprint
import json
from paddlenlp import Taskflow
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
data_input=openreadtxt('./input/nlp.txt')
schema = ['出发地', '目的地','时间']
few_ie = Taskflow('information_extraction', schema=schema, batch_size=8,task_path='./checkpoint/model_best')
results=few_ie(data_input)
print(results)
with open("./output/test.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")
print("数据结果已导出")
[{'出发地': [{'text': '广州', 'start': 15, 'end': 17, 'probability': 0.9807058282747185}], '目的地': [{'text': '佛山', 'start': 18, 'end': 20, 'probability': 0.9976225870969735}], '时间': [{'text': '7月5日', 'start': 6, 'end': 10, 'probability': 0.9993272905042794}]}, {'出发地': [{'text': '百度大厦', 'start': 1, 'end': 5, 'probability': 0.9935426759958332}], '目的地': [{'text': '龙泽苑东区', 'start': 6, 'end': 11, 'probability': 0.996392818258812}]}, {'出发地': [{'text': '上海虹桥', 'start': 0, 'end': 4, 'probability': 0.9523853360916021}], '目的地': [{'text': '杭州', 'start': 7, 'end': 9, 'probability': 0.9970840981070666}], '时间': [{'text': '9月24日', 'start': 12, 'end': 17, 'probability': 0.9987603294852754}]}, {'出发地': [{'text': '北京', 'start': 7, 'end': 9, 'probability': 0.99415014607942}], '目的地': [{'text': '上海', 'start': 10, 'end': 12, 'probability': 0.9967051313549469}], '时间': [{'text': '上周末', 'start': 0, 'end': 3, 'probability': 0.9980770066411537}]}, {'出发地': [{'text': '北京', 'start': 2, 'end': 4, 'probability': 0.9949388730271167}], '目的地': [{'text': '上海', 'start': 5, 'end': 7, 'probability': 0.9972941649245399}], '时间': [{'text': '昨天', 'start': 0, 'end': 2, 'probability': 0.9844455121209528}]}]
数据结果已导出
UIE(Universal Information Extraction):Yaojie Lu等人在ACL-2022中提出了通用信息抽取统一框架UIE。该框架实现了实体抽取、关系抽取、事件抽取、情感分析等任务的统一建模,并使得不同任务间具备良好的迁移和泛化能力。PaddleNLP借鉴该论文的方法,基于ERNIE 3.0知识增强预训练模型,训练并开源了首个中文通用信息抽取模型UIE。该模型可以支持不限定行业领域和抽取目标的关键信息抽取,实现零样本快速冷启动,并具备优秀的小样本微调能力,快速适配特定的抽取目标。
UIE的优势
使用简单: 用户可以使用自然语言自定义抽取目标,无需训练即可统一抽取输入文本中的对应信息。实现开箱即用,并满足各类信息抽取需求。
降本增效: 以往的信息抽取技术需要大量标注数据才能保证信息抽取的效果,为了提高开发过程中的开发效率,减少不必要的重复工作时间,开放域信息抽取可以实现零样本(zero-shot)或者少样本(few-shot)抽取,大幅度降低标注数据依赖,在降低成本的同时,还提升了效果。
效果领先: 开放域信息抽取在多种场景,多种任务上,均有不俗的表现。
本人本次主要通过实体抽取这个案例分享给大家,主要对开源的paddlenlp的案例进行了细化,比如在结果可视化方面以及结果输入输出的增加,使demo项目更佳完善。
当然标注问题是所有问题的痛点,可以参考我的博客来解决这个问题
本人博客:https://blog.csdn.net/sinat_39620217?type=blog
--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
No Description
Python Jupyter Notebook Text Shell Markdown
Dear OpenI User
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.
For more agreement content, please refer to the《Openl Qizhi Community AI Collaboration Platform Usage Agreement》