README.md 7.3 KB
Newer Older
Z
Zeyu Chen 已提交
1
# PaddleHub 序列标注
W
wuzewu 已提交
2 3 4

## 如何开始Finetune

S
Steffy-zxf 已提交
5
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_sequence_label.sh`即可开始使用ERNIE对MSRA_NER数据集进行Finetune。**由于ERNIE模型计算量较大,建议在GPU上使用,且显存需要大于14GB**
W
wuzewu 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

其中脚本参数说明如下:

```bash
# 模型相关
--use_gpu: 是否使用GPU,默认为False
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数
--learning_rate: Finetune的最大学习率
--weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01
--warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0
--num_epoch: Finetune迭代的轮数
--max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数

# 任务相关
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型
```

## 代码步骤

使用PaddleHub Finetune API进行Finetune可以分为4个步骤

### Step1: 加载预训练模型

```python
module = hub.Module(name="ernie")
inputs, outputs, program = module.context(trainable=True, max_seq_len=128)
```
其中最大序列长度`max_seq_len`是可以调整的参数,建议值128,根据任务文本长度不同可以调整该值,但最大不超过512。

如果想尝试BERT模型,只需要更换Module中的`name`参数即可.
PaddleHub还提供BERT模型可供选择, 所有模型对应的加载示例如下:

   模型名                           | PaddleHub Module
---------------------------------- | :------:
ERNIE, Chinese                     | `hub.Module(name='ernie')`
BERT-Base, Uncased                 | `hub.Module(name='bert_uncased_L-12_H-768_A-12')`
BERT-Large, Uncased                | `hub.Module(name='bert_uncased_L-24_H-1024_A-16')`
BERT-Base, Cased                   | `hub.Module(name='bert_cased_L-12_H-768_A-12')`
BERT-Large, Cased                  | `hub.Module(name='bert_cased_L-24_H-1024_A-16')`
BERT-Base, Multilingual Cased      | `hub.Module(nane='bert_multi_cased_L-12_H-768_A-12')`
BERT-Base, Chinese                 | `hub.Module(name='bert_chinese_L-12_H-768_A-12')`


```python
# 更换name参数即可无缝切换BERT中文模型, 代码示例如下
module = hub.Module(name="bert_chinese_L-12_H-768_A-12")
```

W
wuzewu 已提交
54
### Step2: 准备数据集并使用SequenceLabelReader读取数据
W
wuzewu 已提交
55 56 57 58 59 60 61 62
```python
dataset = hub.dataset.MSRA_NER()
reader = hub.reader.SequenceLabelReader(
    dataset=dataset,
    vocab_path=module.get_vocab_path(),
    max_seq_len=128)
```

Z
zhangxuefei 已提交
63
其中数据集的准备代码可以参考 [msra_ner.py](https://github.com/PaddlePaddle/PaddleHub/blob/develop/paddlehub/dataset/msra_ner.py)
W
wuzewu 已提交
64 65 66 67 68 69 70 71 72 73 74

`hub.dataset.MSRA_NER()` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录

`module.get_vaocab_path()` 会返回预训练模型对应的词表

`max_seq_len` 需要与Step1中context接口传入的序列长度保持一致

SequenceLabelReader中的`data_generator`会自动按照模型对应词表对数据进行切词,以迭代器的方式返回ERNIE/BERT所需要的Tensor格式,包括`input_ids``position_ids``segment_id`与序列对应的mask `input_mask`.

**NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。

W
wuzewu 已提交
75
### Step3:选择优化策略和运行配置
W
wuzewu 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

```python
strategy = hub.AdamWeightDecayStrategy(
    learning_rate=5e-5,
    weight_decay=0.01,
    warmup_proportion=0.0,
    lr_scheduler="linear_decay",
)

config = hub.RunConfig(use_cuda=True, num_epoch=3, batch_size=32, strategy=strategy)
```
#### 优化策略
针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy`

`learning_rate`: Finetune过程中的最大学习率;
`weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数;
`warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate;
`lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减;

#### 运行配置
`RunConfig` 主要控制Finetune的训练,包含以下可控制的参数:

* `log_interval`: 进度日志打印间隔,默认每10个step打印一次
* `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集
* `save_ckpt_interval`: 模型保存间隔,请根据任务大小配置,默认只保存验证集效果最好的模型和训练结束的模型
* `use_cuda`: 是否使用GPU训练,默认为False
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: finetune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `enable_memory_optim`: 是否使用内存优化, 默认为True
* `strategy`: Finetune优化策略

W
wuzewu 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
### Step4: 构建网络并创建序列标注迁移任务进行Finetune
```python

sequence_output = outputs["sequence_output"]

# feed_list的Tensor顺序不可以调整
feed_list = [
    inputs["input_ids"].name, inputs["position_ids"].name,
    inputs["segment_ids"].name, inputs["input_mask"].name, label.name
]

seq_label_task = hub.SequenceLabelTask(
    data_reader=reader,
    feature=sequence_output,
    feed_list=feed_list,
    max_seq_len=args.max_seq_len,
    num_classes=dataset.num_labels,
    config=config)

seq_label_task.finetune_and_eval()
```

**NOTE:**
1. `outputs["sequence_output"]`返回了ERNIE/BERT模型输入单词的对应输出,可以用于单词的特征表达。
2. `feed_list`中的inputs参数指名了ERNIE/BERT中的输入tensor的顺序,与SequenceLabelReader返回的结果一致。
W
wuzewu 已提交
133
3. `hub.SequenceLabelTask`通过输入特征,迁移的类别数,可以生成适用于序列标注的迁移任务`SequenceLabelTask`
W
wuzewu 已提交
134

W
wuzewu 已提交
135 136 137 138 139 140 141
## VisualDL 可视化

Finetune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令
```bash
$ visualdl --logdir $CKPT_DIR/vdllog -t ${HOST_IP}
```
其中${HOST_IP}为本机IP地址,如本机IP地址为192.168.0.1,用浏览器打开192.168.0.1:8040,其中8040为端口号,即可看到训练过程中指标的变化情况
W
wuzewu 已提交
142
![img](https://raw.githubusercontent.com/PaddlePaddle/PaddleHub/develop/docs/imgs/seq_label_finetune_vdl.png)
W
wuzewu 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158

## 模型预测

通过Finetune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数
```
CKPT_DIR=".ckpt_sequence_label/best_model"
python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128
```
其中CKPT_DIR为Finetune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致*

参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。
如需了解更多预测步骤,请参考`predict.py`

```
text=它折射出华夏文明的绚丽光环,使这片古老的土地更加异彩纷呈,充满魅力。	label=OOOOB-LOCI-LOCOOOOOOOOOOOOOOOOOOOOOOOOOOOO	predict=OOOOOB-LOCI-LOCOOOOOOOOOOOOOOOOOOOOOOOOOOOOO