资讯 文档
技术能力
语音技术
文字识别
人脸与人体
图像技术
语言与知识
视频技术

文本分类任务

任务简介

  • 文本分类是经典的NLP问题之一,简单来说,它是一种将文本对象(文档或句子)分类到一个固定类别的技术。
  • 当应用场景中的数据量非常大时,文本分类对数据的组织、信息过滤,以及数据存储等方面起到非常大的作用。
  • 常用的场景包括:垃圾邮件识别,文本审核、新闻主题分类,情感分析,以及搜索引擎的页面组织

快速开始

1. 代码结构说明

以下是本项目主要代码结构及说明:

代码目录: textone-premium/tasks/text_classification

.
├── __init__.py                                                                                 
├── env.sh                                                 ## 环境变量配置脚本
├── run_with_json.py                                       ## 只依靠json进行模型训练的入口脚本
├── run_infer.py                                           ## 只依靠json进行模型预测的入口脚本
├── run_lanch.sh                                           ## 利用多进程实现分布式运行的训练入口脚本
├── run_lanch_infer.sh                                     ## 利用多进程实现分布式运行的预测入口脚本
├── lanch.py                                               ## 多进程分布式运行的配置文件
├── finetune_args.py                                       ## 多进程分布式运行的配置参数文件
├── run_without_register.py                                ## 不使用注册机制实现训练的入口脚本
├── demo_classify_data_set_reader.py                       ## 示例文本分类自定义reader文件
├── 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任务的词表文件夹
     ├── 30k-clean.model
     ├── 30k-clean.vocab.albert
     └── vocab.txt

2. 数据准备

