进阶任务:使用ERNIE-Doc进行长文本分类
更新时间:2022-07-05
目录结构
文本分类任务位于/wenxin/tasks/text_classification
├── data
│ ├── dev_data
│ │ └── dev_1.txt
│ ├── dict
│ │ └── vocab.txt
│ ├── download_data.sh
│ ├── iflytek ## 长文本分类开源数据集iflytek
│ │ ├── predict_data ## 预测集,由训练集截取的head 100数据
│ │ │ ├── infer2.txt
│ │ │ └── infer.txt
│ │ ├── test_data ## 测试集
│ │ │ └── part1.txt
│ │ └── train_data ## 训练集,demo中只放了100条数据,完整数据需自行下载
│ │ └── part1.txt
│ ├── predict_data
│ │ └── infer.txt
│ ├── test_data
│ │ └── test.txt
│ ├── train_data
│ │ └── train.txt
├── data_set_reader
│ ├── ernie_classification_base_dataset_reader.py
│ ├── dataset_reader_for_ernie_doc_classification.py ## ERNIE-Doc 数据读取器
│ └── ernie_classification_dataset_reader.py
├── examples
│ ├── cls_bow_ch_infer.json
│ ├── cls_bow_ch.json
│ ├── ......
│ ├── cls_ernie_doc_1.0_one_sent_ch_infer.json ## ERNIE-Doc的长文本分类预测配置文件
│ ├── cls_ernie_doc_1.0_one_sent_ch.json ## ERNIE-Doc的长文本分类训练配置文件
│ ├── cls_ernie_fc_ch_infer.json
│ ├── cls_ernie_fc_ch.json
│ ├── ......
│ └── cls_ernie_tiny_1.0_fc_ch.json
├── inference
│ ├── custom_cls_inference_ernie3.py
│ ├── custom_inference.py
│ ├── ernie_doc_inference.py ## ERNIE-Doc长文本分类任务的预测实现类
│
├── model
│ ├── base_cls.py ## 分类任务的model基类
│ ├── ......
│ ├── bow_classification.py
│ ├── ernie_classification.py ## ERNIE 分类任务的model基类
│ ├── ernie_doc_classification.py ## ERNIE-Doc分类任务的model实现类
├── reader
│ ├── categorical_field_reader.py
│ └── multi_label_field_reader.py
├── run_infer_ernie3.py
├── run_infer.py ## 只依靠json进行模型预测的入口脚本
├── run_trainer.py ## 只依靠json进行模型训练的入口脚本
└── trainer
├── custom_dynamic_ernie_doc_trainer.py ## ERNIE-Doc
├── custom_dynamic_trainer.py
├── custom_trainer_ernie3.py
├── custom_trainer.py
└── __init__.py
`
模型准备
模型均存放于wenxin_appzoo/wenxin_appzoo/models_hub文件夹下,进入文件夹执行sh download_ernie_doc_1.0_ch.sh下载ERNIE-Doc模型参数,字典,模型配置文件。
训练参数配置
文心中的各种参数都是在json文件中进行配置的,你可以通过修改所加载的json文件来进行参数的自定义配置。json配置文件主要分为三个部分:dataset_reader(数据部分)、model(网络部分)、trainer(训练任务)或inference(预测部分),在模型训练的时候,json文件中需要配置dataset_reader、model和trainer这三个部分;在预测推理的时候,json文件中需要配置dataset_reader、inference这两个部分。
{
"dataset_reader": {
"train_reader": { ## 训练、验证、测试各自基于不同的数据集,数据格式也可能不一样,可以在json中配置不同的reader,此处为训练集的reader。
"name": "train_reader",
"type": "ErnieDocClassificationDataSetReader", ## ERNIE-Doc特定的reader,封装了读取tsv、txt文件、组batch、转id等操作。
"fields": [## 域(field)是文心的高阶封装,对于同一个样本存在不同域的时候,不同域有单独的数据类型(文本、数值、整型、浮点型)、单独的词表(vocabulary)等,可以根据不同域进行语义表示,如文本转id等操作,field_reader是实现这些操作的类。
{
"name": "text_a", ## 文本分类只有一个文本特征域,命名为"text_a"
"data_type": "string", ## data_type定义域的数据类型,文本域的类型为string,整型数值为int,浮点型数值为float。
"reader": {
"type": "ErnieTextFieldReaderForErnieDoc" ## 采用针对ERNIE-Doc长文本的reader "ErnieTextFieldReaderForErnieDoc"。数值数组类型域为"ScalarArrayFieldReader",数值标量类型域为"ScalarFieldReader",这里的取值是对应FieldReader的类名。
},
"tokenizer": { ## 切词相关的配置
"type": "FullTokenizer", ## 指定该文本域的tokenizer为FullTokenizer, FullTokenizer为大多数ERNIE模型的切词方式。
"split_char": " ", ## 非Ernie任务需要自己切词,切词之后的明文使用的分隔符在这里设置,默认是通过空格区分不同的token。
"unk_token": "[UNK]" ## unk标记为"[UNK]", 即词表之外的token所对应的默认id,unk必须是词表文件中存在的token。
},
"need_convert": true, ## "need_convert"为true说明数据格式是明文字符串,需要通过词表转换为id。
"vocab_path": "../../models_hub/ernie_doc_1.0_ch_dir/vocab.txt", ## 指定该文本域的词表,"need_convert"为true时一定要设置
"max_seq_len": 512,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
},
{
"name": "label", ## 标签也是一个单独的域,在当前例子中命名为"label"。如果多个不同任务体系的标签存在于多个域中,则可实现最基本的多任务学习。
"data_type": "int", ## 标签是整型数值。
"reader": {
"type": "ScalarFieldReader"
},
"tokenizer": null,
"need_convert": false,
"vocab_path": "",
"max_seq_len": 1,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
}
],
"config": {
"data_path": "./data/iflytek/train_data", ## 训练数据train_reader的数据路径,写到文件夹目录。
"shuffle": true, ## 数据在读取过程中是否需要打乱顺序。
"batch_size": 8, ## 超参数之一,表示每个step训练多少个样本。
"epoch": 5, ## 超参数之一,表示这个数据集中的数据会被重复训练多少轮。
"sampling_rate": 1.0, ## 数据集的采样率,文心预留参数,暂时不起作用,后续版本会升级。
"need_data_distribute": true, ## 表示数据读取过程中是否需要按卡数进行分发,true表示每张卡在同一个step中读取到的数据是不一样的,false表示每张卡在同一个step中读取到的数据是一样的,训练集默认为true,测试集、验证集、预测集都是false。
"need_generate_examples": false, ## 表示在数据读取过程中除了id化好的tensor数据外,是否需要返回原始明文样本,测试集默认取值为true,训练集、测试集、验证集为false
"extra_params": {
"mem_len": 128, ## 指定memeoy长度
"is_repeat": false, ## 指定是否使用回顾式文本输入方式。false为不使用,true为使用
"need_all": false, ## 指定在使用回顾式文本输入方式下,是否使用所有的样本进行训练和评估。false为不使用,true为使用
"only_sec": false ## 指定在使用回顾式文本输入方式下,评估截断是否只使用第二遍的样本。false为不使用,true为使用。
}
}
},
"dev_reader": { ## 验证集配置,可参考train_reader
"name": "dev_reader",
"type": "ErnieDocClassificationDataSetReader",
"fields": [
{
"name": "text_a",
"data_type": "string",
"reader": {
"type": "ErnieTextFieldReaderForErnieDoc"
},
"tokenizer": {
"type": "FullTokenizer",
"split_char": " ",
"unk_token": "[UNK]"
},
"need_convert": true,
"vocab_path": "../../models_hub/ernie_doc_1.0_ch_dir/vocab.txt",
"max_seq_len": 512,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
},
{
"name": "label",
"data_type": "int",
"need_convert": false,
"reader": {
"type": "ScalarFieldReader"
},
"tokenizer": null,
"vocab_path": "",
"max_seq_len": 1,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
}
],
"config": {
"data_path": "./data/iflytek/test_data",
"shuffle": false,
"batch_size": 8,
"epoch": 1,
"sampling_rate": 1.0,
"need_data_distribute": false,
"need_generate_examples": false,
"extra_params": {
"mem_len": 128,
"is_repeat": false,
"need_all": false,
"only_sec": false
}
}
},
"test_reader": { ## 测试集配置,可参考train_reader
"name": "test_reader",
"type": "ErnieDocClassificationDataSetReader",
"fields": [
{
"name": "text_a",
"data_type": "string",
"reader": {
"type": "ErnieTextFieldReaderForErnieDoc"
},
"tokenizer": {
"type": "FullTokenizer",
"split_char": " ",
"unk_token": "[UNK]"
},
"need_convert": true,
"vocab_path": "../../models_hub/ernie_doc_1.0_ch_dir/vocab.txt",
"max_seq_len": 512,
"truncation_type": 0,
"padding_id": 0,
"embedding":null
},
{
"name": "label",
"data_type": "int",
"need_convert": false,
"reader": {
"type": "ScalarFieldReader"
},
"tokenizer": null,
"vocab_path": "",
"max_seq_len": 1,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
}
],
"config": {
"data_path": "./data/iflytek/test_data",
"shuffle": false,
"batch_size": 8,
"epoch": 1,
"need_data_distribute": false,
"need_generate_examples": false,
"sampling_rate": 1.0,
"extra_params": {
"mem_len": 128,
"is_repeat": false,
"need_all": false,
"only_sec": false
}
}
}
},
"model": { ## 模型部分(组网)相关配置
"type": "ErnieDocClassification", ## model设置,设置为对应的类名
"is_dygraph": 1, ## 区分动态图模型和静态图模型,1表示动态图,0表示静态图,目前ERNIE-Doc仅支持动态图,请保证is_dygraph取值为1。
"optimization": { ## 优化器设置,文心ERNIE推荐的默认设置
"learning_rate": 1.5e-4,
"use_lr_decay": true,
"warmup_steps": 0,
"warmup_proportion": 0.1,
"weight_decay": 0.01,
"use_dynamic_loss_scaling": false,
"init_loss_scaling": 128,
"incr_every_n_steps": 100,
"decr_every_n_nan_or_inf": 2,
"incr_ratio": 2.0,
"decr_ratio": 0.8,
"layer_decay_rate": 0.8,
"use_ema": false
},
"embedding": { ## ERNIE中的embedding参数设置,必填参数。
"type": "ErnieTokenEmbedding", ## embedding类型,务必设置为ErnieTokenEmbedding
"emb_dim": 768, ## 当前ERNIE模型的词向量维度,不同版本ERNIE维度不同,具体数值参考对应的config.json中的emb_size参数。
"use_fp16": false,
"train_batch_size": 8, ## 前面篇幅中train_reader设置的batch-size数值
"dev_batch_size": 8, ## 前面篇幅中dev_reader设置的batch-size数值
"test_batch_size": 8, ## 前面篇幅中test_reader设置的batch-size数值
"config_path": "../../models_hub/ernie_doc_1.0_ch_dir/ernie_config.json", ## 当前ERNIE模型的配置文件,下载需要的ERNIE模型压缩包即可看到。
"other": "" ## 预留字段,用来传递一些额外信息。
},
"num_labels": 119, ## label数量,iflytek数据集的标签数量为119
"mem_len": 128, ## 指定memeoy长度
"rel_pos_params_sharing": false ## 是否共享相对位置编码的参数。0为不共享,1为共享。
},
"trainer": {
"type": "CustomDynamicErnieDocTrainer", ## trainer类型,设置为对应的类名,这里固定为CustomDynamicErnieDocTrainer
"PADDLE_PLACE_TYPE": "gpu", ## 运行环境,可支持cpu、gpu、xpu。
"PADDLE_IS_FLEET": 0, ## 是否使用fleet进行多卡训练
"train_log_step": 10, ## 训练时打印训练日志的间隔步数,10表示每间隔10个batch,打印一次训练日志
"use_amp": true, ## 是否使用amp进行自动精度混合训练优化
"save_inference_model": true,
"use_fast_executor": true,
"num_iteration_per_drop_scope": 10,
"is_eval_dev": 1, ## 是否在训练的时候评估开发集,如果取值为1,则一定需要配置dev_reader及其数据路径,同上。
"is_eval_test": 0, ## 是否在训练的时候评估测试集,如果取值为1,则一定需要配置test_reader及其数据路径,同上。
"eval_step": 100, ## 进行测试集或验证集评估的间隔步数,同上。
"save_model_step": 10000000000000, ## 保存模型时的间隔步数,建议设置为eval_step的整数倍,同上。
"load_parameters": "", ## 加载包含各op参数值的训练好的模型,用于热启动。此处填写checkpoint路径。不填则表示不使用热启动。
"load_checkpoint": "", ## 加载包含学习率等所有参数的训练模型,用于热启动。此处填写checkpoint路径。不填则表示不使用热启动。
"pre_train_model": [ ## 加载预训练模型,ERNIE任务的必填参数,非ERNIE任务将当前参数置为[]即可。
{
"name": "ernie_doc_1.0_ch", ## 预训练模型的名称name
"params_path": "../../models_hub/ernie_doc_1.0_ch_dir/params" ## 预训练模型的目录params_path
}
],
"output_path": "./output/cls_ernie_doc_1.0_iflytek_ch", ## 保存模型的输出路径,如置空或者不配置则默认输出路径,为"./output",
"extra_param": { # 除核心必要信息之外,需要额外标明的参数信息,比如一些meta信息可以作为日志统计的关键字。
"meta":{
"job_type": "text_classification"
}
}
}
}
开始训练
- 指定AUTH的配置路径,找到你自己的auth.txt,获取它的绝对路径,如/home/zhangsang/wenxin/wenxin_appzoo,那么将这个绝对路径设给环境变量WENXIN_AUTH_PATH,如下所示:
export WENXIN_AUTH_PATH=/home/zhangsang/wenxin/wenxin_appzoo
- 进入指定目录
cd wenxin_appzoo/wenxin_appzoo/tasks/text_classification
- 如果是gpu训练,先指定卡号,如下所示指定在0号卡上进行训练
export CUDA_VISIBLE_DEVICES=0
- 模型训练的入口脚本为./run_trainer.py , 通过--param_path参数来传入./examples/目录下的json配置文件。
python run_trainer.py --param_path=./examples/cls_ernie_doc_1.0_one_sent_ch.json
训练运行的日志会自动保存在./log/test.log文件中.
训练中以及结束后产生的模型文件会默认保存在./output/cls_ernie_doc_1.0_iflytek_ch/目录下,其中save_inference_model/文件夹会保存用于预测的模型文件,save_checkpoint/文件夹会保存用于热启动的模型文件。
开始预测
- 指定AUTH的配置路径,找到你自己的auth.txt,获取它的绝对路径,如/home/zhangsang/wenxin/wenxin_appzoo,那么将这个绝对路径设给环境变量WENXIN_AUTH_PATH,如下所示:
export WENXIN_AUTH_PATH=/home/zhangsang/wenxin/wenxin_appzoo
- 进入指定目录
cd wenxin_appzoo/wenxin_appzoo/tasks/text_classification
- 如果是gpu训练,先指定卡号,如下所示指定在0号卡上进行训练
export CUDA_VISIBLE_DEVICES=0
- 选定配置好的json文件,把你将要预测的模型对应的inference_model文件路径填入json文件的inference_model_path参数中
- 模型训练的入口脚本为./run_infer.py , 通过--param_path参数来传入./examples/目录下的json配置文件。
python run_trainer.py --param_path=./examples/cls_ernie_doc_1.0_one_sent_ch.json
- 预测运行的日志会自动保存在./output/predict_result.txt文件中。