文本分类任务
更新时间:2021-03-23
任务简介
- 文本分类是经典的NLP问题之一,简单来说,它是一种将文本对象(文档或句子)分类到一个固定类别的技术。
- 当应用场景中的数据量非常大时,文本分类对数据的组织、信息过滤,以及数据存储等方面起到非常大的作用。
- 常用的场景包括:垃圾邮件识别,文本审核、新闻主题分类,情感分析,以及搜索引擎的页面组织
快速开始
1. 代码结构说明
以下是本项目主要代码结构及说明:
代码目录: textone-public/tasks/text_classification
.
├── __init__.py
├── env.sh ## 环境变量配置脚本
├── run_with_json.py ## 只依靠json进行模型训练的入口脚本
├── run_infer.py ## 只依靠json进行模型预测的入口脚本
├── examples ## 各典型网络的json配置文件
│ ├── cls_cnn_ch.json
│ ├── cls_cnn_ch_infer.json
│ ├── cls_ernie_1.0_base_cnn_ch.json
│ └── ...
├── data ## 示例数据文件夹,包括各任务所需训练集(train_data)、测试集(test_data)、验证集(dev_data)和预测集(predict_data)
│ ├── train_data
│ │ └── train.txt
│ ├── test_data
│ │ └── test.txt
│ ├── dev_data
│ │ └── dev.txt
│ ├── predict_data
│ │ └── infer.txt
│ └── ...
└── dict ## 示例非ERNIE任务的词表文件夹
├── vocab.txt
2. 数据准备
非ERNIE数据
- 这里我们提供一份已标注的、经过分词预处理的示例数据集。
- 训练集、测试集、验证集和预测集分别存放在./data目录下的train_data、test_data、dev_data和predict_data文件夹下,对应的示例词表存放在./dict目录下。
- 注:数据集(包含词表)均为utf-8格式。
-
训练集/测试集/验证集
- 训练集、测试集和验证集的数据格式相同,如下所示。数据分为两列,列与列之间用\t进行分隔。第一列为文本,第二列为标签。
房间 太 小 。 其他 的 都 一般 。 。 。 。 。 。 。 。 。 0 LED屏 就是 爽 , 基本 硬件 配置 都 很 均衡 , 镜面 考 漆 不错 , 小黑 , 我喜欢 。 1 差 得 要命 , 很大 股霉味 , 勉强 住 了 一晚 , 第二天 大早 赶紧 溜。 0
-
预测集
- 预测集无需进行标签预占位,其格式如下所示:
USB接口 只有 2个 , 太 少 了 点 , 不能 接 太多 外 接 设备 ! 表面 容易 留下 污垢 ! 平时 只 用来 工作 , 上 上网 , 挺不错 的 , 没有 冗余 的 功能 , 样子 也 比较 正式 ! 还 可以 吧 , 价格 实惠 宾馆 反馈 2008年4月17日 : 谢谢 ! 欢迎 再次 入住 其士 大酒店 。
-
词表
- 词表分为两列,第一列为词,第二列为id(从0开始),列与列之间用\t进行分隔。若用户自备词表,需保持[UNK]项与示例词表一致。部分词表示例如下所示:
[PAD] 0 [CLS] 1 [SEP] 2 [MASK] 3 [UNK] 4 5 郑重 6 丁约翰 7 工地 8 神圣 9
ERNIE数据
- 若使用基于ERNIE的模型进行训练,那么数据集不需要分词且无需准备词表,其格式与非ERNIE的数据集相同,如下所示:
选择珠江花园的原因就是方便,有电动扶梯直接到达海边,周围餐馆、食廊、商场、超市、摊位一应俱全。酒店装修一般,但还算整洁。 1
15.4寸笔记本的键盘确实爽,基本跟台式机差不多了,蛮喜欢数字小键盘,输数字特方便,样子也很美观,做工也相当不错 1
房间太小。其他的都一般。。。。。。。。。 0
3. 训练第一个模型
开始训练
- 使用预置网络进行训练的方式为使用./run_with_json.py入口脚本,通过--param_path参数来传入./examples/目录下的json配置文件。
-
以基于预置CNN网络的文本分类模型为例,训练分为以下几个步骤:
- 请在./env.sh中根据提示配置相应环境变量的路径
- 基于示例的数据集,可以运行以下命令在训练集(train.txt)上进行模型训练,并在测试集(test.txt)上进行验证;
# CNN 模型 # 需要提前参照env.sh进行环境变量配置,在当前shell内去读取 source env.sh # 基于json实现预置网络训练。其调用了配置文件./examples/cls_cnn_ch.json python run_with_json.py --param_path ./examples/cls_cnn_ch.json
- 训练运行的日志会自动保存在./log/test.log文件中;
- 训练中以及结束后产生的模型文件会默认保存在./output/cls_cnn_ch/目录下,其中save_inference_model/文件夹会保存用于预测的模型文件,save_checkpoint/文件夹会保存用于热启动的模型文件。
配置说明
- 使用预置网络训练时,可以通过修改所加载的json文件来进行参数的自定义配置。
- json配置文件主要分为三个部分:dataset_reader、model和trainer。
- 以./examples/cls_cnn_ch.json为例,上述三个部分的配置与说明如下所示。
dataset_reader部分
- dataset_reader用于配置模型训练时的数据读取。
- 以下为./examples/cls_cnn_ch.json中抽取出来的dataset_reader部分配置,并通过注释说明。
{
"dataset_reader": {
"train_reader": { ## 训练、验证、测试各自基于不同的数据集,数据格式也可能不一样,可以在json中配置不同的reader,此处为训练集的reader。
"name": "train_reader",
"type": "BasicDataSetReader", ## 采用BasicDataSetReader,其封装了常见的读取tsv文件、组batch等操作。
"fields": [ ## 域(field)是wenxin的高阶封装,对于同一个样本存在不同域的时候,不同域有单独的数据类型(文本、数值、整型、浮点型)、单独的词表(vocabulary)等,可以根据不同域进行语义表示,如文本转id等操作,field_reader是实现这些操作的类。
{
"name": "text_a", ## 文本分类只有一个文本特征域,命名为"text_a"。
"data_type": "string", ## data_type定义域的数据类型,文本域的类型为string,整型数值为int,浮点型数值为float。
"reader": {"type":"CustomTextFieldReader"}, ## 采用针对文本域的通用reader "CustomTextFieldReader"。数值数组类型域为"ScalarArrayFieldReader",数值标量类型域为"ScalarFieldReader"。
"tokenizer":{
"type":"CustomTokenizer", ## 指定该文本域的tokenizer为CustomTokenizer。
"split_char":" ", ## 通过空格区分不同的token。
"unk_token":"[UNK]", ## unk标记为"[UNK]"。
"params":null
},
"need_convert": true, ## "need_convert"为true说明数据格式是明文字符串,需要通过词表转换为id。
"vocab_path": "./dict/vocab.txt", ## 指定该文本域的词表。
"max_seq_len": 512, ## 设定每个域的最大长度。
"truncation_type": 0, ## 选择截断策略,0为从头开始到最大长度截断,1为从头开始到max_len-1的位置截断,末尾补上最后一个id(词或字),2为保留头和尾两个位置,然后按从头开始到最大长度方式截断。
"padding_id": 0 ## 设定padding时对应的id值。
}, ## 如果每一个样本有多个特征域(文本类型、数值类型均可),可以仿照前面对每个域进行设置,依次增加每个域的配置即可。此时样本的域之间是以\t分隔的。
{
"name": "label", ## 标签也是一个单独的域,命名为"label"。如果多个不同任务体系的标签存在于多个域中,则可实现最基本的多任务学习。
"data_type": "int", ## 标签是整型数值。
"reader":{
"type":"ScalarFieldReader" ## 整型数值域的reader为"ScalarFieldReader"。
},
"tokenizer":null,
"need_convert": false,
"vocab_path": "",
"max_seq_len": 1,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
}
],
"config": {
"data_path": "./data/train_data/", ## 训练数据train_reader的数据路径,写到文件夹目录。
"shuffle": false,
"batch_size": 8,
"epoch": 10,
"sampling_rate": 1.0
}
},
"test_reader": { ## 若要评估测试集,需配置test_reader,其配置方式与train_reader类似。
……
},
"dev_reader": { ## 若要评估验证集,需配置dev_reader,其配置方式与test_reader类似。
……
}
},
……
}
model部分
- model用于配置模型训练时的预置网络,包括预置网络的类别及其优化器的参数等。
- 以下为./examples/cls_cnn_ch.json中抽取出来的model部分配置,并通过注释说明。
{
...
"model": {
"type": "CnnClassification", ## wenxin采用模型(models)的方式定义神经网络的基本操作,本例采用预置的模型CnnClassification实现文本分类,具体网络可参考models目录。
"optimization": { ## 预置模型的优化器所需的参数配置,如学习率等。
"learning_rate": 2e-05
}
},
...
}
trainer部分
- trainer用于配置模型训练的启动器,包括保存模型时的间隔步数、进行测试集或验证集评估的间隔步数等。
- 以下为./examples/cls_cnn_ch.json中抽取出来的trainer部分配置,并通过注释说明。
{
...
"trainer": {
"PADDLE_USE_GPU": 0, ## 是否使用GPU进行训练,1为使用GPU。
"PADDLE_IS_LOCAL": 1, ## 是否单机训练,默认值为0,若要单机训练需要设置为1。
"train_log_step": 20, ## 训练时打印训练日志的间隔步数。
"is_eval_dev": 0, ## 是否在训练的时候评估开发集,如果取值为1一定需要配置dev_reader及其数据路径。
"is_eval_test": 1, ## 是否在训练的时候评估测试集,如果取值为1一定需要配置test_reader及其数据路径。
"eval_step": 100, ## 进行测试集或验证集评估的间隔步数。
"save_model_step": 10000, ## 保存模型时的间隔步数,建议设置为eval_step的整数倍。
"load_parameters": 0, ## 加载包含各op参数值的训练好的模型,用于预测。
"load_checkpoint": " ", ## 加载包含学习率等所有参数的训练模型,用于热启动。此处填写checkpoint路径
"use_fp16": 0, ## 是否使用fp16精度。
"pre_train_model": [], ## 加载预训练模型,例如ernie。使用时需要填写预训练模型的名称name和预训练模型的目录params_path。
"output_path": "./output/cls_cnn_ch" ## 保存模型的输出路径,如置空或者不配置则默认输出路径为"./output"。
}
}
4. 模型预测
开始预测
- 使用预置网络进行预测的方式为使用./run_infer.py入口脚本,通过--param_path参数来传入./examples/目录下的json配置文件。
-
以基于预置CNN网络所训练出的模型为例,其预测分为以下几个步骤:
- 基于./examples/cls_cnn_ch.json训练出的模型默认储存在./output/cls_cnn_ch/save_inference_model/中,在该目录下找到被保存的inference_model文件夹,例如inference_step_251/;
- 在./examples/cls_cnn_ch_infer.json中修改"inference_model_path"参数,填入上述模型保存路径,如下所示:
{ ... "inference":{ ... "inference_model_path":"./output/cls_cnn_ch/save_inference_model/inference_step_251" } }
- 基于示例的数据集,可以运行以下命令在预测集(infer.txt)上进行预测:
# 基于json实现预测。其调用了配置文件./examples/cls_cnn_ch_infer.json python run_infer.py --param_path ./examples/cls_cnn_ch_infer.json
- 预测运行的日志会自动保存在./output/predict_result.txt文件中。
配置说明
- 基于json实现预测时,可以通过修改所加载的json文件来进行参数的自定义配置。
- json配置文件主要分为三个部分:dataset_reader、model和inference。 以./examples/cls_cnn_ch_infer.json为例,上述三个部分的配置与说明如下所示。
{
"dataset_reader": {
"predict_reader": { ## 预测部分需要单独配置reader。
"name": "predict_reader",
"type": "BasicDataSetReader",
"fields": [ ## 本样例中只有一个文本域需要配置,配置方式与训练过程类似,注意无需配label。
{
"name": "text_a",
"data_type": "string",
"reader": {"type":"CustomTextFieldReader"},
"tokenizer":{
……
},
……
}
],
"config": {
"data_path": "./data/predict_data/", ## 需要配置预测数据路径。
……
}
}
},
"model": {
"type": "CnnClassification" ## 如果使用checkpoint需要说明其模型网络。
},
"trainer": {
……
},
"inference":{ ## 需配置预测时所需的参数。
"output_path": "./output/predict_result.txt", ## 预测结果文件的输出路径。
"PADDLE_USE_GPU": 0, ## 是否采用GPU预测。
"PADDLE_IS_LOCAL": 1, ## 是否单机预测,默认值为0,若要单机预测需要设置为1。
"inference_model_path":"./output/cls_cnn_ch/save_inference_model/inference_step_251" ## 训练好的模型路径。
}
}
5. 使用ERNIE中文模型进行训练
- ERNIE模型参数文件下载脚本及相关配置文件和词表保存在../model_files/目录下。
- 不同ernie版本的参数文件(params)、词表(vocab.txt)、网络配置参数(ernie*config.json)大部分不相同,需要注意好对应关系,不同ERNIE模型间的差别及相关配置文件与词表请参考ERNIE预训练模型介绍。
- 若希望通过开关控制ernie训练时不更新ernie参数,请参考ernie网络配置超参数说明中关于freeze_emb和freeze_num_layers的说明
开始训练
- 与非ERNIE的训练方式相同,使用预置网络进行训练的方式为使用./run_with_json.py入口脚本,通过--param_path参数来传入./examples/目录下ernie相关的json配置文件。
-
以预置基于ernie_1.0_base的CNN文本分类模型为例,训练分为以下几个步骤:
- 请使用以下命令在../model_files/中通过对应脚本下载ernie_1.0_base模型参数文件,其对应配置文件ernie_1.0_base_ch_config.json和词表vocab_ernie_1.0_base_ch.txt分别位于../model_files/目录下的config/和dict/文件夹,用户无需更改;
# ernie_1.0_base 模型下载 # 进入model_files目录 cd ../model_files/ # 运行下载脚本 sh download_ernie_1.0_base_ch.sh
- 请准备数据集并放入对应目录中,ERNIE训练所需数据集不需要分词且无需准备词表,其格式与非ERNIE的数据集相同;
- 运行以下命令在训练集(train.txt)上进行模型训练,并在测试集(test.txt)上进行验证;
# 基于json实现预置网络训练。其调用了配置文件./examples/cls_ernie_1.0_base_cnn_ch.json python run_with_json.py --param_path ./examples/cls_ernie_1.0_base_cnn_ch.json
- 训练运行的日志会自动保存在./log/test.log文件中;
6. 进阶使用一
数据处理模块(data)详细说明
- Data部分为文心数据处理模块,通过data_set_reader实现读取数据文件、转换数据格式、组batch、shuffle等操作。
预置reader配置
- 通过json文件中的dataset_reader部分对预置reader进行配置,以文本分类任务cls_cnn_ch.json为例,其dataset_reader部分如下所示:
{
"dataset_reader": {
"train_reader": { ## 训练、验证、测试各自基于不同的数据集,数据格式也可能不一样,可以在json中配置不同的reader,此处为训练集的reader。
"name": "train_reader",
"type": "BasicDataSetReader", ## 采用BasicDataSetReader,其封装了常见的读取tsv文件、组batch等操作。
"fields": [ ## 域(field)是wenxin的高阶封装,对于同一个样本存在不同域的时候,不同域有单独的数据类型(文本、数值、整型、浮点型)、单独的词表(vocabulary)等,可以根据不同域进行语义表示,如文本转id等操作,field_reader是实现这些操作的类。
{
"name": "text_a", ## 文本分类只有一个文本特征域,命名为"text_a"。
"data_type": "string", ## data_type定义域的数据类型,文本域的类型为string,整型数值为int,浮点型数值为float。
"reader": {"type":"CustomTextFieldReader"}, ## 采用针对文本域的通用reader "CustomTextFieldReader"。数值数组类型域为"ScalarArrayFieldReader",数值标量类型域为"ScalarFieldReader"。
"tokenizer":{
"type":"CustomTokenizer", ## 指定该文本域的tokenizer为CustomTokenizer。
"split_char":" ", ## 通过空格区分不同的token。
"unk_token":"[UNK]", ## unk标记为"[UNK]"。
"params":null
},
"need_convert": true, ## "need_convert"为true说明数据格式是明文字符串,需要通过词表转换为id。
"vocab_path": "./dict/vocab.txt", ## 指定该文本域的词表。
"max_seq_len": 512, ## 设定每个域的最大长度。
"truncation_type": 0, ## 选择截断策略,0为从头开始到最大长度截断,1为从头开始到max_len-1的位置截断,末尾补上最后一个id(词或字),2为保留头和尾两个位置,然后按从头开始到最大长度方式截断。
"padding_id": 0 ## 设定padding时对应的id值。
}, ## 如果每一个样本有多个特征域(文本类型、数值类型均可),可以仿照前面对每个域进行设置,依次增加每个域的配置即可。此时样本的域之间是以\t分隔的。
{
"name": "label", ## 标签也是一个单独的域,命名为"label"。如果多个不同任务体系的标签存在于多个域中,则可实现最基本的多任务学习。
"data_type": "int", ## 标签是整型数值。
"reader":{
"type":"ScalarFieldReader" ## 整型数值域的reader为"ScalarFieldReader"。
},
"tokenizer":null,
"need_convert": false,
"vocab_path": "",
"max_seq_len": 1,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
}
],
"config": {
"data_path": "./data/train_data/", ## 训练数据train_reader的数据路径,写到文件夹目录。
"shuffle": false,
"batch_size": 8,
"epoch": 10,
"sampling_rate": 1.0
}
},
……
},
……
}
自定义reader配置
- 自定义reader配置根据具体项目情况通过对base_dataset_reader基类重写来实现。
- 变量设置规则在common.rule.InstanceName中,该部分囊括了model和data部分的全局变量,实现了数据部分与组网部分的衔接,前向传播loss与优化器反向传播loss、计算metric的loss的衔接。部分与数据相关示例如下所示:
...
RECORD_ID = "id"
RECORD_EMB = "emb"
SRC_IDS = "src_ids"
MASK_IDS = "mask_ids"
SEQ_LENS = "seq_lens"
SENTENCE_IDS = "sent_ids"
POS_IDS = "pos_ids"
TASK_IDS = "task_ids"
...
模型核心操作接口(models)详细说明
- 文心采用模型(models)的方式定义神经网络的基本操作,包括前向传播网络(foreward)、优化策略(optimizer)、评估指标(metrics)等部分,均可实现自定义。
预置网络介绍
目录结构
文心所有预置网络位于../../wenxin/models/目录下,与文本分类相关的预置网络如下所示:
.
├── __init__.py
├── model.py
├── bow_classification.py
├── cnn_classification.py
├── cnn_classification_fleet.py
├── gru_classification.py
├── dpcnn_classification.py
├── bilstm_classification.py
├── lstm_classification.py
├── textcnn_classification.py
├── ernie_bilstm_classification.py
├── ernie_bow_classification.py
├── ernie_classification.py
├── ernie_cnn_classification.py
├── ernie_dpcnn_classification.py
├── ernie_gru_classification.py
├── ernie_lstm_classification.py
├── ernie_one_sent_classification_en.py
├── ernie_one_sent_classification.py
├── ernie_textcnn_classification.py
├── ernie_two_sent_classification_en.py
└── ernie_two_sent_classification.py
**基类model
- 基类model主要由前向计算组网forward()、优化器optimizer()、预测结果解析器parse_predict_result()和指标评估get_metrics()四个主要部分构成,其功能和参数如下所示。
...
def forward(self, fields_dict, phase):
"""
必须选项,否则会抛出异常。
核心内容是模型的前向计算组网部分,包括loss值的计算,必须由子类实现。输出即为对输入数据执行变换计算后的结果。
:param: fields_dict
{"field_name":
{"RECORD_ID":
{"InstanceName.SRC_IDS": [ids],
"InstanceName.MASK_IDS": [ids],
"InstanceName.SEQ_LENS": [ids]
}
}
}
序列化好的id,供网络计算使用。
:param: phase: 当前调用的阶段,包含训练、评估和预测,不同的阶段组网可以不一样。
训练:InstanceName.TRAINING
测试集评估:InstanceName.TEST
验证集评估:InstanceName.EVALUATE
预测:InstanceName.SAVE_INFERENCE
:return: 训练:forward_return_dict
{
"InstanceName.PREDICT_RESULT": [predictions],
"InstanceName.LABEL": [label],
"InstanceName.LOSS": [avg_cost]
"自定义变量名": [用户需获取的其余变量]
}
预测:forward_return_dict
{
# 保存预测模型时需要的入参:模型预测时所需的输入变量
"InstanceName.TARGET_FEED_NAMES": [ids, id_lens],
# 保存预测模型时需要的入参:模型预测时输出的结果
"InstanceName.TARGET_PREDICTS": [predictions]
}
实例化的dict,存放TARGET_FEED_NAMES, TARGET_PREDICTS, PREDICT_RESULT,LABEL,LOSS等希望从前向网络中获取的数据。
"""
raise NotImplementedError
def optimizer(self, loss, is_fleet=False):
"""
必须选项,否则会抛出异常。
设置优化器,如Adam,Adagrad,SGD等。
:param loss:前向计算得到的损失值。
:param is_fleet:是否为多机。
:return:OrderedDict: 该dict中存放的是需要在运行过程中fetch出来的tensor,大多数情况下为空,可以按需求添加内容。
"""
raise NotImplementedError
def parse_predict_result(self, predict_result):
"""按需解析模型预测出来的结果
:param predict_result: 模型预测出来的结果
:return:None
"""
raise NotImplementedError
def get_metrics(self, fetch_output_dict, meta_info, phase):
"""指标评估部分的动态计算和打印
:param fetch_output_dict: executor.run过程中fetch出来的forward中定义的tensor
:param meta_info:常用的meta信息,如step, used_time, gpu_id等
:param phase: 当前调用的阶段,包含训练和评估
:return:metrics_return_dict:该dict中存放的是各个指标的结果,以文本分类为例,该dict内容如下所示:
{
"acc": acc,
"precision": precision
}
"""
raise NotImplementedError
...
其他各子类介绍
- 各预置网络基本介绍如下所示:
预置网络配置
- 通过json文件中的model部分对预置网络进行配置,以文本分类任务cls_cnn_ch.json为例,其model部分如下所示:
{
...
"model": {
"type": "CnnClassification", ## wenxin采用模型(models)的方式定义神经网络的基本操作,本例采用预置的模型CnnClassification实现文本分类,具体网络可参考models目录。
"optimization": { ## 预置模型的优化器所需的参数配置,如学习率等。
"learning_rate": 2e-05
}
},
...
}
自定义网络配置
- 自定义网络配置根据具体项目情况通过对model基类重写来实现。在分类任务中,我们提供了自定义cnn网络实现模型训练的入口脚本run_cnn.py供参考
- 变量设置规则在common.rule.InstanceName中,该部分囊括了model和data部分的全局变量,实现了数据部分与组网部分的衔接,前向传播loss与优化器反向传播loss、计算metric的loss的衔接。部分与网络相关示例如下所示:
...
TARGET_FEED_NAMES = "target_feed_name" # 保存模型时需要的入参:表示模型预测时需要输入的变量名称和顺序
TARGET_PREDICTS = "target_predicts" # 保存模型时需要的入参:表示预测时最终输出的结果
PREDICT_RESULT = "predict_result" # 训练过程中需要传递的预测结果
LABEL = "label" # label
LOSS = "loss" # loss
TRAINING = "training" # 训练过程
EVALUATE = "evaluate" # 评估过程
TEST = "test" # 测试过程
SAVE_INFERENCE = "save_inference" # 保存inference model的过程
...
7. 进阶使用二:多标签文本分类
任务简介
- 多标签分类(Multilabel Classification): 给每个样本一系列的目标标签. 可以想象成一个数据点的各属性不是相互排斥的(一个水果既是苹果又是梨就是相互排斥的), 比如一个文档相关的话题. 一个文本可能被同时认为是宗教、政治、金融或者教育相关话题.
- 在这里我们提供一份可运行的多标签文本分类demo样例。
- 本样例基于ernie_1.0_base_ch实现。
代码结构说明
- 以下是本项目主要代码结构及说明:
.
├── __init__.py
├── env.sh ## 环境变量配置脚本
├── run_with_json.py ## 只依靠json进行模型训练的入口脚本
├── run_infer.py ## 只依靠json进行模型预测的入口脚本
├── examples ## 网络的json配置文件
│ ├── cls_ernie_1.0_base_multi_label_ch.json
│ └── cls_ernie_1.0_base_multi_label_ch_infer.json
└── data ## 示例数据文件夹,包括各任务所需训练集(train_data)、测试集(test_data)和预测集(predict_data)
├── predict_data_multi_label
│ └── predict.txt
├── test_data_multi_label
│ └── test.txt
└── train_data_multi_label
└── train.txt
数据准备
- 这里我们提供一份已标注的示例数据集,标签数量为4。
- 训练集、测试集和预测集分别存放在./data目录下的train_data、test_data和predict_data文件夹下。
- 因为本分类网络使用ernie_1.0_base_ch实现,固采用其默认的词表,用户无需自备词表。
训练集/测试集
- 训练集和测试集的数据格式相同,如下所示。数据分为两列,列与列之间用\t进行分隔。第一列为文本,第二列为标签。
- 注:当该样本拥有多个标签时,标签之间使用空格进行分隔。
- 比如你的标签有100种,某个样例的标签是第50个标签和第87个标签,其标签列就是“49 86”。像这个情况就是标签的第49和86维是正例1,其他维是负例0。
互联网创业就如选秀 需求与服务就是价值 0 1
郭德纲式生存:时代的变与未变 2
快讯!腾讯市值突破10000亿港元 3
预测集
- 预测集无需进行标签预占位,其格式如下所示:
互联网创业就如选秀 需求与服务就是价值
郭德纲式生存:时代的变与未变
快讯!腾讯市值突破10000亿港元
训练第一个模型
开始训练
- 使用预置网络进行训练的方式为使用./run_with_json.py入口脚本,通过--param_path参数来传入./examples/目录下的json配置文件。
-
以预置的多标签文本分类模型为例,训练分为以下几个步骤:
- 请使用以下命令在../model_files/中通过对应脚本下载ernie_1.0_base_ch模型参数文件,其对应配置文件ernie_1.0_base_ch_config.json和词表vocab_ernie_1.0_base_ch.txt分别位于../model_files/目录下的config/和dict/文件夹,用户无需更改;
# ernie_1.0_base_ch 模型下载 # 进入model_files目录 cd ../model_files/ # 运行下载脚本 sh download_ernie_1.0_base_ch.sh
- 请在./env.sh中根据提示配置相应环境变量的路径
- 基于示例的数据集,可以运行以下命令在训练集(train.txt)上进行模型训练,并在测试集(test.txt)上进行验证;
# 多标签分类模型 # 需要提前参照env.sh进行环境变量配置,在当前shell内去读取 source env.sh # 基于json实现预置网络训练。其调用了配置文件./examples/cls_ernie_1.0_base_multi_label_ch.json python run_with_json.py --param_path ./examples/cls_ernie_1.0_base_multi_label_ch.json
- 训练运行的日志会自动保存在./log/test.log文件中;
- 训练中以及结束后产生的模型文件会默认保存在./output/cls_ernie_1.0_base/目录下,其中save_inference_model/文件夹会保存用于预测的模型文件,save_checkpoint/文件夹会保存用于热启动的模型文件。
配置说明
- 使用预置网络训练时,可以通过修改所加载的json文件来进行参数的自定义配置。
- json配置文件主要分为三个部分:dataset_reader、model和trainer。
- 以./examples/cls_ernie_1.0_base_multi_label_ch.json为例,上述三个部分的配置与说明如下所示。
dataset_reader部分
- dataset_reader用于配置模型训练时的数据读取。
- 以下为./examples/cls_ernie_1.0_base_multi_label_ch.json中抽取出来的dataset_reader部分配置,并通过注释说明。
{
"dataset_reader": {
"train_reader": { ## 训练、验证、测试各自基于不同的数据集,数据格式也可能不一样,可以在json中配置不同的reader,此处为训练集的reader。
"name": "train_reader",
"type": "BasicDataSetReader", ## 采用BasicDataSetReader,其封装了常见的读取tsv文件、组batch等操作。
"fields": [ ## 域(field)是wenxin的高阶封装,对于同一个样本存在不同域的时候,不同域有单独的数据类型(文本、数值、整型、浮点型)、单独的词表(vocabulary)等,可以根据不同域进行语义表示,如文本转id等操作,field_reader是实现这些操作的类。
{
"name": "text_a", ## 多标签文本分类只有一个文本特征域,命名为"text_a"。
"data_type": "string", ## data_type定义域的数据类型,文本域的类型为string,整型数值为int,浮点型数值为float。
"reader": {"type":"ErnieTextFieldReader"}, ## 采用针对ernie文本域的专用reader "ErnieTextFieldReader"。数值数组类型域为"ScalarArrayFieldReader",数值标量类型域为"ScalarFieldReader"。
"tokenizer":{
"type":"FullTokenizer", ## 指定该文本域的tokenizer为FullTokenizer。
"split_char":" ", ## 通过空格区分不同的token。
"unk_token":"[UNK]", ## unk标记为"[UNK]"。
},
"need_convert": true, ## "need_convert"为true说明数据格式是明文字符串,需要通过词表转换为id。
"vocab_path": "../model_files/dict/vocab_ernie_1.0_base_ch.txt", ## 指定该文本域的词表为ernie_1.0_base_ch的默认词表。
"max_seq_len": 512, ## 设定每个域的最大长度。
"truncation_type": 0, ## 选择截断策略,0为从头开始到最大长度截断,1为从头开始到max_len-1的位置截断,末尾补上最后一个id(词或字),2为保留头和尾两个位置,然后按从头开始到最大长度方式截断。
"padding_id": 0, ## 设定padding时对应的id值。
"embedding": { ## 采用ernie预训练模型作为embedding
"type": "ErnieTokenEmbedding",
"use_reader_emb": false,
"emb_dim": 768,
"config_path": "../model_files/config/ernie_1.0_base_ch_config.json"
}
}, ## 如果每一个样本有多个特征域(文本类型、数值类型均可),可以仿照前面对每个域进行设置,依次增加每个域的配置即可。此时样本的域之间是以\t分隔的。
{
"name": "label", ## 标签也是一个单独的域,命名为"label"。如果多个不同任务体系的标签存在于多个域中,则可实现最基本的多任务学习。
"data_type": "int", ## 标签是整型数值。
"reader":{
"type":"MultiLabelFieldReader" ## 多标签分类任务中标签域的专用reader为"MultiLabelFieldReader"。
},
"tokenizer":null,
"need_convert": false,
"vocab_path": "",
"max_seq_len": 4, ## 标签域的最大长度
"num_labels": 4, ## 指定标签域中有多少种标签
"truncation_type": 0,
"padding_id": 0,
"embedding": null
}
],
"config": {
"data_path": "./data/train_data/", ## 训练数据train_reader的数据路径,写到文件夹目录。
"shuffle": false,
"batch_size": 8,
"epoch": 1,
"sampling_rate": 1.0
}
},
"test_reader": { ## 若要评估测试集,需配置test_reader,其配置方式与train_reader类似。
……
}
},
……
}
model部分
- model用于配置模型训练时的预置网络,包括预置网络的类别及其优化器的参数等。
- 以下为./examples/ernie_1.0_base_multi_label_ch.json中抽取出来的model部分配置,并通过注释说明
{
...
"model": {
"type": "ErnieMultiLabelClassification", ## wenxin采用模型(models)的方式定义神经网络的基本操作,本例采用预置的模型ErnieMultiLabelClassification实现多标签文本分类,具体网络可参考models目录。
"optimization": { ## 预置模型的优化器所需的参数配置,如学习率以及ernie预训练模型的参数等。
"learning_rate": 5e-05,
"lr_scheduler": "linear_warmup_decay",
"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
},
"embedding": {
"type": "ErnieTokenEmbedding",
"emb_dim": 768,
"use_fp16": false,
"config_path": "../model_files/config/ernie_1.0_base_ch_config.json",
"other": ""
},
"num_labels": 4 ## 标签的数量
},
...
}
trainer部分
- trainer用于配置模型训练的启动器,包括保存模型时的间隔步数、进行测试集或验证集评估的间隔步数等。
- 以下为./examples/ernie_1.0_base_multi_label_ch.json中抽取出来的trainer部分配置,并通过注释说明。
{
...
"trainer": {
"PADDLE_USE_GPU": 0, ## 是否使用GPU进行训练,1为使用GPU。
"PADDLE_IS_LOCAL": 1, ## 是否单机训练,默认值为0,若要单机训练需要设置为1。
"train_log_step": 20, ## 训练时打印训练日志的间隔步数。
"is_eval_dev": 0, ## 是否在训练的时候评估开发集,如果取值为1一定需要配置dev_reader及其数据路径。
"is_eval_test": 1, ## 是否在训练的时候评估测试集,如果取值为1一定需要配置test_reader及其数据路径。
"eval_step": 100, ## 进行测试集或验证集评估的间隔步数。
"save_model_step": 10000, ## 保存模型时的间隔步数,建议设置为eval_step的整数倍。
"load_parameters": 0, ## 加载包含各op参数值的训练好的模型,用于预测。
"load_checkpoint": 0, ## 加载包含学习率等所有参数的训练模型,用于热启动。
"use_fp16": 0, ## 是否使用fp16精度。
"pre_train_model": [ ## 加载预训练模型,例如ernie。使用时需要填写预训练模型的名称name和预训练模型的目录params_path。
{
"name": "ernie_1.0_base_ch",
"params_path": "../model_files/ernie_1.0_base_ch_dir/params"
}
],
"output_path": "./output/cls_ernie_1.0_base" ## 保存模型的输出路径,如置空或者不配置则默认输出路径为"./output"。
}
}
模型预测
开始预测
- 使用预置网络进行预测的方式为使用./run_infer.py入口脚本,通过--param_path参数来传入./examples/目录下的json配置文件。
-
以基于预置CNN网络所训练出的模型为例,其预测分为以下几个步骤:
- 基于./examples/ernie_1.0_base_multi_label_ch.json训练出的模型默认储存在./output/cls_ernie_1.0_base/save_inference_model/中,在该目录下找到被保存的inference_model文件夹,例如inference_step_4_enc/;
- 在./examples/cls_ernie_1.0_base_multi_label_ch_infer.json中修改"inference_model_path"参数,填入上述模型保存路径,如下所示:
{
...
"inference":{
...
"inference_model_path":"./output/cls_ernie_1.0_base/save_inference_model/inference_step_4_enc"
}
}
- 基于示例的数据集,可以运行以下命令在预测集(infer.txt)上进行预测:
# 基于json实现预测。其调用了配置文件./examples/ernie_1.0_base_multi_label_ch_infer.json
python run_infer.py --param_path ./examples/cls_ernie_1.0_base_multi_label_ch_infer.json
- 预测运行的日志会自动保存在./output/predict_result.txt文件中。
配置说明
- 基于json实现预测时,可以通过修改所加载的json文件来进行参数的自定义配置。
- json配置文件主要分为三个部分:dataset_reader、model和inference。
- 以./examples/cls_ernie_1.0_base_infer.json为例,上述三个部分的配置与说明如下所示。
{
"dataset_reader": {
"predict_reader": { ## 预测部分需要单独配置reader。
"name": "predict_reader",
"type": "BasicDataSetReader",
"fields": [ ## 本样例中只有一个文本域需要配置,配置方式与训练过程类似,注意无需配label。
{
"name": "text_a",
"data_type": "string",
"reader": {"type":"ErnieTextFieldReader"},
"tokenizer":{
……
},
……
}
],
"config": {
"data_path": "./data/predict_data/", ## 需要配置预测数据路径。
……
}
}
},
"model": {
"type": "ErnieMultiLabelClassification", ## 如果使用checkpoint需要说明其模型网络。
...
"num_labels": 4
},
"inference":{ ## 需配置预测时所需的参数。
"output_path": "./output/predict_result.txt", ## 预测结果文件的输出路径。
"PADDLE_USE_GPU": 0, ## 是否采用GPU预测。
"PADDLE_IS_LOCAL": 1, ## 是否单机预测,默认值为0,若要单机预测需要设置为1。
"inference_model_path":"./output/cls_ernie_1.0_base/save_inference_model/inference_step_4_enc" ## 训练好的模型路径。
}
}