非ERNIE数据
  • 这里我们提供一份已标注的、经过分词预处理的示例数据集。
  • 训练集、测试集、验证集和预测集分别存放在./data目录下的train_data、test_data、dev_data和predict_data文件夹下,对应的示例词表存放在./dict目录下。
  • 注:数据集(包含词表)均为utf-8格式。
  1. 训练集/测试集/验证集

    • 训练集、测试集和验证集的数据格式相同,如下所示。数据分为两列,列与列之间用\t进行分隔。第一列为文本,第二列为标签。
    房间 太 小 。 其他 的 都 一般 。 。 。 。 。 。 。 。 。         0
    LED屏 就是 爽 , 基本 硬件 配置 都 很 均衡 , 镜面 考 漆 不错 , 小黑 , 我喜欢 。         1
    差 得 要命 , 很大 股霉味 , 勉强 住 了 一晚 , 第二天 大早 赶紧 溜。         0
  2. 预测集

    • 预测集无需进行标签预占位,其格式如下所示:
    USB接口 只有 2个 , 太 少 了 点 , 不能 接 太多 外 接 设备 ! 表面 容易 留下 污垢 !
    平时 只 用来 工作 , 上 上网 , 挺不错 的 , 没有 冗余 的 功能 , 样子 也 比较 正式 !
    还 可以 吧 , 价格 实惠   宾馆 反馈   2008417日   :   谢谢 ! 欢迎 再次 入住 其士 大酒店 。
  3. 词表

    • 词表分为两列,第一列为词,第二列为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网络的文本分类模型为例,训练分为以下几个步骤:

    1. 请在./env.sh中根据提示配置相应环境变量的路径
    2. 基于示例的数据集,可以运行以下命令在训练集(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
    1. 训练运行的日志会自动保存在./log/test.log文件中;
    2. 训练中以及结束后产生的模型文件会默认保存在./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网络所训练出的模型为例,其预测分为以下几个步骤:

    1. 基于./examples/cls_cnn_ch.json训练出的模型默认储存在./output/cls_cnn_ch/save_inference_model/中,在该目录下找到被保存的inference_model文件夹,例如inference_step_251/;
    2. 在./examples/cls_cnn_ch_infer.json中修改"inference_model_path"参数,填入上述模型保存路径,如下所示:
    {
      ...
      "inference":{   
         ...
        "inference_model_path":"./output/cls_cnn_ch/save_inference_model/inference_step_251" 
      }
    }
    1. 基于示例的数据集,可以运行以下命令在预测集(infer.txt)上进行预测:
    # 基于json实现预测。其调用了配置文件./examples/cls_cnn_ch_infer.json
    python run_infer.py --param_path ./examples/cls_cnn_ch_infer.json
    1. 预测运行的日志会自动保存在./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文本分类模型为例,训练分为以下几个步骤:

    1. 请使用以下命令在../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
    1. 请准备数据集并放入对应目录中,ERNIE训练所需数据集不需要分词且无需准备词表,其格式与非ERNIE的数据集相同;
    2. 运行以下命令在训练集(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
    1. 训练运行的日志会自动保存在./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
 
...

其他各子类介绍

  • 各预置网络基本介绍如下所示:

image.png

预置网络配置

  • 通过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_2.0_base_ch实现。
代码结构说明
  • 以下是本项目主要代码结构及说明:
.
├── __init__.py
├── env.sh                                                 ## 环境变量配置脚本
├── run_with_json.py                                       ## 只依靠json进行模型训练的入口脚本
├── run_infer.py                                           ## 只依靠json进行模型预测的入口脚本
├── examples                                               ## 网络的json配置文件
│   ├── cls_ernie_2.0_base_multi_label_ch.json
│   └── cls_ernie_2.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_2.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配置文件。
  • 以预置的多标签文本分类模型为例,训练分为以下几个步骤:

    1. 请使用以下命令在../model_files/中通过对应脚本下载ernie_2.0_base_ch模型参数文件,其对应配置文件ernie_2.0_base_ch_config.json和词表vocab_ernie_2.0_base_ch.txt分别位于../model_files/目录下的config/和dict/文件夹,用户无需更改;
    # ernie_2.0_base_ch 模型下载
    # 进入model_files目录
    cd ../model_files/
    # 运行下载脚本
    sh download_ernie_2.0_base_ch.sh
    1. 请在./env.sh中根据提示配置相应环境变量的路径
    2. 基于示例的数据集,可以运行以下命令在训练集(train.txt)上进行模型训练,并在测试集(test.txt)上进行验证;
    # 多标签分类模型
    # 需要提前参照env.sh进行环境变量配置,在当前shell内去读取
    source env.sh
    # 基于json实现预置网络训练。其调用了配置文件./examples/cls_ernie_2.0_base_multi_label_ch.json
    python run_with_json.py --param_path ./examples/cls_ernie_2.0_base_multi_label_ch.json
    1. 训练运行的日志会自动保存在./log/test.log文件中;
    2. 训练中以及结束后产生的模型文件会默认保存在./output/cls_ernie_2.0_base/目录下,其中save_inference_model/文件夹会保存用于预测的模型文件,save_checkpoint/文件夹会保存用于热启动的模型文件。
配置说明
  • 使用预置网络训练时,可以通过修改所加载的json文件来进行参数的自定义配置。
  • json配置文件主要分为三个部分:dataset_reader、model和trainer。
  • 以./examples/cls_ernie_2.0_base_multi_label_ch.json为例,上述三个部分的配置与说明如下所示。
dataset_reader部分
  • dataset_reader用于配置模型训练时的数据读取。
  • 以下为./examples/cls_ernie_2.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_2.0_base_ch.txt",             ## 指定该文本域的词表为ernie_2.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_2.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_2.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_2.0_base_ch_config.json",
      "other": ""
    },
    "num_labels": 4                                     ## 标签的数量     
  },
 ...
}
trainer部分
  • trainer用于配置模型训练的启动器,包括保存模型时的间隔步数、进行测试集或验证集评估的间隔步数等。
  • 以下为./examples/ernie_2.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_2.0_base_ch",
        "params_path": "../model_files/ernie_2.0_base_ch_dir/params"
      }
    ],
    "output_path": "./output/cls_ernie_2.0_base"       ## 保存模型的输出路径,如置空或者不配置则默认输出路径为"./output"。
  }
}
预测我的第一个模型
开始预测
  • 使用预置网络进行预测的方式为使用./run_infer.py入口脚本,通过--param_path参数来传入./examples/目录下的json配置文件。
  • 以基于预置CNN网络所训练出的模型为例,其预测分为以下几个步骤:

    1. 基于./examples/ernie_2.0_base_multi_label_ch.json训练出的模型默认储存在./output/cls_ernie_2.0_base/save_inference_model/中,在该目录下找到被保存的inference_model文件夹,例如inference_step_4_enc/;
    2. 在./examples/cls_ernie_2.0_base_multi_label_ch_infer.json中修改"inference_model_path"参数,填入上述模型保存路径,如下所示:
{
  ...
  "inference":{   
     ...
    "inference_model_path":"./output/cls_ernie_2.0_base/save_inference_model/inference_step_4_enc" 
  }
}
  1. 基于示例的数据集,可以运行以下命令在预测集(infer.txt)上进行预测:
