【PaddleNLP-kie】关键信息抽取2:UIE模型做图片信息提取全流程

news2025/1/11 2:52:35

文章目录

  • 本文参考
  • UIE理论部分
  • step0、UIEX原始模型使用
    • 网页体验
    • 本机安装使用
      • 环境安装
      • 快速开始
  • step1、UIEX模型微调(小样本学习)
  • 微调模型对比
  • step2、服务化部署
  • step3、提升推理速度
    • 模型量化
    • 更换模型
    • fast-tokenizer
    • 提高batch_size(没用)

大模型时代来咯!讲究的就是一个通用!
本文记录我使用PaddleNLP中UIE做增值税发票信息提取的过程,同理适用于任何图片信息提取

首先上个图镇场子,里面红底的就是做图片信息提取,所需要重点关注的文件
在这里插入图片描述

本文参考

  • 项目
    PaddleNLP:https://github.com/PaddlePaddle/PaddleNLP
    其中UIE部分:
    https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie
    发票信息提取使用的UIEX:
    https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/information_extraction/document

  • 教程/文档
    跨模态文档通用信息抽取模型UIE-X来了
    uie的简单介绍b站视频【AI快车道|通用信息抽取技术与产业应用实战】 https://www.bilibili.com/video/BV1Q34y1E7SW/?share_source=copy_web&vd_source=679c63061dfbdf7484b5a4a666d4b9e1
    AI快车道PaddleNLP系列直播课https://aistudio.baidu.com/aistudio/education/group/info/24902
    UIE(Universal Information Extraction)

UIE理论部分

  • UIE原始论文
    论文阅读笔记
    在这里插入图片描述
    在这里插入图片描述

  • Paddle-UIE-X

UIE(Universal Information Extraction):Yaojie Lu等人在ACL-2022中提出了通用信息抽取统一框架UIE。该框架实现了实体抽取、关系抽取、事件抽取、情感分析等任务的统一建模,并使得不同任务间具备良好的迁移和泛化能力。为了方便大家使用UIE的强大能力,PaddleNLP借鉴该论文的方法,基于ERNIE 3.0知识增强预训练模型,训练并开源了首个中文通用信息抽取模型UIE。该模型可以支持不限定行业领域和抽取目标的关键信息抽取,实现零样本快速冷启动,并具备优秀的小样本微调能力,快速适配特定的抽取目标。
来源:https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie

paddle基于论文中的UIE做了修改,论文中的UIE是对text文本字段进行实体抽取、关系抽取、事件抽取、情感分析四种任务处理的,Paddle全新升级UIE-X,除已有纯文本抽取的全部功能外,新增文档抽取能力,具体来说paddle就是在前面增加了paddleOCR的det和rec功能,图片转化为识别出来的文本,再送入进行UIE,再结合布局分析等功能做了优化。UIE-X把这个功能端到端打通了。使用起来非常方便
在这里插入图片描述

step0、UIEX原始模型使用

网页体验

🤗Huggingface hub 正式兼容 PaddleNLP 预训练模型,支持 PaddleNLP Model 和 Tokenizer 直接从 🤗Huggingface hub 下载和上传,欢迎大家在 🤗Huggingface hub 体验 PaddleNLP 预训练模型效果

网页直接体验UIEX原始模型:https://huggingface.co/spaces/PaddlePaddle/UIE-X
输入schema,点击submit即可
在这里插入图片描述

本机安装使用

环境安装

基本都是使用一键预测功能:Taskflow API去做使用的,安装包,引入库,然后就三行代码,就可以使用了,封装得很完善

安装
环境依赖

  • python >= 3.7
  • paddlepaddle >= 2.3
    pip安装
pip install --upgrade paddlenlp

或者可通过以下命令安装最新 develop 分支代码:

pip install --pre --upgrade paddlenlp -f https://www.paddlepaddle.org.cn/whl/paddlenlp.html

更多关于PaddlePaddle和PaddleNLP安装的详细教程请查看get_started。
来源:https://github.com/PaddlePaddle/PaddleNLP#readme

对于环境依赖,可以直接pull预安装 PaddlePaddle 的镜像,再在docker里面安装paddlenlp

nvidia-docker pull registry.baidubce.com/paddlepaddle/paddle:2.4.2-gpu-cuda11.2-cudnn8.2-trt8.0
#以端口号6666对外提供SSH,挂载物理机data文件夹到虚拟机hdd文件夹
nvidia-docker run --name paddle_docker -it -v /data/:/hdd -p 6666:22 registry.baidubce.com/paddlepaddle/paddle:2.4.2-gpu-cuda11.2-cudnn8.2-trt8.0 /bin/bash
#docker自启动
docker update --restart=always paddle_docker

