Compare commits

...

101 Commits

Author SHA1 Message Date
yujun
2c92c543f2 Merge branch 'develop' into ppdiffusers 2022-11-10 15:22:57 +08:00
gongenlei
a85212ed00 [New Features] Add FID score (#3685)
* add fid

* update doc

* update import

* add code annotation

* update docs

* add hack for bn
2022-11-10 15:01:25 +08:00
westfish
6f71c7cf5e PIL.Image.LANCZOS adapt to different version 2022-11-10 06:47:46 +00:00
chenxiaozeng
767d3552e3 Update doc (#3711)
* add online course info

* add online course info

* update group code
2022-11-10 11:42:02 +08:00
Jiaqi Liu
feb9d8296b Add onnx_format arg for Compression API (#3696)
* update compress api

* remove uie compress in md
2022-11-09 15:26:52 +08:00
westfish
00ae25bf35 add ldm superresolution 2022-11-09 07:07:45 +00:00
yujun
e97f670440 support EulerAncestralDiscreteScheduler (#3708) 2022-11-08 20:59:25 +08:00
Yam
6289d9c0d3 add Codegen output & loss (#3465) 2022-11-08 19:59:44 +08:00
Sijun He
7b4cf36b90 Add Chinese and English version of CODE_OF_CONDUCT.md (#3687)
* add CoC

* rename

* v2.1
2022-11-08 19:07:50 +08:00
骑马小猫
a50fbbcc30 [BugFix] fix astype error when dynamic-to-static mode (#3701)
* fix astype warning

* update model_utils for dynamic-to-static

* add comment & imporve Makefile
2022-11-08 18:58:28 +08:00
yujun
9e2a0a8a9f [ppdiffusers] add text_to_image_laion400m example (#3693)
* add text_to_image_laion400m

* add write_filelist
2022-11-08 14:56:58 +08:00
wawltor
f74de55082 fix the taskflow skep large model (#3695) 2022-11-07 21:37:07 +08:00
BinChen
e785bb1163 box2example ori_boxes+ (#3677)
Co-authored-by: x-shadow-man <1494445739@qq.com>
2022-11-07 10:32:14 +08:00
yujun
ce31a77f90 [PPDiffusers] Fix ppdiffusers bug and support ZH stablediffusion (#3663)
* fix win download bug, etc

* add attention mask support zh model

* pad to max length

* update NEG_NF

* update diffusers readme

* fix windows download

* fix windows download
2022-11-06 16:49:04 +08:00
sserdoubleh
58a5a9dcfd Fix FT malloc size for beam search. (#3662)
Co-authored-by: liu zhengxi <380185688@qq.com>
2022-11-04 19:28:09 +08:00
wawltor
6387410b5a Update README.md 2022-11-04 18:29:38 +08:00
Yam
1a53c35887 Add Unimo output loss (#3676) 2022-11-04 16:48:47 +08:00
Yam
fd6ef4058e Revert "Unimo output loss (#3450)" (#3673)
This reverts commit 6471ce331a.
2022-11-04 16:09:39 +08:00
gongenlei
1f2b2c5d58 fix download url (#3670) 2022-11-04 11:10:40 +08:00
gongenlei
7b6454908a Rm debug info (#3667)
* rm debug info

* rm unused import
2022-11-03 19:19:07 +08:00
Jiaqi Liu
02b4383b7e Fix UIE README (#3665)
* fix uie reamde

* test=document_fix
2022-11-03 17:27:04 +08:00
Yam
6471ce331a Unimo output loss (#3450) 2022-11-03 15:51:11 +08:00
Jiaqi Liu
61acf19460 Fix UIE eval (#3653)
* fix uie eval

* fix debug mode
2022-11-03 14:22:15 +08:00
Sijun He
c38902e3a8 Adding inputs_embeds argument and switch to paddle.nn.TransformerEncoder for Electra models (#3401)
* add inputs_embeds input arguments to all electra models

* save past_key_value for next PR

* remove unused input_shape

* fix yapf style check

* address comments

* fix style

* fix unit test

* address comment

Co-authored-by: Guo Sheng <guosheng@baidu.com>
Co-authored-by: 骑马小猫 <1435130236@qq.com>
2022-11-03 13:33:09 +08:00
ymyjl
1fc23a8888 [Tutorial] Add torch migration tutorial (#3641)
Co-authored-by: Zhong Hui <zhonghui.net@gmail.com>
2022-11-03 10:42:47 +08:00
骑马小猫
afeb623588 [BugFix] fix typo (#3651)
* fix typo

* revert scripts

* remove torch description
2022-11-02 20:27:12 +08:00
w5688414
ff546f6d9a Fix FAQ docx ui upload parsing support and reformat docx.py (#3645)
* Fix FAQ docx ui upload parsing support and reformat docx.py

* Add more comments

* Optimize concatenate texts
2022-11-02 17:48:12 +08:00
gongenlei
81bb7d1433 Fix download url on Windows (#3640)
* add pegasus

* rm debug info

* fix decode

* update pegasus

* add faster pegasus

* refactor unimotext summary

* add pegasus summary app

* add requirements

* add pegasus to taskflow

* support inference and deploy

* add FG perf and sample

* update taskflow

* add docs

* rm ProcessInfo.json

* update export model

* update serving doc and shell

* update unimo-text doc

* docs: FasterTransformer-->FasterGeneration

* update docs

* fix: url is error when windows download community model

Co-authored-by: 骑马小猫 <1435130236@qq.com>
2022-11-02 17:23:02 +08:00
chenxiangzhen
6eb6937b69 Update predict.py (#3602)
Delete unnecessary package

Co-authored-by: w5688414 <w5688414@gmail.com>
2022-11-02 16:54:29 +08:00
westfish
228c58a494 fix bug about template 3 (#3646) 2022-11-02 16:00:06 +08:00
Jiaqi Liu
e94af7978a Add compression for UIE (#3496)
* add compression for uie

* update uie readme

* update reamde, recover evaluate.py

* fix resource check

* fix qat ernie-m

* requirement

* update

* update

* delete export_model.py

* delete model export in readme

* set start_positions and end_positions to default for UIE
2022-11-02 14:23:01 +08:00
WangZhen
83a9c3893a [TIPC]Add transformer_big_bs4096 static .sh (#3622)
* Add transformer_big_bs4096 static .sh

* Format shell
2022-11-01 15:43:58 +08:00
lugimzzz
bdd659d266 add bad case analysis for text classification (#3385)
* bad case analysis
2022-11-01 09:43:32 +08:00
lugimzzz
b52c2ea5d2 add soft link from examples to application (#3587) 2022-10-31 20:56:46 +08:00
骑马小猫
2483d4fb85 [Bug fix] update the name of pypi server (#3627)
* update yaml

* update yaml scripts

* deploy dev version

* remove test pypi

* update name of pypi
2022-10-31 20:41:31 +08:00
骑马小猫
7bc85cdfb2 [Bug Fix] update pypi workflow (#3626)
* update yaml

* update yaml scripts

* deploy dev version

* remove test pypi
2022-10-31 19:30:47 +08:00
骑马小猫
513a8328d9 update yaml (#3621) 2022-10-31 17:14:08 +08:00
骑马小猫
3e2ddd182c [NewFeature] add ppdiffusers CD workflow (#3604)
* add ppdiffusers version control

* add ppdiffusers version control

* enable should deploy checking

* revert pipeline ui changes

* ignore version file

* 🔥 update version to 0.6.2

* gi

* bump version

* upate

* deploy package to testpypi

* re-trigger the ci
2022-10-31 16:44:34 +08:00
WangZhen
b90ed42dff Add bs5120 for transformer big tipc config (#3600) 2022-10-31 14:40:56 +08:00
Linjie Chen
b705fa481d Support finetune for uie-m (#3227)
* support finetune for uie-m

* update

* Update utils.py

* support finetune and evaluate for en model
2022-10-31 11:11:20 +08:00
lastrei
cf478ba6ee fix typos (#3607)
Co-authored-by: Linjie Chen <40840292+linjieccc@users.noreply.github.com>
2022-10-31 10:15:43 +08:00
Wang-ck123
9eda9a46c4 Fix docs (#3409)
设置return_dict=False后才能使用idx下标,否则无法使用,运行报错。
2022-10-30 00:56:24 +08:00
chenxiaozeng
1f88c41d14 add PPDiffusers info in README. (#3608)
add PPDiffusers info in README.
2022-10-29 14:50:51 +08:00
liu zhengxi
7f650ac0ca fix missing comma (#3606) 2022-10-28 19:51:34 +08:00
骑马小猫
b6c3589ea6 add bert config solution (#3174)
* add bert config solution

* change num_labels to num_classes

* add unittest for configuration

* update bert model

* update bert config

* update bert test modeling

* update test modeling

* update bert testing and model

* add roberta config

* update bert config

* upate bert-modeling

* update bert modeling

* update code style

* remove unrelated codes

* fix community related code

* update pretrained config

* update configuration name

* add compatibility codes

* add automodel test & improve downstream model test

* remove parse_args & kwargs

* update roberta & bert

* add warning for only-one weight file

* use config to init BertEmbedding & BertPooler

this change will be upgraded when TinyBertConfig is completed

* fix codestyle

* 调整bert pretrained

* use attribute to access the value

* remove ignored keys on loading

* fix stub file bug & add use_cache to configuration_utils

* fix roberta pretrain

* upgrade the  docs and extension of import_utils

* fix default value of `use_cache`

* update type hinting

* update docstring of BertForXXX model

* update warning string

Co-authored-by: Guo Sheng <guosheng@baidu.com>
2022-10-28 19:30:18 +08:00
吴高升
c2e1dc4852 Fix the file upload multiple times of Pipelines (#3568) 2022-10-28 17:19:06 +08:00
yujun
1c5e127866 [PPDiffusers] rename ppdiffusers (#3601)
* rename ppdiffusers

* rename diffusers_paddle
2022-10-28 16:52:59 +08:00
Roc
c8bc4405fc [MOE] use adamw from paddle.optimizer (#3598) 2022-10-28 14:51:31 +08:00
westfish
05e7432ef7 update PaddleNLP v2.4.2 readme.md (#3597)
* update readme

* update readme.md

* update
2022-10-28 14:34:26 +08:00
liu zhengxi
d390dc95e8 Lift restrictions to support more d_inner_hid (#3592)
* lift restrictions

* code style

* add state_dict
2022-10-28 13:59:01 +08:00
WangZhen
b262611f37 [TIPC]Fix dy2st tipc gpt 8 error (#3586)
* Fix dy2st tipc gpt 8 error

* Fix transformer benchmark dy2st config error

Co-authored-by: yujun <50394665+JunnYu@users.noreply.github.com>
2022-10-28 13:05:32 +08:00
feifei-111
78c8615791 Added 4 scripts for benchmark (#3585) 2022-10-28 09:56:59 +08:00
yujun
16aa2ba5b1 [WIP] Add diffusers_paddle (#3445)
* add paddle version diffusers

* add examples but need to test them

* support download from bos

* update diffusers according to https://github.com/JunnYu/diffusers/pull/1

* install & test text_invert dreambooth etc

* update examples and test pass

* add textual_inversion readme and update text to image readme

* update examples

* update https://github.com/JunnYu/diffusers/pull/2

* fix a small bug

* import bug

* fix missing seqlen

* _diffusers_paddle_version

* fix bug

* https://github.com/JunnYu/diffusers/pull/3

* update docs, add dreambooth readme, fix bug

* dreambooth support save every 500 step

* update onnx

* update

* type paramaters

Co-authored-by: Guo Sheng <guosheng@baidu.com>
2022-10-27 17:15:39 +08:00
liu zhengxi
21345f8d2e Fix some unit tests' issue (#3553) 2022-10-27 16:20:56 +08:00
gongenlei
c9c5c15a66 Add pegasus (#3275)
* add pegasus

* rm debug info

* fix decode

* update pegasus

* add faster pegasus

* refactor unimotext summary

* add pegasus summary app

* add requirements

* add pegasus to taskflow

* support inference and deploy

* add FG perf and sample

* update taskflow

* add docs

* rm ProcessInfo.json

* update export model

* update serving doc and shell

* update unimo-text doc

* docs: FasterTransformer-->FasterGeneration

* update docs

Co-authored-by: 骑马小猫 <1435130236@qq.com>
2022-10-27 15:11:51 +08:00
westfish
d57e350f9e Merge pull request #3560 from westfish/qg-example
add qg models and update readme
2022-10-27 13:14:45 +08:00
westfish
295d68e940 Merge branch 'develop' into qg-example 2022-10-27 11:59:12 +08:00
lugimzzz
947007f552 fix dead link in text classification (#3566) 2022-10-27 11:44:01 +08:00
westfish
14c934c1a1 update readme 2022-10-27 03:19:10 +00:00
westfish
e98231f911 add unimo-large/without-template result 2022-10-27 03:15:10 +00:00
Zhong Hui
d1506f8a38 Update modeling.py (#3559) 2022-10-27 10:52:43 +08:00
westfish
94864bc48e rename v2.pdparams to full_domain.pdparams 2022-10-26 12:04:29 +00:00
吴高升
b0f7650ecf Add GIF visualization for pipeline examples (#3561) 2022-10-26 19:47:01 +08:00
westfish
cd5a2e35a6 update readme 2022-10-26 11:27:33 +00:00
westfish
91d5c527dd update taskflow.md and unimo-text/readme.md 2022-10-26 10:21:13 +00:00
westfish
fca7ca25da update taskflow 2022-10-26 09:55:09 +00:00
westfish
b0ba2e1e79 add qg models and update readme 2022-10-26 09:40:05 +00:00
Chenxiao Niu
553ba12211 [MLU] add transformer config support. (#3541) 2022-10-26 17:15:53 +08:00
USTCKAY
122824885c [CustomDevice]add custom NPU support for rnn (#3521)
* [CustomDevice]add custom NPU support for rnn

* delete 'npu' choice of device

* change 'Custom NPU' to 'Ascend NPU'

Co-authored-by: Zeyu Chen <chenzeyu01@baidu.com>
2022-10-25 20:02:19 +08:00
吴高升
211e8204dd Fix README.md of Retrieval based classification (#3551) 2022-10-25 17:07:56 +08:00
wawltor
47f7c36e1e Add the expoort model for the paddlenlp (#3516) 2022-10-25 16:53:08 +08:00
吴高升
7eac0586bc Update docx parsing for Pipelines (#3546) 2022-10-25 14:36:46 +08:00
liu zhengxi
a0f5a8ebcd add support for libpaddle.so (#3545) 2022-10-25 11:53:58 +08:00
chenxiaozeng
636e3430fc add online course info (#3543)
* add online course info

* add online course info
2022-10-25 11:39:35 +08:00
lugimzzz
d52d8e5ea1 update docprompt pipeline example (#3542)
* update docprompt pipeline example
2022-10-24 19:21:50 +08:00
lugimzzz
97fe71d000 Add docprompt example in pipelines (#3534)
* add_docprompt_example_in_pipelines
2022-10-24 15:24:53 +08:00
Sijun He
1bad94989f improve setup.py for easier dev environment setup (#3495)
* setup.py file

* addback newline

* style

Co-authored-by: Guo Sheng <guosheng@baidu.com>
2022-10-24 14:35:13 +08:00
吴高升
04a742106e Fix dead links of pipelines&FAQ Finance (#3540) 2022-10-24 13:28:06 +08:00
westfish
1076b890de fix text summarization taskflow cannot load self-defined model (#3533)
* fix text summarization taskflow cannot load self-defined model

* update taskflow

Co-authored-by: gongenlei <gongel@qq.com>
2022-10-24 11:33:47 +08:00
Jiaqi Liu
219b6abd15 fix tinybert readme bug (#3535) 2022-10-24 11:05:38 +08:00
吴高升
fb0cb9b35b Add ERNIE-ViLG models into Pipelines (#3512)
* Add ERNIE-ViLG models into Pipelines

* Add more comments

* Add missing text_to_image_generation.yaml

* Rename the files

* Add output_dir parameters& Update README.md

* Update README.md
2022-10-21 15:58:03 +08:00
iamWHTWD
293c8308af add xpu to choices (#3527) 2022-10-20 20:58:44 +08:00
westfish
e14487780b Merge pull request #3524 from westfish/qg-example
fix prediction bug in qg example
2022-10-20 17:46:13 +08:00
westfish
39b49c928f Merge branch 'develop' into qg-example 2022-10-20 17:38:29 +08:00
westfish
38fcccbd86 fix bug in prediction 2022-10-20 09:07:47 +00:00
westfish
31dc47aed5 Merge branch 'qg-example' of github.com:westfish/PaddleNLP into qg-example 2022-10-20 08:57:49 +00:00
Linjie Chen
8f3e4e51e3 Update README.md (#3518)
* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md
2022-10-20 00:49:17 +08:00
WangZhen
7476962a6c Add more Dy2St model for TIPC (#3485)
Co-authored-by: yujun <50394665+JunnYu@users.noreply.github.com>
2022-10-19 19:58:05 +08:00
Linjie Chen
b1ac71b2f5 Add file check for custom model (#3506) 2022-10-19 16:22:17 +08:00
Linjie Chen
1ac55f0325 Update README.md (#3503) 2022-10-19 10:28:16 +08:00
chenxiaozeng
0497ce7984 Update README.md (#3502) 2022-10-18 21:43:19 +08:00
Linjie Chen
0a402ca287 Add README.md for Document Intelligence (#3498)
* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md
2022-10-18 17:34:52 +08:00
Jiaqi Liu
a12481fc30 updae compress usage in multi label classification (#3494) 2022-10-17 19:13:14 +08:00
Linjie Chen
3e7d4d8140 Add symbolic link for ERNIE-Layout (#3484)
* add symbolic link for ernie_layout

* Update README.md

* Update README.md

* Update README.md
2022-10-17 18:15:10 +08:00
吴高升
ce67b4fc41 Add windows serving support for faq finance (#3491)
* Add windows serving support for faq finance

* Remove unused comments
2022-10-17 17:51:02 +08:00
Noel
839b2d09bb [fewshot] fix dead links in README (#3492) 2022-10-17 17:19:51 +08:00
westfish
db915e756a Bug fix uie utils (#3490)
* fix bug the result variable is not defined

* update
2022-10-17 16:32:18 +08:00
Jiaqi Liu
217a25cf01 supports strategy 'qat' (#3271) 2022-10-17 15:39:58 +08:00
liu zhengxi
c00d28fcd8 Add MBart unit tests (#3323) 2022-10-17 13:45:12 +08:00
Zhong Hui
90c6f1da59 fix gpt with paddle.matmul (#3483) 2022-10-17 11:46:14 +08:00
westfish
361d826fbd fix typos in readme.md 2022-10-13 04:25:01 +00:00
461 changed files with 51391 additions and 6304 deletions

60
.github/workflows/pypi.yml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: PyPI
on: [push, pull_request]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r docs/requirements.txt
pip install -r ppdiffusers/requirements.txt
ppdiffusers:
name: Pack
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
make install-ppdiffusers
- name: Should Deploy to Pypi Server
id: should-deploy
run: python scripts/should_deploy.py --name ppdiffusers >> $GITHUB_OUTPUT
- name: Check Branch
id: check-branch
run: |
if [[ ${{ github.ref }} =~ ^refs/heads/(develop)$ ]]; then
echo "match=true" >> $GITHUB_OUTPUT
fi # See: https://stackoverflow.com/a/58869470/1123955
- name: Is A Publish Branch
if: steps.check-branch.outputs.match == 'true' && steps.should-deploy.outputs.should_deploy == 'true'
env:
TWINE_USERNAME: paddle-dev
TWINE_PASSWORD: ${{ secrets.paddlenlp }}
run: |
make deploy-ppdiffusers
- name: Should Not Deploy To Pypi Server
if: steps.should-deploy.outputs.should_deploy != 'true'
run: echo 'should not deploy pypi server'
- name: Is Not A Publish Branch
if: steps.check-branch.outputs.match != 'true'
run: echo 'Not A Publish Branch'

1
.gitignore vendored
View File

@@ -123,3 +123,4 @@ FETCH_HEAD
# vscode
.vscode
./ppdiffusers/ppdiffusers/version.py

88
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,88 @@
# 贡献者公约
## 我们的承诺
身为社区成员、贡献者和领袖,我们承诺使社区参与者不受骚扰,无论其年龄、体型、可见或不可见的缺陷、族裔、性征、性别认同和表达、经验水平、教育程度、社会与经济地位、国籍、相貌、种族、种姓、肤色、宗教信仰、性倾向或性取向如何。
我们承诺以有助于建立开放、友善、多样化、包容、健康社区的方式行事和互动。
## 我们的准则
有助于为我们的社区创造积极环境的行为例子包括但不限于:
* 表现出对他人的同情和善意
* 尊重不同的主张、观点和感受
* 提出和大方接受建设性意见
* 承担责任并向受我们错误影响的人道歉
* 注重社区共同诉求,而非个人得失
不当行为例子包括:
* 使用情色化的语言或图像,及性引诱或挑逗
* 嘲弄、侮辱或诋毁性评论,以及人身或政治攻击
* 公开或私下的骚扰行为
* 未经他人明确许可,公布他人的私人信息,如物理或电子邮件地址
* 其他有理由认定为违反职业操守的不当行为
## 责任和权力
社区领袖有责任解释和落实我们所认可的行为准则,并妥善公正地对他们认为不当、威胁、冒犯或有害的任何行为采取纠正措施。
社区领导有权力和责任删除、编辑或拒绝或拒绝与本行为准则不相符的评论(comment)、提交(commits)、代码、维基(wiki)编辑、议题(issues)或其他贡献,并在适当时机知采取措施的理由。
## 适用范围
本行为准则适用于所有社区场合,也适用于在公共场所代表社区时的个人。
代表社区的情形包括使用官方电子邮件地址、通过官方社交媒体帐户发帖或在线上或线下活动中担任指定代表。
## 监督
辱骂、骚扰或其他不可接受的行为可通过 paddlenlp@baidu.com 向负责监督的社区领袖报告。
所有投诉都将得到及时和公平的审查和调查。
所有社区领袖都有义务尊重任何事件报告者的隐私和安全。
## 处理方针
社区领袖将遵循下列社区处理方针来明确他们所认定违反本行为准则的行为的处理方式:
### 1. 纠正
**社区影响**:使用不恰当的语言或其他在社区中被认定为不符合职业道德或不受欢迎的行为。
**处理意见**:由社区领袖发出非公开的书面警告,明确说明违规行为的性质,并解释举止如何不妥。或将要求公开道歉。
### 2. 警告
**社区影响**:单个或一系列违规行为。
**处理意见**:警告并对连续性行为进行处理。在指定时间内,不得与相关人员互动,包括主动与行为准则执行者互动。这包括避免在社区场所和外部渠道中的互动。违反这些条款可能会导致临时或永久封禁。
### 3. 临时封禁
**社区影响**: 严重违反社区准则,包括持续的不当行为。
**处理意见**: 在指定时间内,暂时禁止与社区进行任何形式的互动或公开交流。在此期间,不得与相关人员进行公开或私下互动,包括主动与行为准则执行者互动。违反这些条款可能会导致永久封禁。
### 4. 永久封禁
**社区影响**:行为模式表现出违反社区准则,包括持续的不当行为、骚扰个人或攻击或贬低某个类别的个体。
**处理意见**:永久禁止在社区内进行任何形式的公开互动。
## 参见
本行为准则改编自 [Contributor Covenant][homepage] 2.1 版, 参见 [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]。
社区处理方针灵感来源于 [Mozilla's code of conduct enforcement ladder][Mozilla CoC]。
有关本行为准则的常见问题的答案,参见 [https://www.contributor-covenant.org/faq][FAQ]。
其他语言翻译参见 [https://www.contributor-covenant.org/translations][translations]。
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

133
CODE_OF_CONDUCT_en.md Normal file
View File

@@ -0,0 +1,133 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
paddlenlp@baidu.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

10
Makefile Normal file
View File

@@ -0,0 +1,10 @@
.PHONY: deploy-ppdiffusers
deploy-ppdiffusers:
cd ppdiffusers && make
.PHONY: install-ppdiffusers
install-ppdiffusers:
cd ppdiffusers && make install

View File

@@ -30,6 +30,12 @@
**PaddleNLP**是一款**简单易用**且**功能强大**的自然语言处理开发库。聚合业界**优质预训练模型**并提供**开箱即用**的开发体验,覆盖NLP多场景的模型库搭配**产业实践范例**可满足开发者**灵活定制**的需求。
## News 📢
* 🔥 **2022.10.27 发布 [PaddleNLP v2.4.2](https://github.com/PaddlePaddle/PaddleNLP/releases/tag/v2.4.2)**
* NLG能力扩充:新增📄[**基于Pegasus的中文文本摘要方案**](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/text_summarization/pegasus),效果领先;新增❓[**问题生成解决方案**](./examples/question_generation),提供基于业界领先模型UNIMO-Text和大规模多领域问题生成数据集训练的通用问题生成预训练模型。均支持Taskflow一键调用,支持FasterGeneration高性能推理,训练推理部署全流程打通。
* 发布 🖼[**PPDiffusers**](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/ppdiffusers):支持跨模态(如图像与语音)训练和推理的扩散模型(Diffusion Model)工具箱,可快速体验、二次开发 **Stable Diffusion**,持续支持更多模型。
* 🔥 **2022.10.14 发布 [PaddleNLP v2.4.1](https://github.com/PaddlePaddle/PaddleNLP/releases/tag/v2.4.1)**
* 🧾 发布多语言跨模态布局增强文档智能大模型 [**ERNIE-Layout**](./model_zoo/ernie-layout/),刷新11项任务SOTA。同步发布基于ERNIE-Layout的**文档抽取问答模型DocPrompt** 🔖,精准理解文档图片布局与语义信息,轻松应对各类业务场景。
* 🔥 **2022.9.6 发布 [PaddleNLP v2.4](https://github.com/PaddlePaddle/PaddleNLP/releases/tag/v2.4.0)**
* 💎 NLP工具:**[NLP 流水线系统 Pipelines](./pipelines)** 发布,支持快速搭建搜索引擎、问答系统,可扩展支持各类NLP系统,让解决 NLP 任务像搭积木一样便捷、灵活、高效!
@@ -37,22 +43,17 @@
* 🍭 AIGC 内容生成:新增代码生成 SOTA 模型[**CodeGen**](./examples/code_generation/codegen),支持多种编程语言代码生成;集成[**文图生成潮流模型**](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/model_zoo/taskflow.md#%E6%96%87%E5%9B%BE%E7%94%9F%E6%88%90) DALL·E Mini、Disco Diffusion、Stable Diffusion,更多趣玩模型等你来玩;新增[**中文文本摘要应用**](./applications/text_summarization),基于大规模语料的中文摘要模型首次发布,可支持 Taskflow 一键调用和定制训练;
* 💪 框架升级:[**模型自动压缩 API**](./docs/compression.md) 发布,自动对模型进行裁减和量化,大幅降低模型压缩技术使用门槛;[**小样本 Prompt**](./applications/text_classification/multi_class/few-shot)能力发布,集成 PET、P-Tuning、RGL 等经典算法。
* 🔥 **2022.5.16 发布 [PaddleNLP v2.3](https://github.com/PaddlePaddle/PaddleNLP/releases/tag/v2.3.0)**
* 💎 发布通用信息抽取技术 [**UIE**](./model_zoo/uie),单模型支持实体识别、关系和事件抽取、情感分析等多种开放域信息抽取任务,不限领域和抽取目标,支持**零样本抽取**与全流程**小样本**高效定制开发;
* 😊 发布文心大模型 [**ERNIE 3.0**](./model_zoo/ernie-3.0) 轻量级模型,在 [CLUE ](https://www.cluebenchmarks.com/)上实现同规模结构效果最佳,并提供**🗜️无损压缩**和**⚙️全场景部署**方案;
* 🏥 发布中文医疗领域预训练模型 [**ERNIE-Health**](./model_zoo/ernie-health),[CBLUE](https://github.com/CBLUEbenchmark/CBLUE) 中文医疗信息处理评测冠军模型;
* 💬 发布大规模百亿开放域对话预训练模型 [**PLATO-XL**](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/model_zoo/plato-xl) ,配合⚡**FasterGeneration**⚡快速实现高性能GPU并行推理加速。
## 社区交流
- 微信扫描二维码并填写问卷,回复小助手关键词(NLP)之后,即可加入交流群领取福利
- 与众多社区开发者以及官方团队深度交流。
- 10G重磅NLP学习大礼包!
<div align="center">
<img src="https://user-images.githubusercontent.com/11793384/184784832-bb97930f-a738-4480-99be-517aeb65afac.png" width="150" height="150" />
</div>
<img src="https://user-images.githubusercontent.com/11793384/200770385-a2c02093-0e1d-4189-b324-8b0251cba316.jpg" width="150" height="150" />
</div>
## 特性
#### <a href=#开箱即用的nlp工具集> 📦 开箱即用的NLP工具集 </a>
@@ -209,7 +210,7 @@ PaddleNLP针对信息抽取、语义检索、智能问答、情感分析等高
</div>
更多使用说明请参考[智能问答系统](./applications/question_answering)与[文档智能问答](./applications/doc_vqa)
更多使用说明请参考[智能问答系统](./applications/question_answering)与[文档智能问答](./applications/document_intelligence/doc_vqa)
#### 💌 评论观点抽取与情感分析

View File

@@ -29,6 +29,11 @@
**PaddleNLP** is an *easy-to-use* and *powerful* NLP library with **Awesome** pre-trained model zoo, supporting wide-range of NLP tasks from research to industrial applications.
## News 📢
* 🔥 **2022.10.27 [PaddleNLP v2.4.2](https://github.com/PaddlePaddle/PaddleNLP/releases/tag/v2.4.2) Released!**
* NLG Upgrade: 📄 Release [**Solution of Text Summarization**](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/text_summarization/pegasus) based on Pegasus;❓ Release [**Solution of Problem Generation**](./examples/question_generation), providing **general problem generation pre-trained model** based on Baidu's UNIMO Text and large-scale multi domain problem generation dataset。Supporting high-performance inference ability based on FasterGeneration , and covering the whole process of training , inference and deployment.
* 🔥 **2022.10.14 [PaddleNLP v2.4.1](https://github.com/PaddlePaddle/PaddleNLP/releases/tag/v2.4.1) Released!**
* 🧾 Release multilingual/cross-lingual pre-trained models [**ERNIE-Layout**](./model_zoo/ernie-layout/) which achieves new SOTA results in 11 downstream tasks. **DocPrompt** 🔖 based on ERNIE-Layout is also released which has the ability for multilingual document information extraction and question ansering.
* 🔥 **2022.9.6 [PaddleNLPv2.4](https://github.com/PaddlePaddle/PaddleNLP/releases/tag/v2.4.0) Released!**
* 💎 NLP Tool:**[Pipelines](./pipelines)** released. Supports for fast construction of search engine and question answering systems, and it is expandable to all kinds of NLP systems. Building end-to-end pipelines for NLP tasks like playing Lego!
@@ -40,23 +45,7 @@
* 💪 Framework upgrade: Release [**Auto Model Compression API**](./docs/compression.md), supports for pruning and quantization automatically, lower the barriers of model compression; Release [**Few-shot Prompt**](./applications/text_classification/multi_class/few-shot), includes the algorithms such as PET, P-Tuning and RGL.
* 👀 **2022.9.6 PaddlePaddle intelligent financial industry series live course**
* Centering on the industrial practice and development trend of deep learning technology in the financial industry, experts in the industry are invited to share the industrial practice. Discussion on the Future Development of Science and Technology Finance.
* Release the practical examples of industrial practice: Financial document information extraction based on UIE; FAQ question answering system based on Pipelines.
* **Live broadcast at 19:00 on Tuesdays and Thursdays from September 6th.**, scan the QR code to join the WeChat group and get the live link for free, discuss the experience with experts:
<div align="center">
<img src="https://user-images.githubusercontent.com/11793384/188596360-264415d4-5462-43ad-8517-5b7e690061ce.jpg" width="150" height="150" />
</div>
* 🔥 2022.5.16 PaddleNLP [v2.3](https://github.com/PaddlePaddle/PaddleNLP/releases/tag/v2.3.0) Released!🎉
* 💎 Release [**UIE** (Universal Information Extraction)](./model_zoo/uie) technique, single model supports multiple **open-domain** IE tasks. Super easy to use and finetune with few examples via [Taskflow](./docs/model_zoo/taskflow.md).
* 😊 Release [**ERNIE 3.0**](./model_zoo/ernie-3.0) light-weight model achieved better results compared to ERNIE 2.0 on [CLUE](https://www.cluebenchmarks.com/), also including **🗜️lossless model compression** and **⚙️end-to-end deployment**.
* 🏥 Release [**ERNIE-Health**](./model_zoo/ernie-health), a **SOTA** biomedical pretrained model on [CBLUE](https://github.com/CBLUEbenchmark/CBLUE).
* 💬 Release [**PLATO-XL**](./model_zoo/plato-xl) with ⚡**FasterGeneration**⚡, the *11B open-domain SOTA chatbot model* can be deployed on multi-GPU and do parallel inference easily.
## Features
@@ -205,7 +194,7 @@ We provide question answering pipeline which can support FAQ system, Document-le
</div>
For more details please refer to [Question Answering](./applications/question_answering) and [Document VQA](./applications/doc_vqa).
For more details please refer to [Question Answering](./applications/question_answering) and [Document VQA](./applications/document_intelligence/doc_vqa).
#### 💌 Opinion Extraction and Sentiment Analysis
@@ -328,10 +317,6 @@ Please find all PaddleNLP API Reference from our [readthedocs](https://paddlenlp
## Community
### Special Interest Group (SIG)
Welcome to join [PaddleNLP SIG](https://iwenjuan.baidu.com/?code=bkypg8) for contribution, eg. Dataset, Models and Toolkit.
### Slack
To connect with other users and contributors, welcome to join our [Slack channel](https://paddlenlp.slack.com/).
@@ -340,9 +325,10 @@ To connect with other users and contributors, welcome to join our [Slack channel
Scan the QR code below with your Wechat⬇️. You can access to official technical exchange group. Look forward to your participation.
<div align="center">
<img src="https://user-images.githubusercontent.com/11793384/184784832-bb97930f-a738-4480-99be-517aeb65afac.png" width="150" height="150" />
</div>
<div align="center">
<img src="https://user-images.githubusercontent.com/11793384/200770385-a2c02093-0e1d-4189-b324-8b0251cba316.jpg" width="150" height="150" />
</div>
## Citation

1
VERSION Normal file
View File

@@ -0,0 +1 @@
4.2.3

View File

@@ -1,24 +0,0 @@
export CUDA_VISIBLE_DEVICES=0
QUESTION=$1
python3 change_to_mrc.py ${QUESTION}
python3 ./run_docvqa.py \
--model_name_or_path "layoutxlm-base-uncased" \
--max_seq_len 512 \
--do_test true \
--test_file "data/demo_test.json" \
--num_train_epochs 100 \
--eval_steps 6000 \
--save_steps 6000 \
--output_dir "output/" \
--save_path "data/decode_res.json" \
--init_checkpoint "./checkpoints/layoutxlm/" \
--learning_rate 3e-5 \
--warmup_steps 12000 \
--per_gpu_train_batch_size 4 \
--per_gpu_eval_batch_size 1 \
--seed 2048
python3 view.py

View File

@@ -1,18 +0,0 @@
export CUDA_VISIBLE_DEVICES=0
python3 ./run_docvqa.py \
--model_name_or_path "layoutxlm-base-uncased" \
--max_seq_len 512 \
--train_file "data/train.json" \
--init_checkpoint "checkpoints/base_model" \
--do_train true \
--num_train_epochs 50 \
--eval_steps 24000 \
--save_steps 40 \
--output_dir "output" \
--save_path "data/decode_res.json" \
--learning_rate 3e-5 \
--warmup_steps 40 \
--per_gpu_train_batch_size 4 \
--per_gpu_eval_batch_size 4 \
--seed 2048

View File

@@ -1,20 +0,0 @@
export CUDA_VISIBLE_DEVICES=0
QUESTION=$1
# Question: NFC咋开门
if [ $# != 1 ];then
echo "USAGE: sh script/run_cross_encoder_test.sh \$QUESTION"
exit 1
fi
# compute scores for QUESTION and OCR parsing results with Rerank module
cd Rerank
bash run_test.sh ${QUESTION}
cd ..
# extraction answer for QUESTION from the top1 of rank
cd Extraction
bash run_test.sh ${QUESTION}
cd ..

View File

@@ -0,0 +1,188 @@
# 文档智能应用
**目录**
- [1. 文档智能应用简介](#文档智能应用简介)
- [2. 技术特色介绍](#技术特色介绍)
- [2.1 多语言跨模态训练基座](#多语言跨模态训练基座)
- [2.2 多场景覆盖](#多场景覆盖)
- [3. 快速开始](#快速开始)
- [3.1 开箱即用](#开箱即用)
- [3.2 产业级流程方案](#产业级流程方案)
## 1. 文档智能应用简介
文档智能(DI, Document Intelligence)主要指**对于网页、数字文档或扫描文档所包含的文本以及丰富的排版格式等信息,通过人工智能技术进行理解、分类、提取以及信息归纳**的过程。文档智能技术广泛应用于金融、保险、能源、物流、医疗等行业,常见的应用场景包括财务报销单、招聘简历、企业财报、合同文书、动产登记证、法律判决书、物流单据等多模态文档的关键信息抽取、文档解析、文档比对等。
在实际应用中,需要解决文档格式繁杂、布局多样、信息模态多样、需求开放、业务数据少等多重难题。针对文档智能领域的痛点和难点,PaddleNLP将持续开源一系列产业实践范例,解决开发者们实际应用难题。
<div align="center">
<img width="1000" height="270" alt="文档智能技术一般流程" src="https://user-images.githubusercontent.com/40840292/196361583-6b1c66d1-6a9b-4193-949a-71e2d420a82a.png">
</div>
<a name="技术特色介绍"></a>
## 2. 技术特色介绍
<a name="多语言跨模态训练基座"></a>
### 2.1 多语言跨模态训练基座
近期,百度文心文档智能,基于多语言跨模态布局增强的文档智能大模型[ERNIE-Layout](http://arxiv.org/abs/2210.06155),刷新了五类11项文档智能任务效果。依托文心ERNIE大模型,基于布局知识增强技术,融合文本、图像、布局等信息进行联合建模,能够对多模态文档(如文档图片、PDF 文件、扫描件等)进行深度理解与分析,为各类上层应用提供SOTA模型底座。
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/196373896-597f6178-4c78-41a1-bb12-796546644b32.png width="600"/>
</div>
<a name="多场景覆盖"></a>
### 2.2 多场景覆盖
以下是文档智能技术的一些应用场景展示:
- 发票抽取问答
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/196118171-fd3e49a0-b9f1-4536-a904-c48f709a2dec.png height=350 width=1000 hspace='10'/>
</div>
- 海报抽取问答
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/195610368-04230855-62de-439e-b708-2c195b70461f.png height=600 width=1000 hspace='15'/>
</div>
- 网页抽取问答
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/195611613-bdbe692e-d7f2-4a2b-b548-1a933463b0b9.png height=350 width=1000 hspace='10'/>
</div>
- 表格抽取问答
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/195610692-8367f1c8-32c2-4b5d-9514-a149795cf609.png height=350 width=1000 hspace='10'/>
</div>
- 试卷抽取问答
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/195823294-d891d95a-2ef8-4519-be59-0fedb96c00de.png height=700 width=1000 hspace='10'/>
</div>
- 英文票据多语种(中、英、日、泰、西班牙、俄语)抽取问答
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/195610820-7fb88608-b317-45fc-a6ab-97bf3b20a4ac.png height=400 width=1000 hspace='15'/>
</div>
- 中文票据多语种(中简、中繁、英、日、法语)抽取问答
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/195611075-9323ce9f-134b-4657-ab1c-f4892075d909.png height=350 width=1000 hspace='15'/>
</div>
- Demo图片可在此[下载](https://bj.bcebos.com/paddlenlp/taskflow/document_intelligence/demo.zip)
<a name="快速开始"></a>
## 3. 快速开始
<a name="开箱即用"></a>
### 3.1 开箱即用
开源DocPrompt开放文档抽取问答模型,以ERNIE-Layout为底座,可精准理解图文信息,推理学习附加知识,准备捕捉图片、PDF等多模态文档中的每个细节。
🧾 通过[Huggingface网页](https://huggingface.co/spaces/PaddlePaddle/ERNIE-Layout)体验DocPrompt功能:
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/195749427-864d7744-1fd1-455e-99c6-53a260776483.jpg height=700 width=1100 hspace='10'/>
</div>
#### Taskflow
通过``paddlenlp.Taskflow``三行代码调用DocPrompt功能,具备多语言文档抽取问答能力,部分应用场景展示如下:
- 输入格式
```
[
{"doc": "./invoice.jpg", "prompt": ["发票号码是多少?", "校验码是多少?"]},
{"doc": "./resume.png", "prompt": ["五百丁本次想要担任的是什么职位?", "五百丁是在哪里上的大学?", "大学学的是什么专业?"]}
]
```
默认使用PaddleOCR进行OCR识别,同时支持用户通过``word_boxes``传入自己的OCR结果,格式为``List[str, List[float, float, float, float]]``。
```
[
{"doc": doc_path, "prompt": prompt, "word_boxes": word_boxes}
]
```
- 支持单条、批量预测
- 支持本地图片路径输入
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/194748579-f9e8aa86-7f65-4827-bfae-824c037228b3.png height=800 hspace='20'/>
</div>
```python
>>> from pprint import pprint
>>> from paddlenlp import Taskflow
>>> docprompt = Taskflow("document_intelligence")
>>> pprint(docprompt([{"doc": "./resume.png", "prompt": ["五百丁本次想要担任的是什么职位?", "五百丁是在哪里上的大学?", "大学学的是什么专业?"]}]))
[{'prompt': '五百丁本次想要担任的是什么职位?',
'result': [{'end': 7, 'prob': 1.0, 'start': 4, 'value': '客户经理'}]},
{'prompt': '五百丁是在哪里上的大学?',
'result': [{'end': 37, 'prob': 1.0, 'start': 31, 'value': '广州五百丁学院'}]},
{'prompt': '大学学的是什么专业?',
'result': [{'end': 44, 'prob': 0.82, 'start': 38, 'value': '金融学(本科)'}]}]
```
- http图片链接输入
<div align="center">
<img src=https://user-images.githubusercontent.com/40840292/194748592-e20b2a5f-d36b-46fb-8057-86755d188af0.jpg height=400 hspace='10'/>
</div>
```python
>>> from pprint import pprint
>>> from paddlenlp import Taskflow
>>> docprompt = Taskflow("document_intelligence")
>>> pprint(docprompt([{"doc": "https://bj.bcebos.com/paddlenlp/taskflow/document_intelligence/images/invoice.jpg", "prompt": ["发票号码是多少?", "校验码是多少?"]}]))
[{'prompt': '发票号码是多少?',
'result': [{'end': 2, 'prob': 0.74, 'start': 2, 'value': 'No44527206'}]},
{'prompt': '校验码是多少?',
'result': [{'end': 233,
'prob': 1.0,
'start': 231,
'value': '01107 555427109891646'}]}]
```
- 可配置参数说明
* `batch_size`:批处理大小,请结合机器情况进行调整,默认为1。
* `lang`:选择PaddleOCR的语言,`ch`可在中英混合的图片中使用,`en`在英文图片上的效果更好,默认为`ch`。
* `topn`: 如果模型识别出多个结果,将返回前n个概率值最高的结果,默认为1。
<a name="产业级流程方案"></a>
### 3.2 产业级流程方案
针对文档智能领域的痛点和难点,PaddleNLP将持续开源一系列文档智能产业实践范例,解决开发者们实际应用难题。
- 👉 [汽车说明书跨模态智能问答](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/document_intelligence/doc_vqa#readme)
更多:百度TextMind智能文档分析平台可提供包括文档信息抽取、文本内容审查、企业文档管理、文档格式解析、文档内容比对等全方位一站式的文档智能服务,已形成一套完整的企业文档场景化解决方案,满足银行、券商、法律、能源、传媒、通信、物流等不同行业和场景的文档处理需求,以AI助力企业的办公智能化升级和数字化转型。欢迎深度交流与商业合作,了解详情:https://ai.baidu.com/tech/nlp/Textanalysis
## References
- [文档智能:数据集、模型和应用](http://jcip.cipsc.org.cn/CN/abstract/abstract3331.shtml)
- [ERNIE-Layout: Layout-Knowledge Enhanced Multi-modal Pre-training for Document Understanding](http://arxiv.org/abs/2210.06155)

View File

@@ -0,0 +1,38 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
export CUDA_VISIBLE_DEVICES=0
QUESTION=$1
python3 change_to_mrc.py ${QUESTION}
python3 ./run_docvqa.py \
--model_name_or_path "layoutxlm-base-uncased" \
--max_seq_len 512 \
--do_test true \
--test_file "data/demo_test.json" \
--num_train_epochs 100 \
--eval_steps 6000 \
--save_steps 6000 \
--output_dir "output/" \
--save_path "data/decode_res.json" \
--init_checkpoint "./checkpoints/layoutxlm/" \
--learning_rate 3e-5 \
--warmup_steps 12000 \
--per_gpu_train_batch_size 4 \
--per_gpu_eval_batch_size 1 \
--seed 2048
python3 view.py

View File

@@ -0,0 +1,32 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
export CUDA_VISIBLE_DEVICES=0
python3 ./run_docvqa.py \
--model_name_or_path "layoutxlm-base-uncased" \
--max_seq_len 512 \
--train_file "data/train.json" \
--init_checkpoint "checkpoints/base_model" \
--do_train true \
--num_train_epochs 50 \
--eval_steps 24000 \
--save_steps 40 \
--output_dir "output" \
--save_path "data/decode_res.json" \
--learning_rate 3e-5 \
--warmup_steps 40 \
--per_gpu_train_batch_size 4 \
--per_gpu_eval_batch_size 4 \
--seed 2048

View File

@@ -1,5 +1,19 @@
#!/bin/bash
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
export CUDA_VISIBLE_DEVICES=0
QUESTION=$1

View File

@@ -1,4 +1,19 @@
#!/bin/bash
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
export CUDA_VISIBLE_DEVICES=0
if [ $# != 4 ];then

View File

@@ -0,0 +1,34 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
export CUDA_VISIBLE_DEVICES=0
QUESTION=$1
# Question: NFC咋开门
if [ $# != 1 ];then
echo "USAGE: sh script/run_cross_encoder_test.sh \$QUESTION"
exit 1
fi
# compute scores for QUESTION and OCR parsing results with Rerank module
cd Rerank
bash run_test.sh ${QUESTION}
cd ..
# extraction answer for QUESTION from the top1 of rank
cd Extraction
bash run_test.sh ${QUESTION}
cd ..

View File

@@ -0,0 +1 @@
../../model_zoo/ernie-layout

View File

@@ -24,7 +24,6 @@ from tqdm import tqdm
from paddlenlp.transformers import AutoTokenizer, AutoModel, AutoModelForSequenceClassification
from data import convert_example, read_text_pair, create_dataloader
from model import CrossEncoder
# yapf: disable
parser = argparse.ArgumentParser()

View File

@@ -15,7 +15,7 @@
智能问答是获取信息和知识的更直接、更高效的方式之一,传统的信息检索方法智能找到相关的文档,而智能问答能够直接找到精准的答案,极大的节省了人们查询信息的时间。问答按照技术分为基于阅读理解的问答和检索式的问答,阅读理解的问答是在正文中找到对应的答案片段,检索式问答则是匹配高频的问题,然后把答案返回给用户。本项目属于检索式的问答,问答的领域用途很广,比如搜索引擎,小度音响等智能硬件,政府,金融,银行,电信,电商领域的智能客服,聊天机器人等。
- 本方案是场景的定制化的方案,用户可以使用自己的数据训练一个特定场景的方案。另外,想快速体验FAQ智能问答系统请参考Pipelines的实现[FAQ智能问答](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/pipelines/examples/frequently-asked-question)
- 本方案是场景的定制化的方案,用户可以使用自己的数据训练一个特定场景的方案。另外,想快速体验FAQ智能问答系统请参考Pipelines的实现[FAQ智能问答](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/pipelines/examples/FAQ)
- 本项目的详细教程请参考(包括数据和代码实现)[aistudio教程](https://aistudio.baidu.com/aistudio/projectdetail/3882519)
@@ -416,7 +416,7 @@ pip install paddle-serving-server-gpu==0.8.3.post101 -i https://pypi.tuna.tsingh
# CUDA11.2 + TensorRT8
pip install paddle-serving-server-gpu==0.8.3.post112 -i https://pypi.tuna.tsinghua.edu.cn/simple
```
更详细的安装信息请参考[链接]((https://github.com/PaddlePaddle/Serving/blob/v0.9.0/doc/Install_Linux_Env_CN.md)),安装完依赖后就可以执行下面的步骤。首先把生成的静态图模型导出为 Paddle Serving的格式,命令如下:
更详细的安装信息请参考[链接](https://github.com/PaddlePaddle/Serving/blob/v0.9.0/doc/Install_Linux_Env_CN.md),安装完依赖后就可以执行下面的步骤。首先把生成的静态图模型导出为 Paddle Serving的格式,命令如下:
```
python export_to_serving.py \
@@ -443,17 +443,10 @@ sh scripts/export_to_serving.sh
```
启动 Pipeline Server:
修改Tokenizer:
```
self.tokenizer = AutoTokenizer.from_pretrained('rocketqa-zh-base-query-encoder')
```
然后运行:
```
cd deploy/python/
python web_service.py
python web_service.py --model_name_or_path rocketqa-zh-base-query-encoder
```
启动客户端调用 Server, 使用 POST的方式:
@@ -479,6 +472,22 @@ list_data = [
python rpc_client.py
```
对于Windows用户,启动下面的Pipeline Server:
```
python web_service_windows.py --model_name_or_path rocketqa-zh-base-query-encoder
```
启动客户端调用 Server, 使用 POST的方式(Windows不支持RPC的调用方式),首先修改http_client.py中需要预测的样本:
```
data = {"feed": ["买了社保,是不是就不用买商业保险了?"], "fetch": ["output_embedding"]}
```
然后运行:
```
python http_client.py
```
### 4.5 问答系统整个流程
问答系统使用了Client Server的模式,即抽取向量的模型部署在服务端,然后启动客户端(Client)端去访问。

View File

@@ -0,0 +1,31 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import base64
import time
import numpy as np
import requests
headers = {"Content-type": "application/json"}
url = "http://10.21.226.175:8080/ernie/prediction" # XXX取决于服务端YourService的初始化name参数
data = {"feed": ["买了社保,是不是就不用买商业保险了?"], "fetch": ["output_embedding"]}
data = json.dumps(data)
print(data)
r = requests.post(url=url, headers=headers, data=data)
print(r.json())
json_data = r.json()
data = np.array(json_data['result']['output_embedding'])
print(data.shape)

View File

@@ -14,9 +14,16 @@
import numpy as np
import sys
import argparse
from paddle_serving_server.web_service import WebService, Op
# yapf: disable
parser = argparse.ArgumentParser()
parser.add_argument('--model_name_or_path', default="rocketqa-zh-base-query-encoder", help="Select tokenizer name to for model")
args = parser.parse_args()
# yapf: enable
def convert_example(example,
tokenizer,
@@ -37,8 +44,7 @@ class ErnieOp(Op):
def init_op(self):
from paddlenlp.transformers import AutoTokenizer
self.tokenizer = AutoTokenizer.from_pretrained(
'rocketqa-zh-base-query-encoder')
self.tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
def preprocess(self, input_dicts, data_id, log_id):
from paddlenlp.data import Stack, Tuple, Pad
@@ -54,7 +60,7 @@ class ErnieOp(Op):
batchify_fn = lambda samples, fn=Tuple(
Pad(axis=0, pad_val=self.tokenizer.pad_token_id, dtype="int64"
), # input
Pad(axis=0, pad_val=self.tokenizer.pad_token_id, dtype="int64"
Pad(axis=0, pad_val=self.tokenizer.pad_token_type_id, dtype="int64"
), # segment
): fn(samples)
input_ids, segment_ids = batchify_fn(examples)
@@ -77,6 +83,7 @@ class ErnieService(WebService):
return ernie_op
ernie_service = ErnieService(name="ernie")
ernie_service.prepare_pipeline_config("config_nlp.yml")
ernie_service.run_service()
if __name__ == "__main__":
ernie_service = ErnieService(name="ernie")
ernie_service.prepare_pipeline_config("config_nlp.yml")
ernie_service.run_service()

View File

@@ -0,0 +1,82 @@
# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
import sys
import argparse
from paddle_serving_server.web_service import WebService, Op
# yapf: disable
parser = argparse.ArgumentParser()
parser.add_argument('--model_name_or_path', default="rocketqa-zh-base-query-encoder", help="Select tokenizer name to for model")
args = parser.parse_args()
# yapf: enable
def convert_example(example,
tokenizer,
max_seq_length=512,
pad_to_max_seq_len=False):
result = []
for text in example:
encoded_inputs = tokenizer(text=text,
max_seq_len=max_seq_length,
pad_to_max_seq_len=pad_to_max_seq_len)
input_ids = encoded_inputs["input_ids"]
token_type_ids = encoded_inputs["token_type_ids"]
result += [input_ids, token_type_ids]
return result
class ErnieService(WebService):
def init_service(self):
from paddlenlp.transformers import AutoTokenizer
self.tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
def preprocess(self, feed=[], fetch=[]):
from paddlenlp.data import Stack, Tuple, Pad
print("input dict", feed)
batch_size = len(feed)
is_batch = True
examples = []
for i in range(batch_size):
input_ids, segment_ids = convert_example([feed[i]], self.tokenizer)
examples.append((input_ids, segment_ids))
batchify_fn = lambda samples, fn=Tuple(
Pad(axis=0, pad_val=self.tokenizer.pad_token_id, dtype="int64"
), # input
Pad(axis=0, pad_val=self.tokenizer.pad_token_type_id, dtype="int64"
), # segment
): fn(samples)
input_ids, segment_ids = batchify_fn(examples)
feed_dict = {}
feed_dict['input_ids'] = input_ids
feed_dict['token_type_ids'] = segment_ids
return feed_dict, fetch, is_batch
def postprocess(self, feed=[], fetch=[], fetch_map=None):
for key in fetch_map:
fetch_map[key] = fetch_map[key].tolist()
return fetch_map
if __name__ == "__main__":
ernie_service = ErnieService(name="ernie")
ernie_service.load_model_config("../../serving_server")
ernie_service.prepare_server(workdir="workdir", port=8080)
ernie_service.init_service()
ernie_service.run_debugger_service()
ernie_service.run_web_service()

View File

@@ -115,7 +115,6 @@
【快速开始】
- 快速开启多分类任务参见 👉 [语义索引-多分类指南](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/text_classification/multi_class/retrieval_based#readme)
- 快速开启多标签分类任务参见 👉 [语义索引-多标签分类指南](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/text_classification/multi_label/retrieval_based#readme)
- 快速开启层次分类任务参见 👉 [语义索引-层次分类指南](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/text_classification/hierarchical/retrieval_based#readme)
@@ -179,7 +178,7 @@
- 体验模型分析模块 👉 [多分类-模型分析模块](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/text_classification/multi_class/analysis)
- 体验模型分析模块 👉 [多标签-模型分析模块](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/text_classification/multi_label/analysis)
- 体验模型分析模块 👉 [层次分类多-模型分析模块](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/text_classification/hierarchical/analysis)
- 体验模型分析模块 👉 [层次分类-模型分析模块](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/applications/text_classification/hierarchical/analysis)
<a name="产业级全流程方案"></a>

View File

@@ -36,7 +36,7 @@
- 【标注成本高、标注样本较少的小样本场景】 👉 [提示学习层次分类方案](./few-shot#readme)
- 【标签类别不固定场景】 👉 [语义索引层次分类方案](./retrieval_based#readme)
- 【标签类别不固定场景、标签数量众多】 👉 [语义索引层次分类方案](./retrieval_based#readme)
<a name="快速开始"></a>
@@ -92,20 +92,13 @@ python3 -m pip install scikit-learn==1.0.2
```text
hierarchical/
├── few-shot # 小样本学习方案
├── retrieval_based # 语义索引方案
├── analysis # 分析模块
├── deploy # 部署
│   └── predictor # 离线部署
│   │ ├── infer.py # 测试脚本
│   │ ├── predictor.py 离线部署脚本
│   │ └── README.md # 离线部署使用说明
│ ├── paddle_serving # PaddleServing在线服务化部署
│   │ ├──config.yml # 服务端的配置文件
│   │ ├──rpc_client.py # 客户端预测脚本
│   │ ├──service.py # 服务端的脚本
│   │ └── README.md # 在线服务化部署使用说明
│   └── triton_serving # Triton在线服务化部署
│ ├── README.md # Triton部署使用说明
│ ├── seqcls_grpc_client.py # 客户端预测脚本
│   └── models
├── train.py # 训练评估脚本
├── predict.py # 预测脚本
├── export_model.py # 静态图模型导出脚本
@@ -130,7 +123,7 @@ data/
└── data.txt # 待预测数据文件(可选)
```
**训练、开发、测试数据集文件:** 文本与标签类别名用tab符`'\t'`分隔开,标签中多个标签之间用英文逗号`','`分隔开。
**训练、开发、测试数据集文件:** 文本与标签类别名用tab符`'\t'`分隔开,标签中多个标签之间用英文逗号`','`分隔开,文本中避免出现tab符`'\t'`。
- train.txt/dev.txt/test.txt 文件格式:
```text
@@ -267,10 +260,16 @@ checkpoint/
* 英文和中文以外语言的文本分类任务,推荐使用基于96种语言(涵盖法语、日语、韩语、德语、西班牙语等几乎所有常见语言)进行预训练的多语言预训练模型"ernie-m-base"、"ernie-m-large",详情请参见[ERNIE-M论文](https://arxiv.org/pdf/2012.15674.pdf)。
#### 2.4.2 训练评估与模型优化
训练后的模型我们可以使用 [模型分析模块](./analysis) 对每个类别分别进行评估,并输出预测错误样本(bad case),默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`:
文本分类预测过程中常会遇到诸如"模型为什么会预测出错误的结果","如何提升模型的表现"等问题。[Analysis模块](./analysis) 提供了**模型评估、可解释性分析、数据优化**等功能,旨在帮助开发者更好地分析文本分类模型预测结果和对模型效果进行优化。
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/195241942-70068989-df17-4f53-9f71-c189d8c5c88d.png" width="600">
</div>
**模型评估:** 训练后的模型我们可以使用 [Analysis模块](./analysis) 对每个类别分别进行评估,并输出预测错误样本(bad case),默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`:
```shell
python analysis/evaluate.py --device "gpu" --max_seq_length 128 --batch_size 32 --bad_case_path "./bad_case.txt" --dataset_dir "data" --params_path "./checkpoint"
python analysis/evaluate.py --device "gpu" --max_seq_length 128 --batch_size 32 --bad_case_file "bad_case.txt" --dataset_dir "data" --params_path "./checkpoint"
```
输出打印示例:
@@ -297,15 +296,38 @@ python analysis/evaluate.py --device "gpu" --max_seq_length 128 --batch_size 32
预测错误的样本保存在bad_case.txt文件中:
```text
Prediction Label Text
组织关系,组织关系##解雇 组织关系,组织关系##加盟,组织关系##裁员 据猛龙随队记者JoshLewenberg报道,消息人士透露,猛龙已将前锋萨加巴-科纳特裁掉。此前他与猛龙签下了一份Exhibit10合同。在被裁掉后,科纳特下赛季大概率将前往猛龙的发展联盟球队效力。
组织关系,组织关系##解雇 组织关系,组织关系##裁员 冠军射手被裁掉,欲加入湖人队,但湖人却无意,冠军射手何去何从
组织关系,组织关系##裁员 组织关系,组织关系##退出,组织关系##裁员 有多名魅族员工表示,从6月份开始,魅族开始了新一轮裁员,重点裁员区域是营销和线下。裁员占比超过30%,剩余员工将不过千余人,魅族的知名工程师,爱讲真话的洪汉生已经从钉钉里退出了,外界传言说他去了OPPO。
人生,人生##死亡,灾害/意外,灾害/意外##坍/垮塌 灾害/意外,灾害/意外##坍/垮塌 冲刺千亿的美的置业贵阳项目倒塌致8人死亡已责令全面停工
Text Label Prediction
据猛龙随队记者JoshLewenberg报道,消息人士透露,猛龙已将前锋萨加巴-科纳特裁掉。此前他与猛龙签下了一份Exhibit10合同。在被裁掉后,科纳特下赛季大概率将前往猛龙的发展联盟球队效力。 组织关系,组织关系##加盟,组织关系##裁员 组织关系,组织关系##解雇
冠军射手被裁掉,欲加入湖人队,但湖人却无意,冠军射手何去何从 组织关系,组织关系##裁员 组织关系,组织关系##解雇
6月7日报道,IBM将裁员超过1000人。IBM周四确认,将裁减一千多人。据知情人士称,此次裁员将影响到约1700名员工,约占IBM全球逾34万员工中的0.5%。IBM股价今年累计上涨16%,但该公司4月发布的财报显示,一季度营收下降5%,低于市场预期。 组织关系,组织关系##裁员 组织关系,组织关系##裁员,财经/交易
有多名魅族员工表示,从6月份开始,魅族开始了新一轮裁员,重点裁员区域是营销和线下。裁员占比超过30%,剩余员工将不过千余人,魅族的知名工程师,爱讲真话的洪汉生已经从钉钉里退出了,外界传言说他去了OPPO。 组织关系,组织关系##退出,组织关系##裁员 组织关系,组织关系##裁员
...
```
模型表现常常受限于数据质量,在analysis模块中我们提供了基于[TrustAI](https://github.com/PaddlePaddle/TrustAI)的稀疏数据筛选、脏数据清洗、数据增强三种优化方案助力开发者提升模型效果,更多模型评估和优化方案细节详见[训练评估与模型优化指南](analysis/README.md)。
**可解释性分析:** 基于[TrustAI](https://github.com/PaddlePaddle/TrustAI)提供单词和句子级别的模型可解释性分析,帮助理解模型预测结果,用于错误样本(bad case)分析,细节详见[训练评估与模型优化指南](analysis/README.md)。
- 单词级别可解释性分析,也即分析待预测样本中哪一些单词对模型预测结果起重要作用。以下图为例,用颜色深浅表示单词对预测结果的重要性。
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/195334753-78cc2dc8-a5ba-4460-9fde-3b1bb704c053.png" width="1000">
</div>
- 句子级别可解释性分析 ,也即分析对待预测样本的模型预测结果与训练集中中哪些样本有重要关系。下面的例子表明句子级别可解释性分析可以帮助理解待预测样本的预测结果与训练集中样本之间的关联。
```text
text: 据猛龙随队记者JoshLewenberg报道,消息人士透露,猛龙已将前锋萨加巴-科纳特裁掉。此前他与猛龙签下了一份Exhibit10合同。在被裁掉后,科纳特下赛季大概率将前往猛龙的发展联盟球队效力。
predict label: 组织关系,组织关系##解雇
label: 组织关系,组织关系##加盟,组织关系##裁员
examples with positive influence
support1 text: 尼克斯官方今日宣布,他们已经裁掉了前锋扎克-欧文,后者昨日才与尼克斯签约。 label: 组织关系,组织关系##加盟,组织关系##解雇 score: 0.99357
support2 text: 活塞官方今日宣布,他们已经签下了克雷格-斯沃德,并且裁掉了托德-威瑟斯。 label: 组织关系,组织关系##加盟,组织关系##解雇 score: 0.98344
support3 text: 孟菲斯灰熊今年宣布,球队已经签下后卫达斯蒂-汉纳斯(DustyHannahs,版头图)并裁掉马特-穆尼。 label: 组织关系,组织关系##加盟,组织关系##解雇 score: 0.98219
...
```
**数据优化:** 结合[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[数据增强API](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/dataaug.md)提供了**稀疏数据筛选、脏数据清洗、数据增强**三种优化策略,从多角度优化训练数据提升模型效果,策略细节详见[训练评估与模型优化指南](analysis/README.md)。
- 稀疏数据筛选主要是解决数据不均衡、训练数据覆盖不足的问题,通过数据增强和数据标注两种方式解决这一问题。
- 脏数据清洗可以帮助开发者筛选训练集中错误标注的数据,对这些数据重新进行人工标注,得到标注正确的数据再重新进行训练。
- 数据增强策略提供多种数据增强方案,可以快速扩充数据,提高模型泛化性和鲁棒性。
#### 2.4.3 模型预测
训练结束后,输入待预测数据(data.txt)和类别标签对照列表(label.txt),使用训练好的模型进行,默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`:
@@ -337,7 +359,7 @@ python predict.py --device "gpu" --max_seq_length 128 --batch_size 32 --dataset_
python export_model.py --params_path ./checkpoint/ --output_path ./export
```
如果使用ERNIE M作为预训练模型,运行方式:
如果使用多语言模型 ERNIE M作为预训练模型,运行方式:
```shell
python export_model.py --params_path ./checkpoint/ --output_path ./export --multilingual
```
@@ -418,8 +440,6 @@ prune/
3. ERNIE Base、Medium、Mini、Micro、Nano的模型宽度(multi head数量)为12,ERNIE Xbase、Large 模型宽度(multi head数量)为16,保留比例`width_mult`乘以宽度(multi haed数量)应为整数。
4. **压缩API暂不支持多语言预训练模型ERNIE-M**,相关功能正在加紧开发中。
#### 2.5.3 部署方案
- 离线部署搭建请参考[离线部署](deploy/predictor/README.md)。

View File

@@ -1,18 +1,29 @@
# 层次分类训练评估与模型优化指南
# 训练评估与模型优化指南
**目录**
* [analysis模块介绍](#analysis模块介绍)
* [Analysis模块介绍](#Analysis模块介绍)
* [环境准备](#环境准备)
* [模型评估](#模型评估)
* [稀疏数据筛选方案](#稀疏数据筛选方案)
* [脏数据清洗方案](#脏数据清洗方案)
* [数据增强策略方案](#数据增强策略方案)
* [可解释性分析](#可解释性分析)
* [单词级别可解释性分析](#单词级别可解释性分析)
* [句子级别可解释性分析](#句子级别可解释性分析)
* [数据优化](#数据优化)
* [稀疏数据筛选方案](#稀疏数据筛选方案)
* [脏数据清洗方案](#脏数据清洗方案)
* [数据增强策略方案](#数据增强策略方案)
## analysis模块介绍
## Analysis模块介绍
analysis模块提供了**模型评估**脚本对整体分类情况和每个类别分别进行评估,并打印预测错误样本,帮助开发者分析模型表现找到训练和预测数据中存在的问题问题。同时基于[可信AI工具集](https://github.com/PaddlePaddle/TrustAI)和[数据增强API](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/dataaug.md)提供了**稀疏数据筛选、脏数据清洗、数据增强**三种优化方案从多角度帮助开发者提升模型效果。
Analysis模块提供了**模型评估、可解释性分析、数据优化**等功能,旨在帮助开发者更好地分析文本分类模型预测结果和对模型效果进行优化。
- **模型评估:** 对整体分类情况和每个类别分别进行评估,并打印预测错误样本,帮助开发者分析模型表现找到训练和预测数据中存在的问题。
- **可解释性分析:** 基于[TrustAI](https://github.com/PaddlePaddle/TrustAI)提供单词和句子级别的模型可解释性分析,帮助理解模型预测结果。
- **数据优化:** 结合[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[数据增强API](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/dataaug.md)提供了**稀疏数据筛选、脏数据清洗、数据增强**三种优化策略,从多角度优化训练数据提升模型效果。
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/184790352-7f91da02-aadd-48fe-9130-8323a89c6a43.jpg" width="600">
<img src="https://user-images.githubusercontent.com/63761690/195241942-70068989-df17-4f53-9f71-c189d8c5c88d.png" width="600">
</div>
以下是本项目主要代码结构及说明:
@@ -20,10 +31,27 @@ analysis模块提供了**模型评估**脚本对整体分类情况和每个类
```text
analysis/
├── evaluate.py # 评估脚本
├── sent_interpret.py # 句子级别可解释性分析脚本
├── word_interpret.py # 单词级别可解释性分析notebook
├── sparse.py # 稀疏数据筛选脚本
├── dirty.py # 脏数据清洗脚本
├── aug.py # 数据增强脚本
└── README.md # 层次分类训练评估与模型优化指南
└── README.md # 训练评估与模型优化指南
```
## 环境准备
需要可解释性分析和数据优化需要安装相关环境。
- trustai >= 0.1.7
- interpretdl >= 0.7.0
**安装TrustAI**(可选)如果使用可解释性分析和数据优化中稀疏数据筛选和脏数据清洗需要安装TrustAI。
```shell
pip install trustai==0.1.7
```
**安装InterpretDL**(可选)如果使用词级别可解释性分析GradShap方法,需要安装InterpretDL
```shell
pip install interpretdl==0.7.0
```
## 模型评估
@@ -37,14 +65,14 @@ python evaluate.py \
--params_path "../checkpoint" \
--max_seq_length 128 \
--batch_size 32 \
--bad_case_path "./bad_case.txt"
--bad_case_file "bad_case.txt"
```
默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`
可支持配置的参数:
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含train.txt、dev.txt和label.txt文件;默认为None。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
* `max_seq_length`:分词器tokenizer使用的最大序列长度,ERNIE模型最大不能超过2048。请根据文本长度选择,通常推荐128、256或512,若出现显存不足,请适当调低这一参数;默认为128。
@@ -54,6 +82,7 @@ python evaluate.py \
* `label_file`:本地数据集中标签集文件名;默认为"label.txt"。
* `bad_case_path`:开发集中预测错误样本保存路径;默认为"/bad_case.txt"。
输出打印示例:
```text
@@ -78,30 +107,109 @@ python evaluate.py \
预测错误的样本保存在bad_case.txt文件中:
```text
Prediction Label Text
组织关系,组织关系##解雇 组织关系,组织关系##加盟,组织关系##裁员 据猛龙随队记者JoshLewenberg报道,消息人士透露,猛龙已将前锋萨加巴-科纳特裁掉。此前他与猛龙签下了一份Exhibit10合同。在被裁掉后,科纳特下赛季大概率将前往猛龙的发展联盟球队效力。
组织关系,组织关系##解雇 组织关系,组织关系##裁员 冠军射手被裁掉,欲加入湖人队,但湖人却无意,冠军射手何去何从
组织关系,组织关系##裁员 组织关系,组织关系##退出,组织关系##裁员 有多名魅族员工表示,从6月份开始,魅族开始了新一轮裁员,重点裁员区域是营销和线下。裁员占比超过30%,剩余员工将不过千余人,魅族的知名工程师,爱讲真话的洪汉生已经从钉钉里退出了,外界传言说他去了OPPO。
人生,人生##死亡,灾害/意外,灾害/意外##坍/垮塌 灾害/意外,灾害/意外##坍/垮塌 冲刺千亿的美的置业贵阳项目倒塌致8人死亡已责令全面停工
Text Label Prediction
据猛龙随队记者JoshLewenberg报道,消息人士透露,猛龙已将前锋萨加巴-科纳特裁掉。此前他与猛龙签下了一份Exhibit10合同。在被裁掉后,科纳特下赛季大概率将前往猛龙的发展联盟球队效力。 组织关系,组织关系##加盟,组织关系##裁员 组织关系,组织关系##解雇
冠军射手被裁掉,欲加入湖人队,但湖人却无意,冠军射手何去何从 组织关系,组织关系##裁员 组织关系,组织关系##解雇
6月7日报道,IBM将裁员超过1000人。IBM周四确认,将裁减一千多人。据知情人士称,此次裁员将影响到约1700名员工,约占IBM全球逾34万员工中的0.5%。IBM股价今年累计上涨16%,但该公司4月发布的财报显示,一季度营收下降5%,低于市场预期。 组织关系,组织关系##裁员 组织关系,组织关系##裁员,财经/交易
有多名魅族员工表示,从6月份开始,魅族开始了新一轮裁员,重点裁员区域是营销和线下。裁员占比超过30%,剩余员工将不过千余人,魅族的知名工程师,爱讲真话的洪汉生已经从钉钉里退出了,外界传言说他去了OPPO。 组织关系,组织关系##退出,组织关系##裁员 组织关系,组织关系##裁员
...
```
## 稀疏数据筛选方案
## 可解释性分析
"模型为什么会预测出这个结果?"是文本分类任务开发者时常遇到的问题,如何分析错误样本(bad case)是文本分类任务落地中重要一环,本项目基于TrustAI开源了基于词级别和句子级别的模型可解释性分析方法,帮助开发者更好地理解文本分类模型与数据,有助于后续的模型优化与数据清洗标注。
稀疏数据指缺乏足够训练数据支持导致低置信度的待预测数据,简单来说,由于模型在训练过程中没有学习到足够与待预测样本相似的数据,模型难以正确预测样本所属类别。本项目中稀疏数据筛选基于TrustAI(可信AI)工具集,利用基于特征相似度的实例级证据分析方法,抽取开发集中样本的支持训练证据,并计算支持证据平均分(通常为得分前三的支持训练证据均分)。分数较低的样本表明其训练证据不足,在训练集中较为稀疏,实验表明模型在这些样本上表现也相对较差。更多细节详见[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[实例级证据分析](https://github.com/PaddlePaddle/TrustAI/blob/main/trustai/interpretation/example_level/README.md)。
### 单词级别可解释性分析
本项目开源模型的词级别可解释性分析Notebook,提供LIME、Integrated Gradient、GradShap 三种分析方法,支持分析微调后模型的预测结果,开发者可以通过更改**数据目录**和**模型目录**在自己的任务中使用Jupyter Notebook进行数据分析。
稀疏数据筛选旨在开发集中挖掘缺乏训练证据支持的稀疏数据,通常可以采用**数据增强**或**少量数据标注**的两种低成本方式,提升模型预测效果。
运行 [word_interpret.ipynb](./word_interpreter.ipynb) 代码,即可分析影响样本预测结果的关键词以及可视化所有词对预测结果的贡献情况,颜色越深代表这个词对预测结果影响越大:
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/195334753-78cc2dc8-a5ba-4460-9fde-3b1bb704c053.png" width="1000">
</div>
**安装TrustAI**
```shell
pip install trustai==0.1.4
### 句子级别可解释性分析
本项目基于特征相似度([FeatureSimilarity](https://arxiv.org/abs/2104.04128))算法,计算对样本预测结果正影响的训练数据,帮助理解模型的预测结果与训练集数据的关系。
待分析数据文件`interpret_input_file`应为以下三种格式中的一种:
**格式一:包括文本、标签、预测结果**
```text
<文本>'\t'<标签>'\t'<预测结果>
...
```
### 稀疏数据识别--数据增强
**格式二:包括文本、标签**
```text
<文本>'\t'<标签>
...
```
这里我们将介绍稀疏数据识别--数据增强流程,首先使用数据增强脚本挖掘开发集中的稀疏数据,然后筛选训练集中对稀疏数据的支持数据进行数据增强,然后将得到的数据增强后的支持数据加入到训练集中进行训练。
**格式三:只包括文本**
```text
<文本>
准予原告胡某甲与被告韩某甲离婚。
...
```
现在我们进行稀疏数据识别--数据增强,得到新增训练数据:
我们可以运行代码,得到支持样本模型预测结果的训练数据:
```shell
python sent_interpret.py \
--device "gpu" \
--dataset_dir "../data" \
--params_path "../checkpoint/" \
--max_seq_length 128 \
--batch_size 16 \
--top_k 3 \
--train_file "train.txt" \
--interpret_input_file "bad_case.txt" \
--interpret_result_file "sent_interpret.txt"
```
默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`
可支持配置的参数:
* `device`: 选用什么设备进行训练,可可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含dev.txt和label.txt文件;默认为None。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
* `max_seq_length`:分词器tokenizer使用的最大序列长度,ERNIE模型最大不能超过2048。请根据文本长度选择,通常推荐128、256或512,若出现显存不足,请适当调低这一参数;默认为128。
* `batch_size`:批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为32。
* `seed`:随机种子,默认为3。
* `top_k`:筛选支持训练证据数量;默认为3。
* `train_file`:本地数据集中训练集文件名;默认为"train.txt"。
* `interpret_input_file`:本地数据集中待分析文件名;默认为"bad_case.txt"。
* `interpret_result_file`:保存句子级别可解释性结果文件名;默认为"sent_interpret.txt"。
可解释性结果保存在 `interpret_result_file` 文件中:
```text
text: 据猛龙随队记者JoshLewenberg报道,消息人士透露,猛龙已将前锋萨加巴-科纳特裁掉。此前他与猛龙签下了一份Exhibit10合同。在被裁掉后,科纳特下赛季大概率将前往猛龙的发展联盟球队效力。
predict label: 组织关系,组织关系##解雇
label: 组织关系,组织关系##加盟,组织关系##裁员
examples with positive influence
support1 text: 尼克斯官方今日宣布,他们已经裁掉了前锋扎克-欧文,后者昨日才与尼克斯签约。 label: 组织关系,组织关系##加盟,组织关系##解雇 score: 0.99357
support2 text: 活塞官方今日宣布,他们已经签下了克雷格-斯沃德,并且裁掉了托德-威瑟斯。 label: 组织关系,组织关系##加盟,组织关系##解雇 score: 0.98344
support3 text: 孟菲斯灰熊今年宣布,球队已经签下后卫达斯蒂-汉纳斯(DustyHannahs,版头图)并裁掉马特-穆尼。 label: 组织关系,组织关系##加盟,组织关系##解雇 score: 0.98219
...
```
## 数据优化
### 稀疏数据筛选方案
稀疏数据筛选适用于文本分类中**数据不平衡或训练数据覆盖不足**的场景,简单来说,就是由于模型在训练过程中没有学习到足够与待预测样本相似的数据,模型难以正确预测样本所属类别的情况。稀疏数据筛选旨在开发集中挖掘缺乏训练证据支持的数据,通常可以采用**数据增强**或**少量数据标注**的两种低成本方式,提升模型在开发集的预测效果。
本项目中稀疏数据筛选基于TrustAI,利用基于特征相似度的实例级证据分析方法,抽取开发集中样本的支持训练证据,并计算支持证据平均分(通常为得分前三的支持训练证据均分)。分数较低的样本表明其训练证据不足,在训练集中较为稀疏,实验表明模型在这些样本上表现也相对较差。更多细节详见[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[实例级证据分析](https://github.com/PaddlePaddle/TrustAI/blob/main/trustai/interpretation/example_level/README.md)。
#### 稀疏数据识别—数据增强
这里我们将介绍稀疏数据识别—数据增强流程:
- **稀疏数据识别:** 挖掘开发集中的缺乏训练证据支持数据,记为稀疏数据集(Sparse Dataset);
- **数据增强**:将稀疏数据集在训练集中的支持证据应用数据增强策略,这些数据增强后的训练数据记为支持数据集(Support Dataset);
- **重新训练模型:** 将支持数据集加入到原有的训练集获得新的训练集,重新训练新的文本分类模型。
现在我们进行稀疏数据识别-数据增强,得到支持数据集:
```shell
python sparse.py \
@@ -119,7 +227,7 @@ python sparse.py \
可支持配置的参数:
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含dev.txt和label.txt文件;默认为None。
* `aug_strategy`:数据增强类型,可选"duplicate","substitute", "insert", "delete", "swap";默认为"substitute"。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
@@ -156,9 +264,15 @@ cat ../data/train.txt ../data/support.txt > ../data/train_sparse_aug.txt
|训练集+支持增强集(delete) |90.56| 80.26|
|训练集+支持增强集(swap) |90.18|80.05|
### 稀疏数据识别--数据标注
#### 稀疏数据识别-数据标注
这里我们将介绍稀疏数据识别--数据标注流程,首先使用数据增强脚本挖掘开发集中的稀疏数据,然后筛选对稀疏数据支持的未标注数据,然后将得到支持数据进行标注后加入到训练集中进行训练。
本方案能够有针对性进行数据标注,相比于随机标注数据更好提高模型预测效果。这里我们将介绍稀疏数据识别-数据标注流程:
- **稀疏数据识别:** 挖掘开发集中的缺乏训练证据支持数据,记为稀疏数据集(Sparse Dataset);
- **数据标注**:在未标注数据集中筛选稀疏数据集的支持证据,并进行数据标注,记为支持数据集(Support Dataset);
- **重新训练模型:** 将支持数据集加入到原有的训练集获得新的训练集,重新训练新的文本分类模型。
现在我们进行稀疏数据识别--数据标注,得到待标注数据:
@@ -179,7 +293,7 @@ python sparse.py \
可支持配置的参数:
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含dev.txt和label.txt文件;默认为None。
* `annotate`:选择稀疏数据识别--数据标注模式;默认为False。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
@@ -216,14 +330,13 @@ cat ../data/train.txt ../data/support.txt > ../data/train_sparse_annotate.txt
|训练集+策略采样集(100) |91.12|**84.13**|
|训练集+随机采样集(100) |**91.24**|81.66|
## 脏数据清洗方案
### 脏数据清洗方案
训练数据标注质量对模型效果有较大影响,但受限于标注人员水平、标注任务难易程度等影响,训练数据中都存在一定比例的标注较差的数据(脏数据)。当标注数据规模较大时,数据标注检查就成为一个难题。本项目中脏数据清洗基于TrustAI(可信AI)工具集,利用基于表示点方法的实例级证据分析方法,计算训练数据对模型的影响分数,分数高的训练数据表明对模型影响大,这些数据有较大概率为脏数据(标注错误样本)。更多细节详见[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[实例级证据分析](https://github.com/PaddlePaddle/TrustAI/blob/main/trustai/interpretation/example_level/README.md)。
脏数据清洗方案是基于已训练好的文本分类模型,筛选出训练数据集中标注错误的数据,再由人工检查重新标注,获得标注正确的数据集进行重新训练。我们将介绍脏数据清洗流程:
**安装TrustAI**
```shell
pip install trustai==0.1.4
```
- **脏数据筛选:** 基于TrustAI中表示点方法,计算训练数据对文本分类模型的影响分数,分数高的训练数据表明对模型影响大,这些数据有较大概率为标注错误样本,记为脏数据集(Dirty Dataset)。
- **数据清洗、训练:** 将筛选出的脏数据由人工重新检查,为数据打上正确的标签。将清洗后的训练数据重新放入文本分类模型进行训练。
现在我们进行脏数据识别,脏数据保存在`"train_dirty.txt"`,剩余训练数据保存在`"train_dirty_rest.txt"`:
@@ -246,16 +359,16 @@ python dirty.py \
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含train.txt和label.txt文件;默认为None。
* `max_seq_length`:分词器tokenizer使用的最大序列长度,ERNIE模型最大不能超过2048。请根据文本长度选择,通常推荐128、256或512,若出现显存不足,请适当调低这一参数;默认为128。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `batch_size`:批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为32。
* `seed`:随机种子,默认为3。
* `dirty_file`:保存脏数据文件名,默认为"train_dirty.txt"。
* `rest_file`:保存剩余数据(非脏数据)文件名,默认为"train_dirty_rest.txt"。
* `train_file`:本地数据集中训练集文件名;默认为"train.txt"。
* `dirty_threshold`:筛选脏数据用于重新标注的阈值,只选择影响分数大于阈值作为有效数据,默认为0。
* `dirty_threshold`:筛选脏数据用于重新标注的阈值,只选择影响分数大于阈值作为支持数据,默认为0。
我们将筛选出脏数据进行重新标注,可以将`train_dirty.txt`直接导入标注工具doccano帮助更快重新标注,详情请参考[文本分类任务doccano数据标注使用指南](../../doccano.md)进行文本分类数据标注。然后将已重新标注的脏数据`train_dirty.txt`与剩余训练集数据`train_dirty_rest.txt`合并得到新的训练集`train_clean.txt`重新进行训练:
我们将筛选出脏数据进行人工检查重新标注,可以将`train_dirty.txt`直接导入标注工具doccano帮助更快重新标注,详情请参考[文本分类任务doccano数据标注使用指南](../../doccano.md)进行文本分类数据标注。然后将已重新标注的脏数据`train_dirty.txt`与剩余训练集数据`train_dirty_rest.txt`合并得到新的训练集`train_clean.txt`重新进行训练:
```shell
cat ../data/train_dirty_rest.txt ../data/train_dirty.txt > ../data/train_clean.txt
@@ -273,7 +386,7 @@ cat ../data/train_dirty_rest.txt ../data/train_dirty.txt > ../data/train_clean.t
|训练集(2000,含200条脏数据) + 脏数据清洗(100)|92.48|**87.83**|
|训练集(2000,含200条脏数据) + 脏数据清洗(150)|**92.55**|83.73|
## 数据增强策略方案
### 数据增强策略方案
在数据量较少或某些类别样本量较少时,也可以通过数据增强策略的方式,生成更多的训练数据,提升模型效果。
@@ -289,11 +402,11 @@ python aug.py \
* `train_path`:待增强训练数据集文件路径;默认为"../data/train.txt"。
* `aug_path`:增强生成的训练数据集文件路径;默认为"../data/train_aug.txt"。
* `aug_strategy`:数据增强策略,可选"mix", "substitute", "insert", "delete", "swap"为多种数据策略混合使用;默认为"substitute"。
* `aug_strategy`:数据增强策略,可选"mix", "substitute", "insert", "delete", "swap","mix"为多种数据策略混合使用;默认为"substitute"。
* `aug_type`:词替换/词插入增强类型,可选"synonym", "homonym", "mlm",建议在GPU环境下使用mlm类型;默认为"synonym"。
* `create_n`:生成的句子数量,默认为2。
* `aug_percent`:生成词替换百分比,默认为0.1。
* `device`: 选用什么设备进行增强,选择cpu、gpu、xpu、npu,仅在使用mlm类型有影响;默认为"gpu"。
* `device`: 选用什么设备进行增强,可选择cpu、gpu、xpu、npu,仅在使用mlm类型有影响;默认为"gpu"。
生成的增强数据保存在`"aug.txt"`文件中,与训练集数据`train.txt`合并得到新的训练集`train_aug.txt`重新进行训练:

View File

@@ -37,7 +37,7 @@ parser.add_argument("--batch_size", default=32, type=int, help="Batch size per G
parser.add_argument("--train_file", type=str, default="train.txt", help="Train dataset file name")
parser.add_argument("--dev_file", type=str, default="dev.txt", help="Dev dataset file name")
parser.add_argument("--label_file", type=str, default="label.txt", help="Label file name")
parser.add_argument("--bad_case_path", type=str, default="./bad_case.txt", help="Bad case saving file path")
parser.add_argument("--bad_case_file", type=str, default="./bad_case.txt", help="Bad case saving file path")
args = parser.parse_args()
# yapf: enable
@@ -236,23 +236,22 @@ def evaluate():
report[str(i)]['recall'] * 100,
report[str(i)]['f1-score'] * 100))
logger.info("----------------------------")
with open(args.bad_case_path, 'w', encoding="utf-8") as f:
f.write("Prediction\tLabel\tText\n")
bad_case_path = os.path.join(args.dataset_dir, args.bad_case_file)
with open(bad_case_path, 'w', encoding="utf-8") as f:
f.write("Text\tLabel\tPrediction\n")
for i in range(len(preds)):
for p, l in zip(preds[i], labels[i]):
if (p and l == 0) or (not p and l == 1):
pred_n = [
label_map[i] for i, pp in enumerate(preds[i]) if pp
]
f.write(",".join(pred_n) + "\t" +
f.write(dev_ds.data[i]["text"] + "\t" +
dev_ds.data[i]["label_n"] + "\t" +
dev_ds.data[i]["text"] + "\n")
",".join(pred_n) + "\n")
break
f.close()
logger.info("Bad case in dev dataset saved in {}".format(
args.bad_case_path))
logger.info("Bad case in dev dataset saved in {}".format(bad_case_path))
return

View File

@@ -0,0 +1,172 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import functools
import random
import os
import argparse
import numpy as np
import paddle
import paddle.nn.functional as F
from paddle.io import DataLoader, BatchSampler
from paddlenlp.data import DataCollatorWithPadding
from paddlenlp.datasets import load_dataset
from paddlenlp.transformers import AutoModelForSequenceClassification, AutoTokenizer, LinearDecayWithWarmup
from paddlenlp.utils.log import logger
from trustai.interpretation import FeatureSimilarityModel
# yapf: disable
parser = argparse.ArgumentParser()
parser.add_argument('--device', default="gpu", help="Select which device to train model, defaults to gpu.")
parser.add_argument("--dataset_dir", required=True, type=str, help="The dataset directory should include train.txt,dev.txt and test.txt files.")
parser.add_argument("--params_path", default="../checkpoint/", type=str, help="The path to model parameters to be loaded.")
parser.add_argument("--max_seq_length", default=128, type=int, help="The maximum total input sequence length after tokenization. Sequences longer than this will be truncated, sequences shorter will be padded.")
parser.add_argument("--batch_size", default=16, type=int, help="Batch size per GPU/CPU for training.")
parser.add_argument("--seed", type=int, default=3, help="random seed for initialization")
parser.add_argument("--top_k", type=int, default=3, help="Top K important training data.")
parser.add_argument("--train_file", type=str, default="train.txt", help="Train dataset file name")
parser.add_argument("--interpret_input_file", type=str, default="bad_case.txt", help="interpretation file name")
parser.add_argument("--interpret_result_file", type=str, default="sent_interpret.txt", help="interpreted file name")
args = parser.parse_args()
# yapf: enable
def set_seed(seed):
"""
Set random seed
"""
random.seed(seed)
np.random.seed(seed)
paddle.seed(seed)
os.environ['PYTHONHASHSEED'] = str(seed)
def read_local_dataset(path):
"""
Read dataset file
"""
with open(path, 'r', encoding='utf-8') as f:
for line in f:
items = line.strip().split('\t')
if items[0] == 'Text':
continue
if len(items) == 3:
yield {'text': items[0], 'label': items[1], 'predict': items[2]}
elif len(items) == 2:
yield {'text': items[0], 'label': items[1], 'predict': ''}
elif len(items) == 1:
yield {'text': items[0], 'label': '', 'predict': ''}
else:
logger.info(line.strip())
raise ValueError("{} should be in fixed format.".format(path))
def preprocess_function(examples, tokenizer, max_seq_length):
"""
Preprocess dataset
"""
result = tokenizer(text=examples["text"], max_seq_len=max_seq_length)
return result
class LocalDataCollatorWithPadding(DataCollatorWithPadding):
"""
Convert the result of DataCollatorWithPadding from dict dictionary to a list
"""
def __call__(self, features):
batch = super().__call__(features)
batch = list(batch.values())
return batch
def find_positive_influence_data():
set_seed(args.seed)
paddle.set_device(args.device)
# Define model & tokenizer
if os.path.exists(os.path.join(
args.params_path, "model_state.pdparams")) and os.path.exists(
os.path.join(args.params_path,
"model_config.json")) and os.path.exists(
os.path.join(args.params_path,
"tokenizer_config.json")):
model = AutoModelForSequenceClassification.from_pretrained(
args.params_path)
tokenizer = AutoTokenizer.from_pretrained(args.params_path)
else:
raise ValueError("The {} should exist.".format(args.params_path))
# Prepare & preprocess dataset
train_path = os.path.join(args.dataset_dir, args.train_file)
interpret_path = os.path.join(args.dataset_dir, args.interpret_input_file)
train_ds = load_dataset(read_local_dataset, path=train_path, lazy=False)
interpret_ds = load_dataset(read_local_dataset,
path=interpret_path,
lazy=False)
trans_func = functools.partial(preprocess_function,
tokenizer=tokenizer,
max_seq_length=args.max_seq_length)
train_ds = train_ds.map(trans_func)
interpret_ds = interpret_ds.map(trans_func)
# Batchify dataset
collate_fn = LocalDataCollatorWithPadding(tokenizer)
train_batch_sampler = BatchSampler(train_ds,
batch_size=args.batch_size,
shuffle=False)
interpret_batch_sampler = BatchSampler(interpret_ds,
batch_size=args.batch_size,
shuffle=False)
train_data_loader = DataLoader(dataset=train_ds,
batch_sampler=train_batch_sampler,
collate_fn=collate_fn)
interpret_data_loader = DataLoader(dataset=interpret_ds,
batch_sampler=interpret_batch_sampler,
collate_fn=collate_fn)
# Classifier_layer_name is the layer name of the last output layer
feature_sim = FeatureSimilarityModel(model,
train_data_loader,
classifier_layer_name="classifier")
# Feature similarity analysis & select sparse data
analysis_result = []
for batch in interpret_data_loader:
analysis_result += feature_sim(batch, sample_num=args.top_k)
with open(os.path.join(args.dataset_dir, args.interpret_result_file),
'w') as f:
for i in range(len(analysis_result)):
f.write("text: " + interpret_ds.data[i]["text"] + '\n')
if 'predict' in interpret_ds.data[i]:
f.write("predict label: " + interpret_ds.data[i]["predict"] +
'\n')
if 'label' in interpret_ds.data[i]:
f.write("label: " + interpret_ds.data[i]["label"] + '\n')
f.write("examples with positive influence\n")
for i, (idx, score) in enumerate(
zip(analysis_result[i].pos_indexes,
analysis_result[i].pos_scores)):
f.write("support{} text: ".format(i + 1) +
train_ds.data[idx]["text"] + '\t' + "label: " +
train_ds.data[idx]["label"] + '\t' + "score: " +
"{:.5f}".format(score) + '\n')
f.close()
if __name__ == "__main__":
find_positive_influence_data()

File diff suppressed because one or more lines are too long

View File

@@ -21,7 +21,7 @@
### 安装PaddleNLP
安装PaddleNLP默认开启百度镜像源来加速下载,如果您使用 HTTP 代理可以关闭(删去 -i https://mirror.baidu.com/pypi/simple),更多关于PaddleNLP安装的详细教程请查见[PaddleNLP快速安装](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/get_started/installation.rst)。
安装PaddleNLP默认开启百度镜像源来加速下载,如果您使用 HTTP 代理可以删去` -i https://mirror.baidu.com/pypi/simple` ,更多关于PaddleNLP安装的详细教程请查见[PaddleNLP快速安装](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/get_started/installation.rst)。
```shell
python3 -m pip install --upgrade paddlenlp -i https://mirror.baidu.com/pypi/simple

View File

@@ -257,7 +257,7 @@ python -u -m paddle.distributed.launch --gpus 0,1,2,3 train.py \
可配置参数说明:
- `model_name_or_path`: 内置模型名,或者模型参数配置目录路径。默认为`ernie-3.0-base-zh`。
- `data_dir`: 训练数据集路径,数据格式要求详见[数据准备](数据准备)。
- `data_dir`: 训练数据集路径,数据格式要求详见[数据标注](#数据标注)。
- `output_dir`: 模型参数、训练日志和静态图导出的保存目录。
- `prompt`: 提示模板。定义了如何将文本和提示拼接结合。
- `soft_encoder`: 提示向量的编码器,`lstm`表示双向LSTM, `mlp`表示双层线性层, None表示直接使用提示向量。默认为`lstm`。
@@ -282,7 +282,7 @@ python -u -m paddle.distributed.launch --gpus 0,1,2,3 train.py \
- `evaluation_strategy`: 模型评估的间隔策略。若为`epoch`,则每轮训练结束后评估模型。
- `save_strategy`: 模型保存的间隔策略。若为`epoch`,则每轮训练结束后保存当前模型参数。
更多参数介绍可参考[配置文件](../../../../paddlenlp/trainer/trainer_args.py)。
更多参数介绍可参考[配置文件](https://paddlenlp.readthedocs.io/zh/latest/trainer.html)。
<a name="模型评估"></a>

View File

@@ -99,14 +99,14 @@ pip install -r requirements.txt
**训练、开发、测试数据集**
train.txt(训练数据集文件), dev.txt(开发数据集文件),test.txt(可选,测试数据集文件),文件中文本与标签类别名用tab符`'\t'`分隔开,标签中多个标签之间用`','`英文逗号分隔开。训练集指用于训练模型的数据;开发集指用于评测模型表现的数据,可以根据模型在开发集上的精度调整训练参数和模型;测试集用于测试模型表现,没有测试集时可以使用开发集代替。
train.txt(训练数据集文件), dev.txt(开发数据集文件),test.txt(可选,测试数据集文件),文件中文本与标签类别名用tab符`'\t'`分隔开,层次标签之间用`'##'`号分隔开。训练集指用于训练模型的数据;开发集指用于评测模型表现的数据,可以根据模型在开发集上的精度调整训练参数和模型;测试集用于测试模型表现,没有测试集时可以使用开发集代替。
**注意文本中不能包含tab符`'\t'`**。
- train.txt/dev.txt/test.txt 文件格式:
```text
<文本>'\t'<标签>','<标签>','<标签>
<文本>'\t'<标签>','<标签>
<文本>'\t'<标签>'##'<标签>'##'<标签>
<文本>'\t'<标签>'##'<标签>
...
...
```
@@ -121,7 +121,7 @@ train.txt(训练数据集文件), dev.txt(开发数据集文件),test.txt(
```
**分类标签**
label.txt(层次分类标签文件)记录数据集中所有标签路径集合,在标签路径中,高层的标签指向底层标签,标签之间用`'##'`连接。
label.txt(层次分类标签文件)记录数据集中所有标签路径集合,层次标签之间用`'##'`连接即可,标签的行先后顺序对结果没有影响。
- label.txt 文件格式:
@@ -136,13 +136,11 @@ label.txt(层次分类标签文件)记录数据集中所有标签路径集合,
```
- label.txt 文件样例:
```text
体育/运动##游泳
电脑/网络##程序设计
健康##整形美容##胸部整形
教育/科学##外语学习##日语
教育/科学
教育/科学##院校信息
教育/科学##外语学习##英语考试
教育/科学##理工学科##生物学
教育/科学##职业教育##会计资格考试
健康##内科##呼吸内科
生活##美食/烹饪##餐厅/酒店
...
```
@@ -191,7 +189,7 @@ python -u -m paddle.distributed.launch --gpus "0,1" \
--recall_result_file "recall_result.txt" \
--train_set_file ${data_path}/train.txt \
--corpus_file ${data_path}/label.txt \
--similar_text_pair ${data_path}/dev.txt \
--similar_text_pair_file ${data_path}/dev.txt \
--evaluate True
```
@@ -215,7 +213,6 @@ python -u -m paddle.distributed.launch --gpus "0,1" \
* `recall_num`: 对 1 个文本召回的相似文本数量
* `similar_text_pair`: 由相似文本对构成的评估集
* `corpus_file`: 召回库数据 corpus_file
* `similar_text_pair`: 由相似文本对构成的评估集
也可以使用bash脚本:

View File

@@ -31,5 +31,5 @@ python -u -m paddle.distributed.launch --gpus "0,1" \
--recall_result_file "recall_result.txt" \
--train_set_file ${data_path}/train.txt \
--corpus_file ${data_path}/label.txt \
--similar_text_pair ${data_path}/dev.txt \
--similar_text_pair_file ${data_path}/dev.txt \
--evaluate True

View File

@@ -37,7 +37,7 @@
- 【标注成本高、标注样本较少的小样本场景】 👉 [提示学习多分类方案](./few-shot#readme)
- 【标签类别不固定场景】 👉 [语义索引多分类方案](./retrieval_based#readme)
- 【标签类别不固定场景、标签类别众多】 👉 [语义索引多分类方案](./retrieval_based#readme)
<a name="快速开始"></a>
@@ -95,20 +95,13 @@ python3 -m pip install scikit-learn==1.0.2
```text
multi_class/
├── few-shot # 小样本学习方案
├── retrieval_based # 语义索引方案
├── analysis # 分析模块
├── deploy # 部署
│   └── predictor # 离线部署
│   │ ├── infer.py # 测试脚本
│   │ ├── predictor.py 离线部署脚本
│   │ └── README.md # 离线部署使用说明
│ ├── paddle_serving # PaddleServing在线服务化部署
│   │ ├──config.yml # 服务端的配置文件
│   │ ├──rpc_client.py # 客户端预测脚本
│   │ ├──service.py # 服务端的脚本
│   │ └── README.md # 在线服务化部署使用说明
│   └── triton_serving # Triton在线服务化部署
│ ├── README.md # Triton部署使用说明
│ ├── seqcls_grpc_client.py # 客户端预测脚本
│   └── models
├── train.py # 训练评估脚本
├── predict.py # 预测脚本
├── export_model.py # 静态图模型导出脚本
@@ -132,7 +125,7 @@ data/
└── data.txt # 待预测数据文件
```
**训练、开发、测试数据集** 文件中文本与标签类别名用tab符`'\t'`分隔开。
**训练、开发、测试数据集** 文件中文本与标签类别名用tab符`'\t'`分隔开,文本中避免出现tab符`'\t'`。
- train.txt/dev.txt/test.txt 文件格式:
```text
@@ -273,10 +266,16 @@ checkpoint/
#### 2.4.2 训练评估与模型优化
训练后的模型我们可以使用 [模型分析模块](./analysis) 对每个类别分别进行评估,并输出预测错误样本(bad case),默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`:
文本分类预测过程中常会遇到诸如"模型为什么会预测出错误的结果","如何提升模型的表现"等问题。[Analysis模块](./analysis) 提供了**模型评估、可解释性分析、数据优化**等功能,旨在帮助开发者更好地分析文本分类模型预测结果和对模型效果进行优化。
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/195241942-70068989-df17-4f53-9f71-c189d8c5c88d.png" width="600">
</div>
**模型评估:** 训练后的模型我们可以使用 [Analysis模块](./analysis) 对每个类别分别进行评估,并输出预测错误样本(bad case),默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`:
```shell
python analysis/evaluate.py --device "gpu" --max_seq_length 128 --batch_size 32 --bad_case_path "./bad_case.txt" --dataset_dir "data" --params_path "./checkpoint"
python analysis/evaluate.py --device "gpu" --max_seq_length 128 --batch_size 32 --bad_case_file "bad_case.txt" --dataset_dir "data" --params_path "./checkpoint"
```
输出打印示例:
@@ -301,15 +300,40 @@ python analysis/evaluate.py --device "gpu" --max_seq_length 128 --batch_size 32
预测错误的样本保存在bad_case.txt文件中:
```text
Confidence Prediction Label Text
0.77 注意事项 其他 您好,请问一岁三个月的孩子可以服用复方锌布颗粒吗?
0.94 就医建议 其他 输卵管粘连的基本检查
0.78 病情诊断 其他 经常干呕恶心,这是生病了吗
0.79 后果表述 其他 吃左旋肉碱后的不良反应
Text Label Prediction
您好,请问一岁三个月的孩子可以服用复方锌布颗粒吗? 其他 注意事项
输卵管粘连的基本检查 其他 就医建议
会是胎动么? 其他 病情诊断
经常干呕恶心,这是生病了吗 其他 病情诊断
菏泽哪个医院治疗白癜风比较好?怎么治好 就医建议 治疗方案
...
```
模型表现常常受限于数据质量,在analysis模块中我们提供了基于[TrustAI](https://github.com/PaddlePaddle/TrustAI)的稀疏数据筛选、脏数据清洗、数据增强三种优化方案助力开发者提升模型效果,更多模型评估和优化方案细节详见[训练评估与模型优化指南](analysis/README.md)。
**可解释性分析:** 基于[TrustAI](https://github.com/PaddlePaddle/TrustAI)提供单词和句子级别的模型可解释性分析,帮助理解模型预测结果,用于错误样本(bad case)分析,细节详见[训练评估与模型优化指南](analysis/README.md)。
- 单词级别可解释性分析,也即分析待预测样本中哪一些单词对模型预测结果起重要作用。以下图为例,用颜色深浅表示单词对预测结果的重要性。
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/195086276-6ee16e96-4ec3-4a0f-821f-37546d21746b.png" width="1000">
</div>
- 句子级别可解释性分析 ,也即分析对待预测样本的模型预测结果与训练集中中哪些样本有重要关系。下面的例子表明句子级别可解释性分析可以帮助理解待预测样本的预测结果与训练集中样本之间的关联。
```text
text: 您好,请问一岁三个月的孩子可以服用复方锌布颗粒吗?
predict label: 注意事项
label: 其他
examples with positive influence
support1 text: 感冒期间钙产品要继续服用吗? 钙尔奇就可以,也可以吃婴儿吃的乳钙 label: 注意事项 score: 0.96602
support2 text: 打喷嚏可以吃布洛芬缓释胶囊么 label: 注意事项 score: 0.95687
support3 text: 孕后期可以足疗吗 label: 注意事项 score: 0.94021
...
```
**数据优化:** 结合[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[数据增强API](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/dataaug.md)提供了**稀疏数据筛选、脏数据清洗、数据增强**三种优化策略,从多角度优化训练数据提升模型效果,策略细节详见[训练评估与模型优化指南](analysis/README.md)。
- 稀疏数据筛选主要是解决数据不均衡、训练数据覆盖不足的问题,通过数据增强和数据标注两种方式解决这一问题。
- 脏数据清洗可以帮助开发者筛选训练集中错误标注的数据,对这些数据重新进行人工标注,得到标注正确的数据再重新进行训练。
- 数据增强策略提供多种数据增强方案,可以快速扩充数据,提高模型泛化性和鲁棒性。
#### 2.4.3 模型预测
训练结束后,输入待预测数据(data.txt)和类别标签对照列表(label.txt),使用训练好的模型进行,默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`:
@@ -338,7 +362,7 @@ python predict.py --device "gpu" --max_seq_length 128 --batch_size 32 --dataset_
python export_model.py --params_path ./checkpoint/ --output_path ./export
```
如果使用ERNIE M作为预训练模型,运行方式:
如果使用多语言模型 ERNIE M作为预训练模型,运行方式:
```shell
python export_model.py --params_path ./checkpoint/ --output_path ./export --multilingual
```
@@ -421,7 +445,6 @@ prune/
3. ERNIE Base、Medium、Mini、Micro、Nano的模型宽度(multi head数量)为12,ERNIE Xbase、Large 模型宽度(multi head数量)为16,保留比例`width_mult`乘以宽度(multi haed数量)应为整数。
4. **压缩API暂不支持多语言预训练模型ERNIE-M**,相关功能正在加紧开发中。
#### 2.5.3 部署方案

View File

@@ -1,18 +1,29 @@
# 多分类训练评估与模型优化指南
# 训练评估与模型优化指南
**目录**
* [analysis模块介绍](#analysis模块介绍)
* [Analysis模块介绍](#Analysis模块介绍)
* [环境准备](#环境准备)
* [模型评估](#模型评估)
* [稀疏数据筛选方案](#稀疏数据筛选方案)
* [脏数据清洗方案](#脏数据清洗方案)
* [数据增强策略方案](#数据增强策略方案)
* [可解释性分析](#可解释性分析)
* [单词级别可解释性分析](#单词级别可解释性分析)
* [句子级别可解释性分析](#句子级别可解释性分析)
* [数据优化](#数据优化)
* [稀疏数据筛选方案](#稀疏数据筛选方案)
* [脏数据清洗方案](#脏数据清洗方案)
* [数据增强策略方案](#数据增强策略方案)
## analysis模块介绍
## Analysis模块介绍
analysis模块提供了**模型评估**脚本对整体分类情况和每个类别分别进行评估,并打印预测错误样本,帮助开发者分析模型表现找到训练和预测数据中存在的问题问题。同时基于[可信AI工具集](https://github.com/PaddlePaddle/TrustAI)和[数据增强API](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/dataaug.md)提供了**稀疏数据筛选、脏数据清洗、数据增强**三种优化方案从多角度帮助开发者提升模型效果。
Analysis模块提供了**模型评估、可解释性分析、数据优化**等功能,旨在帮助开发者更好地分析文本分类模型预测结果和对模型效果进行优化。
- **模型评估:** 对整体分类情况和每个类别分别进行评估,并打印预测错误样本,帮助开发者分析模型表现找到训练和预测数据中存在的问题。
- **可解释性分析:** 基于[TrustAI](https://github.com/PaddlePaddle/TrustAI)提供单词和句子级别的模型可解释性分析,帮助理解模型预测结果。
- **数据优化:** 结合[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[数据增强API](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/dataaug.md)提供了**稀疏数据筛选、脏数据清洗、数据增强**三种优化策略,从多角度优化训练数据提升模型效果。
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/184790352-7f91da02-aadd-48fe-9130-8323a89c6a43.jpg" width="600">
<img src="https://user-images.githubusercontent.com/63761690/195241942-70068989-df17-4f53-9f71-c189d8c5c88d.png" width="600">
</div>
以下是本项目主要代码结构及说明:
@@ -20,10 +31,27 @@ analysis模块提供了**模型评估**脚本对整体分类情况和每个类
```text
analysis/
├── evaluate.py # 评估脚本
├── sent_interpret.py # 句子级别可解释性分析脚本
├── word_interpret.py # 单词级别可解释性分析notebook
├── sparse.py # 稀疏数据筛选脚本
├── dirty.py # 脏数据清洗脚本
├── aug.py # 数据增强脚本
└── README.md # 多分类训练评估与模型优化指南
└── README.md # 训练评估与模型优化指南
```
## 环境准备
需要可解释性分析和数据优化需要安装相关环境。
- trustai >= 0.1.7
- interpretdl >= 0.7.0
**安装TrustAI**(可选)如果使用可解释性分析和数据优化中稀疏数据筛选和脏数据清洗需要安装TrustAI。
```shell
pip install trustai==0.1.7
```
**安装InterpretDL**(可选)如果使用词级别可解释性分析GradShap方法,需要安装InterpretDL
```shell
pip install interpretdl==0.7.0
```
## 模型评估
@@ -37,14 +65,14 @@ python evaluate.py \
--params_path "../checkpoint" \
--max_seq_length 128 \
--batch_size 32 \
--bad_case_path "./bad_case.txt"
--bad_case_file "bad_case.txt"
```
默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`
可支持配置的参数:
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含train.txt、dev.txt和label.txt文件;默认为None。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
* `max_seq_length`:分词器tokenizer使用的最大序列长度,ERNIE模型最大不能超过2048。请根据文本长度选择,通常推荐128、256或512,若出现显存不足,请适当调低这一参数;默认为128。
@@ -76,30 +104,109 @@ python evaluate.py \
预测错误的样本保存在bad_case.txt文件中:
```text
Confidence Prediction Label Text
0.77 注意事项 其他 您好,请问一岁三个月的孩子可以服用复方锌布颗粒吗?
0.94 就医建议 其他 输卵管粘连的基本检查
0.78 病情诊断 其他 经常干呕恶心,这是生病了吗
0.79 后果表述 其他 吃左旋肉碱后的不良反应
Text Label Prediction
您好,请问一岁三个月的孩子可以服用复方锌布颗粒吗? 其他 注意事项
输卵管粘连的基本检查 其他 就医建议
会是胎动么? 其他 病情诊断
经常干呕恶心,这是生病了吗 其他 病情诊断
菏泽哪个医院治疗白癜风比较好?怎么治好 就医建议 治疗方案
...
```
## 稀疏数据筛选方案
## 可解释性分析
"模型为什么会预测出这个结果?"是文本分类任务开发者时常遇到的问题,如何分析错误样本(bad case)是文本分类任务落地中重要一环,本项目基于TrustAI开源了基于词级别和句子级别的模型可解释性分析方法,帮助开发者更好地理解文本分类模型与数据,有助于后续的模型优化与数据清洗标注。
稀疏数据指缺乏足够训练数据支持导致低置信度的待预测数据,简单来说,由于模型在训练过程中没有学习到足够与待预测样本相似的数据,模型难以正确预测样本所属类别。本项目中稀疏数据筛选基于TrustAI(可信AI)工具集,利用基于特征相似度的实例级证据分析方法,抽取开发集中样本的支持训练证据,并计算支持证据平均分(通常为得分前三的支持训练证据均分)。分数较低的样本表明其训练证据不足,在训练集中较为稀疏,实验表明模型在这些样本上表现也相对较差。更多细节详见[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[实例级证据分析](https://github.com/PaddlePaddle/TrustAI/blob/main/trustai/interpretation/example_level/README.md)。
### 单词级别可解释性分析
本项目开源模型的词级别可解释性分析Notebook,提供LIME、Integrated Gradient、GradShap 三种分析方法,支持分析微调后模型的预测结果,开发者可以通过更改**数据目录**和**模型目录**在自己的任务中使用Jupyter Notebook进行数据分析。
稀疏数据筛选旨在开发集中挖掘缺乏训练证据支持的稀疏数据,通常可以采用**数据增强**或**少量数据标注**的两种低成本方式,提升模型预测效果。
运行 [word_interpret.ipynb](./word_interpreter.ipynb) 代码,即可分析影响样本预测结果的关键词以及可视化所有词对预测结果的贡献情况,颜色越深代表这个词对预测结果影响越大:
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/192739675-63145d59-23c6-416f-bf71-998fd4995254.png" width="1000">
</div>
**安装TrustAI**
```shell
pip install trustai==0.1.4
### 句子级别可解释性分析
本项目基于特征相似度([FeatureSimilarity](https://arxiv.org/abs/2104.04128))算法,计算对样本预测结果正影响的训练数据,帮助理解模型的预测结果与训练集数据的关系。
待分析数据文件`interpret_input_file`应为以下三种格式中的一种:
**格式一:包括文本、标签、预测结果**
```text
<文本>'\t'<标签>'\t'<预测结果>
...
```
### 稀疏数据识别--数据增强
**格式二:包括文本、标签**
```text
<文本>'\t'<标签>
...
```
这里我们将介绍稀疏数据识别--数据增强流程,首先使用数据增强脚本挖掘开发集中的稀疏数据,然后筛选训练集中对稀疏数据的支持数据进行数据增强,然后将得到的数据增强后的支持数据加入到训练集中进行训练。
**格式三:只包括文本**
```text
<文本>
准予原告胡某甲与被告韩某甲离婚。
...
```
现在我们进行稀疏数据识别--数据增强,得到新增训练数据:
我们可以运行代码,得到支持样本模型预测结果的训练数据:
```shell
python sent_interpret.py \
--device "gpu" \
--dataset_dir "../data" \
--params_path "../checkpoint/" \
--max_seq_length 128 \
--batch_size 16 \
--top_k 3 \
--train_file "train.txt" \
--interpret_input_file "bad_case.txt" \
--interpret_result_file "sent_interpret.txt"
```
默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`
可支持配置的参数:
* `device`: 选用什么设备进行训练,可可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含dev.txt和label.txt文件;默认为None。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
* `max_seq_length`:分词器tokenizer使用的最大序列长度,ERNIE模型最大不能超过2048。请根据文本长度选择,通常推荐128、256或512,若出现显存不足,请适当调低这一参数;默认为128。
* `batch_size`:批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为32。
* `seed`:随机种子,默认为3。
* `top_k`:筛选支持训练证据数量;默认为3。
* `train_file`:本地数据集中训练集文件名;默认为"train.txt"。
* `interpret_input_file`:本地数据集中待分析文件名;默认为"bad_case.txt"。
* `interpret_result_file`:保存句子级别可解释性结果文件名;默认为"sent_interpret.txt"。
可解释性结果保存在 `interpret_result_file` 文件中:
```text
text: 您好,请问一岁三个月的孩子可以服用复方锌布颗粒吗?
predict label: 注意事项
label: 其他
examples with positive influence
support1 text: 感冒期间钙产品要继续服用吗? 钙尔奇就可以,也可以吃婴儿吃的乳钙 label: 注意事项 score: 0.96602
support2 text: 打喷嚏可以吃布洛芬缓释胶囊么 label: 注意事项 score: 0.95687
support3 text: 孕后期可以足疗吗 label: 注意事项 score: 0.94021
...
```
## 数据优化
### 稀疏数据筛选方案
稀疏数据筛选适用于文本分类中**数据不平衡或训练数据覆盖不足**的场景,简单来说,就是由于模型在训练过程中没有学习到足够与待预测样本相似的数据,模型难以正确预测样本所属类别的情况。稀疏数据筛选旨在开发集中挖掘缺乏训练证据支持的数据,通常可以采用**数据增强**或**少量数据标注**的两种低成本方式,提升模型在开发集的预测效果。
本项目中稀疏数据筛选基于TrustAI,利用基于特征相似度的实例级证据分析方法,抽取开发集中样本的支持训练证据,并计算支持证据平均分(通常为得分前三的支持训练证据均分)。分数较低的样本表明其训练证据不足,在训练集中较为稀疏,实验表明模型在这些样本上表现也相对较差。更多细节详见[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[实例级证据分析](https://github.com/PaddlePaddle/TrustAI/blob/main/trustai/interpretation/example_level/README.md)。
#### 稀疏数据识别—数据增强
这里我们将介绍稀疏数据识别—数据增强流程:
- **稀疏数据识别:** 挖掘开发集中的缺乏训练证据支持数据,记为稀疏数据集(Sparse Dataset);
- **数据增强**:将稀疏数据集在训练集中的支持证据应用数据增强策略,这些数据增强后的训练数据记为支持数据集(Support Dataset);
- **重新训练模型:** 将支持数据集加入到原有的训练集获得新的训练集,重新训练新的文本分类模型。
现在我们进行稀疏数据识别-数据增强,得到支持数据集:
```shell
python sparse.py \
@@ -117,7 +224,7 @@ python sparse.py \
可支持配置的参数:
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含dev.txt和label.txt文件;默认为None。
* `aug_strategy`:数据增强类型,可选"duplicate","substitute", "insert", "delete", "swap";默认为"substitute"。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
@@ -153,9 +260,15 @@ cat ../data/train.txt ../data/support.txt > ../data/train_sparse_aug.txt
|训练集+支持增强集(delete) |74.27|
|训练集+支持增强集(swap) |73.66|
### 稀疏数据识别--数据标注
#### 稀疏数据识别-数据标注
这里我们将介绍稀疏数据识别--数据标注流程,首先使用数据增强脚本挖掘开发集中的稀疏数据,然后筛选对稀疏数据支持的未标注数据,然后将得到支持数据进行标注后加入到训练集中进行训练。
本方案能够有针对性进行数据标注,相比于随机标注数据更好提高模型预测效果。这里我们将介绍稀疏数据识别-数据标注流程:
- **稀疏数据识别:** 挖掘开发集中的缺乏训练证据支持数据,记为稀疏数据集(Sparse Dataset);
- **数据标注**:在未标注数据集中筛选稀疏数据集的支持证据,并进行数据标注,记为支持数据集(Support Dataset);
- **重新训练模型:** 将支持数据集加入到原有的训练集获得新的训练集,重新训练新的文本分类模型。
现在我们进行稀疏数据识别--数据标注,得到待标注数据:
@@ -176,7 +289,7 @@ python sparse.py \
可支持配置的参数:
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含dev.txt和label.txt文件;默认为None。
* `annotate`:选择稀疏数据识别--数据标注模式;默认为False。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
@@ -213,14 +326,13 @@ cat ../data/train.txt ../data/support.txt > ../data/train_sparse_annotate.txt
|训练集+策略采样集(100) |**77.64**|
|训练集+随机采样集(100) |76.37|
## 脏数据清洗方案
### 脏数据清洗方案
训练数据标注质量对模型效果有较大影响,但受限于标注人员水平、标注任务难易程度等影响,训练数据中都存在一定比例的标注较差的数据(脏数据)。当标注数据规模较大时,数据标注检查就成为一个难题。本项目中脏数据清洗基于TrustAI(可信AI)工具集,利用基于表示点方法的实例级证据分析方法,计算训练数据对模型的影响分数,分数高的训练数据表明对模型影响大,这些数据有较大概率为脏数据(标注错误样本)。更多细节详见[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[实例级证据分析](https://github.com/PaddlePaddle/TrustAI/blob/main/trustai/interpretation/example_level/README.md)。
脏数据清洗方案是基于已训练好的文本分类模型,筛选出训练数据集中标注错误的数据,再由人工检查重新标注,获得标注正确的数据集进行重新训练。我们将介绍脏数据清洗流程:
**安装TrustAI**
```shell
pip install trustai==0.1.4
```
- **脏数据筛选:** 基于TrustAI中表示点方法,计算训练数据对文本分类模型的影响分数,分数高的训练数据表明对模型影响大,这些数据有较大概率为标注错误样本,记为脏数据集(Dirty Dataset)。
- **数据清洗、训练:** 将筛选出的脏数据由人工重新检查,为数据打上正确的标签。将清洗后的训练数据重新放入文本分类模型进行训练。
现在我们进行脏数据识别,脏数据保存在`"train_dirty.txt"`,剩余训练数据保存在`"train_dirty_rest.txt"`:
@@ -243,7 +355,7 @@ python dirty.py \
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含train.txt和label.txt文件;默认为None。
* `max_seq_length`:分词器tokenizer使用的最大序列长度,ERNIE模型最大不能超过2048。请根据文本长度选择,通常推荐128、256或512,若出现显存不足,请适当调低这一参数;默认为128。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `batch_size`:批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为32。
* `seed`:随机种子,默认为3。
* `dirty_file`:保存脏数据文件名,默认为"train_dirty.txt"。
@@ -252,7 +364,7 @@ python dirty.py \
* `dirty_threshold`:筛选脏数据用于重新标注的阈值,只选择影响分数大于阈值作为支持数据,默认为0。
我们将筛选出脏数据进行重新标注,可以将`train_dirty.txt`直接导入标注工具doccano帮助更快重新标注,详情请参考[文本分类任务doccano数据标注使用指南](../../doccano.md)进行文本分类数据标注。然后将已重新标注的脏数据`train_dirty.txt`与剩余训练集数据`train_dirty_rest.txt`合并得到新的训练集`train_clean.txt`重新进行训练:
我们将筛选出脏数据进行人工检查重新标注,可以将`train_dirty.txt`直接导入标注工具doccano帮助更快重新标注,详情请参考[文本分类任务doccano数据标注使用指南](../../doccano.md)进行文本分类数据标注。然后将已重新标注的脏数据`train_dirty.txt`与剩余训练集数据`train_dirty_rest.txt`合并得到新的训练集`train_clean.txt`重新进行训练:
```shell
cat ../data/train_dirty_rest.txt ../data/train_dirty.txt > ../data/train_clean.txt
@@ -270,7 +382,7 @@ cat ../data/train_dirty_rest.txt ../data/train_dirty.txt > ../data/train_clean.t
|训练集(500,含100条脏数据) + 脏数据清洗(100)|69.36|
|训练集(500,含100条脏数据) + 脏数据清洗(150)|73.15|
## 数据增强策略方案
### 数据增强策略方案
在数据量较少或某些类别样本量较少时,也可以通过数据增强策略的方式,生成更多的训练数据,提升模型效果。
@@ -290,7 +402,7 @@ python aug.py \
* `aug_type`:词替换/词插入增强类型,可选"synonym", "homonym", "mlm",建议在GPU环境下使用mlm类型;默认为"synonym"。
* `create_n`:生成的句子数量,默认为2。
* `aug_percent`:生成词替换百分比,默认为0.1。
* `device`: 选用什么设备进行增强,选择cpu、gpu、xpu、npu,仅在使用mlm类型有影响;默认为"gpu"。
* `device`: 选用什么设备进行增强,可选择cpu、gpu、xpu、npu,仅在使用mlm类型有影响;默认为"gpu"。
生成的增强数据保存在`"aug.txt"`文件中,与训练集数据`train.txt`合并得到新的训练集`train_aug.txt`重新进行训练:

View File

@@ -37,7 +37,7 @@ parser.add_argument("--batch_size", default=32, type=int, help="Batch size per G
parser.add_argument("--train_file", type=str, default="train.txt", help="Train dataset file name")
parser.add_argument("--dev_file", type=str, default="dev.txt", help="Dev dataset file name")
parser.add_argument("--label_file", type=str, default="label.txt", help="Label file name")
parser.add_argument("--bad_case_path", type=str, default="./bad_case.txt", help="Bad case saving file path")
parser.add_argument("--bad_case_file", type=str, default="bad_case.txt", help="Bad case saving file name")
args = parser.parse_args()
# yapf: enable
@@ -192,17 +192,16 @@ def evaluate():
logger.info("Evaluation examples in dev dataset: 0 (0%)")
logger.info("----------------------------")
with open(args.bad_case_path, 'w', encoding="utf-8") as f:
f.write("Confidence\tPrediction\tLabel\tText\n")
bad_case_path = os.path.join(args.dataset_dir, args.bad_case_file)
with open(bad_case_path, 'w', encoding="utf-8") as f:
f.write("Text\tLabel\tPrediction\n")
for i, (p, l) in enumerate(zip(preds, labels)):
p, l = int(p), int(l)
if p != l:
f.write("{:.2f}".format(probs[i][p]) + "\t" + label_list[p] +
"\t" + label_list[l] + "\t" + dev_ds.data[i]["text"] +
"\n")
f.write(dev_ds.data[i]["text"] + "\t" + label_list[l] + "\t" +
label_list[p] + "\n")
f.close()
logger.info("Bad case in dev dataset saved in {}".format(
args.bad_case_path))
logger.info("Bad case in dev dataset saved in {}".format(bad_case_path))
return

View File

@@ -0,0 +1,172 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import functools
import random
import os
import argparse
import numpy as np
import paddle
import paddle.nn.functional as F
from paddle.io import DataLoader, BatchSampler
from paddlenlp.data import DataCollatorWithPadding
from paddlenlp.datasets import load_dataset
from paddlenlp.transformers import AutoModelForSequenceClassification, AutoTokenizer, LinearDecayWithWarmup
from paddlenlp.utils.log import logger
from trustai.interpretation import FeatureSimilarityModel
# yapf: disable
parser = argparse.ArgumentParser()
parser.add_argument('--device', default="gpu", help="Select which device to train model, defaults to gpu.")
parser.add_argument("--dataset_dir", required=True, type=str, help="The dataset directory should include train.txt,dev.txt and test.txt files.")
parser.add_argument("--params_path", default="../checkpoint/", type=str, help="The path to model parameters to be loaded.")
parser.add_argument("--max_seq_length", default=128, type=int, help="The maximum total input sequence length after tokenization. Sequences longer than this will be truncated, sequences shorter will be padded.")
parser.add_argument("--batch_size", default=16, type=int, help="Batch size per GPU/CPU for training.")
parser.add_argument("--seed", type=int, default=3, help="random seed for initialization")
parser.add_argument("--top_k", type=int, default=3, help="Top K important training data.")
parser.add_argument("--train_file", type=str, default="train.txt", help="Train dataset file name")
parser.add_argument("--interpret_input_file", type=str, default="bad_case.txt", help="interpretation file name")
parser.add_argument("--interpret_result_file", type=str, default="sent_interpret.txt", help="interpreted file name")
args = parser.parse_args()
# yapf: enable
def set_seed(seed):
"""
Set random seed
"""
random.seed(seed)
np.random.seed(seed)
paddle.seed(seed)
os.environ['PYTHONHASHSEED'] = str(seed)
def read_local_dataset(path):
"""
Read dataset file
"""
with open(path, 'r', encoding='utf-8') as f:
for line in f:
items = line.strip().split('\t')
if items[0] == 'Text':
continue
if len(items) == 3:
yield {'text': items[0], 'label': items[1], 'predict': items[2]}
elif len(items) == 2:
yield {'text': items[0], 'label': items[1], 'predict': ''}
elif len(items) == 1:
yield {'text': items[0], 'label': '', 'predict': ''}
else:
logger.info(line.strip())
raise ValueError("{} should be in fixed format.".format(path))
def preprocess_function(examples, tokenizer, max_seq_length):
"""
Preprocess dataset
"""
result = tokenizer(text=examples["text"], max_seq_len=max_seq_length)
return result
class LocalDataCollatorWithPadding(DataCollatorWithPadding):
"""
Convert the result of DataCollatorWithPadding from dict dictionary to a list
"""
def __call__(self, features):
batch = super().__call__(features)
batch = list(batch.values())
return batch
def find_positive_influence_data():
set_seed(args.seed)
paddle.set_device(args.device)
# Define model & tokenizer
if os.path.exists(os.path.join(
args.params_path, "model_state.pdparams")) and os.path.exists(
os.path.join(args.params_path,
"model_config.json")) and os.path.exists(
os.path.join(args.params_path,
"tokenizer_config.json")):
model = AutoModelForSequenceClassification.from_pretrained(
args.params_path)
tokenizer = AutoTokenizer.from_pretrained(args.params_path)
else:
raise ValueError("The {} should exist.".format(args.params_path))
# Prepare & preprocess dataset
train_path = os.path.join(args.dataset_dir, args.train_file)
interpret_path = os.path.join(args.dataset_dir, args.interpret_input_file)
train_ds = load_dataset(read_local_dataset, path=train_path, lazy=False)
interpret_ds = load_dataset(read_local_dataset,
path=interpret_path,
lazy=False)
trans_func = functools.partial(preprocess_function,
tokenizer=tokenizer,
max_seq_length=args.max_seq_length)
train_ds = train_ds.map(trans_func)
interpret_ds = interpret_ds.map(trans_func)
# Batchify dataset
collate_fn = LocalDataCollatorWithPadding(tokenizer)
train_batch_sampler = BatchSampler(train_ds,
batch_size=args.batch_size,
shuffle=False)
interpret_batch_sampler = BatchSampler(interpret_ds,
batch_size=args.batch_size,
shuffle=False)
train_data_loader = DataLoader(dataset=train_ds,
batch_sampler=train_batch_sampler,
collate_fn=collate_fn)
interpret_data_loader = DataLoader(dataset=interpret_ds,
batch_sampler=interpret_batch_sampler,
collate_fn=collate_fn)
# Classifier_layer_name is the layer name of the last output layer
feature_sim = FeatureSimilarityModel(model,
train_data_loader,
classifier_layer_name="classifier")
# Feature similarity analysis & select sparse data
analysis_result = []
for batch in interpret_data_loader:
analysis_result += feature_sim(batch, sample_num=args.top_k)
with open(os.path.join(args.dataset_dir, args.interpret_result_file),
'w') as f:
for i in range(len(analysis_result)):
f.write("text: " + interpret_ds.data[i]["text"] + '\n')
if 'predict' in interpret_ds.data[i]:
f.write("predict label: " + interpret_ds.data[i]["predict"] +
'\n')
if 'label' in interpret_ds.data[i]:
f.write("label: " + interpret_ds.data[i]["label"] + '\n')
f.write("examples with positive influence\n")
for i, (idx, score) in enumerate(
zip(analysis_result[i].pos_indexes,
analysis_result[i].pos_scores)):
f.write("support{} text: ".format(i + 1) +
train_ds.data[idx]["text"] + '\t' + "label: " +
train_ds.data[idx]["label"] + '\t' + "score: " +
"{:.5f}".format(score) + '\n')
f.close()
if __name__ == "__main__":
find_positive_influence_data()

File diff suppressed because one or more lines are too long

View File

@@ -21,7 +21,8 @@
### 安装PaddleNLP
安装PaddleNLP默认开启百度镜像源来加速下载,如果您使用 HTTP 代理可以关闭(删去 -i https://mirror.baidu.com/pypi/simple),更多关于PaddleNLP安装的详细教程请查见[PaddleNLP快速安装](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/get_started/installation.rst)。
安装PaddleNLP默认开启百度镜像源来加速下载,如果您使用 HTTP 代理可以删去` -i https://mirror.baidu.com/pypi/simple` ,更多关于PaddleNLP安装的详细教程请查见[PaddleNLP快速安装](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/get_started/installation.rst)。
```shell
python3 -m pip install --upgrade paddlenlp -i https://mirror.baidu.com/pypi/simple

View File

@@ -245,7 +245,7 @@ python -u -m paddle.distributed.launch --gpus 0,1,2,3 train.py \
可配置参数说明:
- `model_name_or_path`: 内置模型名,或者模型参数配置目录路径。默认为`ernie-3.0-base-zh`。
- `data_dir`: 训练数据集路径,数据格式要求详见[数据准备](数据准备)。
- `data_dir`: 训练数据集路径,数据格式要求详见[数据标注](#数据标注)。
- `output_dir`: 模型参数、训练日志和静态图导出的保存目录。
- `prompt`: 提示模板。定义了如何将文本和提示拼接结合。
- `soft_encoder`: 提示向量的编码器,`lstm`表示双向LSTM, `mlp`表示双层线性层, None表示直接使用提示向量。默认为`lstm`。
@@ -266,7 +266,7 @@ python -u -m paddle.distributed.launch --gpus 0,1,2,3 train.py \
- `per_device_train_batch_size`: 每次训练每张卡上的样本数量。可根据实际GPU显存适当调小/调大此配置。
- `per_device_eval_batch_size`: 每次评估每张卡上的样本数量。可根据实际GPU显存适当调小/调大此配置。
更多参数介绍可参考[配置文件](../../../../paddlenlp/trainer/trainer_args.py)。
更多参数介绍可参考[配置文件](https://paddlenlp.readthedocs.io/zh/latest/trainer.html)。
<a name="模型评估"></a>
### 3.5 模型评估

View File

@@ -195,7 +195,6 @@ python -u -m paddle.distributed.launch --gpus "0,1" \
* `recall_num`: 对 1 个文本召回的相似文本数量
* `similar_text_pair`: 由相似文本对构成的评估集
* `corpus_file`: 召回库数据 corpus_file
* `similar_text_pair`: 由相似文本对构成的评估集
也可以使用bash脚本:

View File

@@ -37,9 +37,6 @@
- 【标注成本高、标注样本较少的小样本场景】 👉 [提示学习多标签分类方案](./few-shot#readme)
- 【标签类别不固定场景】 👉 [语义索引多标签分类方案](./retrieval_based#readme)
<a name="快速开始"></a>
## 2. 快速开始
@@ -94,20 +91,12 @@ python3 -m pip install scikit-learn==1.0.2
```text
multi_label/
├── few-shot # 小样本学习方案
├── analysis # 分析模块
├── deploy # 部署
│   └── predictor # 离线部署
│   │ ├── infer.py # 测试脚本
│   │ ├── predictor.py 离线部署脚本
│   │ └── README.md # 离线部署使用说明
│ ├── paddle_serving # PaddleServing在线服务化部署
│   │ ├──config.yml # 服务端的配置文件
│   │ ├──rpc_client.py # 客户端预测脚本
│   │ ├──service.py # 服务端的脚本
│   │ └── README.md # 在线服务化部署使用说明
│   └── triton_serving # Triton在线服务化部署
│ ├── README.md # Triton部署使用说明
│ ├── seqcls_grpc_client.py # 客户端预测脚本
│   └── models
├── train.py # 训练评估脚本
├── predict.py # 预测脚本
├── export_model.py # 静态图模型导出脚本
@@ -130,7 +119,7 @@ data/
├── label.txt # 分类标签文件
└── data.txt # 待预测数据文件(可选)
```
**训练、开发、测试数据集**文件中文本与标签类别名用tab符`'\t'`分隔开,标签中多个标签之间用`','`逗号分隔开。
**训练、开发、测试数据集**文件中文本与标签类别名用tab符`'\t'`分隔开,标签中多个标签之间用`','`逗号分隔开,文本中避免出现tab符`'\t'`。
- train.txt/dev.txt/test.txt 文件格式:
```text
@@ -269,10 +258,16 @@ checkpoint/
#### 2.4.2 训练评估与模型优化
训练后的模型我们可以使用 [模型分析模块](./analysis) 对每个类别分别进行评估,并输出预测错误样本(bad case),默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`:
文本分类预测过程中常会遇到诸如"模型为什么会预测出错误的结果","如何提升模型的表现"等问题。[Analysis模块](./analysis) 提供了**模型评估、可解释性分析、数据优化**等功能,旨在帮助开发者更好地分析文本分类模型预测结果和对模型效果进行优化。
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/195241942-70068989-df17-4f53-9f71-c189d8c5c88d.png" width="600">
</div>
**模型评估:** 训练后的模型我们可以使用 [Analysis模块](./analysis) 对每个类别分别进行评估,并输出预测错误样本(bad case),默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`:
```shell
python analysis/evaluate.py --device "gpu" --max_seq_length 128 --batch_size 32 --bad_case_path "./bad_case.txt" --dataset_dir "data" --params_path "./checkpoint"
python analysis/evaluate.py --device "gpu" --max_seq_length 128 --batch_size 32 --bad_case_file "bad_case.txt" --dataset_dir "data" --params_path "./checkpoint"
```
输出打印示例:
@@ -297,15 +292,37 @@ python analysis/evaluate.py --device "gpu" --max_seq_length 128 --batch_size 32
预测错误的样本保存在bad_case.txt文件中:
```text
Prediction Label Text
不动产分割 不动产分割,有夫妻共同财产 2014年,王X以其与肖X协议离婚时未分割该套楼房的首付款为由,起诉至法院,要求分得楼房的首付款15万元。
婚后分居,准予离婚 二次起诉离婚,准予离婚,婚后分居,法定离婚 但原、被告对已建立起的夫妻感情不够珍惜,因琐事即发生吵闹并最终分居,对夫妻感情造成了严重的影响,现原、被告已分居六年有余,且经人民法院判决不准离婚后仍未和好,夫妻感情确已破裂,依法应准予原、被告离婚。
婚后有子女,限制行为能力子女抚养 婚后有子女 婚后生有一女,取名彭某乙,已11岁,现已由被告从铁炉白族乡中心小学转入走马镇李桥小学读书。
婚后分居 不履行家庭义务,婚后分居 2015年2月23日,被告将原告赶出家门,原告居住于娘家待产,双方分居至今。
Text Label Prediction
2014年,王X以其与肖X协议离婚时未分割该套楼房的首付款为由,起诉至法院,要求分得楼房的首付款15万元。 不动产分割,有夫妻共同财产 不动产分割
但原、被告对已建立起的夫妻感情不够珍惜,因琐事即发生吵闹并最终分居,对夫妻感情造成了严重的影响,现原、被告已分居六年有余,且经人民法院判决不准离婚后仍未和好,夫妻感情确已破裂,依法应准予原、被告离婚。 二次起诉离婚,准予离婚,婚后分居,法定离婚 婚后分居,准予离婚
婚后生有一女,取名彭某乙,已11岁,现已由被告从铁炉白族乡中心小学转入走马镇李桥小学读书。 婚后有子女 婚后有子女,限制行为能力子女抚养
...
```
**可解释性分析:** 基于[TrustAI](https://github.com/PaddlePaddle/TrustAI)提供单词和句子级别的模型可解释性分析,帮助理解模型预测结果,用于错误样本(bad case)分析,细节详见[训练评估与模型优化指南](analysis/README.md)。
- 单词级别可解释性分析,也即分析待预测样本中哪一些单词对模型预测结果起重要作用。以下图为例,用颜色深浅表示单词对预测结果的重要性。
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/192739675-63145d59-23c6-416f-bf71-998fd4995254.png" width="1000">
</div>
- 句子级别可解释性分析 ,也即分析对待预测样本的模型预测结果与训练集中中哪些样本有重要关系。下面的例子表明句子级别可解释性分析可以帮助理解待预测样本的预测结果与训练集中样本之间的关联。
```text
text: 2015年2月23日,被告将原告赶出家门,原告居住于娘家待产,双方分居至今。
predict label: 婚后分居
label: 不履行家庭义务,婚后分居
examples with positive influence
support1 text: 2014年中秋节原告回了娘家,原、被告分居至今。 label: 婚后分居 score: 0.99942
support2 text: 原告于2013年8月13日离开被告家,分居至今。 label: 婚后分居 score: 0.99916
support3 text: 2014年4月,被告外出务工,双方分居至今。 label: 婚后分居 score: 0.99902
...
```
模型表现常常受限于数据质量,在analysis模块中我们提供了基于[TrustAI](https://github.com/PaddlePaddle/TrustAI)的稀疏数据筛选、脏数据清洗、数据增强三种优化方案助力开发者提升模型效果,更多模型评估和优化方案细节详见[训练评估与模型优化指南](analysis/README.md)。
**数据优化:** 结合[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[数据增强API](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/dataaug.md)提供了**稀疏数据筛选、脏数据清洗、数据增强**三种优化策略,从多角度优化训练数据提升模型效果,策略细节详见[训练评估与模型优化指南](analysis/README.md)。
- 稀疏数据筛选主要是解决数据不均衡、训练数据覆盖不足的问题,通过数据增强和数据标注两种方式解决这一问题。
- 脏数据清洗可以帮助开发者筛选训练集中错误标注的数据,对这些数据重新进行人工标注,得到标注正确的数据再重新进行训练。
- 数据增强策略提供多种数据增强方案,可以快速扩充数据,提高模型泛化性和鲁棒性。
#### 2.4.3 模型预测
训练结束后,输入待预测数据(data.txt)和类别标签对照列表(label.txt),使用训练好的模型进行,默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`:
@@ -335,12 +352,15 @@ python predict.py --device "gpu" --max_seq_length 128 --batch_size 32 --dataset_
```shell
python export_model.py --params_path ./checkpoint/ --output_path ./export
```
如果使用ERNIE M作为预训练模型,运行方式:
如果使用多语言模型 ERNIE M作为预训练模型,运行方式:
```shell
python export_model.py --params_path ./checkpoint/ --output_path ./export --multilingual
```
可支持配置的参数:
* `multilingual`:是否为多语言任务(是否使用ERNIE M作为预训练模型);默认为False。
* `params_path`:动态图训练保存的参数路径;默认为"./checkpoint/"。
* `output_path`:静态图图保存的参数路径;默认为"./export"。
@@ -417,7 +437,6 @@ prune/
3. ERNIE Base、Medium、Mini、Micro、Nano的模型宽度(multi head数量)为12,ERNIE Xbase、Large 模型宽度(multi head数量)为16,保留比例`width_mult`乘以宽度(multi haed数量)应为整数。
4. **压缩API暂不支持多语言预训练模型ERNIE-M**,相关功能正在加紧开发中。
#### 2.5.3 部署方案

View File

@@ -1,18 +1,29 @@
# 多标签训练评估与模型优化指南
# 训练评估与模型优化指南
**目录**
* [analysis模块介绍](#analysis模块介绍)
* [Analysis模块介绍](#Analysis模块介绍)
* [环境准备](#环境准备)
* [模型评估](#模型评估)
* [稀疏数据筛选方案](#稀疏数据筛选方案)
* [脏数据清洗方案](#脏数据清洗方案)
* [数据增强策略方案](#数据增强策略方案)
* [可解释性分析](#可解释性分析)
* [单词级别可解释性分析](#单词级别可解释性分析)
* [句子级别可解释性分析](#句子级别可解释性分析)
* [数据优化](#数据优化)
* [稀疏数据筛选方案](#稀疏数据筛选方案)
* [脏数据清洗方案](#脏数据清洗方案)
* [数据增强策略方案](#数据增强策略方案)
## analysis模块介绍
## Analysis模块介绍
analysis模块提供了**模型评估**脚本对整体分类情况和每个类别分别进行评估,并打印预测错误样本,帮助开发者分析模型表现找到训练和预测数据中存在的问题问题。同时基于[可信AI工具集](https://github.com/PaddlePaddle/TrustAI)和[数据增强API](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/dataaug.md)提供了**稀疏数据筛选、脏数据清洗、数据增强**三种优化方案从多角度帮助开发者提升模型效果。
Analysis模块提供了**模型评估、可解释性分析、数据优化**等功能,旨在帮助开发者更好地分析文本分类模型预测结果和对模型效果进行优化。
- **模型评估:** 对整体分类情况和每个类别分别进行评估,并打印预测错误样本,帮助开发者分析模型表现找到训练和预测数据中存在的问题。
- **可解释性分析:** 基于[TrustAI](https://github.com/PaddlePaddle/TrustAI)提供单词和句子级别的模型可解释性分析,帮助理解模型预测结果。
- **数据优化:** 结合[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[数据增强API](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/dataaug.md)提供了**稀疏数据筛选、脏数据清洗、数据增强**三种优化策略,从多角度优化训练数据提升模型效果。
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/184790352-7f91da02-aadd-48fe-9130-8323a89c6a43.jpg" width="600">
<img src="https://user-images.githubusercontent.com/63761690/195241942-70068989-df17-4f53-9f71-c189d8c5c88d.png" width="600">
</div>
以下是本项目主要代码结构及说明:
@@ -20,10 +31,27 @@ analysis模块提供了**模型评估**脚本对整体分类情况和每个类
```text
analysis/
├── evaluate.py # 评估脚本
├── sent_interpret.py # 句子级别可解释性分析脚本
├── word_interpret.py # 单词级别可解释性分析notebook
├── sparse.py # 稀疏数据筛选脚本
├── dirty.py # 脏数据清洗脚本
├── aug.py # 数据增强脚本
└── README.md # 多标签训练评估与模型优化指南
└── README.md # 训练评估与模型优化指南
```
## 环境准备
需要可解释性分析和数据优化需要安装相关环境。
- trustai >= 0.1.7
- interpretdl >= 0.7.0
**安装TrustAI**(可选)如果使用可解释性分析和数据优化中稀疏数据筛选和脏数据清洗需要安装TrustAI。
```shell
pip install trustai==0.1.7
```
**安装InterpretDL**(可选)如果使用词级别可解释性分析GradShap方法,需要安装InterpretDL
```shell
pip install interpretdl==0.7.0
```
## 模型评估
@@ -37,14 +65,14 @@ python evaluate.py \
--params_path "../checkpoint" \
--max_seq_length 128 \
--batch_size 32 \
--bad_case_path "./bad_case.txt"
--bad_case_file "bad_case.txt"
```
默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`
可支持配置的参数:
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含train.txt、dev.txt和label.txt文件;默认为None。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
* `max_seq_length`:分词器tokenizer使用的最大序列长度,ERNIE模型最大不能超过2048。请根据文本长度选择,通常推荐128、256或512,若出现显存不足,请适当调低这一参数;默认为128。
@@ -76,30 +104,108 @@ python evaluate.py \
预测错误的样本保存在bad_case.txt文件中:
```text
Prediction Label Text
不动产分割 不动产分割,有夫妻共同财产 2014年,王X以其与肖X协议离婚时未分割该套楼房的首付款为由,起诉至法院,要求分得楼房的首付款15万元。
婚后分居,准予离婚 二次起诉离婚,准予离婚,婚后分居,法定离婚 但原、被告对已建立起的夫妻感情不够珍惜,因琐事即发生吵闹并最终分居,对夫妻感情造成了严重的影响,现原、被告已分居六年有余,且经人民法院判决不准离婚后仍未和好,夫妻感情确已破裂,依法应准予原、被告离婚。
婚后有子女,限制行为能力子女抚养 婚后有子女 婚后生有一女,取名彭某乙,已11岁,现已由被告从铁炉白族乡中心小学转入走马镇李桥小学读书。
婚后分居 不履行家庭义务,婚后分居 2015年2月23日,被告将原告赶出家门,原告居住于娘家待产,双方分居至今。
Text Label Prediction
2014年,王X以其与肖X协议离婚时未分割该套楼房的首付款为由,起诉至法院,要求分得楼房的首付款15万元。 不动产分割,有夫妻共同财产 不动产分割
但原、被告对已建立起的夫妻感情不够珍惜,因琐事即发生吵闹并最终分居,对夫妻感情造成了严重的影响,现原、被告已分居六年有余,且经人民法院判决不准离婚后仍未和好,夫妻感情确已破裂,依法应准予原、被告离婚。 二次起诉离婚,准予离婚,婚后分居,法定离婚 婚后分居,准予离婚
婚后生有一女,取名彭某乙,已11岁,现已由被告从铁炉白族乡中心小学转入走马镇李桥小学读书。 婚后有子女 婚后有子女,限制行为能力子女抚养
...
```
## 可解释性分析
"模型为什么会预测出这个结果?"是文本分类任务开发者时常遇到的问题,如何分析错误样本(bad case)是文本分类任务落地中重要一环,本项目基于TrustAI开源了基于词级别和句子级别的模型可解释性分析方法,帮助开发者更好地理解文本分类模型与数据,有助于后续的模型优化与数据清洗标注。
### 单词级别可解释性分析
本项目开源模型的词级别可解释性分析Notebook,提供LIME、Integrated Gradient、GradShap 三种分析方法,支持分析微调后模型的预测结果,开发者可以通过更改**数据目录**和**模型目录**在自己的任务中使用Jupyter Notebook进行数据分析。
运行 [word_interpret.ipynb](./word_interpreter.ipynb) 代码,即可分析影响样本预测结果的关键词以及可视化所有词对预测结果的贡献情况,颜色越深代表这个词对预测结果影响越大:
<div align="center">
<img src="https://user-images.githubusercontent.com/63761690/192739675-63145d59-23c6-416f-bf71-998fd4995254.png" width="1000">
</div>
### 句子级别可解释性分析
本项目基于特征相似度([FeatureSimilarity](https://arxiv.org/abs/2104.04128))算法,计算对样本预测结果正影响的训练数据,帮助理解模型的预测结果与训练集数据的关系。
待分析数据文件`interpret_input_file`应为以下三种格式中的一种:
**格式一:包括文本、标签、预测结果**
```text
<文本>'\t'<标签>'\t'<预测结果>
...
```
## 稀疏数据筛选方案
稀疏数据指缺乏足够训练数据支持导致低置信度的待预测数据,简单来说,由于模型在训练过程中没有学习到足够与待预测样本相似的数据,模型难以正确预测样本所属类别。本项目中稀疏数据筛选基于TrustAI(可信AI)工具集,利用基于特征相似度的实例级证据分析方法,抽取开发集中样本的支持训练证据,并计算支持证据平均分(通常为得分前三的支持训练证据均分)。分数较低的样本表明其训练证据不足,在训练集中较为稀疏,实验表明模型在这些样本上表现也相对较差。更多细节详见[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[实例级证据分析](https://github.com/PaddlePaddle/TrustAI/blob/main/trustai/interpretation/example_level/README.md)。
稀疏数据筛选旨在开发集中挖掘缺乏训练证据支持的稀疏数据,通常可以采用**数据增强**或**少量数据标注**的两种低成本方式,提升模型预测效果。
**安装TrustAI**
```shell
pip install trustai==0.1.4
**格式二:包括文本、标签**
```text
<文本>'\t'<标签>
...
```
### 稀疏数据识别--数据增强
**格式三:只包括文本**
```text
<文本>
准予原告胡某甲与被告韩某甲离婚。
...
```
这里我们将介绍稀疏数据识别--数据增强流程,首先使用数据增强脚本挖掘开发集中的稀疏数据,然后筛选训练集中对稀疏数据的支持数据进行数据增强,然后将得到的数据增强后的支持数据加入到训练集中进行训练。
我们可以运行代码,得到支持样本模型预测结果的训练数据:
```shell
python sent_interpret.py \
--device "gpu" \
--dataset_dir "../data" \
--params_path "../checkpoint/" \
--max_seq_length 128 \
--batch_size 16 \
--top_k 3 \
--train_file "train.txt" \
--interpret_input_file "bad_case.txt" \
--interpret_result_file "sent_interpret.txt"
```
现在我们进行稀疏数据识别--数据增强,得到新增训练数据:
默认在GPU环境下使用,在CPU环境下修改参数配置为`--device "cpu"`
可支持配置的参数:
* `device`: 选用什么设备进行训练,可可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含dev.txt和label.txt文件;默认为None。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
* `max_seq_length`:分词器tokenizer使用的最大序列长度,ERNIE模型最大不能超过2048。请根据文本长度选择,通常推荐128、256或512,若出现显存不足,请适当调低这一参数;默认为128。
* `batch_size`:批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为32。
* `seed`:随机种子,默认为3。
* `top_k`:筛选支持训练证据数量;默认为3。
* `train_file`:本地数据集中训练集文件名;默认为"train.txt"。
* `interpret_input_file`:本地数据集中待分析文件名;默认为"bad_case.txt"。
* `interpret_result_file`:保存句子级别可解释性结果文件名;默认为"sent_interpret.txt"。
可解释性结果保存在 `interpret_result_file` 文件中:
```text
text: 2015年2月23日,被告将原告赶出家门,原告居住于娘家待产,双方分居至今。
predict label: 婚后分居
label: 不履行家庭义务,婚后分居
examples with positive influence
support1 text: 2014年中秋节原告回了娘家,原、被告分居至今。 label: 婚后分居 score: 0.99942
support2 text: 原告于2013年8月13日离开被告家,分居至今。 label: 婚后分居 score: 0.99916
support3 text: 2014年4月,被告外出务工,双方分居至今。 label: 婚后分居 score: 0.99902
...
```
## 数据优化
### 稀疏数据筛选方案
稀疏数据筛选适用于文本分类中**数据不平衡或训练数据覆盖不足**的场景,简单来说,就是由于模型在训练过程中没有学习到足够与待预测样本相似的数据,模型难以正确预测样本所属类别的情况。稀疏数据筛选旨在开发集中挖掘缺乏训练证据支持的数据,通常可以采用**数据增强**或**少量数据标注**的两种低成本方式,提升模型在开发集的预测效果。
本项目中稀疏数据筛选基于TrustAI,利用基于特征相似度的实例级证据分析方法,抽取开发集中样本的支持训练证据,并计算支持证据平均分(通常为得分前三的支持训练证据均分)。分数较低的样本表明其训练证据不足,在训练集中较为稀疏,实验表明模型在这些样本上表现也相对较差。更多细节详见[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[实例级证据分析](https://github.com/PaddlePaddle/TrustAI/blob/main/trustai/interpretation/example_level/README.md)。
#### 稀疏数据识别—数据增强
这里我们将介绍稀疏数据识别—数据增强流程:
- **稀疏数据识别:** 挖掘开发集中的缺乏训练证据支持数据,记为稀疏数据集(Sparse Dataset);
- **数据增强**:将稀疏数据集在训练集中的支持证据应用数据增强策略,这些数据增强后的训练数据记为支持数据集(Support Dataset);
- **重新训练模型:** 将支持数据集加入到原有的训练集获得新的训练集,重新训练新的文本分类模型。
现在我们进行稀疏数据识别-数据增强,得到支持数据集:
```shell
python sparse.py \
@@ -117,7 +223,7 @@ python sparse.py \
可支持配置的参数:
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含dev.txt和label.txt文件;默认为None。
* `aug_strategy`:数据增强类型,可选"duplicate","substitute", "insert", "delete", "swap";默认为"substitute"。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
@@ -154,9 +260,15 @@ cat ../data/train.txt ../data/support.txt > ../data/train_sparse_aug.txt
|训练集+支持增强集(delete) |84.83| 51.04|
|训练集+支持增强集(swap) |**84.84**|51.06|
### 稀疏数据识别--数据标注
#### 稀疏数据识别-数据标注
这里我们将介绍稀疏数据识别--数据标注流程,首先使用数据增强脚本挖掘开发集中的稀疏数据,然后筛选对稀疏数据支持的未标注数据,然后将得到支持数据进行标注后加入到训练集中进行训练。
本方案能够有针对性进行数据标注,相比于随机标注数据更好提高模型预测效果。这里我们将介绍稀疏数据识别-数据标注流程:
- **稀疏数据识别:** 挖掘开发集中的缺乏训练证据支持数据,记为稀疏数据集(Sparse Dataset);
- **数据标注**:在未标注数据集中筛选稀疏数据集的支持证据,并进行数据标注,记为支持数据集(Support Dataset);
- **重新训练模型:** 将支持数据集加入到原有的训练集获得新的训练集,重新训练新的文本分类模型。
现在我们进行稀疏数据识别--数据标注,得到待标注数据:
@@ -177,7 +289,7 @@ python sparse.py \
可支持配置的参数:
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含dev.txt和label.txt文件;默认为None。
* `annotate`:选择稀疏数据识别--数据标注模式;默认为False。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
@@ -214,14 +326,13 @@ cat ../data/train.txt ../data/support.txt > ../data/train_sparse_annotate.txt
|训练集+策略采样集(100) |**86.14**|56.93|
|训练集+随机采样集(100) |84.69|50.76|
## 脏数据清洗方案
### 脏数据清洗方案
训练数据标注质量对模型效果有较大影响,但受限于标注人员水平、标注任务难易程度等影响,训练数据中都存在一定比例的标注较差的数据(脏数据)。当标注数据规模较大时,数据标注检查就成为一个难题。本项目中脏数据清洗基于TrustAI(可信AI)工具集,利用基于表示点方法的实例级证据分析方法,计算训练数据对模型的影响分数,分数高的训练数据表明对模型影响大,这些数据有较大概率为脏数据(标注错误样本)。更多细节详见[TrustAI](https://github.com/PaddlePaddle/TrustAI)和[实例级证据分析](https://github.com/PaddlePaddle/TrustAI/blob/main/trustai/interpretation/example_level/README.md)。
脏数据清洗方案是基于已训练好的文本分类模型,筛选出训练数据集中标注错误的数据,再由人工检查重新标注,获得标注正确的数据集进行重新训练。我们将介绍脏数据清洗流程:
**安装TrustAI**
```shell
pip install trustai==0.1.4
```
- **脏数据筛选:** 基于TrustAI中表示点方法,计算训练数据对文本分类模型的影响分数,分数高的训练数据表明对模型影响大,这些数据有较大概率为标注错误样本,记为脏数据集(Dirty Dataset)。
- **数据清洗、训练:** 将筛选出的脏数据由人工重新检查,为数据打上正确的标签。将清洗后的训练数据重新放入文本分类模型进行训练。
现在我们进行脏数据识别,脏数据保存在`"train_dirty.txt"`,剩余训练数据保存在`"train_dirty_rest.txt"`:
@@ -244,21 +355,21 @@ python dirty.py \
* `dataset_dir`:必须,本地数据集路径,数据集路径中应包含train.txt和label.txt文件;默认为None。
* `max_seq_length`:分词器tokenizer使用的最大序列长度,ERNIE模型最大不能超过2048。请根据文本长度选择,通常推荐128、256或512,若出现显存不足,请适当调低这一参数;默认为128。
* `params_path`:保存训练模型的目录;默认为"../checkpoint/"。
* `device`: 选用什么设备进行训练,选择cpu、gpu、xpu、npu;默认为"gpu"。
* `device`: 选用什么设备进行训练,可选择cpu、gpu、xpu、npu;默认为"gpu"。
* `batch_size`:批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为32。
* `seed`:随机种子,默认为3。
* `dirty_file`:保存脏数据文件名,默认为"train_dirty.txt"。
* `rest_file`:保存剩余数据(非脏数据)文件名,默认为"train_dirty_rest.txt"。
* `train_file`:本地数据集中训练集文件名;默认为"train.txt"。
* `dirty_num`:筛选脏数据用于重新标注的数量;默认为100。
* `dirty_threshold`:筛选脏数据用于重新标注的阈值,只选择影响分数大于阈值作为有效数据,默认为0。
* `dirty_threshold`:筛选脏数据用于重新标注的阈值,只选择影响分数大于阈值作为支持数据,默认为0。
我们将筛选出脏数据进行重新标注,可以将`train_dirty.txt`直接导入标注工具doccano帮助更快重新标注,详情请参考[文本分类任务doccano数据标注使用指南](../../doccano.md)进行文本分类数据标注。然后将已重新标注的脏数据`train_dirty.txt`与剩余训练集数据`train_dirty_rest.txt`合并得到新的训练集`train_clean.txt`重新进行训练:
我们将筛选出脏数据进行人工检查重新标注,可以将`train_dirty.txt`直接导入标注工具doccano帮助更快重新标注,详情请参考[文本分类任务doccano数据标注使用指南](../../doccano.md)进行文本分类数据标注。然后将已重新标注的脏数据`train_dirty.txt`与剩余训练集数据`train_dirty_rest.txt`合并得到新的训练集`train_clean.txt`重新进行训练:
```shell
cat ../data/train_dirty_rest.txt ../data/train_dirty.txt > ../data/train_clean.txt
```
**方案效果**
我们在CAIL2019—婚姻家庭要素提取数据集抽取部分训练数据(训练集数据规模:500)进行实验,取50条数据进行脏数据处理,也即50条训练数据为标签错误数据。选择不同`dirty_num`应用脏数据清洗策略进行评测:
@@ -291,7 +402,7 @@ python aug.py \
* `aug_type`:词替换/词插入增强类型,可选"synonym", "homonym", "mlm",建议在GPU环境下使用mlm类型;默认为"synonym"。
* `create_n`:生成的句子数量,默认为2。
* `aug_percent`:生成词替换百分比,默认为0.1。
* `device`: 选用什么设备进行增强,选择cpu、gpu、xpu、npu,仅在使用mlm类型有影响;默认为"gpu"。
* `device`: 选用什么设备进行增强,可选择cpu、gpu、xpu、npu,仅在使用mlm类型有影响;默认为"gpu"。
生成的增强数据保存在`"aug.txt"`文件中,与训练集数据`train.txt`合并得到新的训练集`train_aug.txt`重新进行训练:

View File

@@ -37,7 +37,7 @@ parser.add_argument("--batch_size", default=32, type=int, help="Batch size per G
parser.add_argument("--train_file", type=str, default="train.txt", help="Train dataset file name")
parser.add_argument("--dev_file", type=str, default="dev.txt", help="Dev dataset file name")
parser.add_argument("--label_file", type=str, default="label.txt", help="Label file name")
parser.add_argument("--bad_case_path", type=str, default="./bad_case.txt", help="Bad case saving file path")
parser.add_argument("--bad_case_file", type=str, default="bad_case.txt", help="Bad case saving file name")
args = parser.parse_args()
# yapf: enable
@@ -201,23 +201,22 @@ def evaluate():
report[str(i)]['recall'] * 100,
report[str(i)]['f1-score'] * 100))
logger.info("----------------------------")
with open(args.bad_case_path, 'w', encoding="utf-8") as f:
f.write("Prediction\tLabel\tText\n")
bad_case_path = os.path.join(args.dataset_dir, args.bad_case_file)
with open(bad_case_path, 'w', encoding="utf-8") as f:
f.write("Text\tLabel\tPrediction\n")
for i in range(len(preds)):
for p, l in zip(preds[i], labels[i]):
if (p and l == 0) or (not p and l == 1):
pred_n = [
label_map[i] for i, pp in enumerate(preds[i]) if pp
]
f.write(",".join(pred_n) + "\t" +
f.write(dev_ds.data[i]["text"] + "\t" +
dev_ds.data[i]["label_n"] + "\t" +
dev_ds.data[i]["text"] + "\n")
",".join(pred_n) + "\n")
break
f.close()
logger.info("Bad case in dev dataset saved in {}".format(
args.bad_case_path))
logger.info("Bad case in dev dataset saved in {}".format(bad_case_path))
return

View File

@@ -0,0 +1,172 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import functools
import random
import os
import argparse
import numpy as np
import paddle
import paddle.nn.functional as F
from paddle.io import DataLoader, BatchSampler
from paddlenlp.data import DataCollatorWithPadding
from paddlenlp.datasets import load_dataset
from paddlenlp.transformers import AutoModelForSequenceClassification, AutoTokenizer, LinearDecayWithWarmup
from paddlenlp.utils.log import logger
from trustai.interpretation import FeatureSimilarityModel
# yapf: disable
parser = argparse.ArgumentParser()
parser.add_argument('--device', default="gpu", help="Select which device to train model, defaults to gpu.")
parser.add_argument("--dataset_dir", required=True, type=str, help="The dataset directory should include train.txt,dev.txt and test.txt files.")
parser.add_argument("--params_path", default="../checkpoint/", type=str, help="The path to model parameters to be loaded.")
parser.add_argument("--max_seq_length", default=128, type=int, help="The maximum total input sequence length after tokenization. Sequences longer than this will be truncated, sequences shorter will be padded.")
parser.add_argument("--batch_size", default=16, type=int, help="Batch size per GPU/CPU for training.")
parser.add_argument("--seed", type=int, default=3, help="random seed for initialization")
parser.add_argument("--top_k", type=int, default=3, help="Top K important training data.")
parser.add_argument("--train_file", type=str, default="train.txt", help="Train dataset file name")
parser.add_argument("--interpret_input_file", type=str, default="bad_case.txt", help="interpretation file name")
parser.add_argument("--interpret_result_file", type=str, default="sent_interpret.txt", help="interpreted file name")
args = parser.parse_args()
# yapf: enable
def set_seed(seed):
"""
Set random seed
"""
random.seed(seed)
np.random.seed(seed)
paddle.seed(seed)
os.environ['PYTHONHASHSEED'] = str(seed)
def read_local_dataset(path):
"""
Read dataset file
"""
with open(path, 'r', encoding='utf-8') as f:
for line in f:
items = line.strip().split('\t')
if items[0] == 'Text':
continue
if len(items) == 3:
yield {'text': items[0], 'label': items[1], 'predict': items[2]}
elif len(items) == 2:
yield {'text': items[0], 'label': items[1], 'predict': ''}
elif len(items) == 1:
yield {'text': items[0], 'label': '', 'predict': ''}
else:
logger.info(line.strip())
raise ValueError("{} should be in fixed format.".format(path))
def preprocess_function(examples, tokenizer, max_seq_length):
"""
Preprocess dataset
"""
result = tokenizer(text=examples["text"], max_seq_len=max_seq_length)
return result
class LocalDataCollatorWithPadding(DataCollatorWithPadding):
"""
Convert the result of DataCollatorWithPadding from dict dictionary to a list
"""
def __call__(self, features):
batch = super().__call__(features)
batch = list(batch.values())
return batch
def find_positive_influence_data():
set_seed(args.seed)
paddle.set_device(args.device)
# Define model & tokenizer
if os.path.exists(os.path.join(
args.params_path, "model_state.pdparams")) and os.path.exists(
os.path.join(args.params_path,
"model_config.json")) and os.path.exists(
os.path.join(args.params_path,
"tokenizer_config.json")):
model = AutoModelForSequenceClassification.from_pretrained(
args.params_path)
tokenizer = AutoTokenizer.from_pretrained(args.params_path)
else:
raise ValueError("The {} should exist.".format(args.params_path))
# Prepare & preprocess dataset
train_path = os.path.join(args.dataset_dir, args.train_file)
interpret_path = os.path.join(args.dataset_dir, args.interpret_input_file)
train_ds = load_dataset(read_local_dataset, path=train_path, lazy=False)
interpret_ds = load_dataset(read_local_dataset,
path=interpret_path,
lazy=False)
trans_func = functools.partial(preprocess_function,
tokenizer=tokenizer,
max_seq_length=args.max_seq_length)
train_ds = train_ds.map(trans_func)
interpret_ds = interpret_ds.map(trans_func)
# Batchify dataset
collate_fn = LocalDataCollatorWithPadding(tokenizer)
train_batch_sampler = BatchSampler(train_ds,
batch_size=args.batch_size,
shuffle=False)
interpret_batch_sampler = BatchSampler(interpret_ds,
batch_size=args.batch_size,
shuffle=False)
train_data_loader = DataLoader(dataset=train_ds,
batch_sampler=train_batch_sampler,
collate_fn=collate_fn)
interpret_data_loader = DataLoader(dataset=interpret_ds,
batch_sampler=interpret_batch_sampler,
collate_fn=collate_fn)
# Classifier_layer_name is the layer name of the last output layer
feature_sim = FeatureSimilarityModel(model,
train_data_loader,
classifier_layer_name="classifier")
# Feature similarity analysis & select sparse data
analysis_result = []
for batch in interpret_data_loader:
analysis_result += feature_sim(batch, sample_num=args.top_k)
with open(os.path.join(args.dataset_dir, args.interpret_result_file),
'w') as f:
for i in range(len(analysis_result)):
f.write("text: " + interpret_ds.data[i]["text"] + '\n')
if 'predict' in interpret_ds.data[i]:
f.write("predict label: " + interpret_ds.data[i]["predict"] +
'\n')
if 'label' in interpret_ds.data[i]:
f.write("label: " + interpret_ds.data[i]["label"] + '\n')
f.write("examples with positive influence\n")
for i, (idx, score) in enumerate(
zip(analysis_result[i].pos_indexes,
analysis_result[i].pos_scores)):
f.write("support{} text: ".format(i + 1) +
train_ds.data[idx]["text"] + '\t' + "label: " +
train_ds.data[idx]["label"] + '\t' + "score: " +
"{:.5f}".format(score) + '\n')
f.close()
if __name__ == "__main__":
find_positive_influence_data()

File diff suppressed because one or more lines are too long

View File

@@ -21,7 +21,7 @@
### 安装PaddleNLP
安装PaddleNLP默认开启百度镜像源来加速下载,如果您使用 HTTP 代理可以关闭(删去 -i https://mirror.baidu.com/pypi/simple),更多关于PaddleNLP安装的详细教程请查见[PaddleNLP快速安装](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/get_started/installation.rst)。
安装PaddleNLP默认开启百度镜像源来加速下载,如果您使用 HTTP 代理可以删去` -i https://mirror.baidu.com/pypi/simple` ,更多关于PaddleNLP安装的详细教程请查见[PaddleNLP快速安装](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/get_started/installation.rst)。
```shell
python3 -m pip install --upgrade paddlenlp -i https://mirror.baidu.com/pypi/simple

View File

@@ -258,7 +258,7 @@ python -u -m paddle.distributed.launch --gpus 0,1,2,3 train.py \
可配置参数说明:
- `model_name_or_path`: 内置模型名,或者模型参数配置目录路径。默认为`ernie-3.0-base-zh`。
- `data_dir`: 训练数据集路径,数据格式要求详见[数据准备](数据准备)。
- `data_dir`: 训练数据集路径,数据格式要求详见[数据标注](#数据标注)。
- `output_dir`: 模型参数、训练日志和静态图导出的保存目录。
- `prompt`: 提示模板。定义了如何将文本和提示拼接结合。
- `soft_encoder`: 提示向量的编码器,`lstm`表示双向LSTM, `mlp`表示双层线性层, None表示直接使用提示向量。默认为`lstm`。
@@ -283,7 +283,7 @@ python -u -m paddle.distributed.launch --gpus 0,1,2,3 train.py \
- `evaluation_strategy`: 模型评估的间隔策略。若为`epoch`,则每轮训练结束后评估模型。
- `save_strategy`: 模型保存的间隔策略。若为`epoch`,则每轮训练结束后保存当前模型参数。
更多参数介绍可参考[配置文件](../../../../paddlenlp/trainer/trainer_args.py)。
更多参数介绍可参考[配置文件](https://paddlenlp.readthedocs.io/zh/latest/trainer.html)。
<a name="模型评估"></a>
### 3.5 模型评估

View File

@@ -54,14 +54,12 @@ class ModelArguments:
@paddle.no_grad()
def dynabert_evaluate(model, data_loader):
def dynabert_evaluate(self, model, data_loader):
metric = MetricReport()
model.eval()
metric.reset()
for batch in data_loader:
logits = model(batch['input_ids'],
batch['token_type_ids'],
attention_mask=[None, None])
logits = model(batch['input_ids'], batch['token_type_ids'])
# Supports paddleslim.nas.ofa.OFA model and nn.layer model.
if isinstance(model, OFA):
logits = logits[0]
@@ -129,7 +127,7 @@ def main():
compression_args.print_config()
trainer.compress(custom_dynabert_evaluate=dynabert_evaluate)
trainer.compress(custom_evaluate=dynabert_evaluate)
if __name__ == "__main__":

View File

@@ -1,5 +0,0 @@
python export_model.py \
--model_name_or_path unimo-text-1.0-summary \
--decoding_strategy beam_search \
--inference_model_dir ./inference_model \
--max_out_len 30 \

View File

@@ -0,0 +1,271 @@
# 生成式文本摘要应用
**目录**
- [生成式文本摘要应用](#生成式文本摘要应用)
- [简介](#简介)
- [效果展示](#效果展示)
- [开箱即用](#开箱即用)
- [支持单条、批量预测](#支持单条批量预测)
- [可配置参数说明](#可配置参数说明)
- [训练定制](#训练定制)
- [文本摘要应用定制训练全流程介绍](#文本摘要应用定制训练全流程介绍)
- [环境依赖](#环境依赖)
- [代码结构说明](#代码结构说明)
- [数据准备](#数据准备)
- [数据加载](#数据加载)
- [从本地文件创建数据集](#从本地文件创建数据集)
- [模型训练](#模型训练)
- [模型预测](#模型预测)
- [模型推理部署](#模型推理部署)
- [FasterGeneration加速及模型静态图导出](#fastergeneration加速及模型静态图导出)
- [模型部署](#模型部署)
- [References](#references)
## 简介
文本摘要的目标是自动地将输入文本转换成简短摘要,为用户提供简明扼要的内容描述,是缓解文本信息过载的一个重要手段。
文本摘要也是自然语言生成领域中的一个重要任务,有很多应用场景,如新闻摘要、论文摘要、财报摘要、传记摘要、专利摘要、对话摘要、评论摘要、观点摘要、电影摘要、文章标题生成、商品名生成、自动报告生成、搜索结果预览等。
本项目是基于预训练语言模型PEGASUS的中文文本摘要产业实践,具有以下优势:
- 效果领先。在LCSTS上效果达到SOTA。
- 开箱即用。本项目提供TaskFlow接口,无需训练,仅需几行代码便可预测。
- 高性能推理。本项目基于[FasterGeneration](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/faster_generation)进行推理加速,能够提供更高性能的推理体验。
- 训练推理全流程打通。本项目提供了全面的定制训练流程,从数据准备、模型训练预测,到模型推理部署,一应俱全。
## 效果展示
## 开箱即用
PaddleNLP提供开箱即用的产业级NLP预置任务能力,无需训练,一键预测。
### 支持单条、批量预测
```python
>>> from paddlenlp import Taskflow
>>> summarizer = Taskflow("text_summarization")
# 单条输入
>>> summarizer('2022年,中国房地产进入转型阵痛期,传统“高杠杆、快周转”的模式难以为继,万科甚至直接喊话,中国房地产进入“黑铁时代”')
# 输出:['万科喊话中国房地产进入“黑铁时代”']
# 多条输入
>>> summarizer([
'据悉,2022年教育部将围绕“巩固提高、深化落实、创新突破”三个关键词展开工作。要进一步强化学校教育主阵地作用,继续把落实“双减”作为学校工作的重中之重,重点从提高作业设计水平、提高课后服务水平、提高课堂教学水平、提高均衡发展水平四个方面持续巩固提高学校“双减”工作水平。',
'党参有降血脂,降血压的作用,可以彻底消除血液中的垃圾,从而对冠心病以及心血管疾病的患者都有一定的稳定预防工作作用,因此平时口服党参能远离三高的危害。另外党参除了益气养血,降低中枢神经作用,调整消化系统功能,健脾补肺的功能。'
])
#输出:['教育部:将从四个方面持续巩固提高学校“双减”工作水平', '党参能降低三高的危害']
```
### 可配置参数说明
* `model`:可选模型,默认为`IDEA-CCNL/Randeng-Pegasus-523M-Summary-Chinese`。
* `batch_size`:批处理大小,请结合机器情况进行调整,默认为1。
## 训练定制
### 文本摘要应用定制训练全流程介绍
接下来,我们将按数据准备、训练、预测、推理部署对文本摘要应用的全流程进行介绍。
1. **数据准备**
- 如果没有已标注的数据集,我们推荐[doccano](https://github.com/doccano/doccano)数据标注工具。
如果已有标注好的本地数据集,我们需要根据将数据集整理为文档要求的格式,请参考[从本地文件创建数据集](#从本地文件创建数据集)。
2. **模型训练**
- 数据准备完成后,可以开始使用我们的数据集对预训练模型进行微调训练。我们可以根据任务需求,调整可配置参数,选择使用GPU或CPU进行模型训练,脚本默认保存在开发集最佳表现模型。中文任务默认使用"IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese"模型,还支持large模型: "IDEA-CCNL/Randeng-Pegasus-523M-Summary-Chinese"。
3. **模型预测**
- 训练结束后,我们可以加载保存的最佳模型进行模型测试,打印模型预测结果。
4. **模型推理部署**
- 模型部署需要将保存的最佳模型参数(动态图)导出成静态图参数,用于后续的推理部署。
- 文本摘要应用提供了基于Paddle Inference的本地部署predictor,并且支持在GPU设备使用FasterGeneration进行加速。
- 文本摘要应用提供了基于Paddle Serving的服务端部署方案。
### 环境依赖
### 代码结构说明
以下是本项目主要代码结构及说明:
```text
text_summarization/
├── deploy # 部署
│ ├── paddle_inference # PaddleInference高性能推理部署
│ │ ├── inference_pegasus.py # 推理部署脚本
│ │ └── README.md # 说明文档
│ └── paddle_serving
│ ├── config.yml # 配置文件
│ ├── pipeline_client.py # 客户端程序
│ ├── pipeline_service.py # 服务器程序
│ ├── export_serving.sh # serving模型导出脚本
│ └── README.md # 说明文档
├── export_model.py # 动态图参数导出静态图参数脚本
├── export_model.sh # 动态图参数导出静态图参数shell脚本
├── run_summarization.py # 训练评估脚本
├── run_train.sh # 训练评估shell脚本
├── run_generate.py # 预测脚本
├── run_generate.sh # 预测shell脚本
├── utils.py # 工具函数脚本
├── requirements.txt # 依赖包
└── README.md # 说明文档
```
### 数据准备
#### 数据加载
#### 从本地文件创建数据集
在许多情况,我们需要使用本地数据集来训练我们的文本摘要模型,本项目支持使用固定格式本地数据集文件进行训练。
本地数据集目录结构如下:
```text
data/
├── train.json # 训练数据集文件
└── test.json # 可选,待预测数据文件
```
本地数据集文件格式如下:
- train.json/test.json 文件每行格式:
```text
{
"title": "任志强抨击政府把土地作为投机品地产业被人为破坏",
"content": "“北京的保障房市场就像一个巨大的赌场,每个人都在期待中奖。”面对中国目前现行的保障性住房政策,华远地产董事长任志强再次语出惊人。(分享自@第一财经-中国房地产金融)"
}
```
更多数据集读取格式详见[数据集加载](https://paddlenlp.readthedocs.io/zh/latest/data_prepare/dataset_load.html#)和[自定义数据集](https://paddlenlp.readthedocs.io/zh/latest/data_prepare/dataset_self_defined.html)。
### 模型训练
运行如下命令即可在样例训练集上进行finetune,并在样例验证集上进行验证。
```shell
# GPU启动,参数`--gpus`指定训练所用的GPU卡号,可以是单卡,也可以多卡
unset CUDA_VISIBLE_DEVICES
python -m paddle.distributed.launch --gpus "2,3,4,5,6,7" run_summarization.py \
--model_name_or_path=IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese \
--train_file train.json \
--eval_file test.json \
--output_dir pegesus_out \
--max_source_length 128 \
--max_target_length 64 \
--num_train_epochs 20 \
--logging_steps 1 \
--save_steps 10000 \
--train_batch_size 128 \
--eval_batch_size 128 \
--learning_rate 5e-5 \
--warmup_proportion 0.02 \
--weight_decay=0.01 \
--device=gpu \
```
也可以直接使用`run_train.sh`.
关键参数释义如下:
- `gpus` 指示了训练所用的GPU卡号。
- `train_file` 本地训练数据地址。
- `eval_file` 本地测试数据地址。
- `model_name_or_path` 指示了finetune使用的具体预训练模型,可以是PaddleNLP提供的预训练模型,或者是本地的预训练模型。如果使用本地的预训练模型,可以配置本地模型的目录地址,例如: ./checkpoints/model_xx/,目录中需包含paddle预训练模型model_state.pdparams。如果使用PaddleNLP提供的预训练模型,可以选择下面其中之一。
| PaddleNLP提供的预训练模型 |
|---------------------------------|
| IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese |
| IDEA-CCNL/Randeng-Pegasus-523M-Summary-Chinese |
- `output_dir` 表示模型的保存路径。
- `logging_steps` 表示日志打印间隔。
- `save_steps` 表示模型保存及评估间隔。
- `seed` 表示随机数生成器的种子。
- `num_train_epochs` 表示训练轮数。
- `train_batch_size` 表示每次巡礼哪**每张卡**上的样本数目。
- `eval_batch_size` 表示每次验证**每张卡**上的样本数目。
- `learning_rate` 表示基础学习率大小,将于learning rate scheduler产生的值相乘作为当前学习率。
- `weight_decay` 表示AdamW优化器中使用的weight_decay的系数。
- `warmup_propotion` 表示学习率逐渐升高到基础学习率(即上面配置的learning_rate)所需要的迭代数占总步数的比例,最早的使用可以参考[这篇论文](https://arxiv.org/pdf/1706.02677.pdf)。
- `max_source_length` 模型输入序列的最大长度。
- `max_target_length` 模型训练时标签的最大长度。
- `device` 表示使用的设备,从gpu和cpu中选择。
更多参数详情和参数的默认值请参考`run_summarization.py`。
程序运行时将会自动进行训练和验证,训练过程中会自动保存模型在指定的`output_dir`中。
如:
```text
./pegeaus_model/
├── pegeaus_model_10000
│ ├── model_config.json
│ ├── model_state.pdparams
│ ├── special_tokens_map.json
│ ├── tokenizer_config.json
│ └── vocab.txt
└── ...
```
**NOTE:** 如需恢复模型训练,`model_name_or_path`配置本地模型的目录地址即可。
### 模型预测
运行下方脚本可以使用训练好的模型进行预测。
```shell
unset CUDA_VISIBLE_DEVICES
python run_generate.py \
--model_name_or_path=pegesus_out/pegeaus_model_10000 \
--prefict_file valid.json \
--max_source_length 128 \
--max_target_length 64 \
--batch_size 128 \
--output_path generate.txt \
--device=gpu \
```
程序运行结束后会将预测结果保存在`output_path`中。
Finetuned baseline的模型在[LCSTS](https://aclanthology.org/D15-1229/)测试集上有如下结果:
| model_name | Rouge-1 | Rouge-2 | Rouge-L | BLEU-4 |
| :-----------------------------: | :---: | :-----------: | :-------------------: |:-------------------: |
| finetuned IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese | 43.30 | 30.08 | 40.12 | 24.50 |
| finetuned IDEA-CCNL/Randeng-Pegasus-523M-Summary-Chinese | 48.13 | 36.41 | 45.39 | 31.99 |
### 模型推理部署
#### FasterGeneration加速及模型静态图导出
使用动态图训练结束之后,可以通过[静态图导出脚本](export_model.py)实现基于FasterGeneration的高性能预测加速,并将动态图参数导出成静态图参数,静态图参数保存在`output_path`指定路径中。运行方式:
```shell
python export_model.py \
--model_name_or_path IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese \
--decoding_strategy beam_search \
--inference_model_dir ./inference_model \
--max_out_len 30 \
```
关键参数释义如下:
* `model_name_or_path`:动态图训练保存的参数路径;默认为"IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese"。
* `inference_model_dir`:静态图图保存的参数路径;默认为"./inference_model"。
* `max_out_len`:最大输出长度。
执行命令后将会自动导出模型到指定的 `inference_model` 中,保存模型文件结构如下所示:
```text
inference_model/
├── pegasus.pdiparams
├── pegasus.pdiparams.info
└── pegasus.pdmodel
```
#### 模型部署
文本摘要应用已打通多种场景部署方案,点击链接获取具体的使用教程。
- [Paddle Inference 推理 (Python)](./deploy/paddle_inference/README.md)
- [Paddle Serving 服务化部署(Python)](./deploy/paddle_serving/README.md)
## References
- Zhang J, Zhao Y, Saleh M, et al. Pegasus: Pre-training with extracted gap-sentences for abstractive summarization[C]//International Conference on Machine Learning. PMLR, 2020: 11328-11339.
- Wang J, Zhang Y, Zhang L, et al. Fengshenbang 1.0: Being the Foundation of Chinese Cognitive Intelligence[J]. arXiv preprint arXiv:2209.02970, 2022.

View File

@@ -17,15 +17,15 @@ Paddle Inference Python端预测部署主要包含两个步骤:
## 导出预测部署模型
部署时需要使用预测格式的模型(即动态图转静态图操作)。预测格式模型相对训练格式模型而言,在拓扑上裁剪掉了预测不需要的算子,并且会做特定部署优化。具体操作详见[FasterTransformer加速及模型静态图导出](../../README.md)。
部署时需要使用预测格式的模型(即动态图转静态图操作)。预测格式模型相对训练格式模型而言,在拓扑上裁剪掉了预测不需要的算子,并且会做特定部署优化。具体操作详见[FasterGeneration加速及模型静态图导出](../../README.md)。
## 基于Python预测
<!-- 同上,高性能预测的默认输入和输出形式也为文件,可分别通过 test_path 和 save_path 进行指定,通过如下命令便可以基于Paddle Inference 进行高性能预测: -->
在终端输入以下命令可在GPU上进行预测:
```shell
python deploy/paddle_inference/inference_unimo_text.py --inference_model_dir ./inference_model
python inference_pegasus.py --inference_model_dir ../../inference_model
```
关键参数释义如下:
* `inference_model_dir`:用于高性能推理的静态图模型参数路径;默认为"./inference_model"。
* `inference_model_dir`:用于高性能推理的静态图模型参数路径;默认为"../../inference_model"。

View File

@@ -0,0 +1,106 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import argparse
import numpy as np
from pprint import pprint
import paddle
from paddle import inference
from paddlenlp.transformers import PegasusChineseTokenizer, PegasusForConditionalGeneration
from paddlenlp.ops.ext_utils import load
def setup_args():
"""Setup arguments."""
parser = argparse.ArgumentParser()
parser.add_argument("--inference_model_dir",
default="../../inference_model/",
type=str,
help="Path to save inference model of Pegasus. ")
args = parser.parse_args()
return args
def setup_predictor(args):
"""Setup inference predictor."""
# Load FasterTransformer lib.
load("FasterTransformer", verbose=True)
model_file = os.path.join(args.inference_model_dir, "pegasus.pdmodel")
params_file = os.path.join(args.inference_model_dir, "pegasus.pdiparams")
if not os.path.exists(model_file):
raise ValueError("not find model file path {}".format(model_file))
if not os.path.exists(params_file):
raise ValueError("not find params file path {}".format(params_file))
config = inference.Config(model_file, params_file)
config.enable_use_gpu(100, 0)
config.switch_ir_optim()
config.enable_memory_optim()
config.disable_glog_info()
predictor = inference.create_predictor(config)
return predictor
def convert_example(example, tokenizer, max_seq_len=512):
"""Convert all examples into necessary features."""
tokenized_example = tokenizer(example,
max_length=max_seq_len,
padding=True,
truncation=True,
return_attention_mask=False)
return tokenized_example
def infer(args, predictor):
"""Use predictor to inference."""
tokenizer = PegasusChineseTokenizer.from_pretrained(
'IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese')
inputs = [
"在北京冬奥会自由式滑雪女子坡面障碍技巧决赛中,中国选手谷爱凌夺得银牌。祝贺谷爱凌!今天上午,自由式滑雪女子坡面障碍技巧决赛举行。决赛分三轮进行,取选手最佳成绩排名决出奖牌。第一跳,中国选手谷爱凌获得69.90分。在12位选手中排名第三。完成动作后,谷爱凌又扮了个鬼脸,甚是可爱。第二轮中,谷爱凌在道具区第三个障碍处失误,落地时摔倒。获得16.98分。网友:摔倒了也没关系,继续加油!在第二跳失误摔倒的情况下,谷爱凌顶住压力,第三跳稳稳发挥,流畅落地!获得86.23分!此轮比赛,共12位选手参赛,谷爱凌第10位出场。网友:看比赛时我比谷爱凌紧张,加油!",
"据微信公众号“界面”报道,4日上午10点左右,中国发改委反垄断调查小组突击查访奔驰上海办事处,调取数据材料,并对多名奔驰高管进行了约谈。截止昨日晚9点,包括北京梅赛德斯-奔驰销售服务有限公司东区总经理在内的多名管理人员仍留在上海办公室内"
]
data = convert_example(inputs, tokenizer, max_seq_len=128)
input_handles = {}
for name in predictor.get_input_names():
input_handles[name] = predictor.get_input_handle(name)
input_handles[name].copy_from_cpu(np.array(data[name], dtype='int32'))
output_handles = [
predictor.get_output_handle(name)
for name in predictor.get_output_names()
]
predictor.run()
output = [output_handle.copy_to_cpu() for output_handle in output_handles]
for idx, sample in enumerate(output[0]):
for beam_idx, beam in enumerate(sample):
if beam_idx >= len(sample) // 2:
break
print(
f"Example {idx} beam {beam_idx}: ", "".join(
tokenizer.decode(beam,
skip_special_tokens=True,
clean_up_tokenization_spaces=False)))
if __name__ == "__main__":
args = setup_args()
pprint(args)
predictor = setup_predictor(args)
infer(args, predictor)

View File

@@ -0,0 +1,126 @@
# Paddle Serving服务化部署
本文档将介绍如何使用[Paddle Serving](https://github.com/PaddlePaddle/Serving/blob/develop/README_CN.md)工具部署自动文本摘要在线服务。
## 目录
- [Paddle Serving服务化部署](#paddle-serving服务化部署)
- [目录](#目录)
- [背景介绍](#背景介绍)
- [环境准备](#环境准备)
- [安装Paddle Serving](#安装paddle-serving)
- [模型转换](#模型转换)
- [pipeline部署](#pipeline部署)
- [修改配置文件](#修改配置文件)
- [server启动服务](#server启动服务)
- [client发送服务请求](#client发送服务请求)
## 背景介绍
Paddle Serving 依托深度学习框架 PaddlePaddle 旨在帮助深度学习开发者和企业提供高性能、灵活易用的工业级在线推理服务。Paddle Serving 支持 RESTful、gRPC、bRPC 等多种协议,提供多种异构硬件和多种操作系统环境下推理解决方案,和多种经典预训练模型示例。集成高性能服务端推理引擎 Paddle Inference 和端侧引擎 Paddle Lite。设计并实现基于有向无环图(DAG) 的异步流水线高性能推理框架,具有多模型组合、异步调度、并发推理、动态批量、多卡多流推理、请求缓存等特性。
Paddle Serving Python端预测部署主要包含以下步骤:
- 环境准备
- 模型转换
- 部署模型
## 环境准备
### 安装Paddle Serving
安装client和serving app,用于向服务发送请求:
```shell
pip install paddle_serving_app paddle_serving_client
```
安装GPU server,用于启动服务:
- 安装GPU server, 注意选择跟本地环境一致的命令
```shell
# CUDA10.2 + Cudnn7 + TensorRT6
pip install paddle-serving-server-gpu==0.8.3.post102 # -i https://pypi.tuna.tsinghua.edu.cn/simple
# CUDA10.1 + TensorRT6
pip install paddle-serving-server-gpu==0.8.3.post101 # -i https://pypi.tuna.tsinghua.edu.cn/simple
# CUDA11.2 + TensorRT8
pip install paddle-serving-server-gpu==0.8.3.post112 # -i https://pypi.tuna.tsinghua.edu.cn/simple
```
**NOTE:**
- 可以开启国内清华镜像源来加速下载
- 如果要安装最新版本的PaddleServing参考[链接](https://github.com/PaddlePaddle/Serving/blob/develop/doc/Latest_Packages_CN.md)。
## 模型转换
使用Paddle Serving做服务化部署时,需要将保存的inference模型转换为serving易于部署的模型。
用已安装的paddle_serving_client将静态图参数模型转换成serving格式。关于如何使用将训练后的动态图模型转为静态图模型详见[FasterGeneration加速及模型静态图导出](../../README.md)。
模型转换命令如下:
```shell
python -m paddle_serving_client.convert --dirname ../../inference_model \
--model_filename pegasus.pdmodel \
--params_filename pegasus.pdiparams \
--serving_server inference_model_server \
--serving_client inference_model_client
```
关键参数释义如下:
* `dirname`:模型文件夹地址。
* `model_filename`:模型文件名。
* `params_filename`:模型参数名。
* `serving_server`:server的模型文件和配置文件路径,默认"serving_server"。
* `serving_client`:client的配置文件路径,默认"serving_client"。
也可以直接使用`export_serving.sh`.
更多参数可通过以下命令查询:
```shell
python -m paddle_serving_client.convert --help
```
模型转换完成后,会在paddle_serving文件夹多出inference_model_server和inference_model_client的文件夹,文件夹目录格式如下:
```
inference_model_server/
├── pegasus.pdiparams
├── pegasus.pdmodel
├── serving_server_conf.prototxt
└── serving_server_conf.stream.prototxt
inference_model_client/
├── serving_client_conf.prototxt
└── serving_client_conf.stream.prototxt
```
## pipeline部署
paddle_serving目录包含启动pipeline服务和发送预测请求的代码,包括:
```
paddle_serving/
├──config.yml # 启动服务端的配置文件
├──pipeline_client.py # 发送pipeline预测请求的脚本
└──pipeline_service.py # 启动pipeline服务端的脚本
```
### 修改配置文件
目录中的`config.yml`文件解释了每一个参数的含义,可以根据实际需要修改其中的配置。
### server启动服务
修改好配置文件后,执行下面命令启动服务:
```shell
# 启动服务
python pipeline_service.py
```
成功启动服务后,log.txt中会打印类似如下日志
```
--- Running analysis [ir_graph_to_program_pass]
I1026 09:40:58.660128 20961 analysis_predictor.cc:1035] ======= optimize end =======
I1026 09:40:58.671124 20961 naive_executor.cc:102] --- skip [feed], feed -> input_ids
I1026 09:40:58.679420 20961 naive_executor.cc:102] --- skip [transpose_48.tmp_0], fetch -> fetch
[2022-10-26 09:40:58,682] [ INFO] - Already cached /root/.paddlenlp/models/IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese/vocab.txt
[2022-10-26 09:40:58,684] [ INFO] - Already cached /root/.paddlenlp/models/IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese/added_tokens.json
[2022-10-26 09:40:58,684] [ INFO] - Already cached /root/.paddlenlp/models/IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese/special_tokens_map.json
[2022-10-26 09:40:58,685] [ INFO] - Already cached /root/.paddlenlp/models/IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese/tokenizer_config.json
[PipelineServicer] succ init
2022/10/26 09:40:58 start proxy service
```
### client发送服务请求
执行以下命令发送文本摘要服务请求:
```shell
python pipeline_client.py
```
注意执行客户端请求时关闭代理,并根据实际情况修改server_url地址(启动服务所在的机器)。

View File

@@ -0,0 +1,54 @@
#rpc端口, rpc_port和http_port不允许同时为空。当rpc_port为空且http_port不为空时,会自动将rpc_port设置为http_port+1
rpc_port: 18011
#http端口, rpc_port和http_port不允许同时为空。当rpc_port可用且http_port为空时,不自动生成http_port
http_port: 9999
#worker_num, 最大并发数。
#当build_dag_each_worker=True时, 框架会创建worker_num个进程,每个进程内构建grpcSever和DAG
#当build_dag_each_worker=False时,框架会设置主线程grpc线程池的max_workers=worker_num
worker_num: 10
#build_dag_each_worker, False,框架在进程内创建一条DAG;True,框架会每个进程内创建多个独立的DAG
build_dag_each_worker: false
dag:
#op资源类型, True, 为线程模型;False,为进程模型
is_thread_op: True
#重试次数
retry: 1
#使用性能分析, True,生成Timeline性能数据,对性能有一定影响;False为不使用
use_profile: false
tracer:
interval_s: 10
op:
text_summarization:
#并发数,is_thread_op=True时,为线程并发;否则为进程并发
concurrency: 11
#当op配置没有server_endpoints时,从local_service_conf读取本地服务配置
local_service_conf:
#client类型,包括brpc, grpc和local_predictor.local_predictor不启动Serving服务,进程内预测
client_type: local_predictor
#模型路径
model_config: ./inference_model_server
#Fetch结果列表,以client_config中fetch_var的alias_name为准,不设置默认取全部输出变量
# fetch_list: ["transpose_48.tmp_0"]
# device_type, 0=cpu, 1=gpu, 2=tensorRT, 3=arm cpu, 4=kunlun xpu
device_type: 1
#计算硬件ID,当devices为""或不写时为CPU预测;当devices为"0", "0,1,2"时为GPU预测,表示使用的GPU卡
devices: "0"
#thread_num
thread_num: 12
#ir_optim
ir_optim: False

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
python -m paddle_serving_client.convert --dirname ../../inference_model \
--model_filename pegasus.pdmodel \
--params_filename pegasus.pdiparams \
--serving_server inference_model_server \
--serving_client inference_model_client

View File

@@ -0,0 +1,51 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
import time
from paddle_serving_server.pipeline import PipelineClient
from paddlenlp.utils.log import logger
class Runner(object):
def __init__(
self,
server_url: str,
):
self.client = PipelineClient()
self.client.connect([server_url])
def Run(self, data):
start_time = time.time()
ret = self.client.predict(feed_dict={"inputs": data})
end_time = time.time()
logger.info("time cost :{} seconds".format(end_time - start_time))
if not ret.value:
logger.warning('Fail to fetch summary.')
# ret is special class but a dict
for d, s in zip(data, eval(ret.value[0])):
print("Text: ", d)
print("Summary: ", s[0])
print("-" * 50)
if __name__ == "__main__":
server_url = "127.0.0.1:18011"
runner = Runner(server_url)
texts = [
"在北京冬奥会自由式滑雪女子坡面障碍技巧决赛中,中国选手谷爱凌夺得银牌。祝贺谷爱凌!今天上午,自由式滑雪女子坡面障碍技巧决赛举行。决赛分三轮进行,取选手最佳成绩排名决出奖牌。第一跳,中国选手谷爱凌获得69.90分。在12位选手中排名第三。完成动作后,谷爱凌又扮了个鬼脸,甚是可爱。第二轮中,谷爱凌在道具区第三个障碍处失误,落地时摔倒。获得16.98分。网友:摔倒了也没关系,继续加油!在第二跳失误摔倒的情况下,谷爱凌顶住压力,第三跳稳稳发挥,流畅落地!获得86.23分!此轮比赛,共12位选手参赛,谷爱凌第10位出场。网友:看比赛时我比谷爱凌紧张,加油!",
"据微信公众号“界面”报道,4日上午10点左右,中国发改委反垄断调查小组突击查访奔驰上海办事处,调取数据材料,并对多名奔驰高管进行了约谈。截止昨日晚9点,包括北京梅赛德斯-奔驰销售服务有限公司东区总经理在内的多名管理人员仍留在上海办公室内"
]
runner.Run(texts)

View File

@@ -0,0 +1,88 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
from numpy import array
import paddle_serving_server.pipeline.operator
from paddle_serving_server.web_service import WebService, Op
from paddlenlp.transformers import PegasusChineseTokenizer
from paddlenlp.ops.ext_utils import load
from paddlenlp.utils.log import logger
def convert_example(example, tokenizer, max_seq_len=512):
"""Convert all examples into necessary features."""
tokenized_example = tokenizer(example,
max_length=max_seq_len,
padding=True,
truncation=True,
return_attention_mask=False)
input_dict = {}
input_dict["input_ids"] = np.asarray(tokenized_example['input_ids'],
dtype='int32')
return input_dict
class PegasusOp(Op):
"""Op for pegasus."""
def init_op(self):
self.tokenizer = PegasusChineseTokenizer.from_pretrained(
'IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese')
def preprocess(self, input_dicts, data_id, log_id):
# Convert input format
(_, input_dict), = input_dicts.items()
data = input_dict["inputs"]
if isinstance(data, str) and "array(" in data:
data = eval(data)
else:
logger.error("input value {}is not supported.".format(data))
input_dict = convert_example(list(data),
self.tokenizer,
max_seq_len=128)
# the first return must be a dict or a list of dict, the dict corresponding to a batch of model input
return input_dict, False, None, ""
def postprocess(self, input_dicts, fetch_dict, data_id, log_id):
outputs = fetch_dict['transpose_48.tmp_0']
results = []
for sample in outputs:
result = []
for idx, beam in enumerate(sample):
if idx >= len(sample) // 2:
break
res = self.tokenizer.decode(beam,
skip_special_tokens=True,
clean_up_tokenization_spaces=False)
result.append(res)
results.append(result)
out_dict = {}
out_dict["outputs"] = str(results)
# the first return must be a dict or a list of dict, the dict corresponding to a batch of model output
return out_dict, None, ""
class PegasusService(WebService):
def get_pipeline_response(self, read_op):
return PegasusOp(name="text_summarization", input_ops=[read_op])
if __name__ == "__main__":
# Load FasterTransformer lib.
load("FasterTransformer", verbose=True)
service = PegasusService(name="text_summarization")
service.prepare_pipeline_config("config.yml")
service.run_service()

View File

@@ -0,0 +1,159 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import argparse
import paddle
from pprint import pprint
from paddlenlp.transformers import PegasusChineseTokenizer, PegasusForConditionalGeneration
from paddlenlp.ops import FasterPegasus
from paddlenlp.utils.log import logger
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument(
"--model_name_or_path",
default="IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese",
type=str,
help="The model name to specify the Pegasus to use. ")
parser.add_argument("--inference_model_dir",
default="./inference_model",
type=str,
help="Path to save inference model of Pegasus. ")
parser.add_argument(
"--topk",
default=4,
type=int,
help="The number of candidate to procedure top_k sampling. ")
parser.add_argument(
"--topp",
default=1.0,
type=float,
help="The probability threshold to procedure top_p sampling. ")
parser.add_argument("--max_out_len",
default=64,
type=int,
help="Maximum output length. ")
parser.add_argument("--min_out_len",
default=1,
type=int,
help="Minimum output length. ")
parser.add_argument("--num_return_sequence",
default=1,
type=int,
help="The number of returned sequence. ")
parser.add_argument("--temperature",
default=1.0,
type=float,
help="The temperature to set. ")
parser.add_argument("--num_return_sequences",
default=1,
type=int,
help="The number of returned sequences. ")
parser.add_argument("--use_fp16_decoding",
action="store_true",
help="Whether to use fp16 decoding to predict. ")
parser.add_argument("--decoding_strategy",
default="beam_search",
choices=["beam_search"],
type=str,
help="The main strategy to decode. ")
parser.add_argument(
"--num_beams",
default=4,
type=int,
help="The number of candidate to procedure beam search. ")
parser.add_argument("--diversity_rate",
default=0.0,
type=float,
help="The diversity rate to procedure beam search. ")
parser.add_argument(
"--length_penalty",
default=0.0,
type=float,
help=
"The exponential penalty to the sequence length in the beam_search strategy. "
)
args = parser.parse_args()
return args
def do_predict(args):
place = "gpu"
place = paddle.set_device(place)
model_name_or_path = args.model_name_or_path
model = PegasusForConditionalGeneration.from_pretrained(model_name_or_path)
tokenizer = PegasusChineseTokenizer.from_pretrained(model_name_or_path)
pegasus = FasterPegasus(model=model,
use_fp16_decoding=args.use_fp16_decoding,
trans_out=True)
# Set evaluate mode
pegasus.eval()
# Convert dygraph model to static graph model
pegasus = paddle.jit.to_static(
pegasus,
input_spec=[
# input_ids
paddle.static.InputSpec(shape=[None, None], dtype="int32"),
# encoder_output
None,
# seq_len
None,
# min_length
args.min_out_len,
# max_length
args.max_out_len,
# num_beams. Used for beam_search.
args.num_beams,
# decoding_strategy
args.decoding_strategy,
# decoder_start_token_id
model.decoder_start_token_id,
# bos_token_id
tokenizer.bos_token_id,
# eos_token_id
tokenizer.eos_token_id,
# pad_token_id
tokenizer.pad_token_id,
# diversity rate. Used for beam search.
args.diversity_rate,
# length_penalty
args.length_penalty,
# topk
args.topk,
# topp
args.topp,
# temperature
args.temperature,
# num_return_sequences
args.num_return_sequences,
])
# Save converted static graph model
paddle.jit.save(pegasus, os.path.join(args.inference_model_dir, "pegasus"))
logger.info("PEGASUS has been saved to {}.".format(
args.inference_model_dir))
if __name__ == "__main__":
args = parse_args()
pprint(args)
do_predict(args)

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
python export_model.py \
--model_name_or_path IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese \
--decoding_strategy beam_search \
--inference_model_dir ./inference_model \
--max_out_len 30 \

View File

@@ -0,0 +1 @@
rouge==1.0.1

View File

@@ -0,0 +1,223 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import argparse
import random
import time
from functools import partial
from pprint import pprint
import numpy as np
from datasets import load_dataset
import paddle
from paddle.io import BatchSampler, DataLoader
from paddlenlp.transformers import PegasusForConditionalGeneration, PegasusChineseTokenizer
from utils import convert_example, compute_metrics
from paddlenlp.data import DataCollatorForSeq2Seq
def parse_args():
parser = argparse.ArgumentParser()
# Required parameters
parser.add_argument(
"--model_name_or_path",
default="IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese",
type=str,
required=True,
help="Path to pre-trained model. ")
parser.add_argument("--prefict_file",
type=str,
required=False,
default=None,
help="Predict data path.")
parser.add_argument(
'--output_path',
type=str,
default='generate.txt',
help='The file path where the infer result will be saved.')
parser.add_argument(
"--max_source_length",
default=1024,
type=int,
help="The maximum total input sequence length after "
"tokenization.Sequences longer than this will be truncated, sequences shorter will be padded.",
)
parser.add_argument(
"--min_target_length",
default=0,
type=int,
help=
"The minimum total sequence length for target text when generating. ")
parser.add_argument(
"--max_target_length",
default=142,
type=int,
help="The maximum total sequence length for target text after "
"tokenization. Sequences longer than this will be truncated, sequences shorter will be padded."
"during ``evaluate`` and ``predict``.",
)
parser.add_argument('--decode_strategy',
default='greedy_search',
type=str,
help='The decode strategy in generation.')
parser.add_argument(
'--top_k',
default=2,
type=int,
help=
'The number of highest probability vocabulary tokens to keep for top-k sampling.'
)
parser.add_argument('--top_p',
default=1.0,
type=float,
help='The cumulative probability for top-p sampling.')
parser.add_argument('--num_beams',
default=1,
type=int,
help='The number of beams for beam search.')
parser.add_argument(
'--length_penalty',
default=0.6,
type=float,
help='The exponential penalty to the sequence length for beam search.')
parser.add_argument(
'--early_stopping',
default=False,
type=eval,
help=
'Whether to stop the beam search when at least `num_beams` sentences are finished per batch or not.'
)
parser.add_argument("--diversity_rate",
default=0.0,
type=float,
help="The diversity of beam search. ")
parser.add_argument(
'--faster',
action='store_true',
help='Whether to process inference using faster transformer. ')
parser.add_argument(
'--use_fp16_decoding',
action='store_true',
help=
'Whether to use fp16 when using faster transformer. Only works when using faster transformer. '
)
parser.add_argument(
"--batch_size",
default=64,
type=int,
help="Batch size per GPU/CPU for testing or evaluation.")
parser.add_argument("--seed",
default=42,
type=int,
help="random seed for initialization")
parser.add_argument(
"--device",
default="gpu",
type=str,
choices=["cpu", "gpu", "xpu"],
help="The device to select to train the model, is must be cpu/gpu/xpu.")
parser.add_argument("--logging_steps",
type=int,
default=100,
help="Log every X updates steps.")
args = parser.parse_args()
return args
def set_seed(args):
# Use the same data seed(for data shuffle) for all procs to guarantee data
# consistency after sharding.
random.seed(args.seed)
np.random.seed(args.seed)
# Maybe different op seeds(for dropout) for different procs is better. By:
# `paddle.seed(args.seed + paddle.distributed.get_rank())`
paddle.seed(args.seed)
@paddle.no_grad()
def generate(args):
paddle.set_device(args.device)
set_seed(args)
tokenizer = PegasusChineseTokenizer.from_pretrained(args.model_name_or_path)
model = PegasusForConditionalGeneration.from_pretrained(
args.model_name_or_path)
dataset = load_dataset("json", data_files=args.prefict_file, split="train")
remove_columns = ['content', 'title']
trans_func = partial(convert_example,
text_column='content',
summary_column='title',
tokenizer=tokenizer,
max_source_length=args.max_source_length,
max_target_length=args.max_target_length)
dataset = dataset.map(trans_func,
batched=True,
load_from_cache_file=True,
remove_columns=remove_columns)
batch_sampler = BatchSampler(dataset,
batch_size=args.batch_size,
shuffle=False)
batchify_fn = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=model)
data_loader = DataLoader(dataset=dataset,
batch_sampler=batch_sampler,
num_workers=0,
collate_fn=batchify_fn,
return_list=True)
data_loader.pin_memory = False
model.eval()
total_time = 0.0
start_time = time.time()
all_preds = []
all_labels = []
for step, batch in enumerate(data_loader):
labels = batch.pop('labels').numpy()
preds, _ = model.generate(input_ids=batch['input_ids'],
attention_mask=batch['attention_mask'],
max_length=args.max_target_length,
min_length=args.min_target_length,
decode_strategy=args.decode_strategy,
top_k=args.top_k,
top_p=args.top_p,
num_beams=args.num_beams,
length_penalty=args.length_penalty,
early_stopping=args.early_stopping,
diversity_rate=args.diversity_rate,
use_faster=args.faster)
total_time += (time.time() - start_time)
if step % args.logging_steps == 0:
print('step %d - %.3fs/step' %
(step, total_time / args.logging_steps))
total_time = 0.0
all_preds.extend(
tokenizer.batch_decode(preds.numpy(),
skip_special_tokens=True,
clean_up_tokenization_spaces=False))
labels = np.where(labels != -100, labels, tokenizer.pad_token_id)
all_labels.extend(
tokenizer.batch_decode(labels,
skip_special_tokens=True,
clean_up_tokenization_spaces=False))
start_time = time.time()
compute_metrics(all_preds, all_labels)
with open(args.output_path, 'w', encoding='utf-8') as fout:
for decoded_pred in all_preds:
fout.write(decoded_pred + '\n')
print('Save generated result into: %s' % args.output_path)
if __name__ == '__main__':
args = parse_args()
pprint(args)
generate(args)

View File

@@ -0,0 +1,24 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# GPU启动,参数`--gpus`指定训练所用的GPU卡号,可以是单卡,也可以多卡
unset CUDA_VISIBLE_DEVICES
python run_generate.py \
--model_name_or_path=pegesus_out/bart_model_50000.pdparams \
--prefict_file valid.json \
--max_source_length 128 \
--max_target_length 64 \
--batch_size 128 \
--device=gpu \

View File

@@ -0,0 +1,339 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import json
import argparse
import random
import time
import distutils.util
from pprint import pprint
from functools import partial
from tqdm import tqdm
import numpy as np
import math
from datasets import load_dataset
import paddle
import paddle.nn as nn
from paddle.io import BatchSampler, DistributedBatchSampler, DataLoader
from paddlenlp.transformers import PegasusForConditionalGeneration, PegasusChineseTokenizer
from paddlenlp.transformers import LinearDecayWithWarmup
from paddlenlp.utils.log import logger
from paddlenlp.data import DataCollatorForSeq2Seq
from utils import convert_example, compute_metrics, main_process_first
def parse_args():
parser = argparse.ArgumentParser()
# Required parameters
parser.add_argument(
"--model_name_or_path",
default="IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese",
type=str,
required=True,
help="Path to pre-trained model. ")
parser.add_argument("--train_file",
type=str,
required=False,
default=None,
help="Train data path.")
parser.add_argument("--eval_file",
type=str,
required=False,
default=None,
help="Eval data path.")
parser.add_argument(
"--output_dir",
default="output",
type=str,
required=True,
help=
"The output directory where the model predictions and checkpoints will be written.",
)
parser.add_argument(
"--max_source_length",
default=128,
type=int,
help="The maximum total input sequence length after "
"tokenization.Sequences longer than this will be truncated, sequences shorter will be padded.",
)
parser.add_argument(
"--min_target_length",
default=0,
type=int,
help=
"The minimum total sequence length for target text when generating. ")
parser.add_argument(
"--max_target_length",
default=64,
type=int,
help="The maximum total sequence length for target text after "
"tokenization. Sequences longer than this will be truncated, sequences shorter will be padded."
"during ``evaluate`` and ``predict``.",
)
parser.add_argument("--learning_rate",
default=1e-4,
type=float,
help="The initial learning rate for Adam.")
parser.add_argument(
"--num_train_epochs",
default=3,
type=int,
help="Total number of training epochs to perform.",
)
parser.add_argument("--logging_steps",
type=int,
default=100,
help="Log every X updates steps.")
parser.add_argument("--save_steps",
type=int,
default=100,
help="Save checkpoint every X updates steps.")
parser.add_argument(
"--train_batch_size",
default=20,
type=int,
help="Batch size per GPU/CPU for training.",
)
parser.add_argument(
"--eval_batch_size",
default=12,
type=int,
help="Batch size per GPU/CPU for evaluation.",
)
parser.add_argument("--weight_decay",
default=0.0,
type=float,
help="Weight decay if we apply some.")
parser.add_argument(
"--warmup_steps",
default=0,
type=int,
help=
"Linear warmup over warmup_steps. If > 0: Override warmup_proportion")
parser.add_argument("--warmup_proportion",
default=0.1,
type=float,
help="Linear warmup proportion over total steps.")
parser.add_argument("--adam_epsilon",
default=1e-6,
type=float,
help="Epsilon for Adam optimizer.")
parser.add_argument(
"--max_steps",
default=-1,
type=int,
help=
"If > 0: set total number of training steps to perform. Override num_train_epochs.",
)
parser.add_argument("--seed",
default=42,
type=int,
help="random seed for initialization")
parser.add_argument(
"--device",
default="gpu",
type=str,
choices=["cpu", "gpu", "xpu"],
help="The device to select to train the model, is must be cpu/gpu/xpu.")
parser.add_argument("--use_amp",
default=False,
type=distutils.util.strtobool,
help="Enable mixed precision training.")
parser.add_argument("--scale_loss",
default=2**15,
type=float,
help="The value of scale_loss for fp16.")
args = parser.parse_args()
return args
def set_seed(args):
# Use the same data seed(for data shuffle) for all procs to guarantee data
# consistency after sharding.
random.seed(args.seed)
np.random.seed(args.seed)
# Maybe different op seeds(for dropout) for different procs is better. By:
# `paddle.seed(args.seed + paddle.distributed.get_rank())`
paddle.seed(args.seed)
@paddle.no_grad()
def evaluate(model, data_loader, tokenizer, min_target_length,
max_target_length):
model.eval()
all_preds = []
all_labels = []
model = model._layers if isinstance(model, paddle.DataParallel) else model
for batch in tqdm(data_loader, total=len(data_loader), desc="Eval step"):
labels = batch.pop('labels').numpy()
preds = model.generate(input_ids=batch['input_ids'],
attention_mask=batch['attention_mask'],
min_length=min_target_length,
max_length=max_target_length,
use_cache=True)[0]
all_preds.extend(
tokenizer.batch_decode(preds.numpy(),
skip_special_tokens=True,
clean_up_tokenization_spaces=False))
labels = np.where(labels != -100, labels, tokenizer.pad_token_id)
all_labels.extend(
tokenizer.batch_decode(labels,
skip_special_tokens=True,
clean_up_tokenization_spaces=False))
compute_metrics(all_preds, all_labels)
model.train()
def do_train(args):
paddle.set_device(args.device)
if paddle.distributed.get_world_size() > 1:
paddle.distributed.init_parallel_env()
set_seed(args)
tokenizer = PegasusChineseTokenizer.from_pretrained(args.model_name_or_path)
train_set = load_dataset("json", data_files=args.train_file, split="train")
dev_set = load_dataset("json", data_files=args.eval_file, split="train")
remove_columns = ['content', 'title']
trans_func = partial(convert_example,
text_column='content',
summary_column='title',
tokenizer=tokenizer,
max_source_length=args.max_source_length,
max_target_length=args.max_target_length)
with main_process_first(desc="train dataset map pre-processing"):
train_set = train_set.map(trans_func,
batched=True,
load_from_cache_file=True,
remove_columns=remove_columns)
with main_process_first(desc="dev dataset map pre-processing"):
dev_set = dev_set.map(trans_func,
batched=True,
load_from_cache_file=True,
remove_columns=remove_columns)
model = PegasusForConditionalGeneration.from_pretrained(
args.model_name_or_path)
batchify_fn = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=model)
train_batch_sampler = DistributedBatchSampler(
train_set, batch_size=args.train_batch_size, shuffle=True)
train_data_loader = DataLoader(dataset=train_set,
batch_sampler=train_batch_sampler,
num_workers=0,
collate_fn=batchify_fn,
return_list=True)
dev_batch_sampler = BatchSampler(dev_set,
batch_size=args.eval_batch_size,
shuffle=False)
dev_data_loader = DataLoader(dataset=dev_set,
batch_sampler=dev_batch_sampler,
num_workers=0,
collate_fn=batchify_fn,
return_list=True)
if paddle.distributed.get_world_size() > 1:
model = paddle.DataParallel(model)
if args.max_steps > 0:
num_training_steps = args.max_steps
num_train_epochs = math.ceil(num_training_steps /
len(train_data_loader))
else:
num_training_steps = len(train_data_loader) * args.num_train_epochs
num_train_epochs = args.num_train_epochs
warmup = args.warmup_steps if args.warmup_steps > 0 else args.warmup_proportion
lr_scheduler = LinearDecayWithWarmup(args.learning_rate, num_training_steps,
warmup)
# Generate parameter names needed to perform weight decay.
# All bias and LayerNorm parameters are excluded.
decay_params = [
p.name for n, p in model.named_parameters()
if not any(nd in n for nd in ["bias", "norm"])
]
optimizer = paddle.optimizer.AdamW(
learning_rate=lr_scheduler,
beta1=0.9,
beta2=0.999,
epsilon=args.adam_epsilon,
parameters=model.parameters(),
weight_decay=args.weight_decay,
apply_decay_param_fun=lambda x: x in decay_params)
if args.use_amp:
scaler = paddle.amp.GradScaler(init_loss_scaling=args.scale_loss)
global_step = 0
tic_train = time.time()
for epoch in range(num_train_epochs):
for step, batch in enumerate(train_data_loader):
global_step += 1
with paddle.amp.auto_cast(
args.use_amp,
custom_white_list=["layer_norm", "softmax", "gelu"]):
lm_logits, new_cache, loss = model(**batch)
if args.use_amp:
scaled_loss = scaler.scale(loss)
scaled_loss.backward()
scaler.minimize(optimizer, scaled_loss)
else:
loss.backward()
optimizer.step()
lr_scheduler.step()
optimizer.clear_grad()
if global_step % args.logging_steps == 0:
logger.info(
"global step %d/%d, epoch: %d, batch: %d, rank_id: %s, loss: %f, lr: %.10f, speed: %.4f step/s"
% (global_step, num_training_steps, epoch, step,
paddle.distributed.get_rank(), loss, optimizer.get_lr(),
args.logging_steps / (time.time() - tic_train)))
tic_train = time.time()
if global_step % args.save_steps == 0 or global_step == num_training_steps:
tic_eval = time.time()
evaluate(model, dev_data_loader, tokenizer,
args.min_target_length, args.max_target_length)
logger.info("eval done total : %s s" % (time.time() - tic_eval))
if paddle.distributed.get_rank() == 0:
output_dir = os.path.join(args.output_dir,
"pegeaus_model_%d" % global_step)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Need better way to get inner model of DataParallel
model_to_save = model._layers if isinstance(
model, paddle.DataParallel) else model
model_to_save.save_pretrained(output_dir)
tokenizer.save_pretrained(output_dir)
if global_step >= num_training_steps:
return
if paddle.distributed.get_rank() == 0:
output_dir = os.path.join(args.output_dir,
"pegeaus_modelfinal_%d" % global_step)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Need better way to get inner model of DataParallel
model_to_save = model._layers if isinstance(
model, paddle.DataParallel) else model
model_to_save.save_pretrained(output_dir)
tokenizer.save_pretrained(output_dir)
if __name__ == "__main__":
args = parse_args()
pprint(args)
do_train(args)

View File

@@ -0,0 +1,33 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# GPU启动,参数`--gpus`指定训练所用的GPU卡号,可以是单卡,也可以多卡
unset CUDA_VISIBLE_DEVICES
python -m paddle.distributed.launch --gpus "2,3,4,5,6,7" run_summarization.py \
--model_name_or_path=IDEA-CCNL/Randeng-Pegasus-238M-Summary-Chinese \
--train_file train.json \
--eval_file test.json \
--output_dir pegesus_out \
--max_source_length 128 \
--max_target_length 64 \
--num_train_epochs 20 \
--logging_steps 1 \
--save_steps 10000 \
--train_batch_size 128 \
--eval_batch_size 128 \
--learning_rate 5e-5 \
--warmup_proportion 0.02 \
--weight_decay=0.01 \
--device=gpu \

View File

@@ -0,0 +1,98 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
import contextlib
from rouge import Rouge
import json
import paddle
from paddlenlp.data import Pad
from paddlenlp.metrics import BLEU
from paddlenlp.utils.log import logger
def convert_example(example, text_column, summary_column, tokenizer,
max_source_length, max_target_length):
"""
Convert a example into necessary features.
"""
inputs = example[text_column]
targets = example[summary_column]
model_inputs = tokenizer(inputs,
max_length=max_source_length,
padding=False,
truncation=True,
return_attention_mask=True)
labels = tokenizer(targets,
max_length=max_target_length,
padding=False,
truncation=True)
model_inputs["labels"] = labels["input_ids"]
return model_inputs
def compute_metrics(preds, targets):
assert len(preds) == len(targets), (
'The length of pred_responses should be equal to the length of '
'target_responses. But received {} and {}.'.format(
len(preds), len(targets)))
rouge = Rouge()
bleu4 = BLEU(n_size=4)
scores = []
for pred, target in zip(preds, targets):
try:
score = rouge.get_scores(' '.join(pred), ' '.join(target))
scores.append([
score[0]['rouge-1']['f'], score[0]['rouge-2']['f'],
score[0]['rouge-l']['f']
])
except ValueError:
scores.append([0, 0, 0])
bleu4.add_inst(pred, [target])
rouge1 = np.mean([i[0] for i in scores])
rouge2 = np.mean([i[1] for i in scores])
rougel = np.mean([i[2] for i in scores])
print('\n' + '*' * 15)
print('The auto evaluation result is:')
print('rouge-1:', round(rouge1, 4))
print('rouge-2:', round(rouge2, 4))
print('rouge-L:', round(rougel, 4))
print('BLEU-4:', round(bleu4.score(), 4))
@contextlib.contextmanager
def main_process_first(desc="work"):
if paddle.distributed.get_world_size() > 1:
rank = paddle.distributed.get_rank()
is_main_process = rank == 0
main_process_desc = "main local process"
try:
if not is_main_process:
# tell all replicas to wait
logger.debug(
f"{rank}: waiting for the {main_process_desc} to perform {desc}"
)
paddle.distributed.barrier()
yield
finally:
if is_main_process:
# the wait is over
logger.debug(
f"{rank}: {main_process_desc} completed {desc}, releasing all replicas"
)
paddle.distributed.barrier()
else:
yield

View File

@@ -18,7 +18,7 @@
- [模型训练](#模型训练)
- [模型预测](#模型预测)
- [模型推理部署](#模型推理部署)
- [FasterTransformer加速及模型静态图导出](#fastertransformer加速及模型静态图导出)
- [FasterGeneration加速及模型静态图导出](#fastergeneration加速及模型静态图导出)
- [模型部署](#模型部署)
- [References](#references)
@@ -30,7 +30,7 @@
本项目是基于预训练语言模型UNIMO-Text的文本摘要,具有以下优势:
- 效果领先。
- 开箱即用。本项目提供TaskFlow接口,无需训练,仅需几行代码便可预测。
- 高性能推理。本项目基于FasterTransformer进行推理加速,能够提供更高性能的推理体验。
- 高性能推理。本项目基于[FasterGeneration](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/faster_generation)进行推理加速,能够提供更高性能的推理体验。
- 训练推理全流程打通。本项目提供了全面的定制训练流程,从数据准备、模型训练预测,到模型推理部署,一应俱全。
### 基于预训练语言模型的文本摘要
@@ -92,7 +92,7 @@ PaddleNLP提供开箱即用的产业级NLP预置任务能力,无需训练,
- 模型部署需要将保存的最佳模型参数(动态图)导出成静态图参数,用于后续的推理部署。
- 文本摘要应用提供了基于Paddle Serving的本地部署predictor,并且支持在GPU设备使用Faster Generation进行加速。
- 文本摘要应用提供了基于Paddle Inference的本地部署predictor,并且支持在GPU设备使用FasterGeneration进行加速。
- 文本摘要应用提供了基于Paddle Serving的服务端部署方案。
@@ -112,6 +112,7 @@ text_summarization/
│ ├── config.yml # 配置文件
│ ├── pipeline_client.py # 客户端程序
│ ├── pipeline_service.py # 服务器程序
│ ├── export_serving.sh # serving模型导出脚本
│ └── README.md # 说明文档
├── export_model.py # 动态图参数导出静态图参数脚本
├── export_model.sh # 动态图参数导出静态图参数shell脚本
@@ -258,9 +259,9 @@ Finetuned baseline的模型在[LCSTS](https://aclanthology.org/D15-1229/)测试
### 模型推理部署
#### FasterTransformer加速及模型静态图导出
#### FasterGeneration加速及模型静态图导出
使用动态图训练结束之后,可以通过[静态图导出脚本](export_model.py)实现基于FasterTransformer的高性能预测加速,并将动态图参数导出成静态图参数,静态图参数保存在`output_path`指定路径中。运行方式:
使用动态图训练结束之后,可以通过[静态图导出脚本](export_model.py)实现基于FasterGeneration的高性能预测加速,并将动态图参数导出成静态图参数,静态图参数保存在`output_path`指定路径中。运行方式:
```shell
python export_model.py \

View File

@@ -0,0 +1,31 @@
# Paddle Inference部署
本文档将介绍如何使用[Paddle Inference](https://paddle-inference.readthedocs.io/en/latest/guides/introduction/index_intro.html#paddle-inference)工具进行自动文本摘要应用高性能推理推理部署。
**目录**
* [背景介绍](#背景介绍)
* [导出预测部署模型](#导出预测部署模型)
* [基于Python预测](#基于Python预测)
## 背景介绍
Paddle inference和主框架的Model.predict均可实现推理预测,Paddle Inference 是飞桨的原生推理库, 作用于服务器端和云端,提供高性能的推理能力,主框架的Model 对象是一个具备训练、测试、推理的神经网络。相比于Model.predict,inference可使用MKLDNN、CUDNN、TensorRT进行预测加速。Model.predict适用于训练好的模型直接进行预测,paddle inference适用于对推理性能、通用性有要求的用户,针对不同平台不同的应用场景进行了深度的适配优化,保证模型在服务器端即训即用,快速部署。由于 Paddle Inference 能力直接基于飞桨的训练算子,因此它支持飞桨训练出的所有模型的推理。
Paddle Inference Python端预测部署主要包含两个步骤:
- 导出预测部署模型
- 基于Python预测
## 导出预测部署模型
部署时需要使用预测格式的模型(即动态图转静态图操作)。预测格式模型相对训练格式模型而言,在拓扑上裁剪掉了预测不需要的算子,并且会做特定部署优化。具体操作详见[FasterGeneration加速及模型静态图导出](../../README.md)。
## 基于Python预测
<!-- 同上,高性能预测的默认输入和输出形式也为文件,可分别通过 test_path 和 save_path 进行指定,通过如下命令便可以基于Paddle Inference 进行高性能预测: -->
在终端输入以下命令可在GPU上进行预测:
```shell
python inference_unimo_text.py --inference_model_dir ../../inference_model
```
关键参数释义如下:
* `inference_model_dir`:用于高性能推理的静态图模型参数路径;默认为"../../inference_model"。

View File

@@ -28,7 +28,7 @@ def setup_args():
"""Setup arguments."""
parser = argparse.ArgumentParser()
parser.add_argument("--inference_model_dir",
default="./infer_model",
default="../../inference_model",
type=str,
help="Path to save inference model of UNIMOText. ")
args = parser.parse_args()

View File

@@ -49,15 +49,15 @@ pip install paddle-serving-server-gpu==0.8.3.post112 # -i https://pypi.tuna.tsin
使用Paddle Serving做服务化部署时,需要将保存的inference模型转换为serving易于部署的模型。
用已安装的paddle_serving_client将静态图参数模型转换成serving格式。关于如何使用将训练后的动态图模型转为静态图模型详见[FasterTransformer加速及模型静态图导出](../../README.md)。
用已安装的paddle_serving_client将静态图参数模型转换成serving格式。关于如何使用将训练后的动态图模型转为静态图模型详见[FasterGeneration加速及模型静态图导出](../../README.md)。
模型转换命令如下:
```shell
python -m paddle_serving_client.convert --dirname ./inference_model \
python -m paddle_serving_client.convert --dirname ../../inference_model \
--model_filename unimo_text.pdmodel \
--params_filename unimo_text.pdiparams \
--serving_server ./deploy/paddle_serving/inference_model_server \
--serving_client ./deploy/paddle_serving/inference_model_client
--serving_server inference_model_server \
--serving_client inference_model_client
```
关键参数释义如下:
* `dirname`:模型文件夹地址。
@@ -66,11 +66,13 @@ python -m paddle_serving_client.convert --dirname ./inference_model \
* `serving_server`:server的模型文件和配置文件路径,默认"serving_server"。
* `serving_client`:client的配置文件路径,默认"serving_client"。
也可以直接使用`export_serving.sh`.
更多参数可通过以下命令查询:
```shell
python -m paddle_serving_client.convert --help
```
模型转换完成后,会在./delopy/paddle_serving文件夹多出inference_model_server和inference_model_client的文件夹,文件夹目录格式如下:
模型转换完成后,会在paddle_serving文件夹多出inference_model_server和inference_model_client的文件夹,文件夹目录格式如下:
```
inference_model_server/
├── unimo_text.pdiparams
@@ -99,7 +101,6 @@ paddle_serving/
### server启动服务
修改好配置文件后,执行下面命令启动服务:
```shell
cd deploy/paddle_serving
# 启动服务
python pipeline_service.py
```

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
python -m paddle_serving_client.convert --dirname ../../inference_model \
--model_filename unimo_text.pdmodel \
--params_filename unimo_text.pdiparams \
--serving_server inference_model_server \
--serving_client inference_model_client

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
python export_model.py \
--model_name_or_path unimo-text-1.0-summary \
--decoding_strategy beam_search \
--inference_model_dir ./inference_model \
--max_out_len 30 \

Some files were not shown because too many files have changed in this diff Show More