# 基于json实现预测。其调用了配置文件./examples/ernie_2.0_base_multi_label_ch_infer.json
python run_infer.py --param_path ./examples/cls_ernie_2.0_base_multi_label_ch_infer.json
  1. 预测运行的日志会自动保存在./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":"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_2.0_base/save_inference_model/inference_step_4_enc"     ## 训练好的模型路径。
  }
}

8. 进阶使用三

通过ERNIE-Word进行文本分类
配置及词表
  • ERNIE-Word在不同的NLP任务中均可以作为预训练词向量使用,有助于开发者提升模型效果,特别是浅层模型或训练数据量较少的情况下,建议使用预训练ERNIE-Word词向量。
词表 词表(tasks/model_files/dict) 下载脚本
ernie_word ernie_word_vocab.txt download_ernie_word_ch.sh
通过训练基于ERNIE-Word的文本分类模型
  • wenxin提供了将ERNIE-Word作为预训练词向量,结合CNN进行文本分类的demo:
python run_with_json.py --param_path ./examples/cls_cnn_ernie_word_ch.json
修改组网代码以使用ERNIE-Word进行文本分类
  • 用户可参考以上CNN的demo自行导入ERNIE-Word预训练词向量进行其他NLP任务的训练。
  • 可参考./wenxin/models/cnn_ernie_word_classification.py修改模型组网文件。
  • 需要保证使词向量的参数命名、维度大小和词表大小和ERNIE-Word一致,具体地:

    • 词向量参数名:“emb”,可以使用 fluid.ParamAttr 在 fluid.layers.embedding 处定义。
    • 词向量维度:300维
    • 词表大小:300000
...
 
        dict_dim = self.model_params.get('vocab_size', 300000)
        emb_dim = self.model_params.get('emb_dim', 300)
...
        unpad_data = fluid.layers.sequence_unpad(text_a, length=text_a_lens)
        emb = fluid.layers.embedding(input=unpad_data, size=[dict_dim, emb_dim],
                param_attr=fluid.param_attr.ParamAttr(name="emb"), is_sparse=True)
...

9. 进阶使用四

层次化分类

任务简介
  • 层次化文本分类是指:输入一条文本,输出它的多标签分类结果,且标签之间有父子级层次关系。
  • 例如:考拉是澳大利亚奇特的珍贵原始树栖动物。其标签是:动物界---脊索动物门---脊椎动物亚门---哺乳纲---后兽亚纲---有袋目---树袋熊科---树袋熊属---树袋熊
  • 标签层级关系需要提前以文件的形式存储。
代码结构说明

以下是本项目主要代码结构及说明:

代码目录: textone-premium/tasks/text_classification

.
├── __init__.py
├── run_with_json.py                                       ## 只依靠json进行模型训练的入口脚本                       
├── run_infer.py                                           ## 只依靠json进行模型预测的入口脚本
├── examples                                               ## 各典型网络的json配置文件
│   ├── cls_ernie_2.0_base_hierar_label_ch.json
│   ├── cls_ernie_2.0_base_hierar_label_ch_infer.json
│   ├── cls_textcnn_hierar_label_ch.json
│   └── cls_textcnn_hierar_label_ch_infer.json
├── dict
│   ├── hierar_label.taxonomy
│   ├── hierar_label_map.txt
│   └── hierar_task_vocab.txt
└── data                                                   ## 示例数据文件夹,包括任务所需训练集、测试集、验证集和预测集
    ├── train_data_hierar_label_ch
    │   ├── raw
    │   │   └── train.txt
    │   └── seg
    │        └── train_seg.txt
    ├── test_data_hierar_label_ch
    │   ├── raw
    │   │   └── test.txt
    │   └── seg
    │        └── test_seg.txt
    ├── dev_data_hierar_label_ch
    │   ├── raw
    │   │   └── dev.txt
    │   └── seg
    │        └── dev_seg.txt
    └── predict_data_hierar_label_ch
         ├── raw
         │   └── predict.txt
         └── seg
              └── predict_seg.txt