快速开始

这里以信息抽取-命名实体识别任务,UIE模型为例,来说明如何快速使用PaddleNLP:

  • text类信息提取
    PaddleNLP提供一键预测功能,无需训练,直接输入数据即可开放域抽取结果:
>>> from pprint import pprint
>>> from paddlenlp import Taskflow

>>> schema = ['时间', '选手', '赛事名称'] # Define the schema for entity extraction
>>> ie = Taskflow('information_extraction', schema=schema)
>>> pprint(ie("2月8日上午北京冬奥会自由式滑雪女子大跳台决赛中中国选手谷爱凌以188.25分获得金牌!"))
[{'时间': [{'end': 6,
          'probability': 0.9857378532924486,
          'start': 0,
          'text': '2月8日上午'}],
  '赛事名称': [{'end': 23,
            'probability': 0.8503089953268272,
            'start': 6,
            'text': '北京冬奥会自由式滑雪女子大跳台决赛'}],
  '选手': [{'end': 31,
          'probability': 0.8981548639781138,
          'start': 28,
          'text': '谷爱凌'}]}]
  • 图片类信息提取(使用uie-x)
import paddlenlp, paddleocr
print(paddlenlp.__version__)
print(paddleocr.__version__)

from pprint import pprint
from paddlenlp import Taskflow
schema = ["购买方名称", "购买方纳税人识别号", "货物", "规格型号", "税率", "标题", "发票号码", "销售方名称", "销售方识别号", "销售方开户行账号"]
ie = Taskflow("information_extraction", schema=schema, model="uie-x-base")
pprint(ie({"doc": "./fp1.jpg"}))

直接在/root/目录下运行,第一次运行会在根目录生成.paddlenlp和.paddleocr的隐藏文件夹,用于存储自动下载的uie和ocr模型,然后开始推理
在这里插入图片描述

有一些字段没有显示的,应该就是没有找到,下面只显示的是找到的,可是但凡显示出来的准确度都很高,可以说效果真的很牛,就是密码区一直不认
大概可以得出的结论是:只要图像上靠近且有明显键值对的,都可以识别,只有那种键值对不明显,或者只有值没有键的信息,才会难以提取,才会需要微调。
在这里插入图片描述
测试到这里我就觉得这个方案是可行的了,所以打算基于UIEX做小样本学习,实际上除了发票,对于任何图片信息提取场景,根据它的介绍少量学习都能带来大幅提升,经过我的测试确实如此

在这里插入图片描述

step1、UIEX模型微调(小样本学习)

按https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/information_extraction/document进行模型微调,教程写的挺清楚了,我这里说一些其他的注意点
在这里插入图片描述

  • 数据标注(label_studio)
    这是本地启动服务网页使用的,为了方便数据获取,就在win装,因为我的基本环境烂了,会有一些奇怪报错:django.db.utils.OperationalError: no such function: JSON_VALID所以我在anaconda里面新建py39环境,可以正常运行
pip install label-studio#我安装的是1.7.2,教程里的1.6.0有bug
pip install -U label-studio
label-studio start
  • 这个地方,一定得是image或者text,不能是ocr什么的,在后面数据处理转换json文件为paddle数据集的时候,只认image/test,如果换成其他的会不识别报错在这里插入图片描述

  • 标注的时候,框要偏大一点,不能恰恰好贴着文字,不然会导致提取信息的时候漏掉前面几个字符
    在这里插入图片描述

  • 导出数据转换
    ext:抽取式任务,实体收取和关系抽取都是抽取

python label_studio.py --label_studio_file ./document/data/label_studio.json --save_dir ./document/data --splits 0.8 0.1 0.1 --task_type ext
  • 微调训练:
    我在3090Ti上训练的速度基本是数据集增加一张图片,训练耗时增加一分钟,我标10张图片用了9分钟,标40张图片用了50分钟
    模型大小:“uie-x-base“ 1.05G,训练过程占用显存情况:20G/24G
python finetune.py --device gpu --logging_steps 5 --save_steps 25 --eval_steps 25 --seed 42     --model_name_or_path uie-x-base --output_dir ./checkpoint/model_best --train_path data/train.txt     --dev_path data/dev.txt --max_seq_len 512 --per_device_train_batch_size  8     --per_device_eval_batch_size 8 --num_train_epochs 10 --learning_rate 1e-5 --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
  • 评估:
python evaluate.py --device "gpu" --model_path ./checkpoint/model_best --test_path ./data/dev.txt --output_dir ./checkpoint/model_best --label_names 'start_positions' 'end_positions' --max_seq_len 512  --per_device_eval_batch_size 16 --debug True

