提交 76f10127 编写于 作者: W wuzewu

Merge branch 'release/v1.0.0' into develop

language: python language: python
python: before_install: pip install flake8
- "3.6"
sudo: required before_script: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
os: script: /bin/bash ./scripts/check_code_style.sh
- linux
script:
- /bin/bash ./scripts/check_code_style.sh
notifications: notifications:
email: email:
......
...@@ -4,24 +4,26 @@ ...@@ -4,24 +4,26 @@
[![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](LICENSE) [![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](LICENSE)
[![Version](https://img.shields.io/github/release/PaddlePaddle/PaddleHub.svg)](https://github.com/PaddlePaddle/PaddleHub/releases) [![Version](https://img.shields.io/github/release/PaddlePaddle/PaddleHub.svg)](https://github.com/PaddlePaddle/PaddleHub/releases)
PaddleHub是基于PaddlePaddle开发的预训练模型管理工具,可以借助预训练模型更便捷地开展迁移学习工作。 PaddleHub是基于PaddlePaddle生态下的预训练模型管理和迁移学习工具,可以结合预训练模型更便捷地开展迁移学习工作。通过PaddleHub,您可以:
## 特性 * 便捷地获取PaddlePaddle生态下的所有预训练模型,涵盖了图像分类、目标检测、词法分析、语义模型、情感分析、语言模型、视频分类、图像生成八类主流模型。
* 更多详情可查看官网:http://hub.paddlepaddle.org.cn
通过PaddleHub,您可以: * 通过PaddleHub Fine-tune API,结合少量代码即可完成**大规模预训练模型**的迁移学习,具体Demo可参考以下链接:
* [文本分类](https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.0.0/demo/text-classification)
1. 通过命令行,无需编写代码,一键使用预训练模型进行预测; * [序列标注](https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.0.0/demo/sequence-labeling)
2. 通过hub download命令,快速地获取PaddlePaddle生态下的所有预训练模型; * [多标签分类](https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.0.0/demo/multi-label-classification)
3. 借助PaddleHub Finetune API,使用少量代码完成迁移学习; * [图像分类](https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.0.0/demo/image-classification)
- 更多Demo可参考 [ERNIE文本分类](https://github.com/PaddlePaddle/PaddleHub/tree/develop/demo/text-classification) [图像分类迁移](https://github.com/PaddlePaddle/PaddleHub/tree/develop/demo/image-classification) * [检索式问答任务](https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.0.0/demo/qa_classification)
- 完整教程可参考 [文本分类迁移教程](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E6%96%87%E6%9C%AC%E5%88%86%E7%B1%BB%E8%BF%81%E7%A7%BB%E6%95%99%E7%A8%8B) [图像分类迁移教程](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E5%9B%BE%E5%83%8F%E5%88%86%E7%B1%BB%E8%BF%81%E7%A7%BB%E6%95%99%E7%A8%8B) * PaddleHub引入『**模型即软件**』的设计理念,支持通过Python API或者命令行工具,一键完成预训练模型地预测,更方便的应用PaddlePaddle模型库。
* [PaddleHub命令行工具介绍](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%B7%A5%E5%85%B7)
## 安装
## 环境依赖
**环境依赖**
* Python==2.7 or Python>=3.5 * Python==2.7 or Python>=3.5
* PaddlePaddle>=1.4.0 * PaddlePaddle>=1.4.0
除上述依赖外,PaddleHub的预训练模型和预置数据集需要连接服务端进行下载,请确保机器可以正常访问网络
## 安装
pip安装方式如下: pip安装方式如下:
```shell ```shell
...@@ -29,38 +31,67 @@ $ pip install paddlehub ...@@ -29,38 +31,67 @@ $ pip install paddlehub
``` ```
## 快速体验 ## 快速体验
安装成功后,执行下面的命令,可以快速体验PaddleHub无需代码、一键预测的命令行功能: 安装成功后,执行下面的命令,可以快速体验PaddleHub无需代码、一键预测的命令行功能:
`示例一`
使用[词法分析](http://www.paddlepaddle.org.cn/hub?filter=category&value=LexicalAnalysis)模型LAC进行分词
```shell ```shell
# 使用百度LAC词法分析工具进行分词
$ hub run lac --input_text "今天是个好日子" $ hub run lac --input_text "今天是个好日子"
[{'word': ['今天', '是', '个', '好日子'], 'tag': ['TIME', 'v', 'q', 'n']}]
```
# 使用百度Senta情感分析模型对句子进行预测 `示例二`
$ hub run senta_bilstm --input_text "今天是个好日子"
# 使用SSD检测模型对图片进行目标检测,检测结果如下图所示 使用[情感分析](http://www.paddlepaddle.org.cn/hub?filter=category&value=SentimentAnalysis)模型Senta对句子进行情感预测
$ wget --no-check-certificate https://paddlehub.bj.bcebos.com/resources/test_img_bird.jpg ```shell
$ hub run ssd_mobilenet_v1_pascal --input_path test_img_bird.jpg $ hub run senta_bilstm --input_text "今天是个好日子"
[{'text': '今天是个好日子', 'sentiment_label': 2, 'sentiment_key': 'positive', 'positive_probs': 0.6065, 'negative_probs': 0.3935}]
``` ```
![SSD检测结果](https://raw.githubusercontent.com/PaddlePaddle/PaddleHub/develop/docs/imgs/test_img_bird_output.jpg)
想了解更多PaddleHub已经发布的模型,请使用`hub search`命令查看所有已发布的模型。 `示例三`
使用[目标检测](http://www.paddlepaddle.org.cn/hub?filter=category&value=ObjectDetection)模型 SSD/YOLO v3/Faster RCNN 对图片进行目标检测
```shell ```shell
$ hub search $ wget --no-check-certificate https://paddlehub.bj.bcebos.com/resources/test_object_detection.jpg
$ hub run ssd_mobilenet_v1_pascal --input_path test_object_detection.jpg
$ hub run yolov3_coco2017 --input_path test_object_detection.jpg
$ hub run faster_rcnn_coco2017 --input_path test_object_detection.jpg
``` ```
![SSD检测结果](https://raw.githubusercontent.com/PaddlePaddle/PaddleHub/release/v1.0.0/docs/imgs/object_detection_result.png)
除了上述三类模型外,PaddleHub还发布了语言模型、语义模型、图像分类、生成模型、视频分类等业界主流模型,更多PaddleHub已经发布的模型,请前往 http://hub.paddlepaddle.org.cn 查看
## 教程
[API](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-Finetune-API)
[迁移学习](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E4%B8%8E%E8%BF%81%E7%A7%BB%E5%AD%A6%E4%B9%A0)
[自定义迁移任务](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub:-%E8%87%AA%E5%AE%9A%E4%B9%89Task)
## 深入了解PaddleHub ## 在线体验
* [PaddleHub Wiki](https://github.com/PaddlePaddle/PaddleHub/wiki) 我们在AI Studio和AIBook上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
* [命令行工具](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%B7%A5%E5%85%B7) * ERNIE文本分类:
* [Finetune API与迁移学习](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E4%B8%8E%E8%BF%81%E7%A7%BB%E5%AD%A6%E4%B9%A0) * [AI Studio](https://aistudio.baidu.com/aistudio/projectDetail/79380)
* [API](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-Finetune-API) * [AIBook](https://console.bce.baidu.com/bml/?_=1562072915183#/bml/aibook/ernie_txt_cls)
* ERNIE序列标注:
* [AI Studio](https://aistudio.baidu.com/aistudio/projectDetail/79377)
* [AIBook](https://console.bce.baidu.com/bml/?_=1562072915183#/bml/aibook/ernie_seq_label)
* ELMo文本分类:
* [AI Studio](https://aistudio.baidu.com/aistudio/projectDetail/79400)
* [AIBook](https://console.bce.baidu.com/bml/#/bml/aibook/elmo_txt_cls)
* senta情感分类:
* [AI Studio](https://aistudio.baidu.com/aistudio/projectDetail/79398)
* [AIBook](https://console.bce.baidu.com/bml/#/bml/aibook/senta_bilstm)
* 图像分类:
* [AI Studio](https://aistudio.baidu.com/aistudio/projectDetail/79378)
* [AIBook](https://console.bce.baidu.com/bml/#/bml/aibook/img_cls)
## 答疑 ## 答疑
当安装或者使用遇到问题时,可以通过[FAQ](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-FAQ)查找解决方案。 当安装或者使用遇到问题时,可以通过[FAQ](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-FAQ)查找解决方案。
如果在FAQ中没有找到解决方案,欢迎您将问题和bug报告以[Github Issues](https://github.com/PaddlePaddle/PaddleHub/issues)的形式提交 如果在FAQ中没有找到解决方案,欢迎您将问题和bug报告以[Github Issues](https://github.com/PaddlePaddle/PaddleHub/issues)的形式提交给我们,我们会第一时间进行跟进
## 版权和许可证 ## 版权和许可证
PaddleHub由[Apache-2.0 license](LICENSE)提供 PaddleHub由[Apache-2.0 license](LICENSE)提供
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
>* 文本分类 >* 文本分类
>* 多标签分类
>* 检索式问答任务
## 图像分类 ## 图像分类
该样例展示了PaddleHub如何将ResNet50、ResNet101、ResNet152、MobileNet、NasNet以及PNasNet作为预训练模型在Flowers、DogCat、Indoor67、Food101、StanfordDogs等数据集上进行图像分类的FineTune和预测。 该样例展示了PaddleHub如何将ResNet50、ResNet101、ResNet152、MobileNet、NasNet以及PNasNet作为预训练模型在Flowers、DogCat、Indoor67、Food101、StanfordDogs等数据集上进行图像分类的FineTune和预测。
...@@ -38,8 +42,18 @@ ...@@ -38,8 +42,18 @@
## 文本分类 ## 文本分类
该样例展示了PaddleHub如何将ERNIE和BERT作为预训练模型在ChnSentiCorp、LCQMC和NLPCC-DBQA等数据集上 该样例展示了PaddleHub
完成文本分类的FineTune和预测。 >* 如何将ERNIE和BERT作为预训练模型在ChnSentiCorp、LCQMC和NLPCC-DBQA等数据集上完成文本分类的FineTune和预测。
>* 如何将ELMo预训练得到的中文word embedding加载,完成在ChnSentiCorp数据集上文本分类的FineTune和预测。
## 多标签分类
该样例展示了PaddleHub如何将BERT作为预训练模型在Toxic数据集上完成多标签分类的FineTune和预测。
## 检索式问答任务
该样例展示了PaddleHub如何将ERNIE和BERT作为预训练模型在NLPCC-DBQA等数据集上完成检索式问答任务的FineTune和预测。
**NOTE** **NOTE**
以上任务示例均是利用PaddleHub提供的数据集,若您想在自定义数据集上完成相应任务,请查看[PaddleHub适配自定义数据完成FineTune](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E9%80%82%E9%85%8D%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E5%AE%8C%E6%88%90FineTune) 以上任务示例均是利用PaddleHub提供的数据集,若您想在自定义数据集上完成相应任务,请查看[PaddleHub适配自定义数据完成FineTune](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E9%80%82%E9%85%8D%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E5%AE%8C%E6%88%90FineTune)
# PaddleHub 文本分类
本示例将展示如何使用PaddleHub Finetune API以及加载ELMo预训练中文word embedding在中文情感分析数据集ChnSentiCorp上完成分类任务。
## 如何开始Finetune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_elmo_finetune.sh`即可开始使用ELMo对ChnSentiCorp数据集进行Finetune。
其中脚本参数说明如下:
```bash
# 模型相关
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数use
--use_gpu: 是否使用GPU进行FineTune,默认为True
--learning_rate: Finetune的最大学习率
--weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01
--warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0
--num_epoch: Finetune迭代的轮数
# 任务相关
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型
```
## 代码步骤
使用PaddleHub Finetune API进行Finetune可以分为4个步骤
### Step1: 加载预训练模型
```python
module = hub.Module(name="elmo")
inputs, outputs, program = module.context(trainable=True)
```
### Step2: 准备数据集并使用LACClassifyReader读取数据
```python
dataset = hub.dataset.ChnSentiCorp()
reader = hub.reader.LACClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path())
```
其中数据集的准备代码可以参考 [chnsenticorp.py](https://github.com/PaddlePaddle/PaddleHub/blob/develop/paddlehub/dataset/chnsenticorp.py)
`hub.dataset.ChnSentiCorp()` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录
`module.get_vaocab_path()` 会返回预训练模型对应的词表
LACClassifyReader中的`data_generator`会自动按照模型对应词表对数据进行切词,以迭代器的方式返回ELMo所需要的Tensor格式,包括`word_ids`.
### Step3:选择优化策略和运行配置
```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, use_data_parallel=True, use_pyreader=False, 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
* `use_data_parallel`: 是否使用并行计算,默认False。打开该功能依赖nccl库
* `use_pyreader`: 是否使用pyreader,默认False
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: finetune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `enable_memory_optim`: 是否使用内存优化, 默认为True
* `strategy`: Finetune优化策略
**Note**: 当使用LACClassifyReader时,use_pyreader应该为False。
### Step4: 构建网络并创建分类迁移任务进行Finetune
有了合适的预训练模型和准备要迁移的数据集后,我们开始组建一个Task。
>* 获取module的上下文环境,包括输入和输出的变量,以及Paddle Program;
>* 从输出变量中找到输入单词对应的elmo_embedding, 并拼接上随机初始化word embedding;
>* 在拼接embedding输入gru网络,进行文本分类,生成Task;
```python
word_ids = inputs["word_ids"]
elmo_embedding = outputs["elmo_embed"]
feed_list = [word_ids.name]
switch_main_program(program)
word_embed_dims = 128
word_embedding = fluid.layers.embedding(
input=word_ids,
size=[word_dict_len, word_embed_dims],
param_attr=fluid.ParamAttr(
learning_rate=30,
initializer=fluid.initializer.Uniform(low=-0.1, high=0.1)))
input_feature = fluid.layers.concat(
input=[elmo_embedding, word_embedding], axis=1)
fc = gru_net(program, input_feature)
elmo_task = hub.TextClassifierTask(
data_reader=reader,
feature=fc,
feed_list=feed_list,
num_classes=dataset.num_labels,
config=config)
elmo_task.finetune_and_eval()
```
**NOTE:**
1. `outputs["elmo_embed"]`返回了ELMo模型预训练的word embedding。
2. `hub.TextClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于文本分类的迁移任务`TextClassifierTask`
## 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为端口号,即可看到训练过程中指标的变化情况
## 模型预测
通过Finetune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数
```
CKPT_DIR="./ckpt_chnsentiment"
python predict.py --checkpoint_dir --use_gpu True
```
其中CKPT_DIR为Finetune API保存最佳模型的路径
参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。
如需了解更多预测步骤,请参考`predict.py`
# PaddleHub 多标签分类
本示例将展示如何使用PaddleHub Finetune API以及BERT预训练模型在Toxic完成多标签分类任务。
## 如何开始Finetune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_classifier.sh`即可开始使用BERT对Toxic数据集进行Finetune。**由于BERT模型计算量较大,建议在GPU上使用,且显存需要大于14GB**
其中脚本参数说明如下:
```bash
# 模型相关
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数
--use_gpu: 是否使用GPU进行FineTune,默认为False
--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="bert_uncased_L-12_H-768_A-12")
inputs, outputs, program = module.context(trainable=True, max_seq_len=128)
```
### Step2: 准备数据集并使用MultiLabelClassifyReader读取数据
```python
dataset = hub.dataset.Toxic()
reader = hub.reader.MultiLabelClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path(),
max_seq_len=128)
```
其中数据集的准备代码可以参考 [toxic.py](https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.0.0/paddlehub/dataset/toxic.py)
`hub.dataset.Toxic()` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录
`module.get_vocab_path()` 会返回预训练模型对应的词表
`max_seq_len` 需要与Step1中context接口传入的序列长度保持一致
MultiLabelClassifyReader中的`data_generator`会自动按照模型对应词表对数据进行tokenize,以迭代器的方式返回BERT所需要的Tensor格式,包括`input_ids``position_ids``segment_id`与序列对应的mask `input_mask`.
**NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。
### Step3:选择优化策略和运行配置
```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, use_data_parallel=True, use_pyreader=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
* use_pyreader: 是否使用pyreader,默认False
* use_data_parallel: 是否使用并行计算,默认False。打开该功能依赖nccl库
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: finetune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `enable_memory_optim`: 是否使用内存优化, 默认为True
* `strategy`: Finetune优化策略
### Step4: 构建网络并创建分类迁移任务进行Finetune
```python
pooled_output = outputs["pooled_output"]
# feed_list的Tensor顺序不可以调整
feed_list = [
inputs["input_ids"].name,
inputs["position_ids"].name,
inputs["segment_ids"].name,
inputs["input_mask"].name,
]
cls_task = hub.MultiLabelClassifierTask(
data_reader=reader,
feature=pooled_output,
feed_list=feed_list,
num_classes=dataset.num_labels,
config=config)
cls_task.finetune_and_eval()
```
**NOTE:**
1. `outputs["pooled_output"]`返回了ERNIE/BERT模型对应的[CLS]向量,可以用于句子或句对的特征表达。
2. `feed_list`中的inputs参数指名了ERNIE/BERT中的输入tensor的顺序,与MultiLabelClassifierTask返回的结果一致。
3. `hub.MultiLabelClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于多标签分类的迁移任务`MultiLabelClassifierTask`
## 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为端口号,即可看到训练过程中指标的变化情况
## 模型预测
通过Finetune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数
```
CKPT_DIR="./ckpt_toxic"
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`
# PaddleHub 检索式问答任务
本示例将展示如何使用PaddleHub Finetune API以及Transformer类预训练模型在NLPCC-DBQA数据集上完成检索式问答任务。
## 如何开始Finetune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_classifier.sh`即可开始使用ERNIE对NLPCC-DBQA数据集进行Finetune。**由于ERNIE模型计算量较大,建议在GPU上使用,且显存需要大于14GB**
其中脚本参数说明如下:
```bash
# 模型相关
--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")
```
### Step2: 准备数据集并使用ClassifyReader读取数据
```python
dataset = hub.dataset.NLPCC_DBQA()
reader = hub.reader.ClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path(),
max_seq_len=128)
```
其中数据集的准备代码可以参考 [nlpcc_dbqa.py](https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.0.0/paddlehub/dataset/nlpcc_dbqa.py)
`hub.dataset.NLPCC_DBQA())` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录
`module.get_vocab_path()` 会返回预训练模型对应的词表
`max_seq_len` 需要与Step1中context接口传入的序列长度保持一致
ClassifyReader中的`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这一顺序返回。
### Step3:选择优化策略和运行配置
```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, use_data_parallel=True, use_pyreader=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
* `use_pyreader`: 是否使用pyreader,默认False。
* `use_data_parallel`: 是否使用并行计算,默认False。打开该功能依赖nccl库。
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: finetune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `enable_memory_optim`: 是否使用内存优化, 默认为True
* `strategy`: Finetune优化策略
### Step4: 构建网络并创建分类迁移任务进行Finetune
```python
pooled_output = outputs["pooled_output"]
# feed_list的Tensor顺序不可以调整
feed_list = [
inputs["input_ids"].name,
inputs["position_ids"].name,
inputs["segment_ids"].name,
inputs["input_mask"].name,
]
cls_task = hub.TextClassifierTask(
data_reader=reader,
feature=pooled_output,
feed_list=feed_list,
num_classes=dataset.num_labels,
config=config)
cls_task.finetune_and_eval()
```
**NOTE:**
1. `outputs["pooled_output"]`返回了ERNIE/BERT模型对应的[CLS]向量,可以用于句子或句对的特征表达。
2. `feed_list`中的inputs参数指名了ERNIE/BERT中的输入tensor的顺序,与ClassifyReader返回的结果一致。
3. `hub.TextClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于文本分类的迁移任务`TextClassifierTask`
## 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为端口号,即可看到训练过程中指标的变化情况
## 模型预测
通过Finetune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数
```
CKPT_DIR="./ckpt_qa"
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`
#coding:utf-8
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Finetuning on classification task """
import argparse
import ast
import paddle.fluid as fluid
import paddlehub as hub
# yapf: disable
parser = argparse.ArgumentParser(__doc__)
parser.add_argument("--num_epoch", type=int, default=3, help="Number of epoches for fine-tuning.")
parser.add_argument("--use_gpu", type=ast.literal_eval, default=False, help="Whether use GPU for finetuning, input should be True or False")
parser.add_argument("--learning_rate", type=float, default=5e-5, help="Learning rate used to train with warmup.")
parser.add_argument("--weight_decay", type=float, default=0.01, help="Weight decay rate for L2 regularizer.")
parser.add_argument("--warmup_proportion", type=float, default=0.0, help="Warmup proportion params for warmup strategy")
parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint")
parser.add_argument("--max_seq_len", type=int, default=512, help="Number of words of the longest seqence.")
parser.add_argument("--batch_size", type=int, default=32, help="Total examples' number in batch for training.")
parser.add_argument("--use_pyreader", type=ast.literal_eval, default=False, help="Whether use pyreader to feed data.")
parser.add_argument("--use_data_parallel", type=ast.literal_eval, default=False, help="Whether use data parallel.")
args = parser.parse_args()
# yapf: enable.
if __name__ == '__main__':
# Load Paddlehub ERNIE pretrained model
module = hub.Module(name="ernie")
# module = hub.Module(name="bert_chinese_L-12_H-768_A-12")
inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len)
# Download dataset and use ClassifyReader to read dataset
dataset = hub.dataset.NLPCC_DBQA()
reader = hub.reader.ClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path(),
max_seq_len=args.max_seq_len)
# Construct transfer learning network
# Use "pooled_output" for classification tasks on an entire sentence.
# Use "sequence_output" for token-level output.
pooled_output = outputs["pooled_output"]
# Setup feed list for data feeder
# Must feed all the tensor of ERNIE's module need
feed_list = [
inputs["input_ids"].name,
inputs["position_ids"].name,
inputs["segment_ids"].name,
inputs["input_mask"].name,
]
# Select finetune strategy, setup config and finetune
strategy = hub.AdamWeightDecayStrategy(
weight_decay=args.weight_decay,
learning_rate=args.learning_rate,
lr_scheduler="linear_decay")
# Setup runing config for PaddleHub Finetune API
config = hub.RunConfig(
use_data_parallel=args.use_data_parallel,
use_pyreader=args.use_pyreader,
use_cuda=args.use_gpu,
num_epoch=args.num_epoch,
batch_size=args.batch_size,
checkpoint_dir=args.checkpoint_dir,
strategy=strategy)
# Define a classfication finetune task by PaddleHub's API
cls_task = hub.TextClassifierTask(
data_reader=reader,
feature=pooled_output,
feed_list=feed_list,
num_classes=dataset.num_labels,
config=config)
# Finetune and evaluate by PaddleHub's API
# will finish training, evaluation, testing, save model automatically
cls_task.finetune_and_eval()
#coding:utf-8
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Finetuning on classification task """
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import ast
import numpy as np
import os
import time
import paddle
import paddle.fluid as fluid
import paddlehub as hub
# yapf: disable
parser = argparse.ArgumentParser(__doc__)
parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint")
parser.add_argument("--batch_size", type=int, default=1, help="Total examples' number in batch for training.")
parser.add_argument("--max_seq_len", type=int, default=128, help="Number of words of the longest seqence.")
parser.add_argument("--use_gpu", type=ast.literal_eval, default=False, help="Whether use GPU for finetuning, input should be True or False")
parser.add_argument("--use_pyreader", type=ast.literal_eval, default=False, help="Whether use pyreader to feed data.")
args = parser.parse_args()
# yapf: enable.
if __name__ == '__main__':
# loading Paddlehub ERNIE pretrained model
module = hub.Module(name="ernie")
inputs, outputs, program = module.context(max_seq_len=args.max_seq_len)
# Sentence classification dataset reader
dataset = hub.dataset.NLPCC_DBQA()
reader = hub.reader.ClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path(),
max_seq_len=args.max_seq_len)
place = fluid.CUDAPlace(0) if args.use_gpu else fluid.CPUPlace()
exe = fluid.Executor(place)
# Construct transfer learning network
# Use "pooled_output" for classification tasks on an entire sentence.
# Use "sequence_output" for token-level output.
pooled_output = outputs["pooled_output"]
# Setup feed list for data feeder
# Must feed all the tensor of ERNIE's module need
feed_list = [
inputs["input_ids"].name,
inputs["position_ids"].name,
inputs["segment_ids"].name,
inputs["input_mask"].name,
]
# Setup runing config for PaddleHub Finetune API
config = hub.RunConfig(
use_data_parallel=False,
use_pyreader=args.use_pyreader,
use_cuda=args.use_gpu,
batch_size=args.batch_size,
enable_memory_optim=False,
checkpoint_dir=args.checkpoint_dir,
strategy=hub.finetune.strategy.DefaultFinetuneStrategy())
# Define a classfication finetune task by PaddleHub's API
cls_task = hub.TextClassifierTask(
data_reader=reader,
feature=pooled_output,
feed_list=feed_list,
num_classes=dataset.num_labels,
config=config)
# Data to be prdicted
data = [["北京奥运博物馆的场景效果负责人是谁?", "主要承担奥运文物征集、保管、研究和爱国主义教育基地建设相关工作。"],
["北京奥运博物馆的场景效果负责人是谁", "于海勃,美国加利福尼亚大学教授 场景效果负责人 总设计师"],
["北京奥运博物馆的场景效果负责人是谁?", "洪麦恩,清华大学美术学院教授 内容及主展线负责人 总设计师"]]
index = 0
run_states = cls_task.predict(data=data)
results = [run_state.run_results for run_state in run_states]
max_probs = 0
for index, batch_result in enumerate(results):
# get predict index
if max_probs <= batch_result[0][0, 1]:
max_probs = batch_result[0][0, 1]
max_flag = index
print("question:%s\tthe predict answer:%s\t" % (data[max_flag][0],
data[max_flag][1]))
export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0
CKPT_DIR="./ckpt_qa"
# Recommending hyper parameters for difference task
# ChnSentiCorp: batch_size=24, weight_decay=0.01, num_epoch=3, max_seq_len=128, lr=5e-5
# NLPCC_DBQA: batch_size=8, weight_decay=0.01, num_epoch=3, max_seq_len=512, lr=2e-5
# LCQMC: batch_size=32, weight_decay=0, num_epoch=3, max_seq_len=128, lr=2e-5
python -u classifier.py \
--batch_size=24 \
--use_gpu=True \
--checkpoint_dir=${CKPT_DIR} \
--learning_rate=5e-5 \
--weight_decay=0.01 \
--max_seq_len=128 \
--num_epoch=3 \
--use_pyreader=False \
--use_data_parallel=False \
export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0
CKPT_DIR="./ckpt_qa"
python -u predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128 --use_gpu False
...@@ -74,7 +74,7 @@ reader = hub.reader.ClassifyReader( ...@@ -74,7 +74,7 @@ reader = hub.reader.ClassifyReader(
`hub.dataset.ChnSentiCorp()` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录 `hub.dataset.ChnSentiCorp()` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录
`module.get_vaocab_path()` 会返回预训练模型对应的词表 `module.get_vocab_path()` 会返回预训练模型对应的词表
`max_seq_len` 需要与Step1中context接口传入的序列长度保持一致 `max_seq_len` 需要与Step1中context接口传入的序列长度保持一致
......
...@@ -19,11 +19,10 @@ from __future__ import print_function ...@@ -19,11 +19,10 @@ from __future__ import print_function
import six import six
import sys import sys
import requests
from paddlehub.common.logger import logger from paddlehub.common.logger import logger
from paddlehub.common.utils import sys_stdin_encoding from paddlehub.common.utils import sys_stdin_encoding
from paddlehub.common import stats from paddlehub.common import srv_utils
from paddlehub.commands.base_command import BaseCommand from paddlehub.commands.base_command import BaseCommand
from paddlehub.commands import show from paddlehub.commands import show
from paddlehub.commands import help from paddlehub.commands import help
...@@ -52,7 +51,7 @@ class HubCommand(BaseCommand): ...@@ -52,7 +51,7 @@ class HubCommand(BaseCommand):
help.command.execute(argv) help.command.execute(argv)
exit(1) exit(1)
return False return False
stats.hub_stat(['hub'] + argv) srv_utils.hub_stat(['hub'] + argv)
command = BaseCommand.command_dict[sub_command] command = BaseCommand.command_dict[sub_command]
return command.execute(argv[1:]) return command.execute(argv[1:])
......
...@@ -26,7 +26,7 @@ import yaml ...@@ -26,7 +26,7 @@ import yaml
import random import random
from random import randint from random import randint
from paddlehub.common import utils from paddlehub.common import utils, srv_utils
from paddlehub.common.downloader import default_downloader from paddlehub.common.downloader import default_downloader
from paddlehub.common.server_config import default_server_config from paddlehub.common.server_config import default_server_config
from paddlehub.io.parser import yaml_parser from paddlehub.io.parser import yaml_parser
...@@ -95,9 +95,8 @@ class HubServer(object): ...@@ -95,9 +95,8 @@ class HubServer(object):
payload = {'word': resource_key} payload = {'word': resource_key}
if resource_type: if resource_type:
payload['type'] = resource_type payload['type'] = resource_type
r = requests.get( api_url = srv_utils.uri_path(self.get_server_url(), 'search')
self.get_server_url() + '/' + 'search', params=payload) r = srv_utils.hub_request(api_url, payload)
r = json.loads(r.text)
if r['status'] == 0 and len(r['data']) > 0: if r['status'] == 0 and len(r['data']) > 0:
return [(item['name'], item['type'], item['version'], return [(item['name'], item['type'], item['version'],
item['summary']) for item in r['data']] item['summary']) for item in r['data']]
...@@ -149,9 +148,8 @@ class HubServer(object): ...@@ -149,9 +148,8 @@ class HubServer(object):
payload['type'] = resource_type payload['type'] = resource_type
if version: if version:
payload['version'] = version payload['version'] = version
r = requests.get( api_url = srv_utils.uri_path(self.get_server_url(), 'search')
self.get_server_url() + '/' + 'search', params=payload) r = srv_utils.hub_request(api_url, payload)
r = json.loads(r.text)
if r['status'] == 0 and len(r['data']) > 0: if r['status'] == 0 and len(r['data']) > 0:
return r['data'][0] return r['data'][0]
except: except:
......
...@@ -15,8 +15,10 @@ ...@@ -15,8 +15,10 @@
import os import os
import requests import requests
import time import time
import paddle
from random import randint, seed from random import randint, seed
from paddlehub import version from paddlehub import version
from paddlehub.common.server_config import default_stat_config from paddlehub.common.server_config import default_stat_config
...@@ -33,8 +35,31 @@ def get_stat_server(): ...@@ -33,8 +35,31 @@ def get_stat_server():
def hub_stat(argv): def hub_stat(argv):
try: try:
params = {'command': ' '.join(argv), 'version': version.hub_version} params = {
'command': ' '.join(argv),
'hub_version': version.hub_version,
'paddle_version': paddle.__version__
}
stat_api = get_stat_server() stat_api = get_stat_server()
r = requests.get(stat_api, params=params, timeout=0.5) r = requests.get(stat_api, params=params, timeout=0.5)
except: except:
pass pass
def uri_path(server_url, api):
srv = server_url
if server_url.endswith('/'):
srv = server_url[:-1]
if api.startswith('/'):
srv += api
else:
api = '/' + api
srv += api
return srv
def hub_request(api, params):
params['hub_version'] = version.hub_version
params['paddle_version'] = paddle.__version__
r = requests.get(api, params)
return r.json()
...@@ -19,6 +19,8 @@ from __future__ import print_function ...@@ -19,6 +19,8 @@ from __future__ import print_function
import os import os
import numpy as np
import paddlehub as hub import paddlehub as hub
from paddlehub.common.downloader import default_downloader from paddlehub.common.downloader import default_downloader
......
...@@ -21,7 +21,7 @@ import os ...@@ -21,7 +21,7 @@ import os
import shutil import shutil
from paddlehub.common import utils from paddlehub.common import utils
from paddlehub.common import stats from paddlehub.common import srv_utils
from paddlehub.common.downloader import default_downloader from paddlehub.common.downloader import default_downloader
from paddlehub.common.dir import MODULE_HOME from paddlehub.common.dir import MODULE_HOME
from paddlehub.module import module_desc_pb2 from paddlehub.module import module_desc_pb2
...@@ -81,7 +81,7 @@ class LocalModuleManager(object): ...@@ -81,7 +81,7 @@ class LocalModuleManager(object):
module_dir = self.modules_dict[module_name][0] module_dir = self.modules_dict[module_name][0]
module_tag = module_name if not module_version else '%s-%s' % ( module_tag = module_name if not module_version else '%s-%s' % (
module_name, module_version) module_name, module_version)
stats.hub_stat(['installed', module_tag]) srv_utils.hub_stat(['installed', module_tag])
tips = "Module %s already installed in %s" % (module_tag, tips = "Module %s already installed in %s" % (module_tag,
module_dir) module_dir)
return True, tips, self.modules_dict[module_name] return True, tips, self.modules_dict[module_name]
...@@ -100,7 +100,7 @@ class LocalModuleManager(object): ...@@ -100,7 +100,7 @@ class LocalModuleManager(object):
tips += " with version %s" % module_version tips += " with version %s" % module_version
module_tag = module_name if not module_version else '%s-%s' % ( module_tag = module_name if not module_version else '%s-%s' % (
module_name, module_version) module_name, module_version)
stats.hub_stat(['install fail', module_tag]) srv_utils.hub_stat(['install fail', module_tag])
return False, tips, None return False, tips, None
result, tips, module_zip_file = default_downloader.download_file( result, tips, module_zip_file = default_downloader.download_file(
...@@ -122,7 +122,7 @@ class LocalModuleManager(object): ...@@ -122,7 +122,7 @@ class LocalModuleManager(object):
shutil.move(module_dir, save_path) shutil.move(module_dir, save_path)
module_dir = save_path module_dir = save_path
tips = "Successfully installed %s" % module_name tips = "Successfully installed %s" % module_name
stats.hub_stat(['install', module_name, url]) srv_utils.hub_stat(['install', module_name, url])
if installed_module_version: if installed_module_version:
tips += "-%s" % installed_module_version tips += "-%s" % installed_module_version
return True, tips, (module_dir, installed_module_version) return True, tips, (module_dir, installed_module_version)
...@@ -138,7 +138,7 @@ class LocalModuleManager(object): ...@@ -138,7 +138,7 @@ class LocalModuleManager(object):
1]: 1]:
tips = "%s-%s is not installed" % (module_name, module_version) tips = "%s-%s is not installed" % (module_name, module_version)
return True, tips return True, tips
stats.hub_stat(['uninstall', module_name]) srv_utils.hub_stat(['uninstall', module_name])
tips = "Successfully uninstalled %s" % module_name tips = "Successfully uninstalled %s" % module_name
if module_version: if module_version:
tips += '-%s' % module_version tips += '-%s' % module_version
......
...@@ -382,7 +382,7 @@ class SequenceLabelReader(BaseReader): ...@@ -382,7 +382,7 @@ class SequenceLabelReader(BaseReader):
sub_label = "I-" + label[2:] sub_label = "I-" + label[2:]
ret_labels.extend([sub_label] * (len(sub_token) - 1)) ret_labels.extend([sub_label] * (len(sub_token) - 1))
if len(ret_tokens) != len(labels): if len(ret_tokens) != len(ret_labels):
raise ValueError( raise ValueError(
"The length of ret_tokens can't match with labels") "The length of ret_tokens can't match with labels")
return ret_tokens, ret_labels return ret_tokens, ret_labels
......
...@@ -37,7 +37,7 @@ def convert_to_unicode(text): ...@@ -37,7 +37,7 @@ def convert_to_unicode(text):
elif six.PY2: elif six.PY2:
if isinstance(text, str): if isinstance(text, str):
return text.decode("utf-8", "ignore") return text.decode("utf-8", "ignore")
elif isinstance(text, unicode): elif isinstance(text, unicode): # noqa
return text return text
else: else:
raise ValueError("Unsupported string type: %s" % (type(text))) raise ValueError("Unsupported string type: %s" % (type(text)))
...@@ -60,7 +60,7 @@ def printable_text(text): ...@@ -60,7 +60,7 @@ def printable_text(text):
elif six.PY2: elif six.PY2:
if isinstance(text, str): if isinstance(text, str):
return text return text
elif isinstance(text, unicode): elif isinstance(text, unicode): # noqa
return text.encode("utf-8") return text.encode("utf-8")
else: else:
raise ValueError("Unsupported string type: %s" % (type(text))) raise ValueError("Unsupported string type: %s" % (type(text)))
......
...@@ -13,5 +13,5 @@ ...@@ -13,5 +13,5 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
""" PaddleHub version string """ """ PaddleHub version string """
hub_version = "0.6.5" hub_version = "1.0.0"
module_proto_version = "1.0.0" module_proto_version = "1.0.0"
...@@ -9,4 +9,3 @@ six >= 1.10.0 ...@@ -9,4 +9,3 @@ six >= 1.10.0
chardet == 3.0.4 chardet == 3.0.4
requests requests
pandas pandas
pyahocorasick
...@@ -32,7 +32,7 @@ max_version, mid_version, min_version = python_version() ...@@ -32,7 +32,7 @@ max_version, mid_version, min_version = python_version()
REQUIRED_PACKAGES = [ REQUIRED_PACKAGES = [
'numpy >= 1.12.0', 'six >= 1.10.0', 'pandas', 'protobuf >= 3.1.0', 'pyyaml', 'numpy >= 1.12.0', 'six >= 1.10.0', 'pandas', 'protobuf >= 3.1.0', 'pyyaml',
'Pillow', 'requests', "visualdl >= 1.3.0", "pyahocorasick" 'Pillow', 'requests', "visualdl >= 1.3.0"
] ]
if max_version < 3: if max_version < 3:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册