数据准备
  • 这里我们提供一份已标注的示例数据集,标签数量为4。
  • 这里我们提供两份已标注的示例数据集。基于ERNIE的预置网络模型,数据集不需要分词且无需准备词表;基于TextCNN的预置网络模型,数据集需要分词且需要准备词表。
  • 训练集、测试集、验证集和预测集分别存放在./data目录下的train_data_hierar_label_ch/、test_data_hierar_label_ch/、dev_data_hierar_label_ch/和predict_data_hierar_label_ch/文件夹下。用于基于ERNIE和TextCNN的预置网络模型的数据集分别存放在上述目录的raw/、seg/文件夹下。
  • 词表存放在./dict目录下的hierar_task_vocab.txt。
  • 我们也提供了标签映射词典和标签层级关系,分别存放在./dict目录下的hierar_label_map.txt和hierar_label.taxonomy中。
  • 注:数据集(包含词表)均为utf-8格式。
训练集/测试集/验证集
  • 训练集、测试集和验证集的数据格式相同,如下所示。每个样本占一行,数据分为两列,列与列之间用\t进行分隔。第一列为文本,第二列为标签(1个或多个标签),不同标签之间用空格分隔。与多标签分分类的表示格式一致。
88日,意大利政府表示,9月回购利率为Li万亿欧元的最低回购利率         21 8 2
UMB银行表示,百万加德纳-坎普通债务债券系列净利息成本为%         22 14 4
季度最新先前金额支付10月记录9月芝加哥新闻台         6 3 0
预测集
  • 预测集无需进行标签预占位,其格式如下所示
英格兰队在上半场击败摩尔多瓦欧洲足球锦标赛小组预选赛星期六得分手布鲁斯·戴尔第分钟达伦·埃迪出场
卡尔博瓦涅茨每美元不变乌克兰银行间货币交易所88月美元汇率交易量百万基辅编辑室
去年第二季度政府预算中,政府预算覆盖了去年第二季度的10亿美元
标签映射词典
  • 标签映射词典的格式如下所示。每个标签占一行,数据分为两列,列于列之间用\t进行分隔。第一列为标签文本,第二列为标签id。
CCAT	0
MCAT	1
C15	2
...
标签层级关系
  • 这是层次化文本分类与多标签分类最重要的不同。层级关系用于表示标签之间的父级与子级的多对多关系或一对多关系,其格式如下所示:
Root	CCAT	MCAT
CCAT	C15	C18
C15	C151	C152
C18	C181
MCAT	M13	M14
M13	M131	M132
M14	M141
  • 标签层级关系按图的广度优先遍历进行读取,二级标签作为一级标签的孩子结点,一级标签作为临时节点(Root)的孩子结点。
  • 上述层级关系可理解为如下树状结构:
		     Root                                      ## 临时节点Root
                /            \
  	      /                \
	   CCAT	                MCAT                           ## 一级标签
       /        \           /         \
     C15    	 C18       M13         M14                     ## 二级标签
   /   \        /        /    \       /
C151   C152   C181     M131   M132   M141                      ## 三级标签
训练第一个模型
开始训练