在这里插入图片描述

  • 定制模型一键预测
    我写了一个脚本,来同时执行原始模型和微调模型在同一张图片上的表现,同时可视化和输出识别结果到txt,以便对比:
import pprint
from paddlenlp import Taskflow
from paddlenlp.utils.doc_parser import DocParser
import os
import sys
import time

#输入图片名参数
doc_path = str(sys.argv[1])
print(doc_path)
#发票联次,包括发票联,抵扣联,记账联


# schema = ['发票代码', '校验码', '标题', '发票联次', '发票号码', '开票日期', '购买方名称', '购买方纳税人识别号', '购买方地址电话', '购买方开户行及账号', '密码区', '货物或应税劳务服务名称', '规格型号', '单位', '数量', '单价', '金额', '税率', '税额', '合计金额', '合计税额', '价税合计(大写)', '价税合计(小写)', '销售方名称', '销售方纳税人识别号', '销售方地址电话', '销售方开户行及账号', '收款人', '复核', '开票人', '备注', '销售方(章)', '机器编号']
schema = ['发票代码', '校验码', '标题', '发票联次', '发票号码', '开票日期', '购买方名称', '购买方纳税人识别号', '购买方地址电话', '购买方开户行及账号', '货物或应税劳务服务名称', '规格型号', '单位', '数量', '单价', '金额', '税率', '税额', '合计金额', '合计税额', '价税合计(大写)', '价税合计(小写)', '销售方名称', '销售方纳税人识别号', '销售方地址电话', '销售方开户行及账号', '收款人', '复核', '开票人', '机器编号']

my_ie = Taskflow("information_extraction", model="uie-x-base", schema=schema, task_path='./checkpoint/model_best',layout_analysis=True)
ie = Taskflow("information_extraction", model="uie-x-base", schema=schema,layout_analysis=True)


filename=os.path.basename(doc_path).split('.')[0]

start_time=time.time()
my_results = my_ie({"doc": doc_path})
end_time=time.time()
print('self inference time(s):',end_time-start_time)


start_time=time.time()
results = ie({"doc": doc_path})
end_time=time.time()
print('origin inference time(s):',end_time-start_time)
# pprint(results)

if os.path.exists('./results/'+filename):
    pass
else:
    os.mkdir('./results/'+filename)
    print('mkdir ','./results/'+filename)


# 结果可视化
save_path_self='./results/'+filename+'/'+'image_show_self_'+filename+'.png'
DocParser.write_image_with_results(
    doc_path,
    result=my_results[0],
    save_path=save_path_self)

save_path_origin='./results/'+filename+'/'+'image_show_origin_'+filename+'.png'
DocParser.write_image_with_results(
    doc_path,
    result=results[0],
    save_path=save_path_origin)



#保存结果
with open('./results/'+filename+'/'+filename+'_self.txt','w') as f:
    f.write(str(str(pprint.pformat(my_results))))
    f.close()
with open('./results/'+filename+'/'+filename+'_origin.txt','w') as f:
    f.write(str(str(pprint.pformat(results))))
    f.close()

print('finished')

推理就是

λ 8be5100f3bf1 /hdd/PaddleNLP/applications/information_extraction/document python testuie_self.py data/testimages/b78.jpg

微调模型对比

总体来说微调模型相比原始模型提升很大,有学习到标记的信息,并且可以区分购买方和销售方
在这里插入图片描述
左边一列是微调后的,右边的原始UIE-X-base
在这里插入图片描述

但也有问题:比如会认密码区但不跨行,只有第一行(还不如不要),对于密码区,盖章识别,二维码识别,我就去掉了,不设schema,这些需要额外优化

我在3090Ti上推理一张的时间是5s左右,说实话还是挺慢的,后面再补充提升推理速度的问题

step2、服务化部署

这个部分可以用https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/information_extraction/document/deploy/simple_serving
结合PaddleNLP-develop\docs\server.md进行部署,教程讲的很清楚了

或者使用百度新出的专门用来部署的工具FastDeploy:https://github.com/PaddlePaddle/FastDeploy/tree/develop/examples/vision/ocr/PP-OCR/serving
client和server的简单关系:
在这里插入图片描述

我就讲一些坑:
作为服务器端的环境,如果是docker,要以--net=host进行创建,例如我之前使用的

nvidia-docker run --name paddle_docker -it -v /data/:/hdd -p 6666:22 registry.baidubce.com/paddlepaddle/paddle:2.4.2-gpu-cuda11.2-cudnn8.2-trt8.0 /bin/bash

