Skip to content

Commit ca8541b

Browse files
authored
add sequence classification with ernie/bert/roberta finetuned in dygraph
1 parent 060c13e commit ca8541b

File tree

108 files changed

+6162
-8808
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+6162
-8808
lines changed

demo/text_classification/README.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# PaddleHub Transformer模型fine-tune文本分类(动态图)
2+
3+
本示例将展示如何使用PaddleHub Transformer模型(如 ERNIE、BERT、RoBERTa等模型)module 以动态图方式fine-tune并完成预测任务。
4+
5+
## 如何开始Fine-tune
6+
7+
8+
我们以中文情感分类公开数据集ChnSentiCorp为示例数据集,可以运行下面的命令,在训练集(train.tsv)上进行模型训练,并在开发集(dev.tsv)验证。通过如下命令,即可启动训练。
9+
10+
```shell
11+
# 设置使用的GPU卡号
12+
export CUDA_VISIBLE_DEVICES=0
13+
python train.py
14+
```
15+
16+
17+
## 代码步骤
18+
19+
使用PaddleHub Fine-tune API进行Fine-tune可以分为4个步骤。
20+
21+
### Step1: 选择模型
22+
```python
23+
import paddlehub as hub
24+
25+
model = hub.Module(name='ernie_tiny', version='2.0.0', task='sequence_classification')
26+
```
27+
28+
其中,参数:
29+
30+
* `name`:模型名称,可以选择`ernie``ernie-tiny``bert_chinese_L-12_H-768_A-12``chinese-roberta-wwm-ext``chinese-roberta-wwm-ext-large`等。
31+
* `version`:module版本号
32+
* `task`:fine-tune任务。此处为`sequence_classification`,表示文本分类任务。
33+
34+
### Step2: 下载并加载数据集
35+
36+
```python
37+
train_dataset = hub.datasets.ChnSentiCorp(
38+
tokenizer=model.get_tokenizer(tokenize_chinese_chars=True), max_seq_len=128, mode='train')
39+
dev_dataset = hub.datasets.ChnSentiCorp(
40+
tokenizer=model.get_tokenizer(tokenize_chinese_chars=True), max_seq_len=128, mode='dev')
41+
```
42+
43+
* `tokenizer`:表示该module所需用到的tokenizer,其将对输入文本完成切词,并转化成module运行所需模型输入格式。
44+
* `mode`:选择数据模式,可选项有 `train`, `test`, `val`, 默认为`train`
45+
* `max_seq_len`:ERNIE/BERT模型使用的最大序列长度,若出现显存不足,请适当调低这一参数。
46+
47+
### Step3: 选择优化策略和运行配置
48+
49+
```python
50+
optimizer = paddle.optimizer.Adam(learning_rate=5e-5, parameters=model.parameters())
51+
trainer = hub.Trainer(model, optimizer, checkpoint_dir='test_ernie_text_cls')
52+
53+
trainer.train(train_dataset, epochs=3, batch_size=32, eval_dataset=dev_dataset)
54+
55+
# 在测试集上评估当前训练模型
56+
trainer.evaluate(test_dataset, batch_size=32)
57+
```
58+
59+
#### 优化策略
60+
61+
Paddle2.0-rc提供了多种优化器选择,如`SGD`, `Adam`, `Adamax`等,详细参见[策略](https://www.paddlepaddle.org.cn/documentation/docs/zh/2.0-rc/api/paddle/optimizer/optimizer/Optimizer_cn.html)
62+
63+
其中`Adam`:
64+
65+
* `learning_rate`: 全局学习率。默认为1e-3;
66+
* `parameters`: 待优化模型参数。
67+
68+
#### 运行配置
69+
70+
`Trainer` 主要控制Fine-tune的训练,包含以下可控制的参数:
71+
72+
* `model`: 被优化模型;
73+
* `optimizer`: 优化器选择;
74+
* `use_vdl`: 是否使用vdl可视化训练过程;
75+
* `checkpoint_dir`: 保存模型参数的地址;
76+
* `compare_metrics`: 保存最优模型的衡量指标;
77+
78+
`trainer.train` 主要控制具体的训练过程,包含以下可控制的参数:
79+
80+
* `train_dataset`: 训练时所用的数据集;
81+
* `epochs`: 训练轮数;
82+
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size;
83+
* `num_workers`: works的数量,默认为0;
84+
* `eval_dataset`: 验证集;
85+
* `log_interval`: 打印日志的间隔, 单位为执行批训练的次数。
86+
* `save_interval`: 保存模型的间隔频次,单位为执行训练的轮数。
87+
88+
## 模型预测
89+
90+
当完成Fine-tune后,Fine-tune过程在验证集上表现最优的模型会被保存在`${CHECKPOINT_DIR}/best_model`目录下,其中`${CHECKPOINT_DIR}`目录为Fine-tune时所选择的保存checkpoint的目录。
91+
92+
我们以以下数据为待预测数据,使用该模型来进行预测
93+
94+
```text
95+
这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般
96+
怀着十分激动的心情放映,可是看着看着发现,在放映完毕后,出现一集米老鼠的动画片
97+
作为老的四星酒店,房间依然很整洁,相当不错。机场接机服务很好,可以在车上办理入住手续,节省时间。
98+
```
99+
100+
```python
101+
import paddlehub as hub
102+
103+
data = [
104+
['这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般'],
105+
['怀着十分激动的心情放映,可是看着看着发现,在放映完毕后,出现一集米老鼠的动画片'],
106+
['作为老的四星酒店,房间依然很整洁,相当不错。机场接机服务很好,可以在车上办理入住手续,节省时间。'],
107+
]
108+
label_map = {0: 'negative', 1: 'positive'}
109+
110+
model = hub.Module(
111+
directory='/mnt/zhangxuefei/program-paddle/PaddleHub/modules/text/language_model/ernie_tiny',
112+
version='2.0.0',
113+
task='sequence_classification',
114+
load_checkpoint='./test_ernie_text_cls/best_model/model.pdparams',
115+
label_map=label_map)
116+
results = model.predict(data, max_seq_len=50, batch_size=1, use_gpu=False)
117+
for idx, text in enumerate(data):
118+
print('Data: {} \t Lable: {}'.format(text[0], results[idx]))
119+
```
120+
121+
参数配置正确后,请执行脚本`python predict.py`, 加载模型具体可参见[加载](https://www.paddlepaddle.org.cn/documentation/docs/zh/2.0-rc/api/paddle/framework/io/load_cn.html#load)
122+
123+
### 依赖
124+
125+
paddlepaddle >= 2.0.0rc
126+
127+
paddlehub >= 2.0.0

demo/text_classification/predict.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import paddlehub as hub
15+
16+
if __name__ == '__main__':
17+
18+
data = [
19+
['这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般'],
20+
['怀着十分激动的心情放映,可是看着看着发现,在放映完毕后,出现一集米老鼠的动画片'],
21+
['作为老的四星酒店,房间依然很整洁,相当不错。机场接机服务很好,可以在车上办理入住手续,节省时间。'],
22+
]
23+
label_map = {0: 'negative', 1: 'positive'}
24+
25+
model = hub.Module(
26+
name='ernie_tiny',
27+
version='2.0.0',
28+
task='sequence_classification',
29+
load_checkpoint='./test_ernie_text_cls/best_model/model.pdparams',
30+
label_map=label_map)
31+
results = model.predict(data, max_seq_len=50, batch_size=1, use_gpu=False)
32+
for idx, text in enumerate(data):
33+
print('Data: {} \t Lable: {}'.format(text[0], results[idx]))

demo/text_classification/train.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import paddle
15+
import paddlehub as hub
16+
17+
if __name__ == '__main__':
18+
model = hub.Module(name='ernie_tiny', version='2.0.0', task='sequence_classification')
19+
20+
train_dataset = hub.datasets.ChnSentiCorp(
21+
tokenizer=model.get_tokenizer(tokenize_chinese_chars=True), max_seq_len=128, mode='train')
22+
dev_dataset = hub.datasets.ChnSentiCorp(
23+
tokenizer=model.get_tokenizer(tokenize_chinese_chars=True), max_seq_len=128, mode='dev')
24+
test_dataset = hub.datasets.ChnSentiCorp(
25+
tokenizer=model.get_tokenizer(tokenize_chinese_chars=True), max_seq_len=128, mode='test')
26+
27+
optimizer = paddle.optimizer.AdamW(learning_rate=5e-5, parameters=model.parameters())
28+
trainer = hub.Trainer(model, optimizer, checkpoint_dir='test_ernie_text_cls', use_gpu=True)
29+
30+
trainer.train(train_dataset, epochs=3, batch_size=32, eval_dataset=dev_dataset, save_interval=1)
31+
trainer.evaluate(test_dataset, batch_size=32)
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
```shell
2+
$ hub install bert-base-cased==2.0.0
3+
```
4+
5+
<p align="center">
6+
<img src="https://bj.bcebos.com/paddlehub/paddlehub-img/bert_network.png" hspace='10'/> <br />
7+
</p>
8+
9+
更多详情请参考[BERT论文](https://arxiv.org/abs/1810.04805)
10+
11+
## API
12+
13+
```python
14+
def __init__(
15+
task=None,
16+
load_checkpoint=None,
17+
label_map=None)
18+
```
19+
20+
创建Module对象(动态图组网版本)。
21+
22+
**参数**
23+
24+
* `task`: 任务名称,可为`sequence_classification`
25+
* `load_checkpoint`:使用PaddleHub Fine-tune api训练保存的模型参数文件路径。
26+
* `label_map`:预测时的类别映射表。
27+
28+
```python
29+
def predict(
30+
data,
31+
max_seq_len=128,
32+
batch_size=1,
33+
use_gpu=False)
34+
```
35+
36+
**参数**
37+
38+
* `data`: 待预测数据,格式为\[\[sample\_a\_text\_a, sample\_a\_text\_b\], \[sample\_b\_text\_a, sample\_b\_text\_b\],…,\],其中每个元素都是一个样例,
39+
每个样例可以包含text\_a与text\_b。每个样例文本数量(1个或者2个)需和训练时保持一致。
40+
* `max_seq_len`:模型处理文本的最大长度
41+
* `batch_size`:模型批处理大小
42+
* `use_gpu`:是否使用gpu,默认为False。对于GPU用户,建议开启use_gpu。
43+
44+
**返回**
45+
46+
```python
47+
def get_embedding(
48+
texts,
49+
use_gpu=False
50+
)
51+
```
52+
53+
用于获取输入文本的句子粒度特征与字粒度特征
54+
55+
**参数**
56+
57+
* `texts`:输入文本列表,格式为\[\[sample\_a\_text\_a, sample\_a\_text\_b\], \[sample\_b\_text\_a, sample\_b\_text\_b\],…,\],其中每个元素都是一个样例,每个样例可以包含text\_a与text\_b。
58+
* `use_gpu`:是否使用gpu,默认为False。对于GPU用户,建议开启use_gpu。
59+
60+
**返回**
61+
62+
* `results`:list类型,格式为\[\[sample\_a\_pooled\_feature, sample\_a\_seq\_feature\], \[sample\_b\_pooled\_feature, sample\_b\_seq\_feature\],…,\],其中每个元素都是对应样例的特征输出,每个样例都有句子粒度特征pooled\_feature与字粒度特征seq\_feature。
63+
64+
65+
**代码示例**
66+
67+
```python
68+
import paddlehub as hub
69+
70+
data = [
71+
'这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般',
72+
'怀着十分激动的心情放映,可是看着看着发现,在放映完毕后,出现一集米老鼠的动画片',
73+
'作为老的四星酒店,房间依然很整洁,相当不错。机场接机服务很好,可以在车上办理入住手续,节省时间。',
74+
]
75+
label_map = {0: 'negative', 1: 'positive'}
76+
77+
model = hub.Module(
78+
name='bert-base-cased',
79+
version='2.0.0',
80+
task='sequence_classification',
81+
load_checkpoint='/path/to/parameters',
82+
label_map=label_map)
83+
results = model.predict(data, max_seq_len=50, batch_size=1, use_gpu=False)
84+
for idx, text in enumerate(data):
85+
print('Data: {} \t Lable: {}'.format(text, results[idx]))
86+
```
87+
88+
参考PaddleHub 文本分类示例。https://github.com/PaddlePaddle/PaddleHub/tree/release/v2.0.0-beta/demo/text_classifcation
89+
90+
## 服务部署
91+
92+
PaddleHub Serving可以部署一个在线获取预训练词向量。
93+
94+
### Step1: 启动PaddleHub Serving
95+
96+
运行启动命令:
97+
98+
```shell
99+
$ hub serving start -m bert-base-cased
100+
```
101+
102+
这样就完成了一个获取预训练词向量服务化API的部署,默认端口号为8866。
103+
104+
**NOTE:** 如使用GPU预测,则需要在启动服务之前,请设置CUDA_VISIBLE_DEVICES环境变量,否则不用设置。
105+
106+
### Step2: 发送预测请求
107+
108+
配置好服务端,以下数行代码即可实现发送预测请求,获取预测结果
109+
110+
```python
111+
import requests
112+
import json
113+
114+
# 指定用于预测的文本并生成字典{"text": [text_1, text_2, ... ]}
115+
text = [["今天是个好日子", "天气预报说今天要下雨"], ["这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般"]]
116+
# 以key的方式指定text传入预测方法的时的参数,此例中为"texts"
117+
# 对应本地部署,则为module.get_embedding(texts=text)
118+
data = {"texts": text}
119+
# 发送post请求,content-type类型应指定json方式
120+
url = "http://10.12.121.132:8866/predict/bert-base-cased"
121+
# 指定post请求的headers为application/json方式
122+
headers = {"Content-Type": "application/json"}
123+
124+
r = requests.post(url=url, headers=headers, data=json.dumps(data))
125+
print(r.json())
126+
```
127+
128+
## 查看代码
129+
130+
https://github.com/PaddlePaddle/models/tree/develop/PaddleNLP/pretrain_langauge_models/BERT
131+
132+
133+
## 依赖
134+
135+
paddlepaddle >= 2.0.0
136+
137+
paddlehub >= 2.0.0
138+
139+
## 更新历史
140+
141+
* 1.0.0
142+
143+
初始发布
144+
145+
* 1.1.0
146+
147+
支持get_embedding与get_params_layer
148+
149+
* 2.0.0
150+
151+
全面升级动态图,接口有所变化。

0 commit comments

Comments
 (0)