基于Ernie的预置网络

  • 使用基于Ernie的预置网络进行训练的方式为使用./run_with_json.py入口脚本,通过--param_path参数来传入./examples/目录下的json配置文件。
  • 训练分为以下几个步骤:

    1. 请使用以下命令在../model_files/中通过对应脚本download_ernie_2.0_base_ch.sh下载模型参数文件,其对应配置文件ernie_2.0_base_ch_config.json和词表vocab_ernie_2.0_base_ch.txt分别位于../model_files/目录下的config/和dict/文件夹,用户无需更改;
    # download_ernie_2.0_base_ch.sh 模型下载
    # 进入model_files目录
    cd ../model_files/
    # 运行下载脚本
    sh download_ernie_2.0_base_ch.sh

    2.请在./env.sh中根据提示配置相应环境变量的路径

    3.基于示例的数据集,可以运行以下命令在训练集(train.txt)上进行模型训练,并在测试集(test.txt)上进行验证;

    # 基于ernie的层次化分类-训练
    # 需要提前参照env.sh进行环境变量配置,在当前shell内去读取
    source env.sh
    # 基于json实现预置网络训练。其调用了配置文件./examples/cls_ernie_2.0_base_hierar_label_ch.json
    python run_with_json.py --param_path ./examples/cls_ernie_2.0_base_hierar_label_ch.json
    1. 训练运行的日志会自动保存在./log/test.log文件中;
    2. 训练中以及结束后产生的模型文件会默认保存在./output/目录下,其中save_inference_model/文件夹会保存用于预测的模型文件,save_checkpoint/文件夹会保存用于热启动的模型文件。

基于TextCNN的预置网络

  • 使用基于TextCNN的预置网络进行训练的方式为使用./run_with_json.py入口脚本,通过--param_path参数来传入./examples/目录下的json配置文件。
  • 训练分为以下几个步骤:

    1. 请在./env.sh中根据提示配置相应环境变量的路径,如需了解更多详情,请参考-安装及环境配置详细说明;
    2. 基于示例的数据集,可以运行以下命令在训练集(train_seg.txt)上进行模型训练,并在测试集(test_seg.txt)上进行验证;
    # 基于TextCNN的层次化分类-训练
    # 需要提前参照env.sh进行环境变量配置,在当前shell内去读取
    source env.sh
    # 基于json实现预置网络训练。其调用了配置文件./examples/cls_textcnn_hierar_label_ch.json
    python run_with_json.py --param_path ./examples/cls_textcnn_hierar_label_ch.json
    1. 训练运行的日志会自动保存在./log/test.log文件中;
    2. 训练中以及结束后产生的模型文件会默认保存在./output/目录下,其中save_inference_model/文件夹会保存用于预测的模型文件,save_checkpoint/文件夹会保存用于热启动的模型文件。
模型预测
开始预测
  • 基于Ernie的预置网络

    • 使用基于Ernie的预置网络进行预测的方式为使用./run_infer.py入口脚本,通过--param_path参数来传入./examples/目录下的json配置文件。
    • 预测分为以下几个步骤:

      1. 基于示例的数据集,可以运行以下命令在预测集(predict.txt)上进行预测:
          # 基于Ernie的层次化分类-预测
      # 基于json实现预测。其调用了配置文件./examples/cls_ernie_2.0_base_hierar_label_ch_infer.json
      python run_infer.py --param_path ./examples/cls_ernie_2.0_base_hierar_label_ch_infer.json
      1. 预测运行的日志会自动保存在./output/predict_result_ernie_2.0_base_hierar_label.txt文件中。
      • 层次化分类的预测结果以概率进行输出,即每条样本的预测结果为num_labels个概率值。
      • 将num_labels个概率值依据是否>0.5判断为1和0, 对应为1的label是预测命中的,对应为0的label是预测未命中的。
  • 基于TextCNN的预置网络

    • 使用基于TextCNN的预置网络进行预测的方式为使用./run_infer.py入口脚本,通过--param_path参数来传入./examples/目录下的json配置文件。
    • 预测分为以下几个步骤:

      1. 基于示例的数据集,可以运行以下命令在预测集(predict_seg.txt)上进行预测:
      # 基于TextCNN的层次化分类-预测
      # 基于json实现预测。其调用了配置文件./examples/cls_textcnn_hierar_label_ch_infer.json
      python run_infer.py --param_path ./examples/cls_textcnn_hierar_label_ch_infer.json
      1. 预测运行的日志会自动保存在./output/predict_result_textcnn_hierar_label.txt文件中。
      • 层次化分类的预测结果以概率进行输出,即每条样本的预测结果为num_labels个概率值。
      • 将num_labels个概率值依据是否>0.5判断为1和0, 对应为1的label是预测命中的,对应为0的label是预测未命中的。