是默认–net=bridge,以桥接形式对外提供,不是–net=host,所以无法对外提供服务化部署
应该:

nvidia-docker run --name paddle_serving_docker -it -v /data/:/hdd --net=host registry.baidubce.com/paddlepaddle/paddle:2.4.2-gpu-cuda11.2-cudnn8.2-trt8.0 /bin/bash
#开启进入
sudo docker start paddle_serving_docker
sudo docker exec -it paddle_serving_docker /bin/bash
#安装基本环境
pip install paddlenlp
python3 -m pip install paddleocr
#Server服务启动
paddlenlp server server:app --workers 1 --host 10.24.83.40 --port 8189

step3、提升推理速度

模型量化

可以用PaddleSlim试一下
https://github.com/PaddlePaddle/PaddleSlim/tree/develop/example/auto_compression

更换模型

因为其原理是经过OCR将图片转化为text再输入UIE模型,所以实际上其他size的UIE模型也能用,但会损失精度

https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie

模型结构语言
uie-base (默认)12-layers, 768-hidden, 12-heads中文
uie-base-en12-layers, 768-hidden, 12-heads英文
uie-medical-base12-layers, 768-hidden, 12-heads中文
uie-medium6-layers, 768-hidden, 12-heads中文
uie-mini6-layers, 384-hidden, 12-heads中文
uie-micro4-layers, 384-hidden, 12-heads中文
uie-nano4-layers, 312-hidden, 12-heads中文
uie-m-large24-layers, 1024-hidden, 16-heads中、英文
uie-m-base12-layers, 768-hidden, 12-heads中、英文

fast-tokenizer

https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/uie
TaskFlow的一个参数
use_fast: 使用C++实现的高性能分词算子FastTokenizer进行文本预处理加速。需要通过pip install fast-tokenizer-python安装FastTokenizer库后方可使用。默认为False。更多使用说明可参考FastTokenizer文档。

提高batch_size(没用)

Q&A里面的,但是我实测16和256一样都是5s……
在这里插入图片描述
end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/457736.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第十一章 组合模式

文章目录 前言一、组合模式基本介绍二、UML类图三、完整代码抽象类,所有类都继承此类学校类以父类型引用组合一个学院类学院类以父类型引用组合一个专业类专业类,叶子节点,不能再组合其他类测试类 四、组合模式在JDK集合的源码分析五、组合模…

51单片机(一)软硬件环境和单片机介绍

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其实STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要…

delta.io 参数 spark.databricks.delta.replaceWhere.constraintCheck.enabled

总结 默认值true 你写入的df分区字段必须全部符合覆盖条件 .option("replaceWhere", "c2 == 2") false: df1 overwrite tb1: df1中每个分区的处理逻辑: - tb1中存在(且谓词中匹配)的分区,则覆盖 - tb1中存在(谓词中不匹配)的分区,则append - tb1中不存…

热闹之后,香港是否会成为Web3的“应许之地”?

出品|欧科云链研究院 作者|Jason Jiang 自从2022年底有关虚拟资产在港发展的政策宣言发布后,香港始终是Web3世界的焦点。当港府官员频繁现身以鼓励Web3创新发展,当数以万计的Web3 Builders时隔三年再次聚首香江,当传…

密码学报Latex模板使用

密码学报Latex模板使用 首先从密码学报下载模板 然后注册overleaf账号 创建新项目,把.zip包导入 修改编译器为XeLaTeX 然后点击重新编译即可

信息安全复习六:公开密钥密码学

一、章节梗概 1.公开密钥密码模型的基本原理 2.两个算法:RSA&D-H算法 主要内容 1.对称密钥密码的密钥交换问题 2.公钥密码模型的提出 3.设计公钥密码的基本要求 4.数字签名 5.RSA算法 6.公钥密码的特征总结 二、对称密钥密码 对称加密算法中,数据…

SpringCloud --- Feign远程调用

一、RestTemplate问题 先来看我们以前利用RestTemplate发起远程调用的代码: 存在下面的问题: 代码可读性差,编程体验不统一参数复杂URL难以维护 Feign是一个声明式的http客户端,官方地址:GitHub - OpenFeign/feign:…

程序员如何提高代码能力

目录 程序员如何提高代码能力——C语言方向阅读优秀的代码不断练习学习新技术与他人合作不断反思和改进 程序员如何提高代码能力——C语言方向 C 是一种功能强大的编程语言,广泛应用于操作系统、数据库、游戏开发等领域。而要成为一名优秀的 C 程序员,不…

动力节点Vue笔记④ Vue与Ajax

