Compare commits
343 Commits
v2.3.7
...
ppdiffuser
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c92c543f2 | ||
|
|
a85212ed00 | ||
|
|
6f71c7cf5e | ||
|
|
767d3552e3 | ||
|
|
feb9d8296b | ||
|
|
00ae25bf35 | ||
|
|
e97f670440 | ||
|
|
6289d9c0d3 | ||
|
|
7b4cf36b90 | ||
|
|
a50fbbcc30 | ||
|
|
9e2a0a8a9f | ||
|
|
f74de55082 | ||
|
|
e785bb1163 | ||
|
|
ce31a77f90 | ||
|
|
58a5a9dcfd | ||
|
|
6387410b5a | ||
|
|
1a53c35887 | ||
|
|
fd6ef4058e | ||
|
|
1f2b2c5d58 | ||
|
|
7b6454908a | ||
|
|
02b4383b7e | ||
|
|
6471ce331a | ||
|
|
61acf19460 | ||
|
|
c38902e3a8 | ||
|
|
1fc23a8888 | ||
|
|
afeb623588 | ||
|
|
ff546f6d9a | ||
|
|
81bb7d1433 | ||
|
|
6eb6937b69 | ||
|
|
228c58a494 | ||
|
|
e94af7978a | ||
|
|
83a9c3893a | ||
|
|
bdd659d266 | ||
|
|
b52c2ea5d2 | ||
|
|
2483d4fb85 | ||
|
|
7bc85cdfb2 | ||
|
|
513a8328d9 | ||
|
|
3e2ddd182c | ||
|
|
b90ed42dff | ||
|
|
b705fa481d | ||
|
|
cf478ba6ee | ||
|
|
9eda9a46c4 | ||
|
|
1f88c41d14 | ||
|
|
7f650ac0ca | ||
|
|
b6c3589ea6 | ||
|
|
c2e1dc4852 | ||
|
|
1c5e127866 | ||
|
|
c8bc4405fc | ||
|
|
05e7432ef7 | ||
|
|
d390dc95e8 | ||
|
|
b262611f37 | ||
|
|
78c8615791 | ||
|
|
16aa2ba5b1 | ||
|
|
21345f8d2e | ||
|
|
c9c5c15a66 | ||
|
|
d57e350f9e | ||
|
|
295d68e940 | ||
|
|
947007f552 | ||
|
|
14c934c1a1 | ||
|
|
e98231f911 | ||
|
|
d1506f8a38 | ||
|
|
94864bc48e | ||
|
|
b0f7650ecf | ||
|
|
cd5a2e35a6 | ||
|
|
91d5c527dd | ||
|
|
fca7ca25da | ||
|
|
b0ba2e1e79 | ||
|
|
553ba12211 | ||
|
|
122824885c | ||
|
|
211e8204dd | ||
|
|
47f7c36e1e | ||
|
|
7eac0586bc | ||
|
|
a0f5a8ebcd | ||
|
|
636e3430fc | ||
|
|
d52d8e5ea1 | ||
|
|
97fe71d000 | ||
|
|
1bad94989f | ||
|
|
04a742106e | ||
|
|
1076b890de | ||
|
|
219b6abd15 | ||
|
|
fb0cb9b35b | ||
|
|
293c8308af | ||
|
|
e14487780b | ||
|
|
39b49c928f | ||
|
|
38fcccbd86 | ||
|
|
31dc47aed5 | ||
|
|
8f3e4e51e3 | ||
|
|
7476962a6c | ||
|
|
b1ac71b2f5 | ||
|
|
1ac55f0325 | ||
|
|
0497ce7984 | ||
|
|
0a402ca287 | ||
|
|
a12481fc30 | ||
|
|
3e7d4d8140 | ||
|
|
ce67b4fc41 | ||
|
|
839b2d09bb | ||
|
|
db915e756a | ||
|
|
217a25cf01 | ||
|
|
c00d28fcd8 | ||
|
|
90c6f1da59 | ||
|
|
f43cfd0d79 | ||
|
|
caa37ce8d8 | ||
|
|
988204dfbf | ||
|
|
a6b46912d2 | ||
|
|
a3e92bbb04 | ||
|
|
426b75778f | ||
|
|
6011ed8573 | ||
|
|
b1e373c6db | ||
|
|
e83abbb47f | ||
|
|
361d826fbd | ||
|
|
63b3c312ec | ||
|
|
c65dbb42f8 | ||
|
|
4c4f961b89 | ||
|
|
db1f9919c3 | ||
|
|
7fbd726ccf | ||
|
|
50cd2197f1 | ||
|
|
e544a04f8a | ||
|
|
ddb59bfb56 | ||
|
|
ee696c397d | ||
|
|
0b4985dda2 | ||
|
|
907144f8ee | ||
|
|
aa1bef4890 | ||
|
|
01be7792c8 | ||
|
|
70b6e5043a | ||
|
|
031e2bf8f6 | ||
|
|
eee364e7f8 | ||
|
|
289d8214b1 | ||
|
|
a8f08c8ed5 | ||
|
|
9182f34818 | ||
|
|
1e81d90f1f | ||
|
|
3f9ea47d15 | ||
|
|
b6a718bc87 | ||
|
|
0cb7fe99f7 | ||
|
|
3109311e58 | ||
|
|
507084013c | ||
|
|
c987531a2a | ||
|
|
6b54c4e523 | ||
|
|
9c6300d6a5 | ||
|
|
fcb477de4f | ||
|
|
c5c06ce0bb | ||
|
|
c92632bfe0 | ||
|
|
4f70f7297b | ||
|
|
2dfdfa04a2 | ||
|
|
c297ab07b1 | ||
|
|
fdc9a1b1f2 | ||
|
|
116790b58f | ||
|
|
e08cd026d6 | ||
|
|
afcfb6712d | ||
|
|
3db00167e8 | ||
|
|
e5189e973b | ||
|
|
d6f460e54a | ||
|
|
6a0be69064 | ||
|
|
0eb379261a | ||
|
|
d6f1c61fb6 | ||
|
|
985a9a41c0 | ||
|
|
bc23b8b0c2 | ||
|
|
2cfeadf114 | ||
|
|
3abb3589a8 | ||
|
|
be4b6c2a0e | ||
|
|
3b6b183503 | ||
|
|
131750a5bc | ||
|
|
fe2543d981 | ||
|
|
18e2e1188b | ||
|
|
759ec97e70 | ||
|
|
829f445169 | ||
|
|
521fd43191 | ||
|
|
abf217e9f3 | ||
|
|
252a9c0133 | ||
|
|
adf6fcad61 | ||
|
|
0e159ad0c5 | ||
|
|
07e5c553e6 | ||
|
|
b4b1bdc3ed | ||
|
|
0711a60584 | ||
|
|
fb69d1500f | ||
|
|
3d83e742fd | ||
|
|
24fb15e4ef | ||
|
|
90491a00a5 | ||
|
|
62f55d0e25 | ||
|
|
85d7ac6afe | ||
|
|
07994a19cf | ||
|
|
b525401826 | ||
|
|
ad6fe2403f | ||
|
|
2f57f9b036 | ||
|
|
675bfa14a4 | ||
|
|
c64ed99efd | ||
|
|
68d7946293 | ||
|
|
8dc205c918 | ||
|
|
7708822b76 | ||
|
|
17ca23a15e | ||
|
|
a4065c9917 | ||
|
|
e9d24e5e4e | ||
|
|
2080001221 | ||
|
|
aae81be26d | ||
|
|
31a8dc5c24 | ||
|
|
df9e6473ec | ||
|
|
d5587376de | ||
|
|
929e019712 | ||
|
|
8a3a1aa8ae | ||
|
|
77b65d3999 | ||
|
|
611b7c543d | ||
|
|
0befe965af | ||
|
|
938edda04f | ||
|
|
f6e0068a45 | ||
|
|
b8e12c5a33 | ||
|
|
e893a6304e | ||
|
|
2baa92a84a | ||
|
|
a4749e1f50 | ||
|
|
9a25764763 | ||
|
|
1e919ba45d | ||
|
|
338fe2afec | ||
|
|
eb05f409b1 | ||
|
|
7fdfbf2b2b | ||
|
|
7ce1b5cf35 | ||
|
|
20ab09baa0 | ||
|
|
0bdb7b5141 | ||
|
|
46f395ae1d | ||
|
|
0f464e8303 | ||
|
|
fb4eec74d0 | ||
|
|
8ca5cd8256 | ||
|
|
b1ad85171e | ||
|
|
37a68609f0 | ||
|
|
8fc38d6201 | ||
|
|
87613d4c25 | ||
|
|
135e9fa753 | ||
|
|
28f0b9195b | ||
|
|
e1f700a0a2 | ||
|
|
815ddfb72b | ||
|
|
8f5f965fa8 | ||
|
|
64c695aec1 | ||
|
|
2173cf358b | ||
|
|
363269affb | ||
|
|
4ce8fd9a9b | ||
|
|
3e66b0cd02 | ||
|
|
94dd90ae88 | ||
|
|
6b59ba2ef2 | ||
|
|
8b827f410e | ||
|
|
f4e1b67d62 | ||
|
|
2f84f9791e | ||
|
|
93d9c67ec4 | ||
|
|
51fa58f11c | ||
|
|
b50fa0dd22 | ||
|
|
f32a6cab0d | ||
|
|
0ea3cc4b5e | ||
|
|
332da6ba34 | ||
|
|
f0c64b8666 | ||
|
|
848268d284 | ||
|
|
fbd155d602 | ||
|
|
635eb8cabd | ||
|
|
3dfadff339 | ||
|
|
f05794c4b0 | ||
|
|
23979e704b | ||
|
|
6fa2df53d2 | ||
|
|
88435c2701 | ||
|
|
a837aeead6 | ||
|
|
9570637275 | ||
|
|
63ad917675 | ||
|
|
447c0146f5 | ||
|
|
cbc07032f9 | ||
|
|
9f858e6bf5 | ||
|
|
824982dade | ||
|
|
ead43829e3 | ||
|
|
98f6df61ae | ||
|
|
9ab5a91df6 | ||
|
|
12c605af45 | ||
|
|
bd8fa1a972 | ||
|
|
9b51a64069 | ||
|
|
60a475e157 | ||
|
|
a6ab9c896b | ||
|
|
0ed8de72bc | ||
|
|
c6abe76ab9 | ||
|
|
c7287ce9dc | ||
|
|
4f10afa914 | ||
|
|
b7437055f0 | ||
|
|
19e03c4e71 | ||
|
|
b88fc4ea5b | ||
|
|
58e5e7e4bb | ||
|
|
9d9b00bb75 | ||
|
|
ceded4b4dd | ||
|
|
da23449878 | ||
|
|
b72aa7e5bf | ||
|
|
9729a475ee | ||
|
|
2c82f0327c | ||
|
|
caaa102f64 | ||
|
|
aafd5a9178 | ||
|
|
319c56e6d4 | ||
|
|
ea28142590 | ||
|
|
54df619236 | ||
|
|
6f953a928f | ||
|
|
ab2bd216c1 | ||
|
|
47a2ea50d4 | ||
|
|
920e1e8fe0 | ||
|
|
5401f01af8 | ||
|
|
a51c757af1 | ||
|
|
e49344f5ec | ||
|
|
8fde089f40 | ||
|
|
d789b4f154 | ||
|
|
53bdc2d456 | ||
|
|
7614879da2 | ||
|
|
b82cbe8045 | ||
|
|
d759e87383 | ||
|
|
d56c71470e | ||
|
|
2ed52ed88b | ||
|
|
13a13aff17 | ||
|
|
e08964bb58 | ||
|
|
3a90faa916 | ||
|
|
a087e0c21f | ||
|
|
5bfa11c5e1 | ||
|
|
a8886f898c | ||
|
|
09d8ad519b | ||
|
|
2083256f16 | ||
|
|
cece39407d | ||
|
|
536f3c34c1 | ||
|
|
724da5570c | ||
|
|
e8f8eca101 | ||
|
|
c19efe5f34 | ||
|
|
1abe10bb74 | ||
|
|
66b33fd330 | ||
|
|
f89d26ec5f | ||
|
|
e549b57367 | ||
|
|
58e785a7e7 | ||
|
|
0861160e57 | ||
|
|
26daca4cf1 | ||
|
|
2887ae8071 | ||
|
|
f5636731f4 | ||
|
|
a24c852c63 | ||
|
|
674ac4eba4 | ||
|
|
debad267f1 | ||
|
|
3b89d63f35 | ||
|
|
200af6de8d | ||
|
|
08b51e7ab6 | ||
|
|
b40a3c05d8 | ||
|
|
d4b41227bb | ||
|
|
893987dd7f | ||
|
|
0f133c04ac | ||
|
|
522becff95 | ||
|
|
d6f58c836f | ||
|
|
b1629c0cdf | ||
|
|
75c29031c2 | ||
|
|
7b50b5450a | ||
|
|
52a18de38f | ||
|
|
f20539d80b | ||
|
|
31b6fd99b2 | ||
|
|
48a226f953 |
134
.copyright.hook
Normal file
134
.copyright.hook
Normal file
@@ -0,0 +1,134 @@
|
||||
# Copyright (c) 2020 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.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import argparse
|
||||
import io
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
import datetime
|
||||
|
||||
COPYRIGHT = '''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.'''
|
||||
|
||||
def _generate_copyright(comment_mark):
|
||||
copyright=COPYRIGHT.split(os.linesep)
|
||||
header = copyright[0].rstrip()
|
||||
|
||||
p = re.search('(\d{4})', header).group(0)
|
||||
now = datetime.datetime.now()
|
||||
|
||||
header = header.replace(p,str(now.year))
|
||||
|
||||
ans=[comment_mark + " " + header + os.linesep]
|
||||
for idx, line in enumerate(copyright[1:]):
|
||||
ans.append(comment_mark + " " + line.rstrip() + os.linesep)
|
||||
|
||||
return ans
|
||||
|
||||
def _get_comment_mark(path):
|
||||
lang_type=re.compile(r"\.(py|sh)$")
|
||||
if lang_type.search(path) is not None:
|
||||
return "#"
|
||||
|
||||
lang_type=re.compile(r"\.(h|c|hpp|cc|cpp|cu|go|cuh|proto)$")
|
||||
if lang_type.search(path) is not None:
|
||||
return "//"
|
||||
|
||||
return None
|
||||
|
||||
|
||||
RE_ENCODE = re.compile(r"^[ \t\v]*#.*?coding[:=]", re.IGNORECASE)
|
||||
RE_COPYRIGHT = re.compile(r".*Copyright( \(c\))* \d{4}", re.IGNORECASE)
|
||||
RE_SHEBANG = re.compile(r"^[ \t\v]*#[ \t]?\!")
|
||||
|
||||
def _check_copyright(path):
|
||||
head=[]
|
||||
try:
|
||||
with open(path) as f:
|
||||
head = [next(f) for x in range(4)]
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
for idx, line in enumerate(head):
|
||||
if RE_COPYRIGHT.search(line) is not None:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def generate_copyright(path, comment_mark):
|
||||
original_contents = io.open(path, encoding="utf-8").readlines()
|
||||
head = original_contents[0:4]
|
||||
|
||||
insert_line_no=0
|
||||
for i, line in enumerate(head):
|
||||
if RE_ENCODE.search(line) or RE_SHEBANG.search(line):
|
||||
insert_line_no=i+1
|
||||
|
||||
copyright = _generate_copyright(comment_mark)
|
||||
if insert_line_no == 0:
|
||||
new_contents = copyright
|
||||
if len(original_contents) > 0 and len(original_contents[0].strip()) != 0:
|
||||
new_contents.append(os.linesep)
|
||||
new_contents.extend(original_contents)
|
||||
else:
|
||||
new_contents=original_contents[0:insert_line_no]
|
||||
new_contents.append(os.linesep)
|
||||
new_contents.extend(copyright)
|
||||
if len(original_contents) > insert_line_no and len(original_contents[insert_line_no].strip()) != 0:
|
||||
new_contents.append(os.linesep)
|
||||
new_contents.extend(original_contents[insert_line_no:])
|
||||
new_contents="".join(new_contents)
|
||||
|
||||
with io.open(path, 'w') as output_file:
|
||||
output_file.write(new_contents)
|
||||
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Checker for copyright declaration.')
|
||||
parser.add_argument('filenames', nargs='*', help='Filenames to check')
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
retv = 0
|
||||
for path in args.filenames:
|
||||
comment_mark = _get_comment_mark(path)
|
||||
if comment_mark is None:
|
||||
print("warning:Unsupported file", path, file=sys.stderr)
|
||||
continue
|
||||
|
||||
if _check_copyright(path):
|
||||
continue
|
||||
|
||||
generate_copyright(path, comment_mark)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
exit(main())
|
||||
17
.github/ISSUE_TEMPLATE/----.md
vendored
17
.github/ISSUE_TEMPLATE/----.md
vendored
@@ -1,17 +0,0 @@
|
||||
---
|
||||
name: 问题反馈
|
||||
about: PaddleNLP问题反馈
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
欢迎您反馈PaddleNLP使用问题,非常感谢您对PaddleNLP的贡献!
|
||||
在留下您的问题时,辛苦您同步提供如下信息:
|
||||
- 版本、环境信息
|
||||
1)PaddleNLP和PaddlePaddle版本:请提供您的PaddleNLP和PaddlePaddle版本号,例如PaddleNLP 2.0.4,PaddlePaddle2.1.1
|
||||
2)系统环境:请您描述系统类型,例如Linux/Windows/MacOS/,python版本
|
||||
- 复现信息:如为报错,请给出复现环境、复现步骤
|
||||
|
||||
如还有问题可以到 PaddleNLP github 主页面的**[社区交流](https://github.com/PaddlePaddle/PaddleNLP#%E7%A4%BE%E5%8C%BA%E4%BA%A4%E6%B5%81)**扫描加入微信群,相关值班同学将会为您解答!
|
||||
23
.github/ISSUE_TEMPLATE/ask-question.yml
vendored
Normal file
23
.github/ISSUE_TEMPLATE/ask-question.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: 🐛 Ask Question
|
||||
description: 请描述您使用PaddleNLP时遇到的问题
|
||||
title: "[Question]: "
|
||||
labels:
|
||||
- question
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
#### 你可以在这里提出一个使用/咨询问题,提问之前请确保:
|
||||
|
||||
- 1)已经百度/谷歌搜索过你的问题,但是没有找到解答;
|
||||
|
||||
- 2)已经在官网查询过[API文档](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/index_cn.html)与[FAQ](https://www.paddlepaddle.org.cn/documentation/docs/zh/faq/index_cn.html),但是没有找到解答;
|
||||
|
||||
- 3)已经在[历史issue](https://github.com/PaddlePaddle/Paddle/issues)中搜索过,没有找到同类issue或issue未被解答。
|
||||
|
||||
- type: textarea
|
||||
id: question
|
||||
attributes:
|
||||
label: 请提出你的问题
|
||||
validations:
|
||||
required: true
|
||||
45
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
45
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: 🐛 Bug Report
|
||||
description: PaddleNLP问题反馈
|
||||
title: "[Bug]: "
|
||||
labels: bug
|
||||
body:
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: 软件环境
|
||||
description: |
|
||||
请使用以下命令给出您本地Paddle相关包信息
|
||||
```sh
|
||||
pip list | grep paddle
|
||||
|
||||
```
|
||||
value: |
|
||||
- paddlepaddle:
|
||||
- paddlepaddle-gpu:
|
||||
- paddlenlp:
|
||||
render: Markdown
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: dumplicated-problem
|
||||
attributes:
|
||||
label: 重复问题
|
||||
description: 是否已在issues中搜索相关问题
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: textarea
|
||||
id: descripton
|
||||
attributes:
|
||||
label: 错误描述
|
||||
description: 给出错误详细描述,以便能够更好的追踪相关问题
|
||||
render: Markdown
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: mvp-code
|
||||
attributes:
|
||||
label: 稳定复现步骤 & 代码
|
||||
description: 请给出稳定复现该问题的步骤 & 代码,以便相关人员能够快速定位到具体问题。
|
||||
validations:
|
||||
required: true
|
||||
32
.github/ISSUE_TEMPLATE/docs-report.yml
vendored
Normal file
32
.github/ISSUE_TEMPLATE/docs-report.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: 🐛 Docs Report
|
||||
description: PaddleNLP文档反馈
|
||||
title: "[Docs]: "
|
||||
labels:
|
||||
- documentation
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: 软件环境
|
||||
description: |
|
||||
请使用以下命令给出您本地Paddle相关包信息
|
||||
```sh
|
||||
pip list | grep paddle
|
||||
|
||||
```
|
||||
value: |
|
||||
- paddlepaddle:
|
||||
- paddlepaddle-gpu:
|
||||
- paddlenlp:
|
||||
render: Markdown
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: 详细描述
|
||||
description: 请详细描述您想要反馈的具体问题
|
||||
render: Markdown
|
||||
validations:
|
||||
required: true
|
||||
30
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
30
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: "\U0001F680 Feature request"
|
||||
description: 请详细描述您所需功能
|
||||
labels: [ "feature" ]
|
||||
body:
|
||||
- type: textarea
|
||||
id: feature-request
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Feature request
|
||||
description: |
|
||||
对特性提案的清晰而简明的描述。如果论文和代码存在,请提供链接。
|
||||
|
||||
- type: textarea
|
||||
id: motivation
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: |
|
||||
请概述这项建议的动机。您的特性要求与问题有关吗?
|
||||
|
||||
- type: textarea
|
||||
id: contribution
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Your contribution
|
||||
description: |
|
||||
Is there any way that you could help, e.g. by submitting a PR? Make sure to read the CONTRIBUTING.MD [readme](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md)
|
||||
28
.github/ISSUE_TEMPLATE/new-model.yaml
vendored
Normal file
28
.github/ISSUE_TEMPLATE/new-model.yaml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: "\U0001F31F 添加新模型"
|
||||
description: 请为新模型提交一份说明
|
||||
labels: [ "New model" ]
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
id: description-request
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: 简要描述
|
||||
description: |
|
||||
请简要描述模型的类型、解决的问题等。
|
||||
|
||||
- type: checkboxes
|
||||
id: information-tasks
|
||||
attributes:
|
||||
label: 是否已开源
|
||||
options:
|
||||
- label: 已开源
|
||||
- label: 未开源
|
||||
|
||||
- type: textarea
|
||||
id: additional-info
|
||||
attributes:
|
||||
label: 模型详细信息
|
||||
description: |
|
||||
请给出新模型相关信息,如论文地址、现存代码地址等。
|
||||
23
.github/ISSUE_TEMPLATE/others.yml
vendored
Normal file
23
.github/ISSUE_TEMPLATE/others.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: 🧩 其他 Others
|
||||
description: 提出其他问题。
|
||||
labels: [others]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
#### 你可以在这里提出任何前面几类模板不适用的问题,包括但不限于:优化性建议、框架使用体验反馈、版本兼容性问题、报错信息不清楚等。
|
||||
|
||||
- type: textarea
|
||||
id: others
|
||||
attributes:
|
||||
label: 问题描述
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
感谢你的贡献 🎉!
|
||||
|
||||
|
||||
60
.github/workflows/pypi.yml
vendored
Normal file
60
.github/workflows/pypi.yml
vendored
Normal 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
1
.gitignore
vendored
@@ -123,3 +123,4 @@ FETCH_HEAD
|
||||
|
||||
# vscode
|
||||
.vscode
|
||||
./ppdiffusers/ppdiffusers/version.py
|
||||
@@ -26,3 +26,10 @@ repos:
|
||||
files: \.md$
|
||||
- id: remove-tabs
|
||||
files: \.md$
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: copyright_checker
|
||||
name: copyright_checker
|
||||
entry: python .copyright.hook
|
||||
language: system
|
||||
files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto|xpu|kps|py|sh)$
|
||||
|
||||
88
CODE_OF_CONDUCT.md
Normal file
88
CODE_OF_CONDUCT.md
Normal 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
133
CODE_OF_CONDUCT_en.md
Normal 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
10
Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
.PHONY: deploy-ppdiffusers
|
||||
deploy-ppdiffusers:
|
||||
cd ppdiffusers && make
|
||||
|
||||
.PHONY: install-ppdiffusers
|
||||
install-ppdiffusers:
|
||||
cd ppdiffusers && make install
|
||||
|
||||
38
README_cn.md
38
README_cn.md
@@ -30,26 +30,30 @@
|
||||
**PaddleNLP**是一款**简单易用**且**功能强大**的自然语言处理开发库。聚合业界**优质预训练模型**并提供**开箱即用**的开发体验,覆盖NLP多场景的模型库搭配**产业实践范例**可满足开发者**灵活定制**的需求。
|
||||
|
||||
## News 📢
|
||||
* 📝 2022.8.1 **PaddleNLP v2.3.5**发布 对话式程序生成大模型发布,可Taskflow一键调用;通用信息抽取技术英文模型[**UIE en**](./model_zoo/uie)正式发布,支持英文各项信息抽取工作; [**RGL**](./examples/few_shot/RGL) RGL是百度自研的 Prompt-based tuning 小样本学习算法,论文被 Findings of NAACL 2022 接收,欢迎大家使用!
|
||||
* 🍭 2022.6.29 **PaddleNLP v2.3.4**发布 全系列中文预训练小模型发布,快速提升预训练模型部署效率,通用信息抽取技术[**UIE Tiny**](./model_zoo/uie) 系列模型全新升级,支持速度更快效果更好的UIE小模型。
|
||||
* 🔥 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并行推理加速。
|
||||
* 🔥 **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 任务像搭积木一样便捷、灵活、高效!
|
||||
* 💢 产业应用:新增 **[文本分类全流程应用方案](./applications/text_classification)** ,覆盖多分类、多标签、层次分类各类场景,支持 **小样本学习** 和 **TrustAI** 可信计算模型训练与调优;[**通用信息抽取 UIE 能力升级**](./model_zoo/uie),发布 **UIE-M**,支持中英文混合抽取,新增**UIE 数据蒸馏**方案,打破 UIE 推理瓶颈,推理速度提升 100 倍以上;
|
||||
* 🍭 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 等经典算法。
|
||||
|
||||
* 📬 2021.12.12 **PaddleNLP v2.2**发布!新增开箱即用的NLP能力[Taskflow](./docs/model_zoo/taskflow.md)!配套语义检索、智能问答、评论观点抽取[产业案例](./applications),快速搭建端到端NLP系统!配套视频课程[直通车](https://aistudio.baidu.com/aistudio/course/introduce/24902)!
|
||||
|
||||
## 社区交流
|
||||
|
||||
- 微信扫描二维码并填写问卷之后,加入交流群领取福利
|
||||
- 微信扫描二维码并填写问卷,回复小助手关键词(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>
|
||||
@@ -67,6 +71,14 @@ Taskflow提供丰富的**📦开箱即用**的产业级NLP预置模型,覆盖
|
||||
|
||||

|
||||
|
||||
Taskflow最新集成了文生图的趣玩应用,三行代码体验 **Stable Diffusion**
|
||||
```python
|
||||
from paddlenlp import Taskflow
|
||||
text_to_image = Taskflow("text_to_image", model="CompVis/stable-diffusion-v1-4")
|
||||
image_list = text_to_image('"In the morning light,Chinese ancient buildings in the mountains,Magnificent and fantastic John Howe landscape,lake,clouds,farm,Fairy tale,light effect,Dream,Greg Rutkowski,James Gurney,artstation"')
|
||||
```
|
||||
<img width="300" alt="image" src="https://user-images.githubusercontent.com/16698950/194882669-f7cc7c98-d63a-45f4-99c1-0514c6712368.png">
|
||||
|
||||
更多使用方法可参考[Taskflow文档](./docs/model_zoo/taskflow.md)。
|
||||
|
||||
### 丰富完备的中文模型库
|
||||
@@ -198,7 +210,7 @@ PaddleNLP针对信息抽取、语义检索、智能问答、情感分析等高
|
||||
</div>
|
||||
|
||||
|
||||
更多使用说明请参考[智能问答系统](./applications/question_answering)与[文档智能问答](./applications/doc_vqa)
|
||||
更多使用说明请参考[智能问答系统](./applications/question_answering)与[文档智能问答](./applications/document_intelligence/doc_vqa)
|
||||
|
||||
#### 💌 评论观点抽取与情感分析
|
||||
|
||||
|
||||
44
README_en.md
44
README_en.md
@@ -29,16 +29,23 @@
|
||||
**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.8.1 **PaddleNLP v2.3.5** Released!
|
||||
* Release the dialogic code generation model [**CodeGen**](./examples/code_generation/codegen), which can be easily used via [Taskflow](./docs/model_zoo/taskflow.md).
|
||||
* Release [**UIE en**](./model_zoo/uie), supports for multiple tasks in **open-domain** information extraction.
|
||||
* Release [**RGL**](./examples/few_shot/RGL), an independent research prompt-base tuning approach for few-shot learning, the paper is accepted by NAACL 2022.
|
||||
* 🍭 2022.6.29 **PaddleNLP v2.3.4** Released! Whole series of Chinese pretrained models [**ERNIE Tiny**](./model_zoo/ernie-3.0) are released to quickly improve deployment efficiency. We also provides smaller and faster models [**UIE Tiny**](./model_zoo/uie) for universal information extraction.
|
||||
* 🔥 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.
|
||||
|
||||
* 🔥 **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!
|
||||
|
||||
* 💢 Industrial application:Release **[Complete Solution of Text Classification](./applications/text_classification)** covering various scenarios of text classification: multi-class, multi-label and hierarchical, it also supports for **few-shot learning** and the training and optimization of **TrustAI**. Upgrade for [**Universal Information Extraction**](./model_zoo/uie) and release **UIE-M**, support both Chinese and English information extraction in a single model; release the data distillation solution for UIE to break the bottleneck of time-consuming of inference.
|
||||
|
||||
* 🍭 AIGC: Release code generation SOTA model [**CodeGen**](./examples/code_generation/codegen), supports for multiple programming languages code generation. Integrate [**Text to Image Model**](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, let's play and have some fun! Release [**Chinese Text Summarization Application**](./applications/text_summarization), first release of chinese text summarization model pretrained on a large scale of corpus, it can be use via Taskflow API and support for finetuning on your own data.
|
||||
|
||||
* 💪 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.
|
||||
|
||||
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
@@ -63,7 +70,7 @@ For more usage please refer to [Taskflow Docs](./docs/model_zoo/taskflow.md).
|
||||
|
||||
#### 🀄 Comprehensive Chinese Transformer Models
|
||||
|
||||
We provide **45+** network architectures and over **500+** pretrained models. Not only includes all the SOTA model like ERNIE, PLATO and SKEP released by Baidu, but also integrates most of the high-quality Chinese pretrained model developed by other organizations. Use `AutoModel` API to **⚡SUPER FAST⚡** download pretrained mdoels of different architecture. We welcome all developers to contribute your Transformer models to PaddleNLP!
|
||||
We provide **45+** network architectures and over **500+** pretrained models. Not only includes all the SOTA model like ERNIE, PLATO and SKEP released by Baidu, but also integrates most of the high-quality Chinese pretrained model developed by other organizations. Use `AutoModel` API to **⚡SUPER FAST⚡** download pretrained models of different architecture. We welcome all developers to contribute your Transformer models to PaddleNLP!
|
||||
|
||||
```python
|
||||
from paddlenlp.transformers import *
|
||||
@@ -187,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
|
||||
@@ -310,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/).
|
||||
@@ -322,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
|
||||
@@ -341,7 +345,7 @@ If you find PaddleNLP useful in your research, please consider cite
|
||||
|
||||
## Acknowledge
|
||||
|
||||
We have borrowed from Hugging Face's [Transformer](https://github.com/huggingface/transformers)🤗 excellent design on pretrained models usage, and we would like to express our gratitude to the authors of Hugging Face and its open source community.
|
||||
We have borrowed from Hugging Face's [Transformers](https://github.com/huggingface/transformers)🤗 excellent design on pretrained models usage, and we would like to express our gratitude to the authors of Hugging Face and its open source community.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,19 +0,0 @@
|
||||
import sys
|
||||
import json
|
||||
|
||||
question = sys.argv[1]
|
||||
|
||||
with open('../OCR_process/demo_ocr_res.json', 'r', encoding='utf8') as f:
|
||||
paras = []
|
||||
for line in f:
|
||||
line = json.loads(line.strip())
|
||||
document = line['document']
|
||||
para = []
|
||||
for token in document:
|
||||
token = token.replace('▁', '')
|
||||
para.append(token)
|
||||
paras.append(''.join(para))
|
||||
|
||||
with open('./data/demo.tsv', 'w', encoding='utf8') as f:
|
||||
for para in paras:
|
||||
f.write('{}\t\t{}\t0\n'.format(question, para))
|
||||
@@ -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 ..
|
||||
188
applications/document_intelligence/README.md
Normal file
188
applications/document_intelligence/README.md
Normal 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)
|
||||
@@ -1,3 +1,17 @@
|
||||
# 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 json
|
||||
import numpy as np
|
||||
@@ -1,3 +1,17 @@
|
||||
# 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 cv2
|
||||
import sys
|
||||
@@ -1,3 +1,17 @@
|
||||
# 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 paddle
|
||||
@@ -1,3 +1,17 @@
|
||||
# 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 sys
|
||||
import copy
|
||||
38
applications/document_intelligence/doc_vqa/Extraction/run_test.sh
Executable file
38
applications/document_intelligence/doc_vqa/Extraction/run_test.sh
Executable 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
|
||||
32
applications/document_intelligence/doc_vqa/Extraction/run_train.sh
Executable file
32
applications/document_intelligence/doc_vqa/Extraction/run_train.sh
Executable 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
|
||||
@@ -1,3 +1,17 @@
|
||||
# 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 cv2
|
||||
import json
|
||||
import numpy as np
|
||||
@@ -1,3 +1,17 @@
|
||||
# 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
|
||||
from paddleocr import PaddleOCR
|
||||
@@ -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.
|
||||
|
||||
import sys
|
||||
import json
|
||||
|
||||
question = sys.argv[1]
|
||||
|
||||
with open('../OCR_process/demo_ocr_res.json', 'r', encoding='utf8') as f:
|
||||
paras = []
|
||||
for line in f:
|
||||
line = json.loads(line.strip())
|
||||
document = line['document']
|
||||
para = []
|
||||
for token in document:
|
||||
token = token.replace('▁', '')
|
||||
para.append(token)
|
||||
paras.append(''.join(para))
|
||||
|
||||
with open('./data/demo.tsv', 'w', encoding='utf8') as f:
|
||||
for para in paras:
|
||||
f.write('{}\t\t{}\t0\n'.format(question, para))
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,3 +1,17 @@
|
||||
# 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 time
|
||||
import faiss
|
||||
@@ -1,3 +1,17 @@
|
||||
# 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
|
||||
|
||||
shift = int(sys.argv[1])
|
||||
34
applications/document_intelligence/doc_vqa/run_test.sh
Normal file
34
applications/document_intelligence/doc_vqa/run_test.sh
Normal 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 ..
|
||||
1
applications/document_intelligence/docprompt
Symbolic link
1
applications/document_intelligence/docprompt
Symbolic link
@@ -0,0 +1 @@
|
||||
../../model_zoo/ernie-layout
|
||||
@@ -3,8 +3,11 @@
|
||||
## 1. 场景概述
|
||||
|
||||
检索系统存在于我们日常使用的很多产品中,比如商品搜索系统、学术文献检索系等等,本方案提供了检索系统完整实现。限定场景是用户通过输入检索词 Query,快速在海量数据中查找相似文档。
|
||||
<div align="center">
|
||||
<img src="https://user-images.githubusercontent.com/12107462/191490721-90a8f526-ad64-4f2b-b9b4-34ab06c6749b.png" width="500px">
|
||||
</div>
|
||||
|
||||
所谓语义检索(也称基于向量的检索),是指检索系统不再拘泥于用户 Query 字面本身,而是能精准捕捉到用户 Query 后面的真正意图并以此来搜索,从而更准确地向用户返回最符合的结果。通过使用最先进的语义索引模型找到文本的向量表示,在高维向量空间中对它们进行索引,并度量查询向量与索引文档的相似程度,从而解决了关键词索引带来的缺陷。
|
||||
所谓语义检索(也称基于向量的检索,如上图所示),是指检索系统不再拘泥于用户 Query 字面本身,而是能精准捕捉到用户 Query 后面的真正意图并以此来搜索,从而更准确地向用户返回最符合的结果。通过使用最先进的语义索引模型找到文本的向量表示,在高维向量空间中对它们进行索引,并度量查询向量与索引文档的相似程度,从而解决了关键词索引带来的缺陷。
|
||||
|
||||
例如下面两组文本 Pair,如果基于关键词去计算相似度,两组的相似度是相同的。而从实际语义上看,第一组相似度高于第二组。
|
||||
|
||||
@@ -13,7 +16,7 @@
|
||||
车头如何放置车牌 后牌照怎么装
|
||||
```
|
||||
|
||||
语义检索系统的关键就在于,采用语义而非关键词方式进行召回,达到更精准、更广泛得召回相似结果的目的。
|
||||
语义检索系统的关键就在于,采用语义而非关键词方式进行召回,达到更精准、更广泛得召回相似结果的目的。想快速体验搜索的效果,请参考[Pipelines的实现](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/pipelines)
|
||||
|
||||
## 2. 产品功能介绍
|
||||
|
||||
@@ -33,8 +36,9 @@
|
||||
+ 兼具无监督数据 和 有监督数据:融合模型
|
||||
+ 进一步优化方案: 面向领域的预训练 Domain-adaptive Pretraining
|
||||
+ 性能快
|
||||
+ 基于 Paddle Inference 快速抽取向量
|
||||
+ 基于 Milvus 快速查询和高性能建库
|
||||
+ Paddle Inference 快速抽取向量
|
||||
+ Milvus 快速查询和高性能建库
|
||||
+ Paddle Serving服务化部署
|
||||
|
||||
### 2.2 功能架构
|
||||
|
||||
@@ -43,9 +47,11 @@
|
||||
#### 2.2.1 整体介绍
|
||||
|
||||
|
||||
<div align="center">
|
||||
<img src="https://user-images.githubusercontent.com/12107462/191469309-42a54a67-a3a3-4e43-b6b1-b12be81ddf3d.png" width="800px">
|
||||
</div>
|
||||
|
||||

|
||||
以上是nerual_search的系统流程图,其中左侧为召回环节,核心是语义向量抽取模块;右侧是排序环节,核心是排序模型。图中红色虚线框表示在线计算,黑色虚线框表示离线批量处理。下面我们分别介绍召回中的语义向量抽取模块,以及排序模型。
|
||||
以上是nerual_search的系统流程图,其中左侧为召回环节,核心是语义向量抽取模块;右侧是排序环节,核心是排序模型。召回环节需要用户通过自己的语料构建向量索引库,用户发起query了之后,就可以检索出相似度最高的向量,然后找出该向量对应的文本;排序环节主要是对召回的文本进行重新排序。下面我们分别介绍召回中的语义向量抽取模块,以及排序模型。
|
||||
|
||||
|
||||
#### 2.2.2 召回模块
|
||||
@@ -68,7 +74,9 @@
|
||||
|
||||
#### 2.2.3 排序模块
|
||||
|
||||
排序模块基于前沿的预训练模型 ERNIE-Gram,训练 Pair-wise 语义匹配模型。召回模型负责从海量(千万级)候选文本中快速(毫秒级)筛选出与 Query 相关性较高的 TopK Doc,排序模型会在召回模型筛选出的 TopK Doc 结果基础之上针对每一个 (Query, Doc) Pair 对进行两两匹配计算相关性,排序效果更精准。
|
||||
召回模型负责从海量(千万级)候选文本中快速(毫秒级)筛选出与 Query 相关性较高的 TopK Doc,排序模型会在召回模型筛选出的 TopK Doc 结果基础之上针对每一个 (Query, Doc) Pair 对进行两两匹配计算相关性,排序效果更精准。
|
||||
|
||||
排序模块有2种选择,第一种基于前沿的预训练模型 ERNIE,训练 Pair-wise 语义匹配模型;第二种是基于RocketQA模型训练的Cross Encoder模形。第一种是Pair-wise的排序算法,基本思路是对样本构建偏序文档对,两两比较,从比较中学习顺序,第二种是Poinet-Wise的算法,只考虑当前Query和每个文档的绝对相关度,并没有考虑其他文档与Query的相关度,但是建模方式比较简单。第一种Pair-wise模型可以说是第二种point-wise模型的改进版本,但对于噪声数据更为敏感,即一个错误的标注会导致多个pair对的错误,用户可以先使用基于Point-wise的Cross Encoder构建一个基础模型,需要进一步优化可以使用Pair-wise的方法优化。
|
||||
|
||||
## 3. 文献检索实践
|
||||
|
||||
@@ -78,9 +86,9 @@
|
||||
|
||||
**语义索引**:由于我们既有无监督数据,又有有监督数据,所以结合 SimCSE 和 In-batch Negatives 方案,并采取 Domain-adaptive Pretraining 优化模型效果。
|
||||
|
||||
首先是利用 ERNIE 1.0 模型进行 Domain-adaptive Pretraining,在得到的预训练模型基础上,进行无监督的 SimCSE 训练,最后利用 In-batch Negatives 方法进行微调,得到最终的语义索引模型,把建库的文本放入模型中抽取特征向量,然后把抽取后的向量放到语义索引引擎 milvus 中,利用 milvus 就可以很方便得实现召回了。
|
||||
首先是利用 ERNIE模型进行 Domain-adaptive Pretraining,在得到的预训练模型基础上,进行无监督的 SimCSE 训练,最后利用 In-batch Negatives 方法进行微调,得到最终的语义索引模型,把建库的文本放入模型中抽取特征向量,然后把抽取后的向量放到语义索引引擎 milvus 中,利用 milvus 就可以很方便得实现召回了。
|
||||
|
||||
**排序**:使用 ERNIE-Gram 的单塔结构对召回后的数据精排序。
|
||||
**排序**:使用 ERNIE-Gram 的单塔结构/RocketQA的Cross Encoder对召回后的数据精排序。
|
||||
|
||||
#### 3.1.2 评估指标
|
||||
|
||||
@@ -94,7 +102,7 @@
|
||||
|
||||
* 建库性能和 ANN 查询性能快
|
||||
|
||||
### 3.2 数据说明
|
||||
### 3.2 预置数据说明
|
||||
|
||||
数据集来源于某文献检索系统,既有大量无监督数据,又有有监督数据。
|
||||
|
||||
@@ -104,18 +112,19 @@
|
||||
|
||||
(3)使用文献的的query, title, keywords,构造带正标签的数据集,不包含负标签样本,基于 In-batch Negatives 策略进行训练;
|
||||
|
||||
(4)在排序阶段,使用点击(作为正样本)和展现未点击(作为负样本)数据构造排序阶段的训练集,使用ERNIE-Gram模型进行精排训练。
|
||||
(4)在排序阶段,使用点击(作为正样本)和展现未点击(作为负样本)数据构造排序阶段的训练集,进行精排训练。
|
||||
|
||||
| 阶段 |模型 | 训练集 | 评估集(用于评估模型效果) | 召回库 |测试集 |
|
||||
| ------------ | ------------ |------------ | ------------ | ------------ | ------------ |
|
||||
| 召回 | Domain-adaptive Pretraining | 2kw | - | - | - |
|
||||
| 召回 | 无监督预训练 - SimCSE | 798w | 20000 | 300000| 1000 |
|
||||
| 召回 | 有监督训练 - In-batch Negatives | 3998 | 20000 |300000 | 1000 |
|
||||
| 排序 | 有监督训练 - ERNIE-Gram单塔 Pairwise| 1973538 | 57811 | - | 1000 |
|
||||
| 排序 | 有监督训练 - ERNIE-Gram单塔 Pairwise/RocketQA Cross Encoder| 1973538 | 57811 | - | 1000 |
|
||||
|
||||
我们将除 Domain-adaptive Pretraining 之外的其他数据集全部开源,下载地址:
|
||||
|
||||
- [literature_search_data](https://bj.bcebos.com/v1/paddlenlp/data/literature_search_data.zip)
|
||||
- [literature_search_rank](https://paddlenlp.bj.bcebos.com/applications/literature_search_rank.zip)
|
||||
|
||||
```
|
||||
├── milvus # milvus建库数据集
|
||||
@@ -126,13 +135,147 @@
|
||||
├── dev.csv # 召回阶段验证集,用于评估召回模型的效果,SimCSE 和 In-batch Negative 共用
|
||||
├── corpus.csv # 构建召回库的数据(模拟实际业务线上的语料库,实际语料库远大于这里的规模),用于评估召回阶段模型效果,SimCSE 和 In-batch Negative 共用
|
||||
├── test.csv # 召回阶段测试数据,预测文本之间的相似度,SimCSE 和 In-batch Negative 共用
|
||||
├── data # RocketQA排序数据集
|
||||
├── test.csv # 测试集
|
||||
├── dev_pairwise.csv # 验证集
|
||||
└── train.csv # 训练集
|
||||
├── sort # 排序阶段数据集
|
||||
├── train_pairwise.csv # 排序训练集
|
||||
├── dev_pairwise.csv # 排序验证集
|
||||
└── test_pairwise.csv # 排序测试集
|
||||
```
|
||||
|
||||
### 3.3 运行环境和安装说明
|
||||
|
||||
### 3.3 数据格式
|
||||
|
||||
1. 对于无监督SimCSE的训练方法,格式参考`train_unsupervised.csv`,即一行条文本即可,无需任何标注。对于召回模型训练需要规定格式的本地数据集,需要准备训练集文件`train.csv`,验证集`dev.csv`,召回集文件`corpus.csv`。
|
||||
|
||||
|
||||
训练数据集`train.csv`的格式如下:
|
||||
|
||||
```
|
||||
query1 \t 用户点击的title1
|
||||
query2 \t 用户点击的title2
|
||||
```
|
||||
训练集合`train.csv`的文件样例:
|
||||
```
|
||||
从《唐律疏义》看唐代封爵贵族的法律特权 从《唐律疏义》看唐代封爵贵族的法律特权《唐律疏义》,封爵贵族,法律特权
|
||||
宁夏社区图书馆服务体系布局现状分析 宁夏社区图书馆服务体系布局现状分析社区图书馆,社区图书馆服务,社区图书馆服务体系
|
||||
人口老龄化对京津冀经济 京津冀人口老龄化对区域经济增长的影响京津冀,人口老龄化,区域经济增长,固定效应模型
|
||||
英语广告中的模糊语 模糊语在英语广告中的应用及其功能模糊语,英语广告,表现形式,语用功能
|
||||
甘氨酸二肽的合成 甘氨酸二肽合成中缩合剂的选择甘氨酸,缩合剂,二肽
|
||||
......
|
||||
```
|
||||
|
||||
验证集`dev.csv`的格式如下:
|
||||
|
||||
```
|
||||
query1 \t 用户点击的title1
|
||||
query2 \t 用户点击的title2
|
||||
```
|
||||
|
||||
验证集合`train.csv`的文件样例:
|
||||
```
|
||||
试论我国海岸带经济开发的问题与前景 试论我国海岸带经济开发的问题与前景海岸带,经济开发,问题,前景
|
||||
外语阅读焦虑与英语成绩及性别的关系 外语阅读焦虑与英语成绩及性别的关系外语阅读焦虑,外语课堂焦虑,英语成绩,性别
|
||||
加油站风险分级管控 加油站工作危害风险分级研究加油站,工作危害分析(JHA),风险分级管控
|
||||
```
|
||||
召回集合`corpus.csv`主要作用是检验测试集合的句子对能否被正确召回,它的构造主要是提取验证集的第二列的句子,然后加入很多无关的句子,用来检验模型能够正确的从这些文本中找出测试集合对应的第二列的句子,格式如下:
|
||||
|
||||
```
|
||||
2002-2017年我国法定传染病发病率和死亡率时间变化趋势传染病,发病率,死亡率,病死率
|
||||
陕西省贫困地区城乡青春期少女生长发育调查青春期,生长发育,贫困地区
|
||||
五丈岩水库溢洪道加固工程中的新材料应用碳纤维布,粘钢加固技术,超细水泥,灌浆技术
|
||||
......
|
||||
```
|
||||
|
||||
2. 对于排序模型的训练,排序模型目前提供了2种,第一种是Pairwise训练的方式,第二种是RocketQA的排序模型,对于第一种排序模型,需要准备训练集`train_pairwise.csv`,验证集`dev_pairwise.csv`两个文件,除此之外还可以准备测试集文件`test.csv`或者`test_pairwise.csv`。
|
||||
|
||||
训练数据集`train_pairwise.csv`的格式如下:
|
||||
|
||||
```
|
||||
query1 \t 用户点击的title1 \t 用户未点击的title2
|
||||
query2 \t 用户点击的title3 \t 用户未点击的title4
|
||||
```
|
||||
|
||||
训练数据集`train_pairwise.csv`的示例如下:
|
||||
|
||||
```
|
||||
英语委婉语引起的跨文化交际障碍 英语委婉语引起的跨文化交际障碍及其翻译策略研究英语委婉语,跨文化交际障碍,翻译策略 委婉语在英语和汉语中的文化差异委婉语,文化,跨文化交际
|
||||
范迪慧 嘉兴市中医院 滋阴疏肝汤联合八穴隔姜灸治疗肾虚肝郁型卵巢功能低下的临床疗效滋阴疏肝汤,八穴隔姜灸,肾虚肝郁型卵巢功能低下,性脉甾类激素,妊娠 温针灸、中药薰蒸在半月板损伤术后康复中的疗效分析膝损伤,半月板,胫骨,中医康复,温针疗法,薰洗
|
||||
......
|
||||
```
|
||||
|
||||
验证数据集`dev_pairwise.csv`的格式如下:
|
||||
|
||||
```
|
||||
query1 \t title1 \t label
|
||||
query2 \t title2 \t label
|
||||
```
|
||||
验证数据集`dev_pairwise.csv`的示例如下:
|
||||
|
||||
```
|
||||
作者单位:南州中学 浅谈初中教学管理如何体现人文关怀初中教育,教学管理,人文关怀 1
|
||||
作者单位:南州中学 高中美术课堂教学中藏区本土民间艺术的融入路径藏区,传统民间艺术,美术课堂 0
|
||||
作者单位:南州中学 列宁关于资产阶级民主革命向 社会主义革命过渡的理论列宁,直接过渡,间接过渡,资产阶级民主革命,社会主义革命 0
|
||||
DAA髋关节置换 DAA前侧入路和后外侧入路髋关节置换疗效对比髋关节置换术;直接前侧入路;后外侧入路;髋关节功能;疼痛;并发症 1
|
||||
DAA髋关节置换 DAA全髋关节置换术治疗髋关节病变对患者髋关节运动功能的影响直接前侧入路全髋关节置换术,髋关节病变,髋关节运动功能 0
|
||||
DAA髋关节置换 护患沟通技巧在急诊输液护理中的应用分析急诊科,输液护理,护理沟通技巧,应用 0
|
||||
.......
|
||||
```
|
||||
训练数据集`test_pairwise.csv`的格式如下,其中这个score得分是召回算出来的相似度或者距离,仅供参考,可以忽略:
|
||||
|
||||
```
|
||||
query1 \t title1 \t score
|
||||
query2 \t title2 \t score
|
||||
```
|
||||
训练数据集`test_pairwise.csv`的示例如下:
|
||||
|
||||
```
|
||||
中西方语言与文化的差异 中西方文化差异以及语言体现中西方文化,差异,语言体现 0.43203747272491455
|
||||
中西方语言与文化的差异 论中西方文化差异在非言语交际中的体现中西方文化,差异,非言语交际 0.4644506871700287
|
||||
中西方语言与文化的差异 中西方体态语文化差异跨文化,体态语,非语言交际,差异 0.4917311668395996
|
||||
中西方语言与文化的差异 由此便可以发现两种语言以及两种文化的差异。 0.5039259195327759
|
||||
.......
|
||||
```
|
||||
|
||||
对于第二种基于RocketQA的排序模型。
|
||||
|
||||
训练数据集`train.csv`,验证集`dev_pairwise.csv`的格式如下:
|
||||
|
||||
```
|
||||
query1 \t title1 \t label
|
||||
query2 \t title2 \t label
|
||||
```
|
||||
训练数据集`train.csv`,验证集`dev_pairwise.csv`的示例如下:
|
||||
|
||||
```
|
||||
(小学数学教材比较) 关键词:新加坡 新加坡与中国数学教材的特色比较数学教材,教材比较,问题解决 0
|
||||
徐慧新疆肿瘤医院 头颈部非霍奇金淋巴瘤扩散加权成像ADC值与Ki-67表达相关性分析淋巴瘤,非霍奇金,头颈部肿瘤,磁共振成像 1
|
||||
抗生素关性腹泻 鼠李糖乳杆菌GG防治消化系统疾病的研究进展鼠李糖乳杆菌,腹泻,功能性胃肠病,肝脏疾病,幽门螺杆菌 0
|
||||
德州市图书馆 图书馆智慧化建设与融合创新服务研究图书馆;智慧化;阅读服务;融合创新 1
|
||||
维生素c 综述 维生素C防治2型糖尿病研究进展维生素C;2型糖尿病;氧化应激;自由基;抗氧化剂 0
|
||||
.......
|
||||
```
|
||||
|
||||
训练数据集`test.csv`的格式如下,其中这个score得分是召回算出来的相似度或者距离,仅供参考,可以忽略:
|
||||
|
||||
```
|
||||
query1 \t title1 \t score
|
||||
query2 \t title2 \t score
|
||||
```
|
||||
训练数据集`test.csv`的示例如下:
|
||||
|
||||
```
|
||||
加强科研项目管理有效促进医学科研工作 科研项目管理策略科研项目,项目管理,实施,必要性,策略 0.32163668
|
||||
加强科研项目管理有效促进医学科研工作 关于推进我院科研发展进程的相关问题研究医院科研,主体,环境,信息化 0.32922596
|
||||
加强科研项目管理有效促进医学科研工作 深圳科技计划对高校科研项目资助现状分析与思考基础研究,高校,科技计划,科技创新 0.36869502
|
||||
加强科研项目管理有效促进医学科研工作 普通高校科研管理模式的优化与创新普通高校,科研,科研管理 0.3688045
|
||||
.......
|
||||
```
|
||||
|
||||
|
||||
### 3.4 运行环境和安装说明
|
||||
|
||||
|
||||
(1)运行环境
|
||||
@@ -163,14 +306,91 @@ c. 依赖安装:
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## 4. 动手实践——搭建自己的检索系统
|
||||
## 4. Neural Search 快速体验实践
|
||||
|
||||
PaddleNLP已经基于ERNIE 1.0训练了一个基线模型,如果想快速搭建Neural Search的完整系统。
|
||||
|
||||
### 4.1. 召回
|
||||
|
||||
- 召回向量抽取服务的搭建请参考:[In-batch Negatives](./recall/in_batch_negative/), 只需要下载基于ERNIE 1.0的预训练模型,导出成Paddle Serving的格式,然后启动Pipeline Server服务即可
|
||||
|
||||
- 召回向量检索服务的搭建请参考:[Milvus](./recall/milvus/), 需要搭建Milvus并且插入检索数据的向量
|
||||
|
||||
【注意】如果使用Neural Search训练好的模型,由于该模型是基于ERNIE 1.0训练的,所以需要把 `model_name_or_path`指定为`ernie 1.0`,向量抽取结果才能正常。
|
||||
|
||||
|
||||
### 4.2. 排序
|
||||
|
||||
排序服务的搭建请参考 [ernie_matching](./ranking/ernie_matching/),只需要下载基于ERNIE Gram的预训练模型,导出成Paddle Serving的格式,最后需要启动 Pipeline Serving服务
|
||||
|
||||
【注意】如果使用Neural Search训练好的模型,由于该模型是基于ERNIE Gram训练的,所以需要把 `model_name_or_path`指定为`ernie-gram-zh`,向量抽取结果才能正常。
|
||||
|
||||
### 4.3. 系统运行
|
||||
|
||||
以上召回和排序模型都经过Paddle Serving服务化以后,就可以直接使用下面的命令运行体验:
|
||||
|
||||
```
|
||||
python3 run_system.py
|
||||
```
|
||||
输出的结果为:
|
||||
|
||||
```
|
||||
PipelineClient::predict pack_data time:1656991375.5521955
|
||||
PipelineClient::predict before time:1656991375.5529568
|
||||
Extract feature time to cost :0.0161135196685791 seconds
|
||||
Search milvus time cost is 0.8139839172363281 seconds
|
||||
PipelineClient::predict pack_data time:1656991376.3981335
|
||||
PipelineClient::predict before time:1656991376.3983877
|
||||
time to cost :0.05616641044616699 seconds
|
||||
```
|
||||
会输出2个文件 `recall_result.csv` 是召回检索的结果,`rank_result.csv` 是排序的结果。csv的示例输出下。
|
||||
|
||||
召回的结果:
|
||||
|
||||
```
|
||||
中西方语言与文化的差异,港台文化对内地中小学生的负面影响,0.055068351328372955
|
||||
中西方语言与文化的差异,外来文化在越南的传播与融合,0.05621318891644478
|
||||
中西方语言与文化的差异,临终关怀中的“仪式”,0.05705389380455017
|
||||
中西方语言与文化的差异,历史的真实与艺术加工,0.05745899677276611
|
||||
......
|
||||
```
|
||||
|
||||
排序的结果:
|
||||
|
||||
```
|
||||
中西方语言与文化的差异,论中西方教育差异,0.870943009853363
|
||||
中西方语言与文化的差异,浅析中西方问候语的差异,0.8468159437179565
|
||||
中西方语言与文化的差异,文化认同及其根源,0.8288694620132446
|
||||
中西方语言与文化的差异,从历史文化角度分析中西方学校教育的差异,0.8209370970726013
|
||||
中西方语言与文化的差异,中西医思维方式的差异,0.8150948882102966
|
||||
中西方语言与文化的差异,浅析中韩餐桌文化差异,0.7751647233963013
|
||||
......
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 5. 从头开始搭建自己的检索系统
|
||||
|
||||
这里展示了能够从头至尾跑通的完整代码,您使用自己的业务数据,照着跑,能搭建出一个给定 Query,返回 topK 相关文档的小型检索系统。您可以参照我们给出的效果和性能数据来检查自己的运行过程是否正确。
|
||||
|
||||
### 4.1 召回阶段
|
||||
### 5.1 召回阶段
|
||||
|
||||
**召回模型训练**
|
||||
|
||||
我们进行了多组实践,用来对比说明召回阶段各方案的效果:
|
||||
|
||||
| 模型 | Recall@1 | Recall@5 |Recall@10 |Recall@20 |Recall@50 |策略简要说明|
|
||||
| ------------ | ------------ | ------------ |--------- |--------- |--------- |--------- |
|
||||
| 有监督训练 Baseline | 30.077| 43.513| 48.633 | 53.448 |59.632| 标准 pair-wise 训练范式,通过随机采样产生负样本|
|
||||
| 有监督训练 In-batch Negatives | 51.301 | 65.309| 69.878| 73.996|78.881| In-batch Negatives 有监督训练|
|
||||
| 无监督训练 SimCSE | 42.374 | 57.505| 62.641| 67.09|72.331| SimCSE 无监督训练|
|
||||
| 无监督 + 有监督训练 SimCSE + In-batch Negatives | 55.976 | 71.849| 76.363| 80.49|84.809| SimCSE无监督训练,In-batch Negatives 有监督训练|
|
||||
| Domain-adaptive Pretraining + SimCSE | 51.031 | 66.648| 71.338 | 75.676 |80.144| ERNIE 预训练,SimCSE 无监督训练|
|
||||
| Domain-adaptive Pretraining + SimCSE + In-batch Negatives| **58.248** | **75.099**| **79.813**| **83.801**|**87.733**| ERNIE 预训练,SimCSE 无监督训训练,In-batch Negatives 有监督训练|
|
||||
|
||||
从上述表格可以看出,首先利用 ERNIE 3.0 做 Domain-adaptive Pretraining ,然后把训练好的模型加载到 SimCSE 上进行无监督训练,最后利用 In-batch Negatives 在有监督数据上进行训练能够获得最佳的性能。[模型下载](https://paddlenlp.bj.bcebos.com/models/inbatch_model_best.zip),模型的使用方式参考[In-batch Negatives](./recall/in_batch_negative/) 。
|
||||
|
||||
|
||||
这里采用 Domain-adaptive Pretraining + SimCSE + In-batch Negatives 方案:
|
||||
|
||||
第一步:无监督训练 Domain-adaptive Pretraining
|
||||
@@ -186,19 +406,6 @@ pip install -r requirements.txt
|
||||
几分钟内训练完成,可参考 [In-batch Negatives](./recall/in_batch_negative/)
|
||||
|
||||
|
||||
此外,我们进行了多组实践,用来对比说明召回阶段各方案的效果:
|
||||
|
||||
| 模型 | Recall@1 | Recall@5 |Recall@10 |Recall@20 |Recall@50 |策略简要说明|
|
||||
| ------------ | ------------ | ------------ |--------- |--------- |--------- |--------- |
|
||||
| 有监督训练 Baseline | 30.077| 43.513| 48.633 | 53.448 |59.632| 标准 pair-wise 训练范式,通过随机采样产生负样本|
|
||||
| 有监督训练 In-batch Negatives | 51.301 | 65.309| 69.878| 73.996|78.881| In-batch Negatives 有监督训练|
|
||||
| 无监督训练 SimCSE | 42.374 | 57.505| 62.641| 67.09|72.331| SimCSE 无监督训练|
|
||||
| 无监督 + 有监督训练 SimCSE + In-batch Negatives | 55.976 | 71.849| 76.363| 80.49|84.809| SimCSE无监督训练,In-batch Negatives 有监督训练|
|
||||
| Domain-adaptive Pretraining + SimCSE | 51.031 | 66.648| 71.338 | 75.676 |80.144| ERNIE 预训练,SimCSE 无监督训练|
|
||||
| Domain-adaptive Pretraining + SimCSE + In-batch Negatives| **58.248** | **75.099**| **79.813**| **83.801**|**87.733**| ERNIE 预训练,SimCSE 无监督训训练,In-batch Negatives 有监督训练|
|
||||
|
||||
从上述表格可以看出,首先利用 ERNIE 3.0 做 Domain-adaptive Pretraining ,然后把训练好的模型加载到 SimCSE 上进行无监督训练,最后利用 In-batch Negatives 在有监督数据上进行训练能够获得最佳的性能。[模型下载](https://paddlenlp.bj.bcebos.com/models/inbatch_model_best.zip),模型的使用方式参考[In-batch Negatives](./recall/in_batch_negative/) 。
|
||||
|
||||
**召回系统搭建**
|
||||
|
||||
召回系统使用索引引擎 Milvus,可参考 [milvus_system](./recall/milvus/)。
|
||||
@@ -233,18 +440,19 @@ pip install -r requirements.txt
|
||||
```
|
||||
|
||||
|
||||
### 4.2 排序阶段
|
||||
### 5.2 排序阶段
|
||||
|
||||
排序阶段使用的模型是 ERNIE-3.0-Medium-zh,用时 20h,可参考:
|
||||
排序阶段有2种方案,第一种是[ernie_matching](./ranking/ernie_matching/)使用的模型是 ERNIE-3.0-Medium-zh,用时 20h;第二种是基于RocketQA的排序模型[cross_encoder](./ranking/cross_encoder/),训练用时也是20h左右。
|
||||
|
||||
[ernie_matching](./ranking/ernie_matching/)
|
||||
|
||||
排序阶段的效果评估:
|
||||
|
||||
| 模型 | AUC |
|
||||
| ------------ | ------------ |
|
||||
| Baseline: In-batch Negatives | 0.582 |
|
||||
| ERNIE-Gram | 0.801 |
|
||||
| pairwise ERNIE-Gram |0.801 |
|
||||
| CrossEncoder:rocketqa-base-cross-encoder |**0.835** |
|
||||
|
||||
|
||||
同样输入文本:
|
||||
|
||||
|
||||
399
applications/neural_search/ranking/cross_encoder/README.md
Normal file
399
applications/neural_search/ranking/cross_encoder/README.md
Normal file
@@ -0,0 +1,399 @@
|
||||
|
||||
**目录**
|
||||
|
||||
* [背景介绍](#背景介绍)
|
||||
* [CrossEncoder](#CrossEncoder)
|
||||
* [1. 技术方案和评估指标](#技术方案)
|
||||
* [2. 环境依赖](#环境依赖)
|
||||
* [3. 代码结构](#代码结构)
|
||||
* [4. 数据准备](#数据准备)
|
||||
* [5. 模型训练](#模型训练)
|
||||
* [6. 评估](#开始评估)
|
||||
* [7. 预测](#预测)
|
||||
* [8. 部署](#部署)
|
||||
|
||||
<a name="背景介绍"></a>
|
||||
|
||||
# 背景介绍
|
||||
|
||||
基于RocketQA的CrossEncoder训练的单塔模型,该模型用于搜索的排序阶段,对召回的结果进行重新排序的作用。
|
||||
|
||||
|
||||
<a name="CrossEncoder"></a>
|
||||
|
||||
# CrossEncoder
|
||||
|
||||
<a name="技术方案"></a>
|
||||
|
||||
## 1. 技术方案和评估指标
|
||||
|
||||
### 技术方案
|
||||
|
||||
加载基于ERNIE 3.0训练过的RocketQA单塔CrossEncoder模型。
|
||||
|
||||
|
||||
### 评估指标
|
||||
|
||||
(1)采用 AUC 指标来评估排序模型的排序效果。
|
||||
|
||||
**效果评估**
|
||||
|
||||
| 训练方式 | 模型 | AUC |
|
||||
| ------------ | ------------ |------------ |
|
||||
| pairwise| ERNIE-Gram |0.801 |
|
||||
| CrossEncoder | rocketqa-base-cross-encoder |**0.835** |
|
||||
|
||||
<a name="环境依赖"></a>
|
||||
|
||||
## 2. 环境依赖和安装说明
|
||||
|
||||
**环境依赖**
|
||||
|
||||
* python >= 3.7
|
||||
* paddlepaddle >= 2.3.7
|
||||
* paddlenlp >= 2.3
|
||||
* pandas >= 0.25.1
|
||||
* scipy >= 1.3.1
|
||||
|
||||
<a name="代码结构"></a>
|
||||
|
||||
## 3. 代码结构
|
||||
|
||||
以下是本项目主要代码结构及说明:
|
||||
|
||||
```
|
||||
ernie_matching/
|
||||
├── deply # 部署
|
||||
├── cpp
|
||||
├── rpc_client.py # RPC 客户端的bash脚本
|
||||
├── http_client.py # http 客户端的bash文件
|
||||
└── start_server.sh # 启动C++服务的脚本
|
||||
└── python
|
||||
├── deploy.sh # 预测部署bash脚本
|
||||
├── config_nlp.yml # Pipeline 的配置文件
|
||||
├── web_service.py # Pipeline 服务端的脚本
|
||||
├── rpc_client.py # Pipeline RPC客户端的脚本
|
||||
└── predict.py # python 预测部署示例
|
||||
|—— scripts
|
||||
├── export_model.sh # 动态图参数导出静态图参数的bash文件
|
||||
├── export_to_serving.sh # 导出 Paddle Serving 模型格式的bash文件
|
||||
├── train_ce.sh # 匹配模型训练的bash文件
|
||||
├── evaluate_ce.sh # 评估验证文件bash脚本
|
||||
├── predict_ce.sh # 匹配模型预测脚本的bash文件
|
||||
├── export_model.py # 动态图参数导出静态图参数脚本
|
||||
├── export_to_serving.py # 导出 Paddle Serving 模型格式的脚本
|
||||
├── data.py # 训练样本的转换逻辑
|
||||
├── train_ce.py # 模型训练脚本
|
||||
├── evaluate.py # 评估验证文件
|
||||
├── predict.py # Pair-wise 模型预测脚本,输出文本对是相似度
|
||||
|
||||
```
|
||||
|
||||
<a name="数据准备"></a>
|
||||
|
||||
## 4. 数据准备
|
||||
|
||||
### 数据集说明
|
||||
|
||||
样例数据如下:
|
||||
```
|
||||
(小学数学教材比较) 关键词:新加坡 新加坡与中国数学教材的特色比较数学教材,教材比较,问题解决 0
|
||||
徐慧新疆肿瘤医院 头颈部非霍奇金淋巴瘤扩散加权成像ADC值与Ki-67表达相关性分析淋巴瘤,非霍奇金,头颈部肿瘤,磁共振成像 1
|
||||
抗生素关性腹泻 鼠李糖乳杆菌GG防治消化系统疾病的研究进展鼠李糖乳杆菌,腹泻,功能性胃肠病,肝脏疾病,幽门螺杆菌 0
|
||||
德州市图书馆 图书馆智慧化建设与融合创新服务研究图书馆;智慧化;阅读服务;融合创新 1
|
||||
维生素c 综述 维生素C防治2型糖尿病研究进展维生素C;2型糖尿病;氧化应激;自由基;抗氧化剂 0
|
||||
(白藜芦醇) 关键词:2型糖尿病 2型糖尿病大鼠心肌缺血再灌注损伤转录因子E2相关因子2/血红素氧合酶1信号通路的表达及白藜芦醇的干预研究糖尿病,2型,心肌缺血,再灌注损伤,白藜芦醇 1
|
||||
融资偏好 创新型企业产业风险、融资偏好与融资选择融资偏好;产业风险;融资选择 1
|
||||
星载激光雷达 星载激光雷达望远镜主镜超轻量化结构设计超轻量化;拓扑优化;集成优化;RMS;有限元仿真 1
|
||||
```
|
||||
|
||||
|
||||
### 数据集下载
|
||||
|
||||
|
||||
- [literature_search_rank](https://paddlenlp.bj.bcebos.com/applications/literature_search_rank.zip)
|
||||
|
||||
```
|
||||
├── data # 排序数据集
|
||||
├── test.csv # 测试集
|
||||
├── dev_pairwise.csv # 验证集
|
||||
└── train.csv # 训练集
|
||||
```
|
||||
|
||||
<a name="模型训练"></a>
|
||||
|
||||
## 5. 模型训练
|
||||
|
||||
**排序模型下载链接:**
|
||||
|
||||
|
||||
|Model|训练参数配置|硬件|MD5|
|
||||
| ------------ | ------------ | ------------ |-----------|
|
||||
|[ERNIE-Gram-Sort](https://bj.bcebos.com/v1/paddlenlp/models/ernie_gram_sort.zip)|<div style="width: 150pt">epoch:3 lr:5E-5 bs:64 max_len:64 </div>|<div style="width: 100pt">4卡 v100-16g</div>|d24ece68b7c3626ce6a24baa58dd297d|
|
||||
|
||||
|
||||
### 训练环境说明
|
||||
|
||||
|
||||
- NVIDIA Driver Version: 440.64.00
|
||||
- Ubuntu 16.04.6 LTS (Docker)
|
||||
- Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
|
||||
|
||||
|
||||
### 单机单卡训练/单机多卡训练
|
||||
|
||||
这里采用单机多卡方式进行训练,通过如下命令,指定 GPU 0,1,2,3 卡。如果采用单机单卡训练,只需要把`--gpu`参数设置成单卡的卡号即可
|
||||
|
||||
训练的命令如下:
|
||||
|
||||
```
|
||||
unset CUDA_VISIBLE_DEVICES
|
||||
python -u -m paddle.distributed.launch --gpus "0,1,2,3" --log_dir="logs" train_ce.py \
|
||||
--device gpu \
|
||||
--train_set data/train.csv \
|
||||
--test_file data/dev_pairwise.csv \
|
||||
--save_dir ./checkpoints \
|
||||
--model_name_or_path rocketqa-base-cross-encoder \
|
||||
--batch_size 32 \
|
||||
--save_steps 10000 \
|
||||
--max_seq_len 384 \
|
||||
--learning_rate 1E-5 \
|
||||
--weight_decay 0.01 \
|
||||
--warmup_proportion 0.0 \
|
||||
--logging_steps 10 \
|
||||
--seed 1 \
|
||||
--epochs 3 \
|
||||
--eval_step 1000
|
||||
```
|
||||
也可以运行bash脚本:
|
||||
|
||||
```
|
||||
sh scripts/train_ce.sh
|
||||
```
|
||||
|
||||
<a name="评估"></a>
|
||||
|
||||
## 6. 评估
|
||||
|
||||
|
||||
```
|
||||
python evaluate.py --model_name_or_path rocketqa-base-cross-encoder \
|
||||
--init_from_ckpt checkpoints/model_80000/model_state.pdparams \
|
||||
--test_file data/dev_pairwise.csv
|
||||
```
|
||||
也可以运行bash脚本:
|
||||
|
||||
```
|
||||
sh scripts/evaluate_ce.sh
|
||||
```
|
||||
|
||||
|
||||
成功运行后会输出下面的指标:
|
||||
|
||||
```
|
||||
eval_dev auc:0.829
|
||||
```
|
||||
|
||||
<a name="预测"></a>
|
||||
|
||||
## 7. 预测
|
||||
|
||||
### 准备预测数据
|
||||
|
||||
待预测数据为 tab 分隔的 tsv 文件,每一行为 1 个文本 Pair,和文本pair的语义索引相似度,(该相似度由召回模型算出,仅供参考),部分示例如下:
|
||||
|
||||
```
|
||||
中西方语言与文化的差异 第二语言习得的一大障碍就是文化差异。 0.5160342454910278
|
||||
中西方语言与文化的差异 跨文化视角下中国文化对外传播路径琐谈跨文化,中国文化,传播,翻译 0.5145505666732788
|
||||
中西方语言与文化的差异 从中西方民族文化心理的差异看英汉翻译语言,文化,民族文化心理,思维方式,翻译 0.5141439437866211
|
||||
中西方语言与文化的差异 中英文化差异对翻译的影响中英文化,差异,翻译的影响 0.5138794183731079
|
||||
中西方语言与文化的差异 浅谈文化与语言习得文化,语言,文化与语言的关系,文化与语言习得意识,跨文化交际 0.5131710171699524
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 开始预测
|
||||
|
||||
以上述 demo 数据为例,运行如下命令基于我们开源的rocketqa模型开始计算文本 Pair 的语义相似度:
|
||||
|
||||
```shell
|
||||
unset CUDA_VISIBLE_DEVICES
|
||||
python predict.py \
|
||||
--device 'gpu' \
|
||||
--params_path checkpoints/model_80000/model_state.pdparams \
|
||||
--model_name_or_path rocketqa-base-cross-encoder \
|
||||
--test_set data/test.csv \
|
||||
--topk 10 \
|
||||
--batch_size 128 \
|
||||
--max_seq_length 384
|
||||
```
|
||||
也可以直接执行下面的命令:
|
||||
|
||||
```
|
||||
sh scripts/predict_ce.sh
|
||||
```
|
||||
得到下面的输出,分别是query,title和对应的预测概率:
|
||||
|
||||
```
|
||||
{'text_a': '加强科研项目管理有效促进医学科研工作', 'text_b': '高校\\十四五\\规划中学科建设要处理好五对关系\\十四五\\规划,学科建设,科技创新,人才培养', 'pred_prob': 0.7076062}
|
||||
{'text_a': '加强科研项目管理有效促进医学科研工作', 'text_b': '校企科研合作项目管理模式创新校企科研合作项目,管理模式,问题,创新', 'pred_prob': 0.64633846}
|
||||
{'text_a': '加强科研项目管理有效促进医学科研工作', 'text_b': '科研项目管理策略科研项目,项目管理,实施,必要性,策略', 'pred_prob': 0.63166416}
|
||||
{'text_a': '加强科研项目管理有效促进医学科研工作', 'text_b': '高校科研项目经费管理流程优化研究——以z大学为例高校,科研项目经费\\全流程\\管理,流程优化', 'pred_prob': 0.60351866}
|
||||
{'text_a': '加强科研项目管理有效促进医学科研工作', 'text_b': '关于推进我院科研发展进程的相关问题研究医院科研,主体,环境,信息化', 'pred_prob': 0.5688347}
|
||||
{'text_a': '加强科研项目管理有效促进医学科研工作', 'text_b': '医学临床科研选题原则和方法医学临床,科学研究,选题', 'pred_prob': 0.55190295}
|
||||
```
|
||||
|
||||
<a name="部署"></a>
|
||||
|
||||
## 8. 部署
|
||||
|
||||
### 动转静导出
|
||||
|
||||
首先把动态图模型转换为静态图:
|
||||
|
||||
```
|
||||
python export_model.py \
|
||||
--params_path checkpoints/model_80000/model_state.pdparams \
|
||||
--model_name_or_path rocketqa-base-cross-encoder \
|
||||
--output_path=./output
|
||||
```
|
||||
也可以运行下面的bash脚本:
|
||||
|
||||
```
|
||||
sh scripts/export_model.sh
|
||||
```
|
||||
|
||||
### Paddle Inference
|
||||
|
||||
使用PaddleInference
|
||||
|
||||
```
|
||||
python deploy/python/predict.py --model_dir ./output \
|
||||
--input_file data/test.csv \
|
||||
--model_name_or_path rocketqa-base-cross-encoder
|
||||
```
|
||||
也可以运行下面的bash脚本:
|
||||
|
||||
```
|
||||
sh deploy/python/deploy.sh
|
||||
```
|
||||
得到下面的输出,输出的是样本的query,title以及对应的概率:
|
||||
|
||||
```
|
||||
Data: {'query': '加强科研项目管理有效促进医学科研工作', 'title': '科研项目管理策略科研项目,项目管理,实施,必要性,策略'} prob: 0.5479063987731934
|
||||
Data: {'query': '加强科研项目管理有效促进医学科研工作', 'title': '关于推进我院科研发展进程的相关问题研究医院科研,主体,环境,信息化'} prob: 0.5151925086975098
|
||||
Data: {'query': '加强科研项目管理有效促进医学科研工作', 'title': '深圳科技计划对高校科研项目资助现状分析与思考基础研究,高校,科技计划,科技创新'} prob: 0.42983829975128174
|
||||
Data: {'query': '加强科研项目管理有效促进医学科研工作', 'title': '普通高校科研管理模式的优化与创新普通高校,科研,科研管理'} prob: 0.465454638004303
|
||||
```
|
||||
|
||||
### Paddle Serving部署
|
||||
|
||||
Paddle Serving 的详细文档请参考 [Pipeline_Design](https://github.com/PaddlePaddle/Serving/blob/v0.7.0/doc/Python_Pipeline/Pipeline_Design_CN.md)和[Serving_Design](https://github.com/PaddlePaddle/Serving/blob/v0.7.0/doc/Serving_Design_CN.md),首先把静态图模型转换成Serving的格式:
|
||||
|
||||
```
|
||||
python export_to_serving.py \
|
||||
--dirname "output" \
|
||||
--model_filename "inference.pdmodel" \
|
||||
--params_filename "inference.pdiparams" \
|
||||
--server_path "serving_server" \
|
||||
--client_path "serving_client" \
|
||||
--fetch_alias_names "predict"
|
||||
|
||||
```
|
||||
|
||||
参数含义说明
|
||||
* `dirname`: 需要转换的模型文件存储路径,Program 结构文件和参数文件均保存在此目录。
|
||||
* `model_filename`: 存储需要转换的模型 Inference Program 结构的文件名称。如果设置为 None ,则使用 `__model__` 作为默认的文件名
|
||||
* `params_filename`: 存储需要转换的模型所有参数的文件名称。当且仅当所有模型参数被保>存在一个单独的二进制文件中,它才需要被指定。如果模型参数是存储在各自分离的文件中,设置它的值为 None
|
||||
* `server_path`: 转换后的模型文件和配置文件的存储路径。默认值为 serving_server
|
||||
* `client_path`: 转换后的客户端配置文件存储路径。默认值为 serving_client
|
||||
* `fetch_alias_names`: 模型输出的别名设置,比如输入的 input_ids 等,都可以指定成其他名字,默认不指定
|
||||
* `feed_alias_names`: 模型输入的别名设置,比如输出 pooled_out 等,都可以重新指定成其他模型,默认不指定
|
||||
|
||||
也可以运行下面的 bash 脚本:
|
||||
```
|
||||
sh scripts/export_to_serving.sh
|
||||
```
|
||||
Paddle Serving的部署有两种方式,第一种方式是Pipeline的方式,第二种是C++的方式,下面分别介绍这两种方式的用法:
|
||||
|
||||
#### Pipeline方式
|
||||
|
||||
修改对应预训练模型的`Tokenizer`:
|
||||
|
||||
```
|
||||
self.tokenizer = AutoTokenizer.from_pretrained('rocketqa-base-cross-encoder')
|
||||
```
|
||||
|
||||
启动 Pipeline Server:
|
||||
|
||||
```
|
||||
python web_service.py
|
||||
```
|
||||
|
||||
启动客户端调用 Server。
|
||||
|
||||
首先修改rpc_client.py中需要预测的样本:
|
||||
|
||||
```
|
||||
list_data = [{"query":"加强科研项目管理有效促进医学科研工作","title":"科研项目管理策略科研项目,项目管理,实施,必要性,策略"}]`
|
||||
```
|
||||
然后运行:
|
||||
```
|
||||
python rpc_client.py
|
||||
```
|
||||
模型的输出为:
|
||||
|
||||
```
|
||||
PipelineClient::predict pack_data time:1662354188.422532
|
||||
PipelineClient::predict before time:1662354188.423034
|
||||
time to cost :0.016808509826660156 seconds
|
||||
(1,)
|
||||
[0.5479064]
|
||||
```
|
||||
可以看到客户端发送了1条文本,这条文本的相似的概率值。
|
||||
|
||||
#### C++的方式
|
||||
|
||||
启动C++的Serving:
|
||||
|
||||
```
|
||||
python -m paddle_serving_server.serve --model serving_server --port 8600 --gpu_id 0 --thread 5 --ir_optim True
|
||||
```
|
||||
也可以使用脚本:
|
||||
|
||||
```
|
||||
sh deploy/cpp/start_server.sh
|
||||
```
|
||||
Client 可以使用 http 或者 rpc 两种方式,rpc 的方式为:
|
||||
|
||||
```
|
||||
python deploy/cpp/rpc_client.py
|
||||
```
|
||||
运行的输出为:
|
||||
|
||||
```
|
||||
I0905 05:38:28.876770 28507 general_model.cpp:490] [client]logid=0,client_cost=158.124ms,server_cost=156.385ms.
|
||||
time to cost :0.15848731994628906 seconds
|
||||
[0.54790646]
|
||||
```
|
||||
可以看到服务端返回了相似度结果
|
||||
|
||||
或者使用 http 的客户端访问模式:
|
||||
|
||||
```
|
||||
python deploy/cpp/http_client.py
|
||||
```
|
||||
运行的输出为:
|
||||
```
|
||||
time to cost :0.13054680824279785 seconds
|
||||
0.5479064707850817
|
||||
```
|
||||
可以看到服务端返回了相似度结果
|
||||
|
||||
|
||||
## Reference
|
||||
|
||||
[1] Xiao, Dongling, Yu-Kun Li, Han Zhang, Yu Sun, Hao Tian, Hua Wu, and Haifeng Wang. “ERNIE-Gram: Pre-Training with Explicitly N-Gram Masked Language Modeling for Natural Language Understanding.” ArXiv:2010.12148 [Cs].
|
||||
|
||||
[2] Yingqi Qu, Yuchen Ding, Jing Liu, Kai Liu, Ruiyang Ren, Wayne Xin Zhao, Daxiang Dong, Hua Wu, Haifeng Wang:
|
||||
RocketQA: An Optimized Training Approach to Dense Passage Retrieval for Open-Domain Question Answering. NAACL-HLT 2021: 5835-5847
|
||||
@@ -11,14 +11,15 @@
|
||||
# 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 re
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import paddle
|
||||
|
||||
|
||||
def convert_example(example, tokenizer, max_seq_length=512, is_test=False):
|
||||
def convert_example(example,
|
||||
tokenizer,
|
||||
max_seq_length=512,
|
||||
is_test=False,
|
||||
is_pair=False):
|
||||
"""
|
||||
Builds model inputs from a sequence or a pair of sequence for sequence classification tasks
|
||||
by concatenating and adding special tokens. And creates a mask from the two sequences passed
|
||||
@@ -27,14 +28,8 @@ def convert_example(example, tokenizer, max_seq_length=512, is_test=False):
|
||||
A BERT sequence has the following format:
|
||||
|
||||
- single sequence: ``[CLS] X [SEP]``
|
||||
- pair of sequences: ``[CLS] A [SEP] B [SEP]``
|
||||
|
||||
A BERT sequence pair mask has the following format:
|
||||
::
|
||||
0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
|
||||
| first sequence | second sequence |
|
||||
|
||||
If only one sequence, only returns the first portion of the mask (0's).
|
||||
It returns the first portion of the mask (0's).
|
||||
|
||||
|
||||
Args:
|
||||
@@ -50,14 +45,51 @@ def convert_example(example, tokenizer, max_seq_length=512, is_test=False):
|
||||
token_type_ids(obj: `list[int]`): List of sequence pair mask.
|
||||
label(obj:`numpy.array`, data type of int64, optional): The input label if not is_test.
|
||||
"""
|
||||
encoded_inputs = tokenizer(text=example["text"], max_seq_len=max_seq_length)
|
||||
|
||||
if is_pair:
|
||||
text = example["text_a"]
|
||||
text_pair = example["text_b"]
|
||||
else:
|
||||
text = example["text"]
|
||||
text_pair = None
|
||||
encoded_inputs = tokenizer(text=text,
|
||||
text_pair=text_pair,
|
||||
max_seq_len=max_seq_length)
|
||||
input_ids = encoded_inputs["input_ids"]
|
||||
token_type_ids = encoded_inputs["token_type_ids"]
|
||||
|
||||
if not is_test:
|
||||
label = np.array(example["label"], dtype="float32")
|
||||
return input_ids, token_type_ids, label
|
||||
return input_ids, token_type_ids
|
||||
if is_test:
|
||||
return input_ids, token_type_ids
|
||||
label = np.array([example["label"]], dtype="int64")
|
||||
return input_ids, token_type_ids, label
|
||||
|
||||
|
||||
def read_text_pair(data_path):
|
||||
"""Reads data."""
|
||||
with open(data_path, 'r', encoding='utf-8') as f:
|
||||
for line in f:
|
||||
data = line.rstrip().split("\t")
|
||||
if len(data) != 3:
|
||||
continue
|
||||
yield {'text_a': data[0], 'text_b': data[1]}
|
||||
|
||||
|
||||
def read_data(data_path):
|
||||
"""Reads data."""
|
||||
with open(data_path, 'r', encoding='utf-8', errors='ignore') as f:
|
||||
for i, line in enumerate(f):
|
||||
# Skip column name
|
||||
if (i == 0):
|
||||
continue
|
||||
data = line.rstrip('\n').split("\t")
|
||||
if (len(data) != 3):
|
||||
print(data)
|
||||
continue
|
||||
query = data[0]
|
||||
title = data[1]
|
||||
label = data[-1]
|
||||
# breakpoint()
|
||||
yield {'text_a': query, 'text_b': title, 'label': int(label)}
|
||||
|
||||
|
||||
def create_dataloader(dataset,
|
||||
@@ -82,37 +114,3 @@ def create_dataloader(dataset,
|
||||
batch_sampler=batch_sampler,
|
||||
collate_fn=batchify_fn,
|
||||
return_list=True)
|
||||
|
||||
|
||||
def read_custom_data(filename, is_test=False):
|
||||
"""Reads data."""
|
||||
data = pd.read_csv(filename)
|
||||
for line in data.values:
|
||||
if is_test:
|
||||
text = line[1]
|
||||
yield {"text": clean_text(text), "label": ""}
|
||||
else:
|
||||
text, label = line[1], line[2:]
|
||||
yield {"text": clean_text(text), "label": label}
|
||||
|
||||
|
||||
def clean_text(text):
|
||||
text = text.replace("\r", "").replace("\n", "")
|
||||
text = re.sub(r"\\n\n", ".", text)
|
||||
return text
|
||||
|
||||
|
||||
def write_test_results(filename, results, label_info):
|
||||
"""write test results"""
|
||||
data = pd.read_csv(filename)
|
||||
qids = [line[0] for line in data.values]
|
||||
results_dict = {k: [] for k in label_info}
|
||||
results_dict["id"] = qids
|
||||
results = list(map(list, zip(*results)))
|
||||
for key in results_dict:
|
||||
if key != "id":
|
||||
for result in results:
|
||||
results_dict[key] = result
|
||||
df = pd.DataFrame(results_dict)
|
||||
df.to_csv("sample_test.csv", index=False)
|
||||
print("Test results saved")
|
||||
@@ -0,0 +1,78 @@
|
||||
# coding:utf-8
|
||||
# pylint: disable=doc-string-missing
|
||||
# Copyright (c) 2020 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 time
|
||||
import numpy as np
|
||||
import requests
|
||||
import json
|
||||
|
||||
from paddle_serving_client.httpclient import HttpClient
|
||||
from scipy.special import expit
|
||||
from paddlenlp.transformers import AutoTokenizer
|
||||
import paddlenlp as ppnlp
|
||||
|
||||
|
||||
def convert_example(example, tokenizer, max_seq_length=512):
|
||||
|
||||
query, title = example["query"], example["title"]
|
||||
encoded_inputs = tokenizer(text=query,
|
||||
text_pair=title,
|
||||
max_seq_len=max_seq_length)
|
||||
input_ids = encoded_inputs["input_ids"]
|
||||
token_type_ids = encoded_inputs["token_type_ids"]
|
||||
|
||||
return input_ids, token_type_ids
|
||||
|
||||
|
||||
# 启动python客户端
|
||||
endpoint_list = ['127.0.0.1:8600']
|
||||
client = HttpClient()
|
||||
client.load_client_config('serving_client')
|
||||
client.connect(endpoint_list)
|
||||
feed_names = client.feed_names_
|
||||
fetch_names = client.fetch_names_
|
||||
|
||||
# 创建tokenizer
|
||||
tokenizer = AutoTokenizer.from_pretrained('rocketqa-base-cross-encoder')
|
||||
max_seq_len = 64
|
||||
|
||||
# 数据预处理
|
||||
list_data = [{
|
||||
"query": "加强科研项目管理有效促进医学科研工作",
|
||||
"title": "科研项目管理策略科研项目,项目管理,实施,必要性,策略"
|
||||
}]
|
||||
|
||||
input_ids, token_type_ids = [], []
|
||||
for example in list_data:
|
||||
input_id, token_type_id = convert_example(example,
|
||||
tokenizer,
|
||||
max_seq_length=max_seq_len)
|
||||
input_ids.append(input_id)
|
||||
token_type_ids.append(token_type_id)
|
||||
|
||||
feed_dict = {}
|
||||
feed_dict['input_ids'] = np.array(input_ids)
|
||||
feed_dict['token_type_ids'] = np.array(token_type_ids)
|
||||
# batch设置为True表示的是批量预测
|
||||
b_start = time.time()
|
||||
result = client.predict(feed=feed_dict, fetch=fetch_names, batch=True)
|
||||
b_end = time.time()
|
||||
print(result)
|
||||
print("time to cost :{} seconds".format(b_end - b_start))
|
||||
score = result.outputs[0].tensor[0].float_data
|
||||
sim_score = expit(np.array(score))[1]
|
||||
print(sim_score)
|
||||
@@ -0,0 +1,76 @@
|
||||
# coding:utf-8
|
||||
# pylint: disable=doc-string-missing
|
||||
# Copyright (c) 2020 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 time
|
||||
import numpy as np
|
||||
|
||||
from paddle_serving_client import Client
|
||||
from scipy.special import expit
|
||||
from paddlenlp.transformers import AutoTokenizer
|
||||
import paddlenlp as ppnlp
|
||||
|
||||
|
||||
def convert_example(example, tokenizer, max_seq_length=512):
|
||||
|
||||
query, title = example["query"], example["title"]
|
||||
encoded_inputs = tokenizer(text=query,
|
||||
text_pair=title,
|
||||
max_seq_len=max_seq_length)
|
||||
|
||||
input_ids = encoded_inputs["input_ids"]
|
||||
token_type_ids = encoded_inputs["token_type_ids"]
|
||||
|
||||
return input_ids, token_type_ids
|
||||
|
||||
|
||||
# 启动python客户端
|
||||
endpoint_list = ['127.0.0.1:8600']
|
||||
client = Client()
|
||||
client.load_client_config('serving_client')
|
||||
client.connect(endpoint_list)
|
||||
feed_names = client.feed_names_
|
||||
fetch_names = client.fetch_names_
|
||||
|
||||
# 创建tokenizer
|
||||
tokenizer = AutoTokenizer.from_pretrained('rocketqa-base-cross-encoder')
|
||||
max_seq_len = 64
|
||||
|
||||
# 数据预处理
|
||||
list_data = [{
|
||||
"query": "加强科研项目管理有效促进医学科研工作",
|
||||
"title": "科研项目管理策略科研项目,项目管理,实施,必要性,策略"
|
||||
}]
|
||||
|
||||
input_ids, token_type_ids = [], []
|
||||
for example in list_data:
|
||||
input_id, token_type_id = convert_example(example,
|
||||
tokenizer,
|
||||
max_seq_length=max_seq_len)
|
||||
input_ids.append(input_id)
|
||||
token_type_ids.append(token_type_id)
|
||||
|
||||
feed_dict = {}
|
||||
feed_dict['input_ids'] = np.array(input_ids)
|
||||
feed_dict['token_type_ids'] = np.array(token_type_ids)
|
||||
# batch设置为True表示的是批量预测
|
||||
b_start = time.time()
|
||||
result = client.predict(feed=feed_dict, fetch=fetch_names, batch=True)
|
||||
# breakpoint()
|
||||
sim_score = expit(result['predict'])[:, 1]
|
||||
b_end = time.time()
|
||||
print("time to cost :{} seconds".format(b_end - b_start))
|
||||
print(sim_score)
|
||||
@@ -0,0 +1 @@
|
||||
python -m paddle_serving_server.serve --model serving_server --port 8600 --gpu_id 0 --thread 5 --ir_optim True
|
||||
@@ -0,0 +1,34 @@
|
||||
# worker_num, 最大并发数。当build_dag_each_worker=True时, 框架会创建worker_num个进程,每个进程内构建grpcSever和DAG
|
||||
# 当build_dag_each_worker=False时,框架会设置主线程grpc线程池的max_workers=worker_num
|
||||
worker_num: 20
|
||||
# build_dag_each_worker, False,框架在进程内创建一条DAG;True,框架会每个进程内创建多个独立的DAG
|
||||
build_dag_each_worker: false
|
||||
|
||||
dag:
|
||||
# op资源类型, True, 为线程模型;False,为进程模型
|
||||
is_thread_op: False
|
||||
# 使用性能分析, True,生成Timeline性能数据,对性能有一定影响;False为不使用
|
||||
tracer:
|
||||
interval_s: 10
|
||||
# http端口, rpc_port和http_port不允许同时为空。当rpc_port可用且http_port为空时,不自动生成http_port
|
||||
http_port: 8088
|
||||
# rpc端口, rpc_port和http_port不允许同时为空。当rpc_port为空且http_port不为空时,会自动将rpc_port设置为http_port+1
|
||||
rpc_port: 8089
|
||||
op:
|
||||
ernie:
|
||||
# 并发数,is_thread_op=True时,为线程并发;否则为进程并发
|
||||
concurrency: 1
|
||||
# 当op配置没有server_endpoints时,从local_service_conf读取本地服务配置
|
||||
local_service_conf:
|
||||
# client类型,包括brpc, grpc和local_predictor.local_predictor不启动Serving服务,进程内预测
|
||||
client_type: local_predictor
|
||||
# ir_optim
|
||||
ir_optim: True
|
||||
# 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"
|
||||
# Fetch结果列表,以client_config中fetch_var的alias_name为准, 如果没有设置则全部返回
|
||||
fetch_list: ['predict']
|
||||
# 模型路径
|
||||
model_config: ../../serving_server/
|
||||
@@ -0,0 +1,3 @@
|
||||
python deploy/python/predict.py --model_dir ./output \
|
||||
--input_file data/test.csv \
|
||||
--model_name_or_path rocketqa-base-cross-encoder
|
||||
@@ -14,22 +14,30 @@
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
from scipy.special import softmax
|
||||
from scipy.special import expit
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
import paddle
|
||||
from paddle import inference
|
||||
|
||||
import paddle.nn.functional as F
|
||||
from paddlenlp.data import Stack, Tuple, Pad
|
||||
from paddlenlp.transformers import AutoModel, AutoTokenizer
|
||||
from paddlenlp.datasets import load_dataset
|
||||
from paddlenlp.utils.log import logger
|
||||
from paddlenlp.transformers import AutoTokenizer
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
# yapf: disable
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--model_dir", type=str, required=True,
|
||||
help="The directory to static model.")
|
||||
|
||||
parser.add_argument("--input_file", type=str, required=True,
|
||||
help="The test set file.")
|
||||
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.")
|
||||
@@ -52,10 +60,22 @@ parser.add_argument("--benchmark", type=eval, default=False,
|
||||
help="To log some information about environment and running.")
|
||||
parser.add_argument("--save_log_path", type=str, default="./log_output/",
|
||||
help="The file path to save log.")
|
||||
parser.add_argument('--model_name_or_path', default="rocketqa-base-cross-encoder", help="The pretrained model used for training")
|
||||
|
||||
args = parser.parse_args()
|
||||
# yapf: enable
|
||||
|
||||
|
||||
def read_text_pair(data_path):
|
||||
"""Reads data."""
|
||||
with open(data_path, 'r', encoding='utf-8') as f:
|
||||
for line in f:
|
||||
data = line.rstrip().split("\t")
|
||||
if len(data) != 3:
|
||||
continue
|
||||
yield {'query': data[0], 'title': data[1]}
|
||||
|
||||
|
||||
def convert_example(example, tokenizer, max_seq_length=512, is_test=False):
|
||||
|
||||
query, title = example["query"], example["title"]
|
||||
@@ -136,24 +156,23 @@ class Predictor(object):
|
||||
if args.benchmark:
|
||||
import auto_log
|
||||
pid = os.getpid()
|
||||
self.autolog = auto_log.AutoLogger(model_name="ernie-tiny",
|
||||
model_precision=precision,
|
||||
batch_size=self.batch_size,
|
||||
data_shape="dynamic",
|
||||
save_path=args.save_log_path,
|
||||
inference_config=config,
|
||||
pids=pid,
|
||||
process_name=None,
|
||||
gpu_ids=0,
|
||||
time_keys=[
|
||||
'preprocess_time',
|
||||
'inference_time',
|
||||
'postprocess_time'
|
||||
],
|
||||
warmup=0,
|
||||
logger=logger)
|
||||
self.autolog = auto_log.AutoLogger(
|
||||
model_name=args.model_name_or_path,
|
||||
model_precision=precision,
|
||||
batch_size=self.batch_size,
|
||||
data_shape="dynamic",
|
||||
save_path=args.save_log_path,
|
||||
inference_config=config,
|
||||
pids=pid,
|
||||
process_name=None,
|
||||
gpu_ids=0,
|
||||
time_keys=[
|
||||
'preprocess_time', 'inference_time', 'postprocess_time'
|
||||
],
|
||||
warmup=0,
|
||||
logger=logger)
|
||||
|
||||
def predict(self, data, tokenizer, label_map):
|
||||
def predict(self, data, tokenizer):
|
||||
"""
|
||||
Predicts the data labels.
|
||||
|
||||
@@ -179,8 +198,9 @@ class Predictor(object):
|
||||
examples.append((input_ids, segment_ids))
|
||||
|
||||
batchify_fn = lambda samples, fn=Tuple(
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id), # input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id), # segment
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype="int64"), # input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype="int64"
|
||||
), # segment
|
||||
): fn(samples)
|
||||
|
||||
if args.benchmark:
|
||||
@@ -190,19 +210,15 @@ class Predictor(object):
|
||||
self.input_handles[0].copy_from_cpu(input_ids)
|
||||
self.input_handles[1].copy_from_cpu(segment_ids)
|
||||
self.predictor.run()
|
||||
probs = self.output_handle.copy_to_cpu()
|
||||
sim_score = self.output_handle.copy_to_cpu()
|
||||
if args.benchmark:
|
||||
self.autolog.times.stamp()
|
||||
|
||||
#probs = softmax(logits, axis=1)
|
||||
idx = np.argmax(probs, axis=1)
|
||||
idx = idx.tolist()
|
||||
labels = [label_map[i] for i in idx]
|
||||
sim_score = expit(sim_score)[:, 1]
|
||||
|
||||
if args.benchmark:
|
||||
self.autolog.times.end(stamp=True)
|
||||
|
||||
return labels
|
||||
return sim_score
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -211,9 +227,11 @@ if __name__ == "__main__":
|
||||
args.batch_size, args.use_tensorrt, args.precision,
|
||||
args.cpu_threads, args.enable_mkldnn)
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
|
||||
test_ds = load_dataset("lcqmc", splits=["test"])
|
||||
test_ds = load_dataset(read_text_pair,
|
||||
data_path=args.input_file,
|
||||
lazy=False)
|
||||
|
||||
data = [{'query': d['query'], 'title': d['title']} for d in test_ds]
|
||||
|
||||
@@ -221,12 +239,11 @@ if __name__ == "__main__":
|
||||
data[idx:idx + args.batch_size]
|
||||
for idx in range(0, len(data), args.batch_size)
|
||||
]
|
||||
label_map = {0: 'dissimilar', 1: 'similar'}
|
||||
|
||||
results = []
|
||||
for batch_data in batches:
|
||||
results.extend(predictor.predict(batch_data, tokenizer, label_map))
|
||||
results.extend(predictor.predict(batch_data, tokenizer))
|
||||
for idx, text in enumerate(data):
|
||||
print('Data: {} \t Label: {}'.format(text, results[idx]))
|
||||
print('Data: {} \t prob: {}'.format(text, results[idx]))
|
||||
if args.benchmark:
|
||||
predictor.autolog.report()
|
||||
@@ -0,0 +1,37 @@
|
||||
# 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 time
|
||||
import numpy as np
|
||||
|
||||
from paddle_serving_server.pipeline import PipelineClient
|
||||
|
||||
client = PipelineClient()
|
||||
client.connect(['127.0.0.1:8089'])
|
||||
|
||||
list_data = [{
|
||||
"query": "加强科研项目管理有效促进医学科研工作",
|
||||
"title": "科研项目管理策略科研项目,项目管理,实施,必要性,策略"
|
||||
}]
|
||||
feed = {}
|
||||
for i, item in enumerate(list_data):
|
||||
feed[str(i)] = str(item)
|
||||
|
||||
print(feed)
|
||||
start_time = time.time()
|
||||
ret = client.predict(feed_dict=feed)
|
||||
end_time = time.time()
|
||||
print("time to cost :{} seconds".format(end_time - start_time))
|
||||
result = np.array(eval(ret.value[0]))
|
||||
print(result.shape)
|
||||
print(result)
|
||||
@@ -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 json
|
||||
|
||||
from scipy.special import expit
|
||||
from paddle_serving_server.web_service import WebService, Op
|
||||
|
||||
|
||||
def convert_example(example, tokenizer, max_seq_length=512):
|
||||
|
||||
query, title = example["query"], example["title"]
|
||||
encoded_inputs = tokenizer(text=query,
|
||||
text_pair=title,
|
||||
max_seq_len=max_seq_length)
|
||||
|
||||
input_ids = encoded_inputs["input_ids"]
|
||||
token_type_ids = encoded_inputs["token_type_ids"]
|
||||
|
||||
return input_ids, token_type_ids
|
||||
|
||||
|
||||
class ErnieOp(Op):
|
||||
|
||||
def init_op(self):
|
||||
from paddlenlp.transformers import AutoTokenizer
|
||||
self.tokenizer = AutoTokenizer.from_pretrained(
|
||||
'rocketqa-base-cross-encoder')
|
||||
|
||||
def preprocess(self, input_dicts, data_id, log_id):
|
||||
from paddlenlp.data import Stack, Tuple, Pad
|
||||
|
||||
(_, input_dict), = input_dicts.items()
|
||||
print("input dict", input_dict)
|
||||
batch_size = len(input_dict.keys())
|
||||
examples = []
|
||||
for i in range(batch_size):
|
||||
example = json.loads(input_dict[str(i)].replace("\'", "\""))
|
||||
input_ids, segment_ids = convert_example(example, 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, False, None, ""
|
||||
|
||||
def postprocess(self, input_dicts, fetch_dict, data_id, log_id):
|
||||
new_dict = {}
|
||||
sim_score = expit(fetch_dict["predict"])[:, 1]
|
||||
new_dict["predict"] = str(sim_score)
|
||||
return new_dict, None, ""
|
||||
|
||||
|
||||
class ErnieService(WebService):
|
||||
|
||||
def get_pipeline_response(self, read_op):
|
||||
ernie_op = ErnieOp(name="ernie", input_ops=[read_op])
|
||||
return ernie_op
|
||||
|
||||
|
||||
ernie_service = ErnieService(name="ernie")
|
||||
ernie_service.prepare_pipeline_config("config_nlp.yml")
|
||||
ernie_service.run_service()
|
||||
125
applications/neural_search/ranking/cross_encoder/evaluate.py
Normal file
125
applications/neural_search/ranking/cross_encoder/evaluate.py
Normal file
@@ -0,0 +1,125 @@
|
||||
# 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.
|
||||
|
||||
from functools import partial
|
||||
import argparse
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from tqdm import tqdm
|
||||
import paddle
|
||||
import paddle.nn.functional as F
|
||||
from paddlenlp.data import Stack, Tuple, Pad
|
||||
from paddlenlp.datasets import load_dataset
|
||||
from paddlenlp.transformers import LinearDecayWithWarmup, AutoModelForSequenceClassification, AutoTokenizer
|
||||
|
||||
from data import create_dataloader
|
||||
from data import convert_example, read_data
|
||||
|
||||
# yapf: disable
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--test_file", type=str, required=True, help="The full path of test file")
|
||||
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=32, type=int, help="Batch size per GPU/CPU for training.")
|
||||
parser.add_argument('--model_name_or_path', default="rocketqa-base-cross-encoder", help="The pretrained model used for training")
|
||||
parser.add_argument("--init_from_ckpt", type=str, default=None, help="The path of checkpoint to be loaded.")
|
||||
parser.add_argument("--seed", type=int, default=1000, help="Random seed for initialization.")
|
||||
parser.add_argument('--device', choices=['cpu', 'gpu'], default="gpu", help="Select which device to train model, defaults to gpu.")
|
||||
args = parser.parse_args()
|
||||
# yapf: enable
|
||||
|
||||
|
||||
def set_seed(seed):
|
||||
"""sets random seed"""
|
||||
random.seed(seed)
|
||||
np.random.seed(seed)
|
||||
paddle.seed(seed)
|
||||
|
||||
|
||||
@paddle.no_grad()
|
||||
def evaluate(model, metric, data_loader, phase="dev"):
|
||||
"""
|
||||
Given a dataset, it evals model and computes the metric.
|
||||
|
||||
Args:
|
||||
model(obj:`paddle.nn.Layer`): A model to classify texts.
|
||||
data_loader(obj:`paddle.io.DataLoader`): The dataset loader which generates batches.
|
||||
metric(obj:`paddle.metric.Metric`): The evaluation metric.
|
||||
"""
|
||||
model.eval()
|
||||
metric.reset()
|
||||
|
||||
for idx, batch in enumerate(data_loader):
|
||||
input_ids, token_type_ids, labels = batch
|
||||
|
||||
pos_probs = model(input_ids=input_ids, token_type_ids=token_type_ids)
|
||||
|
||||
sim_score = F.softmax(pos_probs)
|
||||
metric.update(preds=sim_score.numpy(), labels=labels)
|
||||
|
||||
print("eval_{} auc:{:.3}".format(phase, metric.accumulate()))
|
||||
metric.reset()
|
||||
model.train()
|
||||
|
||||
|
||||
def main():
|
||||
paddle.set_device(args.device)
|
||||
rank = paddle.distributed.get_rank()
|
||||
if paddle.distributed.get_world_size() > 1:
|
||||
paddle.distributed.init_parallel_env()
|
||||
|
||||
set_seed(args.seed)
|
||||
|
||||
dev_ds = load_dataset(read_data, data_path=args.test_file, lazy=False)
|
||||
|
||||
model = AutoModelForSequenceClassification.from_pretrained(
|
||||
args.model_name_or_path, num_classes=2)
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
|
||||
trans_func_eval = partial(convert_example,
|
||||
tokenizer=tokenizer,
|
||||
max_seq_length=args.max_seq_length,
|
||||
is_pair=True)
|
||||
|
||||
batchify_fn_eval = lambda samples, fn=Tuple(
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype="int64"
|
||||
), # pair_input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_type_id, dtype="int64"
|
||||
), # pair_segment
|
||||
Stack(dtype="int64") # label
|
||||
): [data for data in fn(samples)]
|
||||
|
||||
dev_data_loader = create_dataloader(dev_ds,
|
||||
mode='dev',
|
||||
batch_size=args.batch_size,
|
||||
batchify_fn=batchify_fn_eval,
|
||||
trans_fn=trans_func_eval)
|
||||
|
||||
if args.init_from_ckpt and os.path.isfile(args.init_from_ckpt):
|
||||
state_dict = paddle.load(args.init_from_ckpt)
|
||||
model.set_dict(state_dict)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Please set --params_path with correct pretrained model file")
|
||||
|
||||
metric = paddle.metric.Auc()
|
||||
evaluate(model, metric, dev_data_loader, "dev")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -14,31 +14,33 @@
|
||||
|
||||
import argparse
|
||||
import os
|
||||
from functools import partial
|
||||
|
||||
import numpy as np
|
||||
import paddle
|
||||
import paddle.nn.functional as F
|
||||
from paddlenlp.transformers import AutoModelForSequenceClassification
|
||||
from paddlenlp.data import Stack, Tuple, Pad
|
||||
from paddlenlp.transformers import AutoModelForSequenceClassification, AutoTokenizer
|
||||
|
||||
# yapf: disable
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--params_path", type=str, required=True, default='./checkpoint/model_900/model_state.pdparams', help="The path to model parameters to be loaded.")
|
||||
parser.add_argument("--output_path", type=str, default='./output', help="The path of model parameter in static graph to be saved.")
|
||||
parser.add_argument('--model_name_or_path', default="rocketqa-base-cross-encoder", help="The pretrained model used for training")
|
||||
args = parser.parse_args()
|
||||
# yapf: enable
|
||||
|
||||
if __name__ == "__main__":
|
||||
# The number of labels should be in accordance with the training dataset.
|
||||
label_map = {0: 'negative', 1: 'positive'}
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
model = AutoModelForSequenceClassification.from_pretrained(
|
||||
"ernie-3.0-medium-zh", num_classes=len(label_map))
|
||||
args.model_name_or_path, num_classes=2)
|
||||
|
||||
if args.params_path and os.path.isfile(args.params_path):
|
||||
state_dict = paddle.load(args.params_path)
|
||||
model.set_dict(state_dict)
|
||||
print("Loaded parameters from %s" % args.params_path)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Please set --params_path with correct pretrained model file")
|
||||
model.eval()
|
||||
|
||||
# Convert to static graph with specific input description
|
||||
@@ -0,0 +1,47 @@
|
||||
# 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 argparse
|
||||
import paddle_serving_client.io as serving_io
|
||||
# yapf: disable
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--dirname", type=str, required=True,
|
||||
default='./output', help="Path of saved model files. Program file and parameter files are saved in this directory.")
|
||||
parser.add_argument("--model_filename", type=str, required=True,
|
||||
default='inference.pdmodel', help="The name of file to load the inference program. If it is None, the default filename __model__ will be used.")
|
||||
parser.add_argument("--params_filename", type=str, required=True,
|
||||
default='inference.pdiparams', help="The name of file to load all parameters. It is only used for the case that all parameters were saved in a single binary file. If parameters were saved in separate files, set it as None. Default: None.")
|
||||
parser.add_argument("--server_path", type=str, default='./serving_server',
|
||||
help="The path of server parameter in static graph to be saved.")
|
||||
parser.add_argument("--client_path", type=str, default='./serving_client',
|
||||
help="The path of client parameter in static graph to be saved.")
|
||||
parser.add_argument("--feed_alias_names", type=str, default=None,
|
||||
help='set alias names for feed vars, split by comma \',\', you should run --show_proto to check the number of feed vars')
|
||||
parser.add_argument("--fetch_alias_names", type=str, default=None,
|
||||
help='set alias names for feed vars, split by comma \',\', you should run --show_proto to check the number of fetch vars')
|
||||
parser.add_argument("--show_proto", type=bool, default=False,
|
||||
help='If yes, you can preview the proto and then determine your feed var alias name and fetch var alias name.')
|
||||
# yapf: enable
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = parser.parse_args()
|
||||
serving_io.inference_model_to_serving(
|
||||
dirname=args.dirname,
|
||||
serving_server=args.server_path,
|
||||
serving_client=args.client_path,
|
||||
model_filename=args.model_filename,
|
||||
params_filename=args.params_filename,
|
||||
show_proto=args.show_proto,
|
||||
feed_alias_names=args.feed_alias_names,
|
||||
fetch_alias_names=args.fetch_alias_names)
|
||||
99
applications/neural_search/ranking/cross_encoder/predict.py
Normal file
99
applications/neural_search/ranking/cross_encoder/predict.py
Normal file
@@ -0,0 +1,99 @@
|
||||
# Copyright (c) 2020 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 argparse
|
||||
import os
|
||||
from functools import partial
|
||||
|
||||
import paddle
|
||||
import paddle.nn.functional as F
|
||||
from paddlenlp.datasets import load_dataset
|
||||
from paddlenlp.data import Stack, Tuple, Pad
|
||||
from tqdm import tqdm
|
||||
from paddlenlp.transformers import AutoTokenizer, AutoModel, AutoModelForSequenceClassification
|
||||
|
||||
from data import convert_example, read_text_pair, create_dataloader
|
||||
|
||||
# yapf: disable
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--params_path", type=str, required=True, default="checkpoints/model_900/model_state.pdparams", help="The path to model parameters to be loaded.")
|
||||
parser.add_argument("--max_seq_length", type=int, default=128, 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", type=int, default=32, help="Batch size per GPU/CPU for training.")
|
||||
parser.add_argument("--test_set", type=str, required=True, help="The full path of test_set.")
|
||||
parser.add_argument("--topk", type=int, default=10, help="The Topk texts.")
|
||||
parser.add_argument('--device', choices=['cpu', 'gpu', 'xpu', 'npu'], default="gpu", help="Select which device to train model, defaults to gpu.")
|
||||
parser.add_argument('--model_name_or_path', default="rocketqa-base-cross-encoder", help="The pretrained model used for training")
|
||||
args = parser.parse_args()
|
||||
# yapf: enable
|
||||
|
||||
|
||||
@paddle.no_grad()
|
||||
def predict(model, data_loader):
|
||||
results = []
|
||||
model.eval()
|
||||
with paddle.no_grad():
|
||||
for batch in data_loader:
|
||||
input_ids, token_type_ids = batch
|
||||
logits = model(input_ids, token_type_ids)
|
||||
probs = F.softmax(logits)
|
||||
probs = probs.numpy()
|
||||
results.extend(probs[:, 1])
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
paddle.set_device(args.device)
|
||||
|
||||
test_ds = load_dataset(read_text_pair, data_path=args.test_set, lazy=False)
|
||||
model = AutoModelForSequenceClassification.from_pretrained(
|
||||
args.model_name_or_path, num_classes=2)
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
|
||||
trans_func = partial(convert_example,
|
||||
tokenizer=tokenizer,
|
||||
max_seq_length=args.max_seq_length,
|
||||
is_test=True,
|
||||
is_pair=True)
|
||||
|
||||
batchify_fn = lambda samples, fn=Tuple(
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype="int64"), # input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_type_id, dtype="int64"
|
||||
), # segment
|
||||
): [data for data in fn(samples)]
|
||||
|
||||
test_data_loader = create_dataloader(test_ds,
|
||||
mode='predict',
|
||||
batch_size=args.batch_size,
|
||||
batchify_fn=batchify_fn,
|
||||
trans_fn=trans_func)
|
||||
|
||||
if args.params_path and os.path.isfile(args.params_path):
|
||||
state_dict = paddle.load(args.params_path)
|
||||
model.set_dict(state_dict)
|
||||
print("Loaded parameters from %s" % args.params_path)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Please set --params_path with correct pretrained model file")
|
||||
results = predict(model, test_data_loader)
|
||||
test_ds = load_dataset(read_text_pair, data_path=args.test_set, lazy=False)
|
||||
text_pairs = []
|
||||
for idx, prob in enumerate(results):
|
||||
text_pair = test_ds[idx]
|
||||
text_pair["pred_prob"] = prob
|
||||
text_pairs.append(text_pair)
|
||||
text_pairs = sorted(text_pairs, key=lambda x: x['pred_prob'],
|
||||
reverse=True)[:args.topk]
|
||||
for item in text_pairs:
|
||||
print(item)
|
||||
@@ -0,0 +1,3 @@
|
||||
python evaluate.py --model_name_or_path rocketqa-base-cross-encoder \
|
||||
--init_from_ckpt checkpoints/model_80000/model_state.pdparams \
|
||||
--test_file data/dev_pairwise.csv
|
||||
@@ -0,0 +1,4 @@
|
||||
python export_model.py \
|
||||
--params_path checkpoints/model_80000/model_state.pdparams \
|
||||
--model_name_or_path rocketqa-base-cross-encoder \
|
||||
--output_path=./output
|
||||
@@ -0,0 +1,7 @@
|
||||
python export_to_serving.py \
|
||||
--dirname "output" \
|
||||
--model_filename "inference.pdmodel" \
|
||||
--params_filename "inference.pdiparams" \
|
||||
--server_path "serving_server" \
|
||||
--client_path "serving_client" \
|
||||
--fetch_alias_names "predict"
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
unset CUDA_VISIBLE_DEVICES
|
||||
export CUDA_VISIBLE_DEVICES=0
|
||||
python predict.py \
|
||||
--device 'gpu' \
|
||||
--params_path checkpoints/model_80000/model_state.pdparams \
|
||||
--model_name_or_path rocketqa-base-cross-encoder \
|
||||
--test_set data/test.csv \
|
||||
--topk 10 \
|
||||
--batch_size 128 \
|
||||
--max_seq_length 384
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
unset CUDA_VISIBLE_DEVICES
|
||||
python -u -m paddle.distributed.launch --gpus "0,1,2,3" --log_dir="logs" train_ce.py \
|
||||
--device gpu \
|
||||
--train_set data/train.csv \
|
||||
--test_file data/dev_pairwise.csv \
|
||||
--save_dir ./checkpoints \
|
||||
--model_name_or_path rocketqa-base-cross-encoder \
|
||||
--batch_size 32 \
|
||||
--save_steps 10000 \
|
||||
--max_seq_len 384 \
|
||||
--learning_rate 1E-5 \
|
||||
--weight_decay 0.01 \
|
||||
--warmup_proportion 0.0 \
|
||||
--logging_steps 10 \
|
||||
--seed 1 \
|
||||
--epochs 3 \
|
||||
--eval_step 1000
|
||||
@@ -24,15 +24,17 @@ import paddle
|
||||
import paddle.nn.functional as F
|
||||
from paddlenlp.data import Stack, Tuple, Pad
|
||||
from paddlenlp.datasets import load_dataset
|
||||
from paddlenlp.transformers import AutoModelForSequenceClassification, AutoTokenizer
|
||||
from paddlenlp.transformers import LinearDecayWithWarmup
|
||||
|
||||
from utils import convert_example
|
||||
from paddlenlp.transformers import AutoTokenizer, AutoModel, AutoModelForSequenceClassification
|
||||
from paddlenlp.transformers import PolyDecayWithWarmup
|
||||
from paddle.distributed.fleet.utils.hybrid_parallel_util import fused_allreduce_gradients
|
||||
from data import convert_example, read_data, create_dataloader
|
||||
|
||||
# yapf: disable
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--save_dir", default='./checkpoint', type=str, help="The output directory where the model checkpoints will be written.")
|
||||
parser.add_argument("--dataset", choices=["chnsenticorp", "xnli_cn"], default="chnsenticorp", type=str, help="Dataset for classfication tasks.")
|
||||
parser.add_argument("--train_set", type=str, required=True, help="The full path of train_set_file.")
|
||||
parser.add_argument("--test_file", type=str, required=True, help="The full path of test file")
|
||||
|
||||
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=32, type=int, help="Batch size per GPU/CPU for training.")
|
||||
@@ -48,10 +50,39 @@ parser.add_argument("--seed", type=int, default=1000, help="random seed for init
|
||||
parser.add_argument('--device', choices=['cpu', 'gpu', 'xpu', 'npu'], default="gpu", help="Select which device to train model, defaults to gpu.")
|
||||
parser.add_argument("--use_amp", type=distutils.util.strtobool, default=False, help="Enable mixed precision training.")
|
||||
parser.add_argument("--scale_loss", type=float, default=2**15, help="The value of scale_loss for fp16.")
|
||||
parser.add_argument('--model_name_or_path', default="rocketqa-base-cross-encoder", help="The pretrained model used for training")
|
||||
parser.add_argument("--eval_step", default=200, type=int, help="Step interval for evaluation.")
|
||||
args = parser.parse_args()
|
||||
# yapf: enable
|
||||
|
||||
|
||||
@paddle.no_grad()
|
||||
def evaluate(model, metric, data_loader, phase="dev"):
|
||||
"""
|
||||
Given a dataset, it evals model and computes the metric.
|
||||
|
||||
Args:
|
||||
model(obj:`paddle.nn.Layer`): A model to classify texts.
|
||||
data_loader(obj:`paddle.io.DataLoader`): The dataset loader which generates batches.
|
||||
metric(obj:`paddle.metric.Metric`): The evaluation metric.
|
||||
"""
|
||||
model.eval()
|
||||
metric.reset()
|
||||
|
||||
for idx, batch in enumerate(data_loader):
|
||||
input_ids, token_type_ids, labels = batch
|
||||
|
||||
pos_probs = model(input_ids=input_ids, token_type_ids=token_type_ids)
|
||||
|
||||
sim_score = F.softmax(pos_probs)
|
||||
|
||||
metric.update(preds=sim_score.numpy(), labels=labels)
|
||||
|
||||
print("eval_{} auc:{:.3}".format(phase, metric.accumulate()))
|
||||
metric.reset()
|
||||
model.train()
|
||||
|
||||
|
||||
def set_seed(seed):
|
||||
"""sets random seed"""
|
||||
random.seed(seed)
|
||||
@@ -59,82 +90,33 @@ def set_seed(seed):
|
||||
paddle.seed(seed)
|
||||
|
||||
|
||||
@paddle.no_grad()
|
||||
def evaluate(model, criterion, metric, data_loader):
|
||||
"""
|
||||
Given a dataset, it evals model and computes the metric.
|
||||
|
||||
Args:
|
||||
model(obj:`paddle.nn.Layer`): A model to classify texts.
|
||||
data_loader(obj:`paddle.io.DataLoader`): The dataset loader which generates batches.
|
||||
criterion(obj:`paddle.nn.Layer`): It can compute the loss.
|
||||
metric(obj:`paddle.metric.Metric`): The evaluation metric.
|
||||
"""
|
||||
model.eval()
|
||||
metric.reset()
|
||||
losses = []
|
||||
for batch in data_loader:
|
||||
input_ids, token_type_ids, labels = batch
|
||||
logits = model(input_ids, token_type_ids)
|
||||
loss = criterion(logits, labels)
|
||||
losses.append(loss.numpy())
|
||||
correct = metric.compute(logits, labels)
|
||||
metric.update(correct)
|
||||
accu = metric.accumulate()
|
||||
print("eval loss: %.5f, accuracy: %.5f" % (np.mean(losses), accu))
|
||||
model.train()
|
||||
metric.reset()
|
||||
|
||||
|
||||
def create_dataloader(dataset,
|
||||
mode='train',
|
||||
batch_size=1,
|
||||
batchify_fn=None,
|
||||
trans_fn=None):
|
||||
if trans_fn:
|
||||
dataset = dataset.map(trans_fn)
|
||||
|
||||
shuffle = True if mode == 'train' else False
|
||||
if mode == 'train':
|
||||
batch_sampler = paddle.io.DistributedBatchSampler(dataset,
|
||||
batch_size=batch_size,
|
||||
shuffle=shuffle)
|
||||
else:
|
||||
batch_sampler = paddle.io.BatchSampler(dataset,
|
||||
batch_size=batch_size,
|
||||
shuffle=shuffle)
|
||||
|
||||
return paddle.io.DataLoader(dataset=dataset,
|
||||
batch_sampler=batch_sampler,
|
||||
collate_fn=batchify_fn,
|
||||
return_list=True)
|
||||
|
||||
|
||||
def do_train():
|
||||
paddle.set_device(args.device)
|
||||
rank = paddle.distributed.get_rank()
|
||||
if paddle.distributed.get_world_size() > 1:
|
||||
paddle.distributed.init_parallel_env()
|
||||
|
||||
dev_count = paddle.distributed.get_world_size()
|
||||
set_seed(args.seed)
|
||||
|
||||
train_ds, dev_ds, test_ds = load_dataset(args.dataset,
|
||||
splits=["train", "dev", "test"])
|
||||
train_ds = load_dataset(read_data, data_path=args.train_set, lazy=False)
|
||||
dev_ds = load_dataset(read_data, data_path=args.test_file, lazy=False)
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
model = AutoModelForSequenceClassification.from_pretrained(
|
||||
'ernie-3.0-medium-zh', num_classes=len(train_ds.label_list))
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
args.model_name_or_path, num_classes=2)
|
||||
|
||||
trans_func = partial(convert_example,
|
||||
tokenizer=tokenizer,
|
||||
max_seq_length=args.max_seq_length,
|
||||
is_pair=args.dataset == "xnli_cn")
|
||||
is_pair=True)
|
||||
|
||||
batchify_fn = lambda samples, fn=Tuple(
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id), # input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_type_id), # segment
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype="int64"), # input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_type_id, dtype="int64"
|
||||
), # segment
|
||||
Stack(dtype="int64") # label
|
||||
): [data for data in fn(samples)]
|
||||
|
||||
train_data_loader = create_dataloader(train_ds,
|
||||
mode='train',
|
||||
batch_size=args.batch_size,
|
||||
@@ -149,12 +131,19 @@ def do_train():
|
||||
if args.init_from_ckpt and os.path.isfile(args.init_from_ckpt):
|
||||
state_dict = paddle.load(args.init_from_ckpt)
|
||||
model.set_dict(state_dict)
|
||||
|
||||
model = paddle.DataParallel(model)
|
||||
|
||||
num_training_steps = len(train_data_loader) * args.epochs
|
||||
num_training_examples = len(train_ds)
|
||||
# 4卡 gpu
|
||||
max_train_steps = args.epochs * num_training_examples // args.batch_size // dev_count
|
||||
|
||||
lr_scheduler = LinearDecayWithWarmup(args.learning_rate, num_training_steps,
|
||||
args.warmup_proportion)
|
||||
warmup_steps = int(max_train_steps * args.warmup_proportion)
|
||||
|
||||
print("Device count: %d" % dev_count)
|
||||
print("Num train examples: %d" % num_training_examples)
|
||||
print("Max train steps: %d" % max_train_steps)
|
||||
print("Num warmup steps: %d" % warmup_steps)
|
||||
|
||||
# Generate parameter names needed to perform weight decay.
|
||||
# All bias and LayerNorm parameters are excluded.
|
||||
@@ -163,14 +152,14 @@ def do_train():
|
||||
if not any(nd in n for nd in ["bias", "norm"])
|
||||
]
|
||||
optimizer = paddle.optimizer.AdamW(
|
||||
learning_rate=lr_scheduler,
|
||||
learning_rate=args.learning_rate,
|
||||
parameters=model.parameters(),
|
||||
weight_decay=args.weight_decay,
|
||||
apply_decay_param_fun=lambda x: x in decay_params)
|
||||
apply_decay_param_fun=lambda x: x in decay_params,
|
||||
grad_clip=paddle.nn.ClipGradByGlobalNorm(1.0))
|
||||
|
||||
criterion = paddle.nn.loss.CrossEntropyLoss()
|
||||
|
||||
metric = paddle.metric.Accuracy()
|
||||
metric = paddle.metric.Auc()
|
||||
if args.use_amp:
|
||||
scaler = paddle.amp.GradScaler(init_loss_scaling=args.scale_loss)
|
||||
global_step = 0
|
||||
@@ -178,24 +167,13 @@ def do_train():
|
||||
for epoch in range(1, args.epochs + 1):
|
||||
for step, batch in enumerate(train_data_loader, start=1):
|
||||
input_ids, token_type_ids, labels = batch
|
||||
with paddle.amp.auto_cast(
|
||||
args.use_amp,
|
||||
custom_white_list=["layer_norm", "softmax", "gelu"],
|
||||
):
|
||||
logits = model(input_ids, token_type_ids)
|
||||
loss = criterion(logits, labels)
|
||||
logits = model(input_ids, token_type_ids)
|
||||
loss = criterion(logits, labels)
|
||||
probs = F.softmax(logits, axis=1)
|
||||
correct = metric.compute(probs, labels)
|
||||
metric.update(correct)
|
||||
acc = metric.accumulate()
|
||||
acc = paddle.metric.accuracy(input=probs, label=labels)
|
||||
loss.backward()
|
||||
|
||||
if args.use_amp:
|
||||
scaler.scale(loss).backward()
|
||||
scaler.minimize(optimizer, loss)
|
||||
else:
|
||||
loss.backward()
|
||||
optimizer.step()
|
||||
lr_scheduler.step()
|
||||
optimizer.step()
|
||||
optimizer.clear_grad()
|
||||
|
||||
global_step += 1
|
||||
@@ -206,19 +184,23 @@ def do_train():
|
||||
% (global_step, epoch, step, loss, acc,
|
||||
args.logging_steps / time_diff))
|
||||
tic_train = time.time()
|
||||
|
||||
if global_step % args.valid_steps == 0 and rank == 0:
|
||||
evaluate(model, criterion, metric, dev_data_loader)
|
||||
tic_train = time.time()
|
||||
|
||||
if global_step % args.eval_step == 0 and rank == 0:
|
||||
evaluate(model, metric, dev_data_loader, "dev")
|
||||
if global_step % args.save_steps == 0 and rank == 0:
|
||||
save_dir = os.path.join(args.save_dir, "model_%d" % global_step)
|
||||
if not os.path.exists(save_dir):
|
||||
os.makedirs(save_dir)
|
||||
model._layers.save_pretrained(save_dir)
|
||||
model_to_save = model._layers if isinstance(
|
||||
model, paddle.DataParallel) else model
|
||||
model_to_save.save_pretrained(save_dir)
|
||||
tokenizer.save_pretrained(save_dir)
|
||||
tic_train = time.time()
|
||||
|
||||
# save final checkpoint
|
||||
save_dir = os.path.join(args.save_dir, "model_%d" % global_step)
|
||||
model_to_save = model._layers if isinstance(model,
|
||||
paddle.DataParallel) else model
|
||||
model_to_save.save_pretrained(save_dir)
|
||||
tokenizer.save_pretrained(save_dir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
do_train()
|
||||
@@ -152,7 +152,7 @@ ernie_matching/
|
||||
训练的命令如下:
|
||||
|
||||
```
|
||||
python -u -m paddle.distributed.launch --gpus "0,2,3,4" train_pairwise.py \
|
||||
python -u -m paddle.distributed.launch --gpus "0,1,2,3" train_pairwise.py \
|
||||
--device gpu \
|
||||
--save_dir ./checkpoints \
|
||||
--batch_size 32 \
|
||||
@@ -250,7 +250,9 @@ sh scripts/predict_pairwise.sh
|
||||
首先把动态图模型转换为静态图:
|
||||
|
||||
```
|
||||
python export_model.py --params_path checkpoints/model_30000/model_state.pdparams --output_path=./output
|
||||
python export_model.py --params_path checkpoints/model_30000/model_state.pdparams \
|
||||
--output_path=./output \
|
||||
--model_name_or_path ernie-3.0-medium-zh
|
||||
```
|
||||
也可以运行下面的bash脚本:
|
||||
|
||||
@@ -260,21 +262,17 @@ sh scripts/export_model.sh
|
||||
|
||||
### Paddle Inference
|
||||
|
||||
修改预测文件路径:
|
||||
使用PaddleInference:
|
||||
|
||||
```
|
||||
input_file='../../sort/test_pairwise.csv'
|
||||
```
|
||||
|
||||
然后使用PaddleInference
|
||||
|
||||
```
|
||||
python predict.py --model_dir=../../output
|
||||
python deploy/python/predict.py --model_dir ./output \
|
||||
--input_file sort/test_pairwise.csv \
|
||||
--model_name_or_path ernie-3.0-medium-zh
|
||||
```
|
||||
也可以运行下面的bash脚本:
|
||||
|
||||
```
|
||||
sh deploy.sh
|
||||
sh deploy/python/deploy.sh
|
||||
```
|
||||
得到下面的输出,输出的是样本的query,title以及对应的概率:
|
||||
|
||||
@@ -318,6 +316,12 @@ Paddle Serving的部署有两种方式,第一种方式是Pipeline的方式,
|
||||
|
||||
#### Pipeline方式
|
||||
|
||||
修改`Tokenizer`
|
||||
|
||||
```
|
||||
self.tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
```
|
||||
|
||||
启动 Pipeline Server:
|
||||
|
||||
```
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
python deploy/python/predict.py --model_dir ./output
|
||||
python deploy/python/predict.py --model_dir ./output \
|
||||
--input_file sort/test_pairwise.csv \
|
||||
--model_name_or_path ernie-3.0-medium-zh
|
||||
@@ -44,7 +44,8 @@ parser.add_argument("--batch_size", default=32, type=int,
|
||||
help="Batch size per GPU/CPU for training.")
|
||||
parser.add_argument('--device', choices=['cpu', 'gpu', 'xpu'], default="gpu",
|
||||
help="Select which device to train model, defaults to gpu.")
|
||||
|
||||
parser.add_argument("--input_file", type=str, required=True,
|
||||
help="The test set file.")
|
||||
parser.add_argument('--use_tensorrt', default=False, type=eval, choices=[True, False],
|
||||
help='Enable to use tensorrt to speed up.')
|
||||
parser.add_argument("--precision", default="fp32", type=str, choices=["fp32", "fp16", "int8"],
|
||||
@@ -59,6 +60,7 @@ parser.add_argument("--benchmark", type=eval, default=False,
|
||||
help="To log some information about environment and running.")
|
||||
parser.add_argument("--save_log_path", type=str, default="./log_output/",
|
||||
help="The file path to save log.")
|
||||
parser.add_argument('--model_name_or_path', default="ernie-3.0-medium-zh", help="The pretrained model used for training")
|
||||
args = parser.parse_args()
|
||||
# yapf: enable
|
||||
|
||||
@@ -196,8 +198,9 @@ class Predictor(object):
|
||||
examples.append((input_ids, segment_ids))
|
||||
|
||||
batchify_fn = lambda samples, fn=Tuple(
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id), # input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id), # segment
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype="int64"), # input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype="int64"
|
||||
), # segment
|
||||
): fn(samples)
|
||||
|
||||
if args.benchmark:
|
||||
@@ -224,11 +227,11 @@ if __name__ == "__main__":
|
||||
args.batch_size, args.use_tensorrt, args.precision,
|
||||
args.cpu_threads, args.enable_mkldnn)
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
|
||||
input_file = 'sort/test_pairwise.csv'
|
||||
|
||||
test_ds = load_dataset(read_text_pair, data_path=input_file, lazy=False)
|
||||
test_ds = load_dataset(read_text_pair,
|
||||
data_path=args.input_file,
|
||||
lazy=False)
|
||||
|
||||
data = [{'query': d['query'], 'title': d['title']} for d in test_ds]
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ class ErnieOp(Op):
|
||||
|
||||
def init_op(self):
|
||||
from paddlenlp.transformers import AutoTokenizer
|
||||
self.tokenizer = AutoTokenizer.from_pretrained('ernie-gram-zh')
|
||||
self.tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
|
||||
def preprocess(self, input_dicts, data_id, log_id):
|
||||
from paddlenlp.data import Stack, Tuple, Pad
|
||||
|
||||
@@ -40,12 +40,7 @@ parser.add_argument("--test_file", type=str, required=True, help="The full path
|
||||
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=32, type=int, help="Batch size per GPU/CPU for training.")
|
||||
parser.add_argument("--learning_rate", default=5e-5, type=float, help="The initial learning rate for Adam.")
|
||||
parser.add_argument("--weight_decay", default=0.0, type=float, help="Weight decay if we apply some.")
|
||||
parser.add_argument("--epochs", default=3, type=int, help="Total number of training epochs to perform.")
|
||||
parser.add_argument("--eval_step", default=200, type=int, help="Step interval for evaluation.")
|
||||
parser.add_argument('--save_step', default=10000, type=int, help="Step interval for saving checkpoint.")
|
||||
parser.add_argument("--warmup_proportion", default=0.0, type=float, help="Linear warmup proption over the training process.")
|
||||
parser.add_argument('--model_name_or_path', default="ernie-3.0-medium-zh", help="The pretrained model used for training")
|
||||
parser.add_argument("--init_from_ckpt", type=str, default=None, help="The path of checkpoint to be loaded.")
|
||||
parser.add_argument("--seed", type=int, default=1000, help="Random seed for initialization.")
|
||||
parser.add_argument('--device', choices=['cpu', 'gpu'], default="gpu", help="Select which device to train model, defaults to gpu.")
|
||||
@@ -108,7 +103,7 @@ def read_test(src_path, is_predict=False):
|
||||
yield {'query': query, 'title': title, 'label': label}
|
||||
|
||||
|
||||
def do_train():
|
||||
def main():
|
||||
paddle.set_device(args.device)
|
||||
rank = paddle.distributed.get_rank()
|
||||
if paddle.distributed.get_world_size() > 1:
|
||||
@@ -119,8 +114,8 @@ def do_train():
|
||||
dev_ds = load_dataset(read_test, src_path=args.test_file, lazy=False)
|
||||
print(dev_ds[0])
|
||||
|
||||
pretrained_model = AutoModel.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
pretrained_model = AutoModel.from_pretrained(args.model_name_or_path)
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
|
||||
trans_func_eval = partial(convert_example,
|
||||
tokenizer=tokenizer,
|
||||
@@ -152,4 +147,4 @@ def do_train():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
do_train()
|
||||
main()
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
import argparse
|
||||
import os
|
||||
from functools import partial
|
||||
|
||||
import numpy as np
|
||||
import paddle
|
||||
@@ -27,19 +26,22 @@ from model import PairwiseMatching
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--params_path", type=str, required=True, default='./checkpoint/model_900/model_state.pdparams', help="The path to model parameters to be loaded.")
|
||||
parser.add_argument("--output_path", type=str, default='./output', help="The path of model parameter in static graph to be saved.")
|
||||
parser.add_argument('--model_name_or_path', default="ernie-3.0-medium-zh", help="The pretrained model used for training")
|
||||
args = parser.parse_args()
|
||||
# yapf: enable
|
||||
|
||||
if __name__ == "__main__":
|
||||
pretrained_model = AutoModel.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
pretrained_model = AutoModel.from_pretrained(args.model_name_or_path)
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
model = PairwiseMatching(pretrained_model)
|
||||
|
||||
if args.params_path and os.path.isfile(args.params_path):
|
||||
state_dict = paddle.load(args.params_path)
|
||||
model.set_dict(state_dict)
|
||||
print("Loaded parameters from %s" % args.params_path)
|
||||
|
||||
else:
|
||||
raise ValueError(
|
||||
"Please set --params_path with correct pretrained model file")
|
||||
model.eval()
|
||||
|
||||
# Convert to static graph with specific input description
|
||||
|
||||
@@ -36,6 +36,7 @@ parser.add_argument("--input_file", type=str, required=True, help="The full path
|
||||
parser.add_argument("--params_path", type=str, required=True, help="The path to model parameters to be loaded.")
|
||||
parser.add_argument("--max_seq_length", default=64, 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('--model_name_or_path', default="ernie-3.0-medium-zh", help="The pretrained model used for training")
|
||||
parser.add_argument("--batch_size", default=32, type=int, help="Batch size per GPU/CPU for training.")
|
||||
parser.add_argument('--device', choices=['cpu', 'gpu'], default="gpu", help="Select which device to train model, defaults to gpu.")
|
||||
args = parser.parse_args()
|
||||
@@ -75,8 +76,8 @@ def predict(model, data_loader):
|
||||
if __name__ == "__main__":
|
||||
paddle.set_device(args.device)
|
||||
|
||||
pretrained_model = AutoModel.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
pretrained_model = AutoModel.from_pretrained(args.model_name_or_path)
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
|
||||
trans_func = partial(convert_example,
|
||||
tokenizer=tokenizer,
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
python export_model.py --params_path checkpoints/model_30000/model_state.pdparams --output_path=./output
|
||||
python export_model.py --params_path checkpoints/model_30000/model_state.pdparams \
|
||||
--output_path=./output \
|
||||
--model_name_or_path ernie-3.0-medium-zh
|
||||
@@ -1,5 +1,5 @@
|
||||
# gpu
|
||||
python -u -m paddle.distributed.launch --gpus "0,1,2,3" train_pairwise.py \
|
||||
python -u -m paddle.distributed.launch --gpus="0,1,2,3" train_pairwise.py \
|
||||
--device gpu \
|
||||
--save_dir ./checkpoints \
|
||||
--batch_size 32 \
|
||||
|
||||
@@ -49,6 +49,7 @@ parser.add_argument("--eval_step", default=200, type=int, help="Step interval fo
|
||||
parser.add_argument('--save_step', default=10000, type=int, help="Step interval for saving checkpoint.")
|
||||
parser.add_argument("--warmup_proportion", default=0.0, type=float, help="Linear warmup proption over the training process.")
|
||||
parser.add_argument("--init_from_ckpt", type=str, default=None, help="The path of checkpoint to be loaded.")
|
||||
parser.add_argument('--model_name_or_path', default="ernie-3.0-medium-zh", help="The pretrained model used for training")
|
||||
parser.add_argument("--seed", type=int, default=1000, help="Random seed for initialization.")
|
||||
parser.add_argument('--device', choices=['cpu', 'gpu'], default="gpu", help="Select which device to train model, defaults to gpu.")
|
||||
args = parser.parse_args()
|
||||
@@ -121,8 +122,8 @@ def do_train():
|
||||
train_ds = load_dataset(read, src_path=args.train_file, lazy=False)
|
||||
dev_ds = load_dataset(read_test, src_path=args.test_file, lazy=False)
|
||||
|
||||
pretrained_model = AutoModel.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
pretrained_model = AutoModel.from_pretrained(args.model_name_or_path)
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
|
||||
trans_func_train = partial(convert_example,
|
||||
tokenizer=tokenizer,
|
||||
|
||||
@@ -42,7 +42,7 @@ In-batch Negatives 策略的训练数据为语义相似的 Pair 对,策略核
|
||||
|
||||
### 技术方案
|
||||
|
||||
双塔模型,采用ERNIE1.0热启,在召回训练阶段引入In-batch Negatives 策略,使用hnswlib建立索引库,进行召回测试。
|
||||
双塔模型,在召回训练阶段引入In-batch Negatives 策略,使用hnswlib建立索引库,进行召回测试。
|
||||
|
||||
|
||||
### 评估指标
|
||||
@@ -53,10 +53,10 @@ Recall@K召回率是指预测的前topK(top-k是指从最后的按得分排序
|
||||
|
||||
**效果评估**
|
||||
|
||||
| 模型 | Recall@1 | Recall@5 |Recall@10 |Recall@20 |Recall@50 |策略简要说明|
|
||||
| 策略 | 模型 | Recall@1 | Recall@5 |Recall@10 |Recall@20 |Recall@50 |
|
||||
| ------------ | ------------ | ------------ |--------- |--------- |--------- |--------- |
|
||||
| In-batch Negatives | 51.301 | 65.309| 69.878| 73.996|78.881| Inbatch-negative有监督训练|
|
||||
|
||||
| In-batch Negatives | ernie 1.0 | 51.301 | 65.309| 69.878| 73.996|78.881|
|
||||
| In-batch Negatives | rocketqa-zh-base-query-encoder | **59.622** | **75.089**| **79.668**| **83.404**|**87.773**|
|
||||
|
||||
|
||||
<a name="环境依赖"></a>
|
||||
@@ -166,11 +166,11 @@ Recall@K召回率是指预测的前topK(top-k是指从最后的按得分排序
|
||||
|
||||
|Model|训练参数配置|硬件|MD5|
|
||||
| ------------ | ------------ | ------------ |-----------|
|
||||
|[batch_neg](https://bj.bcebos.com/v1/paddlenlp/models/inbatch_model.zip)|<div style="width: 150pt">margin:0.2 scale:30 epoch:3 lr:5E-5 bs:64 max_len:64 </div>|<div style="width: 100pt">4卡 v100-16g</div>|f3e5c7d7b0b718c2530c5e1b136b2d74|
|
||||
|[batch_neg](https://bj.bcebos.com/v1/paddlenlp/models/inbatch_model.zip)|<div style="width: 150pt">ernie 1.0 margin:0.2 scale:30 epoch:3 lr:5E-5 bs:64 max_len:64 </div>|<div style="width: 100pt">4卡 v100-16g</div>|f3e5c7d7b0b718c2530c5e1b136b2d74|
|
||||
|
||||
|
||||
### 训练环境说明
|
||||
|
||||
|
||||
- NVIDIA Driver Version: 440.64.00
|
||||
- Ubuntu 16.04.6 LTS (Docker)
|
||||
- Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
|
||||
@@ -185,7 +185,7 @@ Recall@K召回率是指预测的前topK(top-k是指从最后的按得分排序
|
||||
然后运行下面的命令使用GPU训练,得到语义索引模型:
|
||||
|
||||
```
|
||||
root_path=recall
|
||||
root_path=inbatch
|
||||
python -u -m paddle.distributed.launch --gpus "0,1,2,3" \
|
||||
train_batch_neg.py \
|
||||
--device gpu \
|
||||
@@ -194,19 +194,18 @@ python -u -m paddle.distributed.launch --gpus "0,1,2,3" \
|
||||
--learning_rate 5E-5 \
|
||||
--epochs 3 \
|
||||
--output_emb_size 256 \
|
||||
--model_name_or_path rocketqa-zh-base-query-encoder \
|
||||
--save_steps 10 \
|
||||
--max_seq_length 64 \
|
||||
--margin 0.2 \
|
||||
--train_set_file recall/train.csv \
|
||||
--evaluate \
|
||||
--recall_result_dir "recall_result_dir" \
|
||||
--recall_result_file "recall_result.txt" \
|
||||
--hnsw_m 100 \
|
||||
--hnsw_ef 100 \
|
||||
--recall_num 50 \
|
||||
--similar_text_pair "recall/dev.csv" \
|
||||
--corpus_file "recall/corpus.csv" \
|
||||
--similar_text_pair "recall/dev.csv"
|
||||
--similar_text_pair_file "recall/dev.csv" \
|
||||
--corpus_file "recall/corpus.csv"
|
||||
```
|
||||
|
||||
参数含义说明
|
||||
@@ -217,6 +216,7 @@ python -u -m paddle.distributed.launch --gpus "0,1,2,3" \
|
||||
* `learning_rate`: 训练的学习率的大小
|
||||
* `epochs`: 训练的epoch数
|
||||
* `output_emb_size`: Transformer 顶层输出的文本向量维度
|
||||
* `model_name_or_path`: 预训练模型,用于模型和`Tokenizer`的参数初始化
|
||||
* `save_steps`: 模型存储 checkpoint 的间隔 steps 个数
|
||||
* `max_seq_length`: 输入序列的最大长度
|
||||
* `margin`: 正样本相似度与负样本之间的目标 Gap
|
||||
@@ -227,14 +227,13 @@ python -u -m paddle.distributed.launch --gpus "0,1,2,3" \
|
||||
* `hnsw_m`: hnsw 算法相关参数,保持默认即可
|
||||
* `hnsw_ef`: hnsw 算法相关参数,保持默认即可
|
||||
* `recall_num`: 对 1 个文本召回的相似文本数量
|
||||
* `similar_text_pair`: 由相似文本对构成的评估集
|
||||
* `similar_text_pair_file`: 由相似文本对构成的评估集
|
||||
* `corpus_file`: 召回库数据 corpus_file
|
||||
* `similar_text_pair`: 由相似文本对构成的评估集 semantic_similar_pair.tsv
|
||||
|
||||
也可以使用bash脚本:
|
||||
|
||||
```
|
||||
sh scripts/train_batch_neg.sh
|
||||
sh scripts/train.sh
|
||||
```
|
||||
|
||||
|
||||
@@ -270,6 +269,7 @@ python -u -m paddle.distributed.launch --gpus "3" --log_dir "recall_log/" \
|
||||
--recall_result_dir "recall_result_dir" \
|
||||
--recall_result_file "recall_result.txt" \
|
||||
--params_path "${root_dir}/model_40/model_state.pdparams" \
|
||||
--model_name_or_path rocketqa-zh-base-query-encoder \
|
||||
--hnsw_m 100 \
|
||||
--hnsw_ef 100 \
|
||||
--batch_size 64 \
|
||||
@@ -280,16 +280,17 @@ python -u -m paddle.distributed.launch --gpus "3" --log_dir "recall_log/" \
|
||||
--corpus_file "recall/corpus.csv"
|
||||
```
|
||||
参数含义说明
|
||||
* `device`: 使用 cpu/gpu 进行训练
|
||||
* `recall_result_dir`: 召回结果存储目录
|
||||
* `recall_result_file`: 召回结果的文件名
|
||||
* `device`: 使用 cpu/gpu 进行训练
|
||||
* `recall_result_dir`: 召回结果存储目录
|
||||
* `recall_result_file`: 召回结果的文件名
|
||||
* `params_path`: 待评估模型的参数文件名
|
||||
* `hnsw_m`: hnsw 算法相关参数,保持默认即可
|
||||
* `hnsw_ef`: hnsw 算法相关参数,保持默认即可
|
||||
* `output_emb_size`: Transformer 顶层输出的文本向量维度
|
||||
* `recall_num`: 对 1 个文本召回的相似文本数量
|
||||
* `similar_text_pair`: 由相似文本对构成的评估集
|
||||
* `corpus_file`: 召回库数据 corpus_file
|
||||
* `model_name_or_path`: 预训练模型,用于模型和`Tokenizer`的参数初始化
|
||||
* `hnsw_m`: hnsw 算法相关参数,保持默认即可
|
||||
* `hnsw_ef`: hnsw 算法相关参数,保持默认即可
|
||||
* `output_emb_size`: Transformer 顶层输出的文本向量维度
|
||||
* `recall_num`: 对 1 个文本召回的相似文本数量
|
||||
* `similar_text_pair`: 由相似文本对构成的评估集
|
||||
* `corpus_file`: 召回库数据 corpus_file
|
||||
|
||||
也可以使用下面的bash脚本:
|
||||
|
||||
@@ -383,10 +384,11 @@ python inference.py
|
||||
```
|
||||
root_dir="checkpoints/inbatch"
|
||||
|
||||
python -u -m paddle.distributed.launch --gpus "3" \
|
||||
python -u -m paddle.distributed.launch --gpus "0" \
|
||||
predict.py \
|
||||
--device gpu \
|
||||
--params_path "${root_dir}/model_40/model_state.pdparams" \
|
||||
--model_name_or_path rocketqa-zh-base-query-encoder \
|
||||
--output_emb_size 256 \
|
||||
--batch_size 128 \
|
||||
--max_seq_length 64 \
|
||||
@@ -396,6 +398,7 @@ python -u -m paddle.distributed.launch --gpus "3" \
|
||||
参数含义说明
|
||||
* `device`: 使用 cpu/gpu 进行训练
|
||||
* `params_path`: 预训练模型的参数文件名
|
||||
* `model_name_or_path`: 预训练模型,用于模型和`Tokenizer`的参数初始化
|
||||
* `output_emb_size`: Transformer 顶层输出的文本向量维度
|
||||
* `text_pair_file`: 由文本 Pair 构成的待预测数据集
|
||||
|
||||
@@ -423,7 +426,9 @@ predict.sh文件包含了cpu和gpu运行的脚本,默认是gpu运行的脚本
|
||||
首先把动态图模型转换为静态图:
|
||||
|
||||
```
|
||||
python export_model.py --params_path checkpoints/inbatch/model_40/model_state.pdparams --output_path=./output
|
||||
python export_model.py --params_path checkpoints/inbatch/model_40/model_state.pdparams \
|
||||
--model_name_or_path rocketqa-zh-base-query-encoder \
|
||||
--output_path=./output
|
||||
```
|
||||
也可以运行下面的bash脚本:
|
||||
|
||||
@@ -449,7 +454,9 @@ corpus_list=[['中西方语言与文化的差异','中西方文化差异以及
|
||||
然后使用PaddleInference
|
||||
|
||||
```
|
||||
python deploy/python/predict.py --model_dir=./output
|
||||
python deploy/python/predict.py \
|
||||
--model_dir=./output \
|
||||
--model_name_or_path rocketqa-zh-base-query-encoder
|
||||
```
|
||||
也可以运行下面的bash脚本:
|
||||
|
||||
@@ -501,9 +508,16 @@ Paddle Serving的部署有两种方式,第一种方式是Pipeline的方式,
|
||||
|
||||
#### Pipeline方式
|
||||
|
||||
启动 Pipeline Server:
|
||||
修改模型需要用到的`Tokenizer`
|
||||
|
||||
```
|
||||
self.tokenizer = AutoTokenizer.from_pretrained("rocketqa-zh-base-query-encoder")
|
||||
```
|
||||
|
||||
然后启动 Pipeline Server:
|
||||
|
||||
```
|
||||
cd deploy/python
|
||||
python web_service.py
|
||||
```
|
||||
|
||||
@@ -520,7 +534,7 @@ list_data = [
|
||||
然后运行:
|
||||
|
||||
```
|
||||
python rpc_client.py
|
||||
python deploy/python/rpc_client.py
|
||||
```
|
||||
模型的输出为:
|
||||
|
||||
@@ -547,12 +561,12 @@ python -m paddle_serving_server.serve --model serving_server --port 9393 --gpu_i
|
||||
也可以使用脚本:
|
||||
|
||||
```
|
||||
sh deploy/C++/start_server.sh
|
||||
sh deploy/cpp/start_server.sh
|
||||
```
|
||||
Client 可以使用 http 或者 rpc 两种方式,rpc 的方式为:
|
||||
|
||||
```
|
||||
python deploy/C++/rpc_client.py
|
||||
python deploy/cpp/rpc_client.py
|
||||
```
|
||||
运行的输出为:
|
||||
```
|
||||
@@ -571,7 +585,7 @@ time to cost :0.3960278034210205 seconds
|
||||
或者使用 http 的客户端访问模式:
|
||||
|
||||
```
|
||||
python deploy/C++/http_client.py
|
||||
python deploy/cpp/http_client.py
|
||||
```
|
||||
运行的输出为:
|
||||
|
||||
@@ -599,6 +613,7 @@ python -u -m paddle.distributed.launch --gpus "0,1,2,3" \
|
||||
train_batch_neg.py \
|
||||
--device gpu \
|
||||
--save_dir ./checkpoints/simcse_inbatch_negative \
|
||||
--model_name_or_path rocketqa-zh-base-query-encoder \
|
||||
--batch_size 64 \
|
||||
--learning_rate 5E-5 \
|
||||
--epochs 3 \
|
||||
|
||||
@@ -54,7 +54,7 @@ print(feed_names)
|
||||
print(fetch_names)
|
||||
|
||||
# 创建tokenizer
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained('rocketqa-zh-base-query-encoder')
|
||||
max_seq_len = 64
|
||||
|
||||
# 数据预处理
|
||||
@@ -50,7 +50,7 @@ print(feed_names)
|
||||
print(fetch_names)
|
||||
|
||||
# 创建tokenizer
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained('rocketqa-zh-base-query-encoder')
|
||||
max_seq_len = 64
|
||||
|
||||
# 数据预处理
|
||||
@@ -40,7 +40,7 @@ parser.add_argument("--batch_size", default=15, type=int,
|
||||
help="Batch size per GPU/CPU for training.")
|
||||
parser.add_argument('--device', choices=['cpu', 'gpu', 'xpu'], default="gpu",
|
||||
help="Select which device to train model, defaults to gpu.")
|
||||
|
||||
parser.add_argument('--model_name_or_path', default="rocketqa-zh-base-query-encoder", help="model name.")
|
||||
parser.add_argument('--use_tensorrt', default=False, type=eval, choices=[True, False],
|
||||
help='Enable to use tensorrt to speed up.')
|
||||
parser.add_argument("--precision", default="fp32", type=str, choices=["fp32", "fp16", "int8"],
|
||||
@@ -156,22 +156,21 @@ class Predictor(object):
|
||||
if args.benchmark:
|
||||
import auto_log
|
||||
pid = os.getpid()
|
||||
self.autolog = auto_log.AutoLogger(model_name="ernie-3.0-medium-zh",
|
||||
model_precision=precision,
|
||||
batch_size=self.batch_size,
|
||||
data_shape="dynamic",
|
||||
save_path=args.save_log_path,
|
||||
inference_config=config,
|
||||
pids=pid,
|
||||
process_name=None,
|
||||
gpu_ids=0,
|
||||
time_keys=[
|
||||
'preprocess_time',
|
||||
'inference_time',
|
||||
'postprocess_time'
|
||||
],
|
||||
warmup=0,
|
||||
logger=logger)
|
||||
self.autolog = auto_log.AutoLogger(
|
||||
model_name=args.model_name_or_path,
|
||||
model_precision=precision,
|
||||
batch_size=self.batch_size,
|
||||
data_shape="dynamic",
|
||||
save_path=args.save_log_path,
|
||||
inference_config=config,
|
||||
pids=pid,
|
||||
process_name=None,
|
||||
gpu_ids=0,
|
||||
time_keys=[
|
||||
'preprocess_time', 'inference_time', 'postprocess_time'
|
||||
],
|
||||
warmup=0,
|
||||
logger=logger)
|
||||
|
||||
def extract_embedding(self, data, tokenizer):
|
||||
"""
|
||||
@@ -279,7 +278,7 @@ if __name__ == "__main__":
|
||||
|
||||
# ErnieTinyTokenizer is special for ernie-tiny pretained model.
|
||||
output_emb_size = 256
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
id2corpus = {0: '国有企业引入非国有资本对创新绩效的影响——基于制造业国有上市公司的经验证据'}
|
||||
corpus_list = [{idx: text} for idx, text in id2corpus.items()]
|
||||
res = predictor.extract_embedding(corpus_list, tokenizer)
|
||||
|
||||
@@ -40,7 +40,8 @@ class ErnieOp(Op):
|
||||
|
||||
def init_op(self):
|
||||
from paddlenlp.transformers import AutoTokenizer
|
||||
self.tokenizer = AutoTokenizer.from_pretrained('ernie-1.0')
|
||||
self.tokenizer = AutoTokenizer.from_pretrained(
|
||||
"rocketqa-zh-base-query-encoder")
|
||||
|
||||
def preprocess(self, input_dicts, data_id, log_id):
|
||||
from paddlenlp.data import Stack, Tuple, Pad
|
||||
@@ -56,7 +57,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)
|
||||
|
||||
@@ -76,8 +76,6 @@ if __name__ == "__main__":
|
||||
relevance_labels.append(1)
|
||||
else:
|
||||
relevance_labels.append(0)
|
||||
# print(len(rs))
|
||||
# print(rs[:50])
|
||||
|
||||
recall_N = []
|
||||
recall_num = [1, 5, 10, 20, 50]
|
||||
@@ -92,4 +90,3 @@ if __name__ == "__main__":
|
||||
print('recall@{}={}'.format(key, val))
|
||||
res.append(str(val))
|
||||
result.write('\t'.join(res) + '\n')
|
||||
# print("\t".join(recall_N))
|
||||
|
||||
@@ -28,6 +28,7 @@ from base_model import SemanticIndexBase, SemanticIndexBaseStatic
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--params_path", type=str, required=True,
|
||||
default='./checkpoint/model_900/model_state.pdparams', help="The path to model parameters to be loaded.")
|
||||
parser.add_argument('--model_name_or_path', default="rocketqa-zh-base-query-encoder", help="Select model to train, defaults to rocketqa-zh-base-query-encoder.")
|
||||
parser.add_argument("--output_path", type=str, default='./output',
|
||||
help="The path of model parameter in static graph to be saved.")
|
||||
args = parser.parse_args()
|
||||
@@ -35,8 +36,8 @@ args = parser.parse_args()
|
||||
|
||||
if __name__ == "__main__":
|
||||
output_emb_size = 256
|
||||
pretrained_model = AutoModel.from_pretrained("ernie-1.0")
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-1.0')
|
||||
pretrained_model = AutoModel.from_pretrained(args.model_name_or_path)
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
model = SemanticIndexBaseStatic(pretrained_model,
|
||||
output_emb_size=output_emb_size)
|
||||
if args.params_path and os.path.isfile(args.params_path):
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
# 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.
|
||||
|
||||
from functools import partial
|
||||
import argparse
|
||||
import os
|
||||
@@ -26,9 +40,10 @@ if __name__ == "__main__":
|
||||
batch_size = 1
|
||||
params_path = 'checkpoints/inbatch/model_40/model_state.pdparams'
|
||||
id2corpus = {0: '国有企业引入非国有资本对创新绩效的影响——基于制造业国有上市公司的经验证据'}
|
||||
model_name_or_path = "rocketqa-zh-base-query-encoder"
|
||||
paddle.set_device(device)
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path)
|
||||
trans_func = partial(convert_example,
|
||||
tokenizer=tokenizer,
|
||||
max_seq_length=max_seq_length)
|
||||
@@ -38,7 +53,7 @@ if __name__ == "__main__":
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_type_id), # text_segment
|
||||
): [data for data in fn(samples)]
|
||||
|
||||
pretrained_model = AutoModel.from_pretrained("ernie-3.0-medium-zh")
|
||||
pretrained_model = AutoModel.from_pretrained(model_name_or_path)
|
||||
|
||||
model = SemanticIndexBaseStatic(pretrained_model,
|
||||
output_emb_size=output_emb_size)
|
||||
|
||||
@@ -37,6 +37,7 @@ parser.add_argument("--params_path", type=str, required=True,
|
||||
help="The path to model parameters to be loaded.")
|
||||
parser.add_argument("--max_seq_length", default=64, 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('--model_name_or_path', default="rocketqa-zh-base-query-encoder", help="The pretrained model used for training")
|
||||
parser.add_argument("--batch_size", default=32, type=int,
|
||||
help="Batch size per GPU/CPU for training.")
|
||||
parser.add_argument("--output_emb_size", default=None,
|
||||
@@ -83,7 +84,7 @@ def predict(model, data_loader):
|
||||
if __name__ == "__main__":
|
||||
paddle.set_device(args.device)
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
|
||||
trans_func = partial(convert_example,
|
||||
tokenizer=tokenizer,
|
||||
@@ -91,10 +92,14 @@ if __name__ == "__main__":
|
||||
pad_to_max_seq_len=args.pad_to_max_seq_len)
|
||||
|
||||
batchify_fn = lambda samples, fn=Tuple(
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id), # query_input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_type_id), # query_segment
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id), # title_input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_type_id), # tilte_segment
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype='int64'
|
||||
), # query_input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_type_id, dtype='int64'
|
||||
), # query_segment
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_id, dtype='int64'
|
||||
), # title_input
|
||||
Pad(axis=0, pad_val=tokenizer.pad_token_type_id, dtype='int64'
|
||||
), # tilte_segment
|
||||
): [data for data in fn(samples)]
|
||||
|
||||
valid_ds = load_dataset(read_text_pair,
|
||||
@@ -107,7 +112,7 @@ if __name__ == "__main__":
|
||||
batchify_fn=batchify_fn,
|
||||
trans_fn=trans_func)
|
||||
|
||||
pretrained_model = AutoModel.from_pretrained("ernie-3.0-medium-zh")
|
||||
pretrained_model = AutoModel.from_pretrained(args.model_name_or_path)
|
||||
|
||||
model = SemanticIndexBase(pretrained_model,
|
||||
output_emb_size=args.output_emb_size)
|
||||
|
||||
@@ -55,7 +55,7 @@ parser.add_argument("--output_emb_size", default=None,
|
||||
type=int, help="output_embedding_size")
|
||||
parser.add_argument("--recall_num", default=10, type=int,
|
||||
help="Recall number for each query from Ann index.")
|
||||
|
||||
parser.add_argument('--model_name_or_path', default="rocketqa-zh-base-query-encoder", help="The pretrained model used for training")
|
||||
parser.add_argument("--hnsw_m", default=100, type=int,
|
||||
help="Recall number for each query from Ann index.")
|
||||
parser.add_argument("--hnsw_ef", default=100, type=int,
|
||||
@@ -74,7 +74,7 @@ if __name__ == "__main__":
|
||||
if paddle.distributed.get_world_size() > 1:
|
||||
paddle.distributed.init_parallel_env()
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
|
||||
trans_func = partial(convert_example,
|
||||
tokenizer=tokenizer,
|
||||
@@ -87,7 +87,7 @@ if __name__ == "__main__":
|
||||
), # text_segment
|
||||
): [data for data in fn(samples)]
|
||||
|
||||
pretrained_model = AutoModel.from_pretrained("ernie-3.0-medium-zh")
|
||||
pretrained_model = AutoModel.from_pretrained(args.model_name_or_path)
|
||||
|
||||
model = SemanticIndexBase(pretrained_model,
|
||||
output_emb_size=args.output_emb_size)
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
python export_model.py --params_path checkpoints/inbatch/model_40/model_state.pdparams --output_path=./output
|
||||
python export_model.py --params_path checkpoints/inbatch/model_40/model_state.pdparams \
|
||||
--model_name_or_path rocketqa-zh-base-query-encoder \
|
||||
--output_path=./output
|
||||
@@ -1,10 +1,10 @@
|
||||
# gpu version
|
||||
|
||||
root_dir="checkpoints/inbatch"
|
||||
python -u -m paddle.distributed.launch --gpus "3" \
|
||||
python -u -m paddle.distributed.launch --gpus "0" \
|
||||
predict.py \
|
||||
--device gpu \
|
||||
--params_path "${root_dir}/model_40/model_state.pdparams" \
|
||||
--model_name_or_path rocketqa-zh-base-query-encoder \
|
||||
--output_emb_size 256 \
|
||||
--batch_size 128 \
|
||||
--max_seq_length 64 \
|
||||
|
||||
@@ -6,6 +6,7 @@ python -u -m paddle.distributed.launch --gpus "3" --log_dir "recall_log/" \
|
||||
--recall_result_dir "recall_result_dir" \
|
||||
--recall_result_file "recall_result.txt" \
|
||||
--params_path "${root_dir}/model_40/model_state.pdparams" \
|
||||
--model_name_or_path rocketqa-zh-base-query-encoder \
|
||||
--hnsw_m 100 \
|
||||
--hnsw_ef 100 \
|
||||
--batch_size 64 \
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
# GPU training
|
||||
root_path=inbatch
|
||||
python -u -m paddle.distributed.launch --gpus "0,1,2,3" \
|
||||
train_batch_neg.py \
|
||||
--device gpu \
|
||||
--save_dir ./checkpoints/${root_path} \
|
||||
--batch_size 64 \
|
||||
--learning_rate 5E-5 \
|
||||
--epochs 3 \
|
||||
--output_emb_size 256 \
|
||||
--save_steps 10 \
|
||||
--max_seq_length 64 \
|
||||
--margin 0.2 \
|
||||
--train_set_file recall/train.csv
|
||||
|
||||
|
||||
# cpu training
|
||||
# root_path=inbatch
|
||||
# python train_batch_neg.py \
|
||||
# --device cpu \
|
||||
# --save_dir ./checkpoints/${root_path} \
|
||||
# --batch_size 64 \
|
||||
# --learning_rate 5E-5 \
|
||||
# --epochs 3 \
|
||||
# --output_emb_size 256 \
|
||||
# --save_steps 10 \
|
||||
# --max_seq_length 64 \
|
||||
# --margin 0.2 \
|
||||
# --train_set_file recall/train.csv
|
||||
|
||||
|
||||
|
||||
# 加载simcse训练的模型,模型放在simcse/model_20000
|
||||
# python -u -m paddle.distributed.launch --gpus "0,1,2,3" \
|
||||
# train_batch_neg.py \
|
||||
# --device gpu \
|
||||
# --save_dir ./checkpoints/simcse_inbatch_negative \
|
||||
# --batch_size 64 \
|
||||
# --learning_rate 5E-5 \
|
||||
# --epochs 3 \
|
||||
# --output_emb_size 256 \
|
||||
# --save_steps 10 \
|
||||
# --max_seq_length 64 \
|
||||
# --margin 0.2 \
|
||||
# --evaluate \
|
||||
# --train_set_file recall/train.csv \
|
||||
# --init_from_ckpt simcse/model_20000/model_state.pdparams
|
||||
|
||||
# 加载post training的模型,模型放在simcse/post_model_10000
|
||||
# python -u -m paddle.distributed.launch --gpus "0,1,2,3" \
|
||||
# train_batch_neg.py \
|
||||
# --device gpu \
|
||||
# --save_dir ./checkpoints/post_simcse_inbatch_negative \
|
||||
# --batch_size 64 \
|
||||
# --learning_rate 5E-5 \
|
||||
# --epochs 3 \
|
||||
# --output_emb_size 256 \
|
||||
# --save_steps 10 \
|
||||
# --max_seq_length 64 \
|
||||
# --margin 0.2 \
|
||||
# --train_set_file recall/train.csv \
|
||||
# --init_from_ckpt simcse/post_model_10000/model_state.pdparams
|
||||
@@ -37,6 +37,7 @@ parser.add_argument("--max_seq_length", default=512, type=int,
|
||||
"Sequences longer than this will be truncated, sequences shorter will be padded.")
|
||||
parser.add_argument("--batch_size", default=32, type=int,
|
||||
help="Batch size per GPU/CPU for training.")
|
||||
parser.add_argument('--model_name_or_path', default="rocketqa-zh-base-query-encoder", help="The pretrained model used for training")
|
||||
parser.add_argument("--output_emb_size", default=256,
|
||||
type=int, help="output_embedding_size")
|
||||
parser.add_argument("--learning_rate", default=5E-5, type=float,
|
||||
@@ -172,9 +173,9 @@ def do_train():
|
||||
data_path=args.train_set_file,
|
||||
lazy=False)
|
||||
|
||||
pretrained_model = AutoModel.from_pretrained('ernie-3.0-medium-zh')
|
||||
pretrained_model = AutoModel.from_pretrained(args.model_name_or_path)
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained('ernie-3.0-medium-zh')
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path)
|
||||
|
||||
trans_func = partial(convert_example,
|
||||
tokenizer=tokenizer,
|
||||
|
||||
@@ -104,6 +104,7 @@ Milvus 搭建完系统以后就可以插入和检索向量了,首先生成 emb
|
||||
```
|
||||
CUDA_VISIBLE_DEVICES=0 python feature_extract.py \
|
||||
--model_dir=./output \
|
||||
--model_name_or_path rocketqa-zh-base-query-encoder \
|
||||
--corpus_file "data/milvus_data.csv"
|
||||
```
|
||||
其中 output 目录下存放的是召回的 Paddle Inference 静态图模型。
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user