10. 进阶使用五

小样本分类

任务简介
  • 小样本文本分类是指训练集中样本数较少情况下的文本分类任务。特别是当类别数较多(大于50),样本数较小(每个类别有5个样本左右)的时候,能够显著提升其相对直接使用ERNIE分类网络finetune的效果。
  • 本案例实现的技术是将分类任务变为pairwise匹配任务,样本数可相应增多,有助于小样本学习。因此需要将分类训练集处理得到匹配训练集,训练匹配双塔网络,loss可由cosine或l2距离等计算方式得到,提供的示例model文件采取余弦相似度的距离计算方式。
  • 测试时有两种计算方式:
  1. 将待测试数据与训练集各样本计算相似度,取相似度最高的训练数据类别标签作为测试数据的类别标签。 a. 就相当于KNN算法中K为1的情况。 b. 当样本数较小时建议采用这个方案。
  2. 将训练集同类别数据计算类平均表示作为该类的表示,将待测试数据与训练集各类别的类平均表示计算相似度,取相似度最高的训练数据类别作为测试数据的类别标签。
代码结构说明

以下是本项目主要代码结构及说明:

代码目录: textone-premium/tasks/few_shot_text_classification

.                                                      
├── data                     ## 示例数据文件夹,包括任务所需训练集(train_data)、测试集(test_data)、验证集(dev_data)和预测集(predict_data),以及处理数据的代码文件
│   ├── data_for_pairwise_match.py  ## 处理分类数据生成pairwise匹配数据
│   ├── process_data_and_train.sh   ## 处理数据并训练的脚本文件
│   ├── dev_data
│   │   └── dev.txt
│   ├── predict_data
│   │   └── predict.txt
│   ├── test_data
│   │   └── test.txt
│   └── train_data
│       └── train.txt
├── examples
│   ├── fstc_ernie_sim_1.0_pairwise_simnet_ch.json
│   └── fstc_ernie_sim_1.0_pairwise_simnet_ch_infer.json
├── __init__.py
├── run_infer.py       ## 只依靠json进行模型预测的入口脚本
└── run_with_json.py   ## 只依靠json进行模型训练的入口脚本
数据准备
  • 这里我们提供一份已标注的示例数据集,因默认为ernie任务,因此数据未分词。正常情况下,基于ernie的任务不需要分词,非ernie的任务需要分词。
  • 训练集、测试集、验证集和预测集分别存放在./data目录下的train_data、test_data、dev_data和predict_data文件夹下
  • 注:数据集(包含词表)均为utf-8格
训练集/测试集/验证集
  • 训练集、测试集和验证集的数据格式相同,每个样本占一行,一行两列(两个key),列之间用\t分隔。第一列为明文text, 第二列为对应的分类标签。
英国央行邀请英国货币市场运营商提供波段票据兑换现金帮助缓解预测亿stg流动性短缺市场预测修正初始十亿美元	2
结果墨西哥足球锦标赛星期二在蒙特雷举行	4
预测集
  • 训练集、测试集和验证集的数据格式相同,每个样本占一行,一行两列(两个key),列之间用\t分隔。第一列为明文text, 第二列为对应的分类标签。
英国央行邀请英国货币市场运营商提供波段票据兑换现金帮助缓解预测亿stg流动性短缺市场预测修正初始十亿美元	2
结果墨西哥足球锦标赛星期二在蒙特雷举行	4
训练第一个模型
开始训练
  1. 请在./env.sh中根据提示配置相应环境变量的路径