四、Vue与AJAX 4.1 回顾发送AJAX异步请求的方式 发送AJAX异步请求的常见方式包括: 原生方式,使用浏览器内置的JS对象XMLHttpRequest const xhr new XMLHttpRequest()xhr.onreadystatechange function(){}xhr.open()xhr.send() 原生方式&#xff0…

RK3568平台开发系列讲解(调试篇)内核函数调用堆栈打印方法汇总

🚀返回专栏总目录 文章目录 一、dump_stack 函数二、WARN_ON(condition)函数三、BUG_ON (condition)函数四、panic (fmt...)函数沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将对驱动调试方法进行汇总学习。 一、dump_stack 函数 dump_stack 作用:打印内核调…

C++、STL标准模板库和泛型编程 ——迭代器、 算法、仿函数(侯捷)

C、STL标准模板库和泛型编程 ——迭代器、 算法、仿函数 (侯捷) 迭代器iterator_category 算法accumulatefor_eachreplacecountfindsortbinary_search 仿函数 functors(六大部件中最简单的一种!) 使用一个东西,却不明白它的道理&a…

Compiler- volatile关键字

为了直观的感受编译器为程序所做的编译优化&#xff0c;我们通过以下的C程序来进行演示&#xff08;只能体现编译优化的一小部分hh~&#xff09;。 请大家预测一下下面代码的输出结果 #include <iostream>int main(void) {const volatile int local 10;int* ptr (int…

中国人民大学与加拿大女王大学金融硕士国际班——海归学子最强后援

有人脉&#xff0c;成功像坐电梯&#xff1b;没人脉&#xff0c;成功像爬楼梯。这是每一个职场人都有体悟的“潜规则”。对海归同学来说&#xff0c;加入母校校友会是结识优秀人才、迅速拓展本地人脉圈的不二法宝。中国人民大学与加拿大女王大学金融硕士国际班为海归学子提供最…

QMS-云质说质量 - 4 为什么有的质量人不属于质量部?

想管理好质量&#xff0c;首先就要把质量人员放在合适的组织架构中。 对人进行管理&#xff0c;基本原则是&#xff1a;尽量让员工的利益与企业的利益保持同步&#xff0c;虽然无法做到完全重合&#xff0c;但出发点肯定要战略一致。 俗话说“屁股决定脑袋”&#xff0c;因此&a…

【数据结构初阶】第六节.队列的实现

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、队列的初步认识 二、Java中队列的使用 三、队列的模拟实现 四、力扣刷题演练 4.1 设计循环队列 4.2 用栈实现队列 4.3 最小栈 总结 前言 今天我…

日撸 Java 三百行day36

文章目录 day36 领接表1. 领接表知识点2.结合上图去抽象一个邻接表结点的对象3.广度优先遍历4.深度优先遍历 #说明 闵老师的文章链接&#xff1a; 日撸 Java 三百行&#xff08;总述&#xff09;_minfanphd的博客-CSDN博客 自己也把手敲的代码放在了github上维护&#xff1a;h…

Vue3+Three.js+antvG2实战项目 智慧城市(三)

前言 在网上找了很久都没有找到使用Three.js开发智慧城市的免费文章或者免费视频,自己花了一点时间做了一个纯前端的智慧城市项目。 技术栈都是最新的:vue3vitetypeScriptThreeantv G2 源码分享 源码 模型,天空图盒子链接分享(不想下载源码可以只用下这个)提取码1234 20230424_…

【iOS】—— KVC再学习

KVC 文章目录 KVCKVC常用的四种方法 key和keyPath的区别用法&#xff1a; 批量存值操作批量赋值操作字典模型相互转化KVC的其他方法 KVC原理探索setValue:forKey: 的原理&#xff08;KVC赋值原理&#xff09;valueForKey:的原理&#xff08;KVC取值原理&#xff09; 注意事项 K…

C++数据结构:手撕AVL树

目录 一. 什么是AVL树 二. AVL树的节点定义 三. AVL树的插入操作 3.1 寻找插入位置 3.2 更新平衡因子 3.3 AVL树的旋转调整 3.4 AVL树插入操作的整体实现 四. AVL树的检验 附录&#xff1a;AVL树的实现完整代码 AVL树定义代码 -- AVLTree.h AVL树检验代码 -- test.…

你了解PostProcessor机制吗?

Spring框架对于后置处理器的最佳实践 PostProcessor译为后置处理器&#xff0c;大多数开发人员都使用过springboot对后置处理器的实例级别实践&#xff0c;也就是BeanPostProcessor接口。其实spring还提供了两种容器级别的实践&#xff1a;BeanDefinitionRegistryPostProcesso…