diff --git a/README.md b/README.md index 77b46391478b68ef2ea68f9b86aa34f5d3f13fb4..58b0bd325878ff9c68927f0717ad5ed0688dab41 100644 --- a/README.md +++ b/README.md @@ -984,7 +984,7 @@ python -u infer_classifyer.py \ --init_checkpoint "./checkpoints/step_100" \ --save_inference_model_path ./saved_model \ --predict_set ${TASK_DATA_PATH}/xnli/test.tsv \ - --vocab_path ${MODEL_PATH}/vocab.txt + --vocab_path ${MODEL_PATH}/vocab.txt \ --num_labels 3 ``` diff --git a/README.zh.md b/README.zh.md index 4106e0d9e4bb72d297475c2d599054c902de32a2..998eff1fad2bb8bfde4a62d5cdfecd5c8bb44440 100644 --- a/README.zh.md +++ b/README.zh.md @@ -646,9 +646,11 @@ ERNIE 2.0 的英文效果验证在 GLUE 上进行。GLUE 评测的官方地址 * [序列标注任务](#序列标注任务) * [实体识别](#实体识别) * [阅读理解任务](#阅读理解任务-1) + * [利用Propeller进行二次开发](#利用propeller进行二次开发) * [预训练 (ERNIE 1.0)](#预训练-ernie-10) * [数据预处理](#数据预处理) * [开始训练](#开始训练) + * [向量服务器](#向量服务器) * [蒸馏](#蒸馏) * [上线](#上线) * [生成inference_model](#生成inference_model) @@ -659,11 +661,12 @@ ERNIE 2.0 的英文效果验证在 GLUE 上进行。GLUE 评测的官方地址 * [FAQ3: 运行脚本中的batch size指的是单卡分配的数据量还是多卡的总数据量?](#faq3-运行脚本中的batch-size指的是单卡分配的数据量还是多卡的总数据量) * [FAQ4: Can not find library: libcudnn.so. Please try to add the lib path to LD_LIBRARY_PATH.](#faq4-can-not-find-library-libcudnnso-please-try-to-add-the-lib-path-to-ld_library_path) * [FAQ5: Can not find library: libnccl.so. Please try to add the lib path to LD_LIBRARY_PATH.](#faq5-can-not-find-library-libncclso-please-try-to-add-the-lib-path-to-ld_library_path) + * [FQA6: 运行报错`ModuleNotFoundError: No module named 'propeller'`](#faq6) ## PaddlePaddle安装 -本项目依赖于 Paddle Fluid 1.5,请参考[安装指南](http://www.paddlepaddle.org/#quick-start)进行安装。 +本项目依赖于 Paddle Fluid 1.5,* 暂时不支持Paddle 1.6的使用 *,请参考[安装指南](http://www.paddlepaddle.org/#quick-start)进行安装。 **【重要】安装后,需要及时的将 CUDA、cuDNN、NCCL2 等动态库路径加入到环境变量 LD_LIBRARY_PATH 之中,否则训练过程中会报相关的库错误。具体的paddlepaddle配置细节请查阅[这里](http://en.paddlepaddle.org/documentation/docs/zh/1.5/beginners_guide/quick_start_cn.html)** @@ -891,6 +894,54 @@ text_a label [test evaluation] em: 88.061838, f1: 93.520152, avg: 90.790995, question_num: 3493 ``` +## 利用Propeller进行二次开发 + +[Propeller](./propeller/README.md) 是基于PaddlePaddle构建的一键式训练API,对于具备一定机器学习应用经验的开发者可以使用Propeller获得定制化开发体验。 +您可以通过`export PYTHONPATH=./:$PYTHONPATH`的方式引入Propeller. +Propeller基础教程可以参考`./example/propeller_xnli_demo.ipynb`. +您只需定义好自己的模型以及 Dataset, 剩下的工作,如多卡并行,模型存储等等,都交给Propeller来处理吧。 +./example/ 里放了使用Propeller进行分类任务、排序任务和命名实体识别任务的finetune流程,可以作为您修改的模板。 + +模板中使用的demo数据可以从[这里](https://ernie.bj.bcebos.com/demo_data.tar.gz)下载,解压完成后放到 ${TASK_DATA_PATH} 中。 +以分类任务为例,用下面脚本即可启动finetune,在训练的过程中框架会自动把准确率最好的模型保存在 `./output/best/inference` 下面。利用 infernce\_model 进行在线预测的方案请参考: [在线预测](#在线预测) + +```script +python3 ./example/finetune_classifier.py \ + --data_dir ${TASK_DATA_PATH}/chnsenticorp/ \ + --warm_start_from ${MODEL_PATH}/params \ + --vocab_file ${MODEL_PATH}/vocab.txt \ + --max_seqlen 128 \ + --run_config '{ + "model_dir": "output", + "max_steps": '$((10 * 9600 / 32))', + "save_steps": 100, + "log_steps": 10, + "max_ckpt": 1, + "skip_steps": 0, + "eval_steps": 100 + }' \ + --hparam ${MODEL_PATH}/ernie_config.json \ + --hparam '{ # model definition + "sent_type_vocab_size": None, # default term in official config + "use_task_id": False, + "task_id": 0, + }' \ + --hparam '{ # learn + "warmup_proportion": 0.1, + "weight_decay": 0.01, + "use_fp16": 0, + "learning_rate": 0.00005, + "num_label": 2, + "batch_size": 32 + }' +``` + +finetune完成后,在上述脚本中加入--do_predict 参数后即可启动开始预测: + +```script +cat input_file | python3 ./example/finetune_classifier.py --do_predict ... > output_score +``` + ## 预训练 (ERNIE 1.0) @@ -926,6 +977,37 @@ epoch: 1, progress: 1/1, step: 50, loss: 10.360563, ppl: 16398.287109, next_sent 如果用自定义的真实数据进行训练,请参照[`script/zh_task/pretrain.sh`](./script/zh_task/pretrain.sh)脚本对参数做相应修改。 +## 向量服务器 + +经过预训练的 ERNIE 模型能够直接用于文本语义表示。模型预测的句子 embedding 可以很方便地应用于语义近邻搜索(ANN), 或者下游任务feature-based finetune 任务中。为了更方便地将 ERNIE 用作特征抽取器,我们提供了一个ERNIE server来完成这项工作。 +ERNIE server 依赖propeller, +您可以通过`export PYTHONPATH=./:$PYTHONPATH`的方式引入Propeller. +请从 [这里](https://ernie.bj.bcebos.com/ernie1.0_zh_inference_model.tar.gz) 下载中文 ERNIE1.0-base 模型的 inference\_model, 随后您可以通过下面的指令启动ERNIE server服务 + +```script +python3 ernie/service/encoder_server.py -m ./ernie1.0_base_inference_model/ -p 8888 -v --encode_layer pooler +``` + +通过 `--encode_layer` 可以指定特征抽取的位置,`pooler` 代表选取 ERNIE pooler fc 的输出作为特征。 + +您可以通过下面的方式请求ERNIE server服务,目前客户端支持python3调用: +```python +from ernie.service.client import ErnieClient +client = ErnieClient('./config/vocab.txt', host='localhost', port=8888) +ret = client(['谁有狂三这张高清的', '英雄联盟什么英雄最好']) # 单句输入 +# output: +# array([[-1. , -1. , 0.9937699 , ..., -0.99991065, +# -0.9999997 , -0.9999985 ], +# [-1. , -1. , -0.05038145, ..., -0.9912302 , +# -0.9999436 , -0.9739356 ]], dtype=float32) +ret = client(['谁有狂三这张高清的', '这张高清图,谁有'], ['英雄联盟什么英雄最好', '英雄联盟最好英雄是什么']) # 句对输入 +# output: +# array([[-1. , -0.99528974, -0.99174845, ..., -0.9781673 , +# -1. , -1. ], +# [-1. , -1. , -0.8699475 , ..., -0.997155 , +# -1. , -0.99999994]], dtype=float32) +``` + ## 蒸馏 ERNIE提供了通过数据蒸馏从而达到模型压缩、加速的开发套件,具体开发流程请参考 这里 @@ -937,10 +1019,10 @@ ERNIE提供了通过数据蒸馏从而达到模型压缩、加速的开发套件 ### 生成inference\_model 运行`infer_classifyer.py` 脚本时通过指定 `--save_inference_model_path` 便可生成 inference_model 到指定位置。 -如果您采用 `propeller` 完成finetune,则 `BestInferenceExporter` 会在finetune过程中根据预测指标,挑最好的模型生成 inference_model . 使用 `propeller` 完成finetune的流程请参考 `propeller_xnli_demo.ipynb` +如果您采用 `propeller` 完成finetune,则 `BestInferenceExporter` 会在finetune过程中根据预测指标,挑最好的模型生成 inference_model . ### 在线预测 -随后您可以使用[PaddleInference C++ API](https://www.paddlepaddle.org.cn/documentation/docs/zh/advanced_usage/deploy/inference/native_infer.html)将模型的前向预测代码联编到您的生产环境中。或者您可以使用我们为您构建好的python预测引擎来完成一个简单的服务。只需将本代码库中的 `./propeller` 文件夹放入您的 `PYTHONPATH` 中并执行如下指令,便可以开启一个propeller server: +随后您可以使用[PaddleInference C++ API](https://www.paddlepaddle.org.cn/documentation/docs/zh/advanced_usage/deploy/inference/native_infer.html)将模型的前向预测代码联编到您的生产环境中。或者您可以使用我们为您构建好的python预测引擎来完成一个简单的服务。执行如下指令,便可以开启一个propeller server: ```script python -m propeller.tools.start_server -m /path/to/saved/model -p 8888 @@ -949,18 +1031,21 @@ python -m propeller.tools.start_server -m /path/to/saved/model -p 8888 您可以在python脚本很方便地调用propeller server: ```python from propeller.service.client import InferenceClient -client = InferenceClient('tcp://localhost:8113') -result = client(sentence_id, position_id, token_type_id, input_mask) +client = InferenceClient('tcp://localhost:8888') +sentence_id = np.array([[[20], [1560], [1175], [8], [42]]], dtype=np.int64) +position_id = np.array([[[0], [1], [2], [3], [4]]], dtype=np.int64) +token_type_id = np.array([[[0], [0], [0], [1], [1]]], dtype=np.int64) +input_mask = np.array([[1., 1., 1., 1., 1.]], dtype=np.float32) +result = client(sentence_id, token_type_id, position_id, input_mask) ``` -`client`的请求参数类型是numpy array,对应了save_inference_model时指定的输入tensor. 如果是使用`classify_infer.py` 生成的inference_model则请求参数有四个:(sentence_id, position_id, token_type_id, input_mask)。 如果是`propeller` 生成的inference_model, client的请求参数对应您`eval_dataset` 的元素类型。 - +`client`的请求参数类型是numpy array,对应了save_inference_model时指定的输入tensor. 如果是使用`infer_classifyer.py` 生成的inference_model则请求参数有四个:(sentence_id, position_id, token_type_id, input_mask)。 如果是`propeller` 生成的inference_model, client的请求参数对应您`eval_dataset` 的元素类型。目前`InferenceClient`只支持在python3环境下使用。 ## FAQ ### FAQ1: 如何获取输入句子/词经过 ERNIE 编码后的 Embedding 表示? -可以通过 ernie_encoder.py 抽取出输入句子的 Embedding 表示和句子中每个 token 的 Embedding 表示,数据格式和 [Fine-tuning 任务](#fine-tuning-任务) 一节中介绍的各种类型 Fine-tuning 任务的训练数据格式一致;以获取 LCQMC dev 数据集中的句子 Embedding 和 token embedding 为例,示例脚本如下: +可以通过 `ernie_encoder.py` 抽取出输入句子的 Embedding 表示和句子中每个 token 的 Embedding 表示,数据格式和 [Fine-tuning 任务](#fine-tuning-任务) 一节中介绍的各种类型 Fine-tuning 任务的训练数据格式一致;以获取 LCQMC dev 数据集中的句子 Embedding 和 token embedding 为例,示例脚本如下: ``` export FLAGS_sync_nccl_allreduce=1 @@ -990,7 +1075,7 @@ python -u infer_classifyer.py \ --init_checkpoint "./checkpoints/step_100" \ --save_inference_model_path ./saved_model \ --predict_set ${TASK_DATA_PATH}/xnli/test.tsv \ - --vocab_path ${MODEL_PATH}/vocab.txt + --vocab_path ${MODEL_PATH}/vocab.txt \ --num_labels 3 ``` @@ -1000,20 +1085,20 @@ python -u infer_classifyer.py \ **Note**: predict_set 的数据格式是由 text_a、text_b(可选) 组成的 1 列 / 2 列 tsv 文件。 - ### FAQ3: 运行脚本中的batch size指的是单卡分配的数据量还是多卡的总数据量? 单独一张显卡分配到的数据量。 - ### FAQ4: Can not find library: libcudnn.so. Please try to add the lib path to LD_LIBRARY_PATH. 在 LD_LIBRARY_PATH 中添加 cudnn 库的路径,如 `export LD_LIBRARY_PATH=/home/work/cudnn/cudnn_v[your cudnn version]/cuda/lib64` - ### FAQ5: Can not find library: libnccl.so. Please try to add the lib path to LD_LIBRARY_PATH. 需要先下载 [NCCL](https://developer.nvidia.com/nccl/nccl-download),然后在 LD_LIBRARY_PATH 中添加 NCCL 库的路径,如`export LD_LIBRARY_PATH=/home/work/nccl/lib` +### FQA6: 运行报错`ModuleNotFoundError: No module named 'propeller'` + +您可以通过`export PYTHONPATH=./:$PYTHONPATH`的方式引入Propeller.