# 需要提前参照env.sh进行环境变量配置,在当前shell内去读取
source env.sh
  1. 在训练前需先将分类数据处理为pairwise匹配数据,./data/data_for_pairwise_match.py可处理分类数据,默认处理的数据文件路径为训练集./data/train_data、测试集./data/test_data、验证集./data/dev_data。其中根据需求可调节生成pairwise数据的方式,neg_sampling_rate为生成pairwise格式数据时负样本的采样率、max_data_num为pairwise格式训练数据的最大数据量,-1表示不设置最大数据量。生成后的数据各数据集存放的路径为:
  • 训练集:./data/train_pairwise/
  • 测试集:./data/test_combine/
  • 验证集:./data/dev_combine/
  • 处理后将对应的文件夹路径填写在训练所使用的json配置中。
  • 具体生成的pairwise数据格式如下: pairwise训练集

    • 训练集一行三列(三个key),列之间用\t分隔,都为text。第一列和第二列为同类别的text,第三列为其他类别的负样本text。
    WernerDieter前首席执行官曼内斯曼(MannesmannAG)表示,将寻求法律咨询,以决定是否接受检察官在周二出版的《BoersenZeitung》报纸上提供的交易	法国住房部给出了以下未经调整的数据:7月住房开工率5月底5月底7月住房批准总数量同比变动百分比非住宅建筑批准面积百万年同比变动开工率百万巴黎新闻编辑室	墨西哥足球锦标赛星期二在蒙特雷举行

    pairwise所需的测试集/验证集

    • 测试集和验证集格式一样,一行三列(三个key),列之间用\t分隔。第一列文本text,第二列为文本对应的分类label,第三列为标识该数据是否为训练集,1为训练集的数据,0为测试集/验证集的数据。
    • 具体操作为将训练集(./data/train_data/)中的数据与测试集/验证集(./data/test_data 或 ./data/dev_data)中的数据进行拼接,通过第三列标识符进行区分。在具体测试过程中,会分别读出训练集和测试集/验证集数据,根据训练集的embedding与测试集/验证集的embedding进行相似度的计算得到测试集/验证集样本的类别。
    捷克国家银行周二公布的捷克股市综合指数上涨8点,捷克国家银行表示,7-10个行业指数上涨,食品饮料行业指数上涨最多,布拉格新闻编辑室    3   0
  1. 使用ernie预训练模型,以ernie_1.0_sim为例:请使用以下命令在../model_files/中通过对应脚本download_ernie_sim_1.0_ch.sh下载模型参数文件,其对应的配置文件ernie_sim_1.0_ch_config.json和词表vocab_ernie_sim_1.0_ch.txt分别位于../model_files/目录下的config/和dict/文件夹下,用户无需修改;
# download_ernie_sim_1.0_ch.sh 模型下载
# 进入model_files目录
cd ../model_files/
# 运行下载脚本
sh download_ernie_sim_1.0_ch.sh
  1. 需生成pairwise数据并训练模型,则需先运行pairwise数据处理代码,数据生成成功后训练模型,其中json配置文件为./examples/fstc_ernie_sim_1.0_pairwise_simnet_ch.json。
# 处理分类数据为pairwise数据格式
python ./data/data_for_pairwise_match.py
# 模型训练
python run_with_json.py --param_path ./examples/fstc_ernie_sim_1.0_pairwise_simnet_ch.json
  • 若已生成了pairwise数据则可直接训练模型
# 模型训练
python run_with_json.py --param_path ./examples/fstc_ernie_sim_1.0_pairwise_simnet_ch.json
  • 训练运行的日志会自动保存在./log/test.log文件中;
  • 训练中以及结束后产生的模型文件会默认保存在./output/目录下,其中save_inference_model/文件夹会保存用于预测的模型文件,save_checkpoint/文件夹会保存用于热启动的模型文件。
模型预测
开始预测
  • 使用预置网络进行预测的方式为使用./run_infer.py入口脚本,通过--param_path参数来传入./examples/目录下的json配置文件。
  • 预测分为以下几个步骤:
  1. 基于示例的数据集,可以运行以下命令在预测集(./data/predict_data)上进行预测:
# 基于json实现预测。其调用了配置文件./examples/fstc_ernie_sim_1.0_pairwise_simnet_ch_infer.json
python run_infer.py --param_path ./example/fstc_ernie_sim_1.0_pairwise_simnet_ch_infer.json

预测运行的日志会自动保存在./output/predict_result.txt文件中。

  1. 预测结果如下所示,输出每个text的embedding向量,格式为text\t[embedding]。
  2. 可利用预测得到的预测集的embedding和训练集的embedding进行相似度计算得出分类结果,具体计算方式可参考ernie_recall_siamese_pairwise.py中的get_metrics函数。