提交 ef273daa 编写于 作者: K kinghuin 提交者: wuzewu

ready 1.5 (#290)

* Update README.md

Polish README
Co-authored-by: NZeyu Chen <chenzeyu01@baidu.com>
Co-authored-by: NSteffy-zxf <48793257+Steffy-zxf@users.noreply.github.com>
上级 c77b4ebc
...@@ -4,26 +4,16 @@ ...@@ -4,26 +4,16 @@
[![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特性: PaddleHub是飞桨预训练模型管理和迁移学习工具,通过PaddleHub开发者可以使用高质量的预训练模型结合Fine-tune API快速完成迁移学习到应用部署的全流程工作。PaddleHub具有以下特性:
* 便捷地获取PaddlePaddle生态下的所有预训练模型,涵盖了图像分类、目标检测、词法分析、语义模型、情感分析、语言模型、视频分类、图像生成、图像分割等主流模型。 * 便捷获取飞桨生态下的高质量预训练模型,涵盖了图像分类、目标检测、词法分析、语义模型、情感分析、视频分类、图像生成、图像分割、文本审核、关键点检测等主流模型。更多模型详情请查看官网:https://www.paddlepaddle.org.cn/hub
* 更多详情可查看官网:https://www.paddlepaddle.org.cn/hub * 通过高质量预训练模型与PaddleHub Fine-tune API,只需要少量代码即可实现自然语言处理和计算机视觉场景的深度学习模型,更多Demo请参考以下链接:
* 通过PaddleHub Fine-tune API,结合少量代码即可完成**大规模预训练模型**的迁移学习,具体Demo可参考以下链接:
* [文本分类](./demo/text-classification) [文本分类](./demo/text_classification) [序列标注](./demo/sequence_labeling) [多标签分类](./demo/multi_label_classification) [图像分类](./demo/image_classification) [检索式问答任务](./demo/qa_classification) [回归任务](./demo/regression) [句子语义相似度计算](./demo/sentence_similarity) [阅读理解任务](./demo/reading_comprehension)
* [序列标注](./demo/sequence-labeling)
* [多标签分类](./demo/multi-label-classification) ***模型即软件**』的设计理念,通过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)
* [图像分类](./demo/image-classification) * PaddleHub提供便捷的服务化部署能力,简单一行命令即可搭建属于自己的模型的API服务,更多详情请参考教程[PaddleHub Serving一键服务化部署](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-Serving%E4%B8%80%E9%94%AE%E6%9C%8D%E5%8A%A1%E9%83%A8%E7%BD%B2)[使用示例](./demo/serving)
* [检索式问答任务](./demo/qa_classification) * 支持AutoDL Finetuner超参优化技术, 自动搜索最优模型超参得到更好的模型效果。详情请参考[AutoDL Finetuner超参优化功能教程](./tutorial/autofinetune.md)
* [回归任务](./demo/sentence_similarity)
* [句子语义相似度计算](./demo/sentence_similarity)
* [阅读理解任务](./demo/reading-comprehension)
* 支持超参优化(AutoDL Finetuner),自动调整超参数,给出效果较佳的超参数组合。
* [PaddleHub超参优化功能AutoDL Finetuner使用示例](./demo/autofinetune)
* 引入『**模型即软件**』的设计理念,通过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)
* 一键Module服务化部署 - HubServing
* [PaddleHub-Serving一键服务部署](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-Serving%E4%B8%80%E9%94%AE%E6%9C%8D%E5%8A%A1%E9%83%A8%E7%BD%B2)
* [使用示例](./demo/serving)
## 目录 ## 目录
...@@ -53,7 +43,7 @@ pip安装方式如下: ...@@ -53,7 +43,7 @@ pip安装方式如下:
```shell ```shell
$ pip install paddlehub $ pip install paddlehub
``` ```
2. 下载数据集、module等,PaddleHub要求机器可以访问外网。可以使用server_check()可以检查本地与远端PaddleHub-Server的连接状态,使用方法如下: 2. 使用PaddleHub下载数据集、预训练模型等,要求机器可以访问外网。可以使用server_check()可以检查本地与远端PaddleHub-Server的连接状态,使用方法如下:
```python ```python
import paddlehub import paddlehub
...@@ -64,9 +54,7 @@ paddlehub.server_check() ...@@ -64,9 +54,7 @@ paddlehub.server_check()
## 快速体验 ## 快速体验
安装成功后,执行下面的命令,可以快速体验PaddleHub无需代码、一键预测的命令行功能: 安装成功后,执行命令[hub run](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%B7%A5%E5%85%B7#run),可以快速体验PaddleHub无需代码、一键预测的命令行功能,如下三个示例:
`示例一`
使用[词法分析](http://www.paddlepaddle.org.cn/hub?filter=category&value=LexicalAnalysis)模型LAC进行分词 使用[词法分析](http://www.paddlepaddle.org.cn/hub?filter=category&value=LexicalAnalysis)模型LAC进行分词
```shell ```shell
...@@ -74,82 +62,85 @@ $ hub run lac --input_text "今天是个好日子" ...@@ -74,82 +62,85 @@ $ hub run lac --input_text "今天是个好日子"
[{'word': ['今天', '是', '个', '好日子'], 'tag': ['TIME', 'v', 'q', 'n']}] [{'word': ['今天', '是', '个', '好日子'], 'tag': ['TIME', 'v', 'q', 'n']}]
``` ```
`示例二`
使用[情感分析](http://www.paddlepaddle.org.cn/hub?filter=category&value=SentimentAnalysis)模型Senta对句子进行情感预测 使用[情感分析](http://www.paddlepaddle.org.cn/hub?filter=category&value=SentimentAnalysis)模型Senta对句子进行情感预测
```shell ```shell
$ hub run senta_bilstm --input_text "今天天气真好" $ hub run senta_bilstm --input_text "今天天气真好"
{'text': '今天天气真好', 'sentiment_label': 1, 'sentiment_key': 'positive', 'positive_probs': 0.9798, 'negative_probs': 0.0202}] {'text': '今天天气真好', 'sentiment_label': 1, 'sentiment_key': 'positive', 'positive_probs': 0.9798, 'negative_probs': 0.0202}]
``` ```
`示例三`
使用[目标检测](http://www.paddlepaddle.org.cn/hub?filter=category&value=ObjectDetection)模型 SSD/YOLO v3/Faster RCNN 对图片进行目标检测 使用[目标检测](http://www.paddlepaddle.org.cn/hub?filter=category&value=ObjectDetection)模型 SSD/YOLO v3/Faster RCNN 对图片进行目标检测
```shell ```shell
$ wget --no-check-certificate https://paddlehub.bj.bcebos.com/resources/test_object_detection.jpg $ wget https://paddlehub.bj.bcebos.com/resources/test_object_detection.jpg
$ hub run ssd_mobilenet_v1_pascal --input_path 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 yolov3_darknet53_coco2017 --input_path test_object_detection.jpg
$ hub run faster_rcnn_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.3/docs/imgs/object_detection_result.png) ![SSD检测结果](https://raw.githubusercontent.com/PaddlePaddle/PaddleHub/release/v1.3/docs/imgs/object_detection_result.png)
除了上述三类模型外,PaddleHub还发布了语言模型、语义模型、图像分类、生成模型、视频分类等业界主流模型,更多PaddleHub已经发布的模型,请前往 https://www.paddlepaddle.org.cn/hub 查看 除了上述三类模型外,PaddleHub还发布了图像分类、语义模型、视频分类、图像生成、图像分割、文本审核、关键点检测等业界主流模型,更多PaddleHub已经发布的模型,请前往 https://www.paddlepaddle.org.cn/hub 查看
## 教程
同时,我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下: 我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
|类别|AIStudio链接| |预训练模型|任务类型|数据集|AIStudio链接|备注|
|-|-| |-|-|-|-|-|
|ERNIE Tiny 文本分类|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/186443) |ResNet|图像分类|猫狗数据集DogCat|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216772)||
|ERNIE文本分类|[点击体验](https://aistudio.baidu.com/aistudio/projectDetail/79380)| |ERNIE|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216764)||
|ERNIE序列标注|[点击体验](https://aistudio.baidu.com/aistudio/projectDetail/79377)| |ERNIE|文本分类|中文新闻分类数据集THUNEWS|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216649)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成文本分类迁移学习。|
|ELMo文本分类|[点击体验](https://aistudio.baidu.com/aistudio/projectDetail/79400)| |ERNIE|序列标注|中文序列标注数据集MSRA_NER|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216787)||
|senta情感分类|[点击体验](https://aistudio.baidu.com/aistudio/projectDetail/79398)| |ERNIE|序列标注|中文快递单数据集Express|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216683)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成序列标注迁移学习。|
|图像分类| [点击体验](https://aistudio.baidu.com/aistudio/projectDetail/79378)| |ERNIE Tiny|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215599)||
|自定义数据FineTune(序列标注任务)|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/184200)| |Senta|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216851)|本教程讲述了任何利用Senta和Fine-tune API完成情感分类迁移学习。|
|自定义数据FineTune(文本分类任务)|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/185121) | |Senta|情感分析预测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216735)||
|LAC|词法分析|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215641)||
|Ultra-Light-Fast-Generic-Face-Detector-1MB|人脸检测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216749)||
## 教程 同时,关于PaddleHub更多信息参考:
[Fine-tune API](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-Finetune-API)
[自定义数据集如何Fine-tune](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 Fine-tune API 详情参考[wiki教程](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-Finetune-API) [实现自定义迁移任务](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub:-%E8%87%AA%E5%AE%9A%E4%B9%89Task)
PaddleHub如何完成迁移学习,详情参考[wiki教程](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub%E4%B8%8E%E8%BF%81%E7%A7%BB%E5%AD%A6%E4%B9%A0) [PaddleHub Serving一键服务化部署](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-Serving%E4%B8%80%E9%94%AE%E6%9C%8D%E5%8A%A1%E9%83%A8%E7%BD%B2)
PaddleHub如何自定义迁移任务,详情参考[wiki教程](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub:-%E8%87%AA%E5%AE%9A%E4%B9%89Task) [自动优化超参AutoDL Finetuner使用教程](https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.3/tutorial/autofinetune.md)
[迁移学习与ULMFiT微调策略](https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.3/tutorial/strategy_exp.md)
PaddleHub如何自动优化超参数,详情参考[AutoDL Finetuner使用教程](https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.3/tutorial/autofinetune.md)
PaddleHub如何使用ULMFiT策略微调预训练模型,详情参考[PaddleHub 迁移学习与ULMFiT微调策略](https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.3/tutorial/strategy_exp.md)
## FAQ ## FAQ
**Q:** 利用PaddleHub ernie/bert进行Finetune时,运行出错并提示`paddle.fluid.core_avx.EnforceNotMet: Input ShapeTensor cannot be found in Op reshape2`等信息 **Q:** 利用PaddleHub Fine-tune如何适配自定义数据集
**A:** 参考[PaddleHub适配自定义数据集完成Fine-tune](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)
**A:** 因为ernie/bert module的创建时和此时运行环境中PaddlePaddle版本不对应。可以将PaddlePaddle和PaddleHub升级至最新版本,同时将ernie卸载。
```shell
$ pip install --upgrade paddlehub
$ hub uninstall ernie
```
**Q:** 使用PaddleHub时,无法下载预置数据集、Module的等现象 **Q:** 使用PaddleHub时,无法下载预置数据集、Module的等现象
**A:** PaddleHub中的预训练模型和预置数据集都需要通过服务端进行下载,因此PaddleHub默认用户访问外网权限。 **A:** 下载数据集、module等,PaddleHub要求机器可以访问外网。可以使用server_check()可以检查本地与远端PaddleHub-Server的连接状态,使用方法如下:
可以通过以下命令确认是否可以访问外网。
```python ```python
import requests import paddlehub
paddlehub.server_check()
# 如果可以连接远端PaddleHub-Server,则显示Request Hub-Server successfully.
# 如果无法连接远端PaddleHub-Server,则显示Request Hub-Server unsuccessfully.
```
res = requests.get('http://paddlepaddle.org.cn/paddlehub/search', {'word': 'ernie', 'type': 'Module'}) **Q:** 利用PaddleHub ernie/bert进行Fine-tune时,运行出错并提示`paddle.fluid.core_avx.EnforceNotMet: Input ShapeTensor cannot be found in Op reshape2`等信息
print(res)
# the common result is like this: **A:** 因为ernie/bert module的创建时和此时运行环境中PaddlePaddle版本不对应。可以将PaddlePaddle和PaddleHub升级至最新版本,同时将ernie卸载。
# <Response [200]> ```shell
$ pip install --upgrade paddlehub
$ hub uninstall ernie
``` ```
**Note:** PaddleHub 1.1.1版本已支持离线运行Module
**Q:** 利用PaddleHub Finetune如何适配自定义数据集
**A:** 参考[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) **NOTE**: PaddleHub 1.1.1版本已支持离线运行Module
**更多问题** **更多问题**
...@@ -165,4 +156,6 @@ print(res) ...@@ -165,4 +156,6 @@ print(res)
## 更新历史 ## 更新历史
PaddleHub v1.4.1已发布!
详情参考[更新历史](./RELEASE.md) 详情参考[更新历史](./RELEASE.md)
...@@ -99,4 +99,4 @@ ...@@ -99,4 +99,4 @@
**命令行一键使用**: 无需代码,通过命令行即可直接使用预训练模型进行预测,快速调研训练模型效果。目前版本支持以下模型:词法分析LAC;情感分析Senta;目标检测SSD;图像分类ResNet, MobileNet, NASNet等。 **命令行一键使用**: 无需代码,通过命令行即可直接使用预训练模型进行预测,快速调研训练模型效果。目前版本支持以下模型:词法分析LAC;情感分析Senta;目标检测SSD;图像分类ResNet, MobileNet, NASNet等。
**迁移学习**: 提供了基于预训练模型的Finetune API,用户通过少量代码即可完成迁移学习,包括BERT/ERNIE文本分类、序列标注、图像分类迁移等。 **迁移学习**: 提供了基于预训练模型的Fine-tune API,用户通过少量代码即可完成迁移学习,包括BERT/ERNIE文本分类、序列标注、图像分类迁移等。
...@@ -2,78 +2,66 @@ ...@@ -2,78 +2,66 @@
目前PaddleHub有以下任务示例: 目前PaddleHub有以下任务示例:
>* 图像分类 * [图像分类](./image-classification)
该样例展示了PaddleHub如何将ResNet50、ResNet101、ResNet152、MobileNet、NasNet以及PNasNet作为预训练模型在Flowers、DogCat、Indoor67、Food101、StanfordDogs等数据集上进行图像分类的FineTune和预测。
>* 中文词法分析 * [中文词法分析](./lac)
该样例展示了PaddleHub如何利用中文词法分析LAC进行预测。
>* 情感分析 * [情感分析](./senta)
该样例展示了PaddleHub如何利用中文情感分析模型Senta进行FineTune和预测。
>* 序列标注 * [序列标注](./sequence-labeling)
该样例展示了PaddleHub如何将ERNIE/BERT等Transformer类模型作为预训练模型在MSRA_NER数据集上完成序列标注的FineTune和预测。
>* 目标检测 * [目标检测](./ssd)
该样例展示了PaddleHub如何将SSD作为预训练模型在PascalVOC数据集上完成目标检测的预测。
>* 文本分类 * [文本分类](./text-classification)
该样例展示了PaddleHub如何将ERNIE/BERT等Transformer类模型作为预训练模型在GLUE、ChnSentiCorp等数据集上完成文本分类的FineTune和预测。
>* 多标签分类 * [多标签分类](./multi-label-classification)
该样例展示了PaddleHub如何将BERT作为预训练模型在Toxic数据集上完成多标签分类的FineTune和预测。
>* 回归任务 * [回归任务](./regression)
该样例展示了PaddleHub如何将BERT作为预训练模型在GLUE-STSB数据集上完成回归任务的FineTune和预测。
>* 阅读理解 * [阅读理解](./reading-comprehension)
该样例展示了PaddleHub如何将BERT作为预训练模型在SQAD数据集上完成阅读理解的FineTune和预测。
>* 检索式问答任务 * [检索式问答任务](./qa_classfication)
该样例展示了PaddleHub如何将ERNIE和BERT作为预训练模型在NLPCC-DBQA等数据集上完成检索式问答任务的FineTune和预测。
>* 句子语义相似度计算 * [句子语义相似度计算](./sentence_similarity)
该样例展示了PaddleHub如何将word2vec_skipgram用于计算两个文本语义相似度。
## 图像分类 * [超参优化AutoDL Finetuner使用](./autofinetune)
该样例展示了PaddleHub超参优化AutoDL Finetuner如何使用,给出了自动搜素图像分类/文本分类任务的较佳超参数示例。
该样例展示了PaddleHub如何将ResNet50、ResNet101、ResNet152、MobileNet、NasNet以及PNasNet作为预训练模型在Flowers、DogCat、Indoor67、Food101、StanfordDogs等数据集上进行图像分类的FineTune和预测。 * [服务化部署Hub Serving使用](./serving)
该样例文件夹下展示了服务化部署Hub Serving如何使用,将PaddleHub支持的可预测Module如何服务化部署。
## 中文词法分析 **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如何利用中文词法分析LAC进行预测。
## 情感分析
该样例展示了PaddleHub如何利用中文情感分析模型Senta进行FineTune和预测。
## 序列标注
该样例展示了PaddleHub如何将ERNIE和BERT作为预训练模型在MSRA_NER数据集上
完成序列标注的FineTune和预测。
## 目标检测
该样例展示了PaddleHub如何将SSD作为预训练模型在PascalVOC数据集上
完成目标检测的预测。
## 文本分类
该样例展示了PaddleHub
>* 如何将ERNIE和BERT作为预训练模型在ChnSentiCorp、LCQMC和NLPCC-DBQA等数据集上完成文本分类的FineTune和预测。
>* 如何将ELMo预训练得到的中文word embedding加载,完成在ChnSentiCorp数据集上文本分类的FineTune和预测。
## 多标签分类
该样例展示了PaddleHub如何将BERT作为预训练模型在Toxic数据集上完成多标签分类的FineTune和预测。
## 回归任务
该样例展示了PaddleHub如何将BERT作为预训练模型在GLUE-STSB数据集上完成回归任务的FineTune和预测。
## 阅读理解
该样例展示了PaddleHub如何将BERT作为预训练模型在SQAD数据集上完成阅读理解的FineTune和预测。
## 检索式问答任务 ## 快速体验
该样例展示了PaddleHub如何将ERNIE和BERT作为预训练模型在NLPCC-DBQA等数据集上完成检索式问答任务的FineTune和预测。 我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
## 句子语义相似度计算 |预训练模型|任务类型|数据集|AIStudio链接|备注|
|-|-|-|-|-|
|ResNet|图像分类|猫狗数据集DogCat|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216772)||
|ERNIE|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216764)||
|ERNIE|文本分类|中文新闻分类数据集THUNEWS|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216649)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成文本分类迁移学习。|
|ERNIE|序列标注|中文序列标注数据集MSRA_NER|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216787)||
|ERNIE|序列标注|中文快递单数据集Express|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216683)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成序列标注迁移学习。|
|ERNIE Tiny|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215599)||
|Senta|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216851)|本教程讲述了任何利用Senta和Fine-tune API完成情感分类迁移学习。|
|Senta|情感分析预测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216735)||
|LAC|词法分析|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215641)||
|Ultra-Light-Fast-Generic-Face-Detector-1MB|人脸检测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216749)||
该样例展示了PaddleHub如何将word2vec_skipgram用于计算两个文本语义相似度。
## 模型服务化 ## 超参优化AutoDL Finetuner
展示了PaddleHub-Serving如何利用模型进行服务化部署,主要包括模型预测服务化和Bert-as-Service服务化。
**NOTE** PaddleHub还提供了超参优化(Hyperparameter Tuning)功能, 自动搜索最优模型超参得到更好的模型效果。详细信息参见[AutoDL Finetuner超参优化功能教程](../tutorial/autofinetune.md)
以上任务示例均是利用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/release/v1.2/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`
## 可视化
Finetune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令
```bash
$ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM}
```
其中${HOST_IP}为本机IP地址,${PORT_NUM}为可用端口号,如本机IP地址为192.168.0.1,端口号8040,用浏览器打开192.168.0.1: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`
#coding:utf-8
import argparse
import ast
import io
import numpy as np
from paddle.fluid.framework import switch_main_program
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=True, help="Whether use GPU for finetuning, input should be True or False")
parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint")
parser.add_argument("--batch_size", type=int, default=32, help="Total examples' number in batch for training.")
parser.add_argument("--learning_rate", type=float, default=1e-4, help="Learning rate used to train with warmup.")
parser.add_argument("--weight_decay", type=float, default=5, help="Weight decay rate for L2 regularizer.")
parser.add_argument("--warmup_proportion", type=float, default=0.05, help="Warmup proportion params for warmup strategy")
args = parser.parse_args()
# yapf: enable.
def bow_net(program, input_feature, hid_dim=128, hid_dim2=96):
switch_main_program(program)
bow = fluid.layers.sequence_pool(input=input_feature, pool_type='sum')
bow_tanh = fluid.layers.tanh(bow)
fc_1 = fluid.layers.fc(input=bow_tanh, size=hid_dim, act="tanh")
fc = fluid.layers.fc(input=fc_1, size=hid_dim2, act="tanh")
return fc
def cnn_net(program, input_feature, win_size=3, hid_dim=128, hid_dim2=96):
switch_main_program(program)
conv_3 = fluid.nets.sequence_conv_pool(
input=input_feature,
num_filters=hid_dim,
filter_size=win_size,
act="relu",
pool_type="max")
fc = fluid.layers.fc(input=conv_3, size=hid_dim2)
return fc
def gru_net(program, input_feature, hid_dim=128, hid_dim2=96):
switch_main_program(program)
fc0 = fluid.layers.fc(input=input_feature, size=hid_dim * 3)
gru_h = fluid.layers.dynamic_gru(input=fc0, size=hid_dim, is_reverse=False)
gru_max = fluid.layers.sequence_pool(input=gru_h, pool_type='max')
gru_max_tanh = fluid.layers.tanh(gru_max)
fc = fluid.layers.fc(input=gru_max_tanh, size=hid_dim2, act='tanh')
return fc
def bilstm_net(program, input_feature, hid_dim=128, hid_dim2=96):
switch_main_program(program)
fc0 = fluid.layers.fc(input=input_feature, size=hid_dim * 4)
rfc0 = fluid.layers.fc(input=input_feature, size=hid_dim * 4)
lstm_h, c = fluid.layers.dynamic_lstm(
input=fc0, size=hid_dim * 4, is_reverse=False)
rlstm_h, c = fluid.layers.dynamic_lstm(
input=rfc0, size=hid_dim * 4, is_reverse=True)
# extract last step
lstm_last = fluid.layers.sequence_last_step(input=lstm_h)
rlstm_last = fluid.layers.sequence_last_step(input=rlstm_h)
lstm_last_tanh = fluid.layers.tanh(lstm_last)
rlstm_last_tanh = fluid.layers.tanh(rlstm_last)
# concat layer
lstm_concat = fluid.layers.concat(input=[lstm_last, rlstm_last], axis=1)
# full connect layer
fc = fluid.layers.fc(input=lstm_concat, size=hid_dim2, act='tanh')
return fc
def lstm_net(program, input_feature, hid_dim=128, hid_dim2=96):
switch_main_program(program)
fc0 = fluid.layers.fc(input=input_feature, size=hid_dim * 4)
lstm_h, c = fluid.layers.dynamic_lstm(
input=fc0, size=hid_dim * 4, is_reverse=False)
lstm_max = fluid.layers.sequence_pool(input=lstm_h, pool_type='max')
lstm_max_tanh = fluid.layers.tanh(lstm_max)
fc = fluid.layers.fc(input=lstm_max_tanh, size=hid_dim2, act='tanh')
return fc
if __name__ == '__main__':
# Step1: load Paddlehub elmo pretrained model
module = hub.Module(name="elmo")
inputs, outputs, program = module.context(trainable=True)
# Step2: Download dataset and use LACClassifyReade to read dataset
dataset = hub.dataset.ChnSentiCorp()
reader = hub.reader.LACClassifyReader(
dataset=dataset, vocab_path=module.get_vocab_path())
word_dict_len = len(reader.vocab)
word_ids = inputs["word_ids"]
elmo_embedding = outputs["elmo_embed"]
# Step3: switch program and build network
# Choose the net which you would like: bow, cnn, gru, bilstm, lstm
switch_main_program(program)
# Embedding layer
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)))
# Add elmo embedding
input_feature = fluid.layers.concat(
input=[elmo_embedding, word_embedding], axis=1)
# Choose the net which you would like: bow, cnn, gru, bilstm, lstm
# We recommend you to choose the gru_net
fc = gru_net(program, input_feature)
# Setup feed list for data feeder
# Must feed all the tensor of senta's module need
feed_list = [word_ids.name]
# Step4: Select finetune strategy, setup config and finetune
strategy = hub.AdamWeightDecayStrategy(
weight_decay=args.weight_decay,
learning_rate=args.learning_rate,
lr_scheduler="linear_decay",
warmup_proportion=args.warmup_proportion)
# Step5: Setup runing config for PaddleHub Finetune API
config = hub.RunConfig(
use_cuda=args.use_gpu,
use_data_parallel=True,
use_pyreader=False,
num_epoch=args.num_epoch,
batch_size=args.batch_size,
checkpoint_dir=args.checkpoint_dir,
strategy=strategy)
# Step6: Define a classfication finetune task by PaddleHub's API
elmo_task = hub.TextClassifierTask(
data_reader=reader,
feature=fc,
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
elmo_task.finetune_and_eval()
#coding:utf-8
import argparse
import ast
import io
import numpy as np
from paddle.fluid.framework import switch_main_program
import paddle.fluid as fluid
import paddlehub as hub
# yapf: disable
parser = argparse.ArgumentParser(__doc__)
parser.add_argument("--use_gpu", type=ast.literal_eval, default=True, help="Whether use GPU for finetuning, input should be True or False")
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("--learning_rate", type=float, default=1e-4, help="Learning rate used to train with warmup.")
parser.add_argument("--weight_decay", type=float, default=5, help="Weight decay rate for L2 regularizer.")
parser.add_argument("--warmup_proportion", type=float, default=0.05, help="Warmup proportion params for warmup strategy")
args = parser.parse_args()
# yapf: enable.
def bow_net(program, input_feature, hid_dim=128, hid_dim2=96):
switch_main_program(program)
bow = fluid.layers.sequence_pool(input=input_feature, pool_type='sum')
bow_tanh = fluid.layers.tanh(bow)
fc_1 = fluid.layers.fc(input=bow_tanh, size=hid_dim, act="tanh")
fc = fluid.layers.fc(input=fc_1, size=hid_dim2, act="tanh")
return fc
def cnn_net(program, input_feature, win_size=3, hid_dim=128, hid_dim2=96):
switch_main_program(program)
conv_3 = fluid.nets.sequence_conv_pool(
input=input_feature,
num_filters=hid_dim,
filter_size=win_size,
act="relu",
pool_type="max")
fc = fluid.layers.fc(input=conv_3, size=hid_dim2)
return fc
def gru_net(program, input_feature, hid_dim=128, hid_dim2=96):
switch_main_program(program)
fc0 = fluid.layers.fc(input=input_feature, size=hid_dim * 3)
gru_h = fluid.layers.dynamic_gru(input=fc0, size=hid_dim, is_reverse=False)
gru_max = fluid.layers.sequence_pool(input=gru_h, pool_type='max')
gru_max_tanh = fluid.layers.tanh(gru_max)
fc = fluid.layers.fc(input=gru_max_tanh, size=hid_dim2, act='tanh')
return fc
def bilstm_net(program, input_feature, hid_dim=128, hid_dim2=96):
switch_main_program(program)
fc0 = fluid.layers.fc(input=input_feature, size=hid_dim * 4)
rfc0 = fluid.layers.fc(input=input_feature, size=hid_dim * 4)
lstm_h, c = fluid.layers.dynamic_lstm(
input=fc0, size=hid_dim * 4, is_reverse=False)
rlstm_h, c = fluid.layers.dynamic_lstm(
input=rfc0, size=hid_dim * 4, is_reverse=True)
# extract last step
lstm_last = fluid.layers.sequence_last_step(input=lstm_h)
rlstm_last = fluid.layers.sequence_last_step(input=rlstm_h)
lstm_last_tanh = fluid.layers.tanh(lstm_last)
rlstm_last_tanh = fluid.layers.tanh(rlstm_last)
# concat layer
lstm_concat = fluid.layers.concat(input=[lstm_last, rlstm_last], axis=1)
# full connect layer
fc = fluid.layers.fc(input=lstm_concat, size=hid_dim2, act='tanh')
return fc
def lstm_net(program, input_feature, hid_dim=128, hid_dim2=96):
switch_main_program(program)
fc0 = fluid.layers.fc(input=input_feature, size=hid_dim * 4)
lstm_h, c = fluid.layers.dynamic_lstm(
input=fc0, size=hid_dim * 4, is_reverse=False)
lstm_max = fluid.layers.sequence_pool(input=lstm_h, pool_type='max')
lstm_max_tanh = fluid.layers.tanh(lstm_max)
fc = fluid.layers.fc(input=lstm_max_tanh, size=hid_dim2, act='tanh')
return fc
if __name__ == '__main__':
# Step1: load Paddlehub elmo pretrained model
module = hub.Module(name="elmo")
inputs, outputs, program = module.context(trainable=True)
# Step2: Download dataset and use LACClassifyReade to read dataset
dataset = hub.dataset.ChnSentiCorp()
reader = hub.reader.LACClassifyReader(
dataset=dataset, vocab_path=module.get_vocab_path())
word_dict_len = len(reader.vocab)
word_ids = inputs["word_ids"]
elmo_embedding = outputs["elmo_embed"]
# Step3: switch program and build network
# Choose the net which you would like: bow, cnn, gru, bilstm, lstm
switch_main_program(program)
# Embedding layer
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)))
# Add elmo embedding
input_feature = fluid.layers.concat(
input=[elmo_embedding, word_embedding], axis=1)
# Choose the net which you would like: bow, cnn, gru, bilstm, lstm
# We recommend you to choose the gru_net
fc = gru_net(program, input_feature)
# Setup feed list for data feeder
# Must feed all the tensor of senta's module need
feed_list = [word_ids.name]
# Step4: Select finetune strategy, setup config and finetune
strategy = hub.AdamWeightDecayStrategy(
weight_decay=args.weight_decay,
learning_rate=args.learning_rate,
lr_scheduler="linear_decay",
warmup_proportion=args.warmup_proportion)
# Step5: Setup runing config for PaddleHub Finetune API
config = hub.RunConfig(
use_cuda=args.use_gpu,
use_data_parallel=True,
use_pyreader=False,
batch_size=args.batch_size,
checkpoint_dir=args.checkpoint_dir,
strategy=strategy)
# Step6: Define a classfication finetune task by PaddleHub's API
elmo_task = hub.TextClassifierTask(
data_reader=reader,
feature=fc,
feed_list=feed_list,
num_classes=dataset.num_labels,
config=config)
# Data to be prdicted
data = [
"这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般", "交通方便;环境很好;服务态度很好 房间较小",
"还稍微重了点,可能是硬盘大的原故,还要再轻半斤就好了。其他要进一步验证。贴的几种膜气泡较多,用不了多久就要更换了,屏幕膜稍好点,但比没有要强多了。建议配赠几张膜让用用户自己贴。",
"前台接待太差,酒店有A B楼之分,本人check-in后,前台未告诉B楼在何处,并且B楼无明显指示;房间太小,根本不像4星级设施,下次不会再选择入住此店啦",
"19天硬盘就罢工了~~~算上运来的一周都没用上15天~~~可就是不能换了~~~唉~~~~你说这算什么事呀~~~"
]
print(elmo_task.predict(data=data, return_result=True))
# PaddleHub 图像分类
## 关于
本示例将展示如何使用PaddleHub Finetune API以及[图像分类](https://github.com/PaddlePaddle/models/tree/release/v1.2/PaddleCV/image_classification)预训练模型完成分类任务。
## 准备工作
在运行本目录的脚本前,需要先安装1.3.0版本以上的PaddlePaddle(如果您本地已经安装了符合条件的PaddlePaddle版本,那么可以跳过`准备工作`这一步)。
如果您的机器支持GPU,我们建议下载GPU版本的PaddlePaddle,使用GPU进行训练和预测的效率都比使用CPU要高。
```shell
# 安装GPU版本的PaddlePaddle
$ pip install --upgrade paddlepaddle-gpu
```
如果您的机器不支持GPU,可以通过下面的命令来安装CPU版本的PaddlePaddle
```shell
# 安装CPU版本的PaddlePaddle
$ pip install --upgrade paddlepaddle
```
在安装过程中如果遇到问题,您可以到[Paddle官方网站](http://www.paddlepaddle.org/)上查看解决方案。
## 开始Fine-tune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_classifier.sh`即可开始使用进行finetune。
脚本支持的参数如下:
```shell
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数。默认为16
--num_epoch: finetune迭代的轮数。默认为1
--module: 使用哪个Module作为finetune的特征提取器,脚本支持{resnet50/resnet101/resnet152/mobilenet/nasnet/pnasnet}等模型。默认为resnet50
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型。默认为paddlehub_finetune_ckpt
--dataset: 使用什么数据集进行finetune, 脚本支持分别是{flowers/dogcat/stanforddogs/indoor67/food101}。默认为flowers
--use_gpu: 是否使用GPU进行训练,如果机器支持GPU且安装了GPU版本的PaddlePaddle,我们建议您打开这个开关。默认关闭
--use_data_parallel: 是否使用数据并行,打开该开关时,会将数据分散到不同的卡上进行训练(CPU下会分布到不同线程)。默认关闭
--use_pyreader: 是否使用pyreader进行数据喂入。默认关闭
```
## 进行预测
当完成finetune后,finetune过程在验证集上表现最优的模型会被保存在`${CHECKPOINT_DIR}/best_model`目录下,其中`${CHECKPOINT_DIR}`目录为finetune时所选择的保存checkpoint的目录。
我们使用该模型来进行预测。执行脚本`sh predict.sh`即可开始使用进行预测。
脚本支持的参数如下:
```shell
--module: 使用哪个Module作为finetune的特征提取器,脚本支持{resnet50/resnet101/resnet152/mobilenet/nasnet/pnasnet}等模型。默认为resnet50
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型。默认为paddlehub_finetune_ckpt
--dataset: 使用什么数据集进行finetune, 脚本支持分别是{flowers/dogcat}。默认为flowers
--use_gpu: 使用使用GPU进行训练,如果本机支持GPU且安装了GPU版本的PaddlePaddle,我们建议您打开这个开关。默认关闭
--use_pyreader: 是否使用pyreader进行数据喂入。默认关闭
```
`注意`:进行预测时,所选择的module,checkpoint_dir,dataset必须和finetune所用的一样
# PaddleHub 图像分类
本示例将展示如何使用PaddleHub Fine-tune API以及[ResNet](https://www.paddlepaddle.org.cn/hubdetail?name=resnet_v2_50_imagenet&en_category=ImageClassification)等预训练模型完成分类任务。
## 如何开始Fine-tune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_classifier.sh`即可开始使用ResNet对[Flowers](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Dataset#class-hubdatasetflowersdataset)等数据集进行Fine-tune。
其中脚本参数说明如下:
```shell
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数。默认为16
--num_epoch: Fine-tune迭代的轮数。默认为1
--module: 使用哪个Module作为Fine-tune的特征提取器,脚本支持{resnet50/resnet101/resnet152/mobilenet/nasnet/pnasnet}等模型。默认为resnet50
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型。默认为paddlehub_finetune_ckpt
--dataset: 使用什么数据集进行Fine-tune, 脚本支持分别是{flowers/dogcat/stanforddogs/indoor67/food101}。默认为flowers
--use_gpu: 是否使用GPU进行训练,如果机器支持GPU且安装了GPU版本的PaddlePaddle,我们建议您打开这个开关。默认关闭
--use_data_parallel: 是否使用数据并行,打开该开关时,会将数据分散到不同的卡上进行训练(CPU下会分布到不同线程)。默认打开
```
## 代码步骤
使用PaddleHub Fine-tune API进行Fine-tune可以分为4个步骤
### Step1: 加载预训练模型
```python
module = hub.Module(name="resnet_v2_50_imagenet")
inputs, outputs, program = module.context(trainable=True)
```
PaddleHub提供许多图像分类预训练模型,如xception、mobilenet、efficientnet等,详细信息参见[图像分类模型](https://www.paddlepaddle.org.cn/hub?filter=en_category&value=ImageClassification)
如果想尝试efficientnet模型,只需要更换Module中的`name`参数即可.
```python
# 更换name参数即可无缝切换efficientnet模型, 代码示例如下
module = hub.Module(name="efficientnetb7_imagenet")
```
### Step2: 下载数据集并使用ImageClassificationReader读取数据
```python
dataset = hub.dataset.Flowers()
data_reader = hub.reader.ImageClassificationReader(
image_width=module.get_expected_image_width(),
image_height=module.get_expected_image_height(),
images_mean=module.get_pretrained_images_mean(),
images_std=module.get_pretrained_images_std(),
dataset=dataset)
```
其中数据集的准备代码可以参考 [flowers.py](../../paddlehub/dataset/flowers.py)
同时,PaddleHub提供了更多的图像分类数据集:
| 数据集 | API |
| -------- | ------------------------------------------ |
| Flowers | hub.dataset.Flowers() |
| DogCat | hub.dataset.DogCat() |
| Indoor67 | hub.dataset.Indoor67() |
| Food101 | hub.dataset.Food101() |
`hub.dataset.Flowers()` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录
`module.get_expected_image_width()``module.get_expected_image_height()`会返回预训练模型对应的图片尺寸
`module.module.get_pretrained_images_mean()``module.get_pretrained_images_std()`会返回预训练模型对应的图片均值和方差
#### 自定义数据集
如果想加载自定义数据集完成迁移学习,详细参见[自定义数据集](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)
### Step3:选择优化策略和运行配置
```python
strategy = hub.DefaultFinetuneStrategy(
learning_rate=1e-4,
optimizer_name="adam",
regularization_coeff=1e-3)
config = hub.RunConfig(use_cuda=True, use_data_parallel=True, num_epoch=3, batch_size=32, strategy=strategy)
```
#### 优化策略
PaddleHub提供了许多优化策略,如`AdamWeightDecayStrategy``ULMFiTStrategy``DefaultFinetuneStrategy`等,详细信息参见[策略](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Strategy)
其中`DefaultFinetuneStrategy`:
* `learning_rate`: 全局学习率。默认为1e-4
* `optimizer_name`: 优化器名称。默认adam
* `regularization_coeff`: 正则化的λ参数。默认为1e-3
#### 运行配置
`RunConfig` 主要控制Fine-tune的训练,包含以下可控制的参数:
* `log_interval`: 进度日志打印间隔,默认每10个step打印一次
* `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集
* `save_ckpt_interval`: 模型保存间隔,请根据任务大小配置,默认只保存验证集效果最好的模型和训练结束的模型
* `use_cuda`: 是否使用GPU训练,默认为False
* `use_pyreader`: 是否使用pyreader,默认False
* `use_data_parallel`: 是否使用并行计算,默认True。打开该功能依赖nccl库
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: Fine-tune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `strategy`: Fine-tune优化策略
### Step4: 构建网络并创建分类迁移任务进行Fine-tune
```python
feature_map = output_dict["feature_map"]
feed_list = [input_dict["image"].name]
task = hub.ImageClassifierTask(
data_reader=data_reader,
feed_list=feed_list,
feature=feature_map,
num_classes=dataset.num_labels,
config=config)
task.finetune_and_eval()
```
**NOTE:**
1. `output_dict["feature_map"]`返回了resnet/mobilenet等模型对应的feature_map,可以用于图片的特征表达。
2. `feed_list`中的inputs参数指明了resnet/mobilenet等模型的输入tensor的顺序,与ImageClassifierTask返回的结果一致。
3. `hub.ImageClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于图像分类的迁移任务`ImageClassifierTask`
#### 自定义迁移任务
如果想改变迁移任务组网,详细参见[自定义迁移任务](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub:-%E8%87%AA%E5%AE%9A%E4%B9%89Task)
## 可视化
Fine-tune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令
```bash
$ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM}
```
其中${HOST_IP}为本机IP地址,${PORT_NUM}为可用端口号,如本机IP地址为192.168.0.1,端口号8040,用浏览器打开192.168.0.1:8040,即可看到训练过程中指标的变化情况
## 模型预测
当完成Fine-tune后,Fine-tune过程在验证集上表现最优的模型会被保存在`${CHECKPOINT_DIR}/best_model`目录下,其中`${CHECKPOINT_DIR}`目录为Fine-tune时所选择的保存checkpoint的目录。
我们使用该模型来进行预测。predict.py脚本支持的参数如下:
```shell
--module: 使用哪个Module作为Fine-tune的特征提取器,脚本支持{resnet50/resnet101/resnet152/mobilenet/nasnet/pnasnet}等模型。默认为resnet50
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型。默认为paddlehub_finetune_ckpt
--dataset: 使用什么数据集进行Fine-tune, 脚本支持分别是{flowers/dogcat}。默认为flowers
--use_gpu: 使用使用GPU进行训练,如果本机支持GPU且安装了GPU版本的PaddlePaddle,我们建议您打开这个开关。默认关闭
--use_pyreader: 是否使用pyreader进行数据喂入。默认关闭
```
`注意`:进行预测时,所选择的module,checkpoint_dir,dataset必须和Fine-tune所用的一样
参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下图片分类预测结果
如需了解更多预测步骤,请参考`predict.py`
我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
|预训练模型|任务类型|数据集|AIStudio链接|备注|
|-|-|-|-|-|
|ResNet|图像分类|猫狗数据集DogCat|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216772)||
|ERNIE|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216764)||
|ERNIE|文本分类|中文新闻分类数据集THUNEWS|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216649)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成文本分类迁移学习。|
|ERNIE|序列标注|中文序列标注数据集MSRA_NER|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216787)||
|ERNIE|序列标注|中文快递单数据集Express|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216683)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成序列标注迁移学习。|
|ERNIE Tiny|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215599)||
|Senta|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216851)|本教程讲述了任何利用Senta和Fine-tune API完成情感分类迁移学习。|
|Senta|情感分析预测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216735)||
|LAC|词法分析|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215641)||
|Ultra-Light-Fast-Generic-Face-Detector-1MB|人脸检测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216749)||
## 超参优化AutoDL Finetuner
PaddleHub还提供了超参优化(Hyperparameter Tuning)功能, 自动搜索最优模型超参得到更好的模型效果。详细信息参见[AutoDL Finetuner超参优化功能教程](../../tutorial/autofinetune.md)[使用样例](../autofinetune)
...@@ -15,7 +15,6 @@ parser.add_argument("--checkpoint_dir", type=str, default="pad ...@@ -15,7 +15,6 @@ parser.add_argument("--checkpoint_dir", type=str, default="pad
parser.add_argument("--batch_size", type=int, default=16, help="Total examples' number in batch for training.") parser.add_argument("--batch_size", type=int, default=16, help="Total examples' number in batch for training.")
parser.add_argument("--module", type=str, default="resnet50", help="Module used as feature extractor.") parser.add_argument("--module", type=str, default="resnet50", help="Module used as feature extractor.")
parser.add_argument("--dataset", type=str, default="flowers", help="Dataset to finetune.") parser.add_argument("--dataset", type=str, default="flowers", help="Dataset to finetune.")
parser.add_argument("--use_pyreader", type=ast.literal_eval, default=True, help="Whether use pyreader to feed data.")
parser.add_argument("--use_data_parallel", type=ast.literal_eval, default=True, help="Whether use data parallel.") parser.add_argument("--use_data_parallel", type=ast.literal_eval, default=True, help="Whether use data parallel.")
# yapf: enable. # yapf: enable.
...@@ -30,9 +29,11 @@ module_map = { ...@@ -30,9 +29,11 @@ module_map = {
def finetune(args): def finetune(args):
# Load Paddlehub pretrained model
module = hub.Module(name=args.module) module = hub.Module(name=args.module)
input_dict, output_dict, program = module.context(trainable=True) input_dict, output_dict, program = module.context(trainable=True)
# Download dataset
if args.dataset.lower() == "flowers": if args.dataset.lower() == "flowers":
dataset = hub.dataset.Flowers() dataset = hub.dataset.Flowers()
elif args.dataset.lower() == "dogcat": elif args.dataset.lower() == "dogcat":
...@@ -46,6 +47,7 @@ def finetune(args): ...@@ -46,6 +47,7 @@ def finetune(args):
else: else:
raise ValueError("%s dataset is not defined" % args.dataset) raise ValueError("%s dataset is not defined" % args.dataset)
# Use ImageClassificationReader to read dataset
data_reader = hub.reader.ImageClassificationReader( data_reader = hub.reader.ImageClassificationReader(
image_width=module.get_expected_image_width(), image_width=module.get_expected_image_width(),
image_height=module.get_expected_image_height(), image_height=module.get_expected_image_height(),
...@@ -55,25 +57,27 @@ def finetune(args): ...@@ -55,25 +57,27 @@ def finetune(args):
feature_map = output_dict["feature_map"] feature_map = output_dict["feature_map"]
img = input_dict["image"] # Setup feed list for data feeder
feed_list = [img.name] feed_list = [input_dict["image"].name]
# Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
use_data_parallel=args.use_data_parallel, use_data_parallel=args.use_data_parallel,
use_pyreader=args.use_pyreader,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
num_epoch=args.num_epoch, num_epoch=args.num_epoch,
batch_size=args.batch_size, batch_size=args.batch_size,
enable_memory_optim=False,
checkpoint_dir=args.checkpoint_dir, checkpoint_dir=args.checkpoint_dir,
strategy=hub.finetune.strategy.DefaultFinetuneStrategy()) strategy=hub.finetune.strategy.DefaultFinetuneStrategy())
# Define a reading comprehension finetune task by PaddleHub's API
task = hub.ImageClassifierTask( task = hub.ImageClassifierTask(
data_reader=data_reader, data_reader=data_reader,
feed_list=feed_list, feed_list=feed_list,
feature=feature_map, feature=feature_map,
num_classes=dataset.num_labels, num_classes=dataset.num_labels,
config=config) config=config)
# Finetune by PaddleHub's API
task.finetune_and_eval() task.finetune_and_eval()
......
...@@ -9,12 +9,11 @@ import numpy as np ...@@ -9,12 +9,11 @@ import numpy as np
# yapf: disable # yapf: disable
parser = argparse.ArgumentParser(__doc__) parser = argparse.ArgumentParser(__doc__)
parser.add_argument("--use_gpu", type=ast.literal_eval, default=False, help="Whether use GPU for predict.") parser.add_argument("--use_gpu", type=ast.literal_eval, default=True, help="Whether use GPU for predict.")
parser.add_argument("--checkpoint_dir", type=str, default="paddlehub_finetune_ckpt", help="Path to save log data.") parser.add_argument("--checkpoint_dir", type=str, default="paddlehub_finetune_ckpt", help="Path to save log data.")
parser.add_argument("--batch_size", type=int, default=16, help="Total examples' number in batch for training.") parser.add_argument("--batch_size", type=int, default=16, help="Total examples' number in batch for training.")
parser.add_argument("--module", type=str, default="resnet50", help="Module used as a feature extractor.") parser.add_argument("--module", type=str, default="resnet50", help="Module used as a feature extractor.")
parser.add_argument("--dataset", type=str, default="flowers", help="Dataset to finetune.") parser.add_argument("--dataset", type=str, default="flowers", help="Dataset to finetune.")
parser.add_argument("--use_pyreader", type=ast.literal_eval, default=False, help="Whether use pyreader to feed data.")
# yapf: enable. # yapf: enable.
module_map = { module_map = {
...@@ -28,9 +27,11 @@ module_map = { ...@@ -28,9 +27,11 @@ module_map = {
def predict(args): def predict(args):
# Load Paddlehub pretrained model
module = hub.Module(name=args.module) module = hub.Module(name=args.module)
input_dict, output_dict, program = module.context(trainable=True) input_dict, output_dict, program = module.context(trainable=True)
# Download dataset
if args.dataset.lower() == "flowers": if args.dataset.lower() == "flowers":
dataset = hub.dataset.Flowers() dataset = hub.dataset.Flowers()
elif args.dataset.lower() == "dogcat": elif args.dataset.lower() == "dogcat":
...@@ -44,6 +45,7 @@ def predict(args): ...@@ -44,6 +45,7 @@ def predict(args):
else: else:
raise ValueError("%s dataset is not defined" % args.dataset) raise ValueError("%s dataset is not defined" % args.dataset)
# Use ImageClassificationReader to read dataset
data_reader = hub.reader.ImageClassificationReader( data_reader = hub.reader.ImageClassificationReader(
image_width=module.get_expected_image_width(), image_width=module.get_expected_image_width(),
image_height=module.get_expected_image_height(), image_height=module.get_expected_image_height(),
...@@ -53,19 +55,19 @@ def predict(args): ...@@ -53,19 +55,19 @@ def predict(args):
feature_map = output_dict["feature_map"] feature_map = output_dict["feature_map"]
img = input_dict["image"] # Setup feed list for data feeder
feed_list = [img.name] feed_list = [input_dict["image"].name]
# Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
use_data_parallel=False, use_data_parallel=False,
use_pyreader=args.use_pyreader,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
batch_size=args.batch_size, batch_size=args.batch_size,
enable_memory_optim=False,
checkpoint_dir=args.checkpoint_dir, checkpoint_dir=args.checkpoint_dir,
strategy=hub.finetune.strategy.DefaultFinetuneStrategy()) strategy=hub.finetune.strategy.DefaultFinetuneStrategy())
task = hub.ClassifierTask( # Define a reading comprehension finetune task by PaddleHub's API
task = hub.ImageClassifierTask(
data_reader=data_reader, data_reader=data_reader,
feed_list=feed_list, feed_list=feed_list,
feature=feature_map, feature=feature_map,
......
# LAC # LAC 词法分析
## 关于
本示例展示如何使用LAC Module进行预测。 本示例展示如何使用LAC Module进行预测。
LAC是中文词法分析模型,可以用于进行中文句子的分词/词性标注/命名实体识别等功能,关于模型的训练细节,请查看[LAC](https://github.com/baidu/lac) LAC是中文词法分析模型,可以用于进行中文句子的分词/词性标注/命名实体识别等功能,关于模型的细节参见[模型介绍](https://www.paddlepaddle.org.cn/hubdetail?name=lac&en_category=LexicalAnalysis)
## 准备工作
在运行本目录的脚本前,需要先安装1.3.0版本以上的PaddlePaddle(如果您本地已经安装了符合条件的PaddlePaddle版本,那么可以跳过`准备工作`这一步)。 ## 命令行方式预测
`cli_demo.sh`给出了使用命令行接口(Command Line Interface)调用Module预测的示例脚本
通过以下命令试验下效果
如果您的机器支持GPU,我们建议下载GPU版本的PaddlePaddle,使用GPU进行训练和预测的效率都比使用CPU要高。
```shell ```shell
# 安装GPU版本的PaddlePaddle $ hub run lac --input_text "今天是个好日子"
$ pip install --upgrade paddlepaddle-gpu $ hub run lac --input_file test.txt --user_dict user.dict
``` ```
test.txt 存放待分词文本, 如:
如果您的机器不支持GPU,可以通过下面的命令来安装CPU版本的PaddlePaddle ```text
今天是个好日子
```shell 今天天气晴朗
# 安装CPU版本的PaddlePaddle
$ pip install --upgrade paddlepaddle
``` ```
user.dict为用户自定义词典,可以不指定,当指定自定义词典时,可以干预默认分词结果。
词典包含三列,第一列为单词,第二列为单词词性,第三列为单词词频,以水平制表符\t分隔。词频越高的单词,对分词结果影响越大,词典样例如下:
在安装过程中如果遇到问题,您可以到[Paddle官方网站](http://www.paddlepaddle.org/)上查看解决方案。 ```text
天气预报 n 400000
经 v 1000
常 d 1000
```
## 命令行方式预测 **NOTE:**
`cli_demo.sh`给出了使用命令行接口(Command Line Interface)调用Module预测的示例脚本 * 该PaddleHub Module使用词典干预功能时,依赖于第三方库pyahocorasick,请自行安装
通过以下命令试验下效果 * 请不要直接复制示例文本使用,复制后的格式可能存在问题
```shell
$ sh cli_demo.sh
```
## 通过Python API预测 ## 通过Python API预测
......
python ../../paddlehub/commands/hub.py run lac --input_file test/test.txt
今天是个好日子
天气预报说今天要下雨
下一班地铁马上就要到了
input_data:
text:
type : TEXT
key : TEXT_INPUT
# PaddleHub 多标签分类 # PaddleHub 多标签分类
本示例将展示如何使用PaddleHub Finetune API以及BERT预训练模型在Toxic完成多标签分类任务。 本示例将展示如何使用PaddleHub Fine-tune API以及BERT预训练模型在Toxic完成多标签分类任务。
## 如何开始Finetune 多标签分类是广义的多分类,多分类是将样本精确地分类为两个以上类别之一的单标签问题。 在多标签问题中,样本可以分配给多个类别,没有限制。
如下图所示:
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_classifier.sh`即可开始使用BERT对Toxic数据集进行Finetune。 <p align="center">
<img src="https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.4/docs/imgs/multi-label-cls.png" hspace='10'/> <br />
</p>
*图片来源于https://mc.ai/building-a-multi-label-text-classifier-using-bert-and-tensorflow/*
## 如何开始Fine-tune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_classifier.sh`即可开始使用BERT对Toxic数据集进行Fine-tune。
其中脚本参数说明如下: 其中脚本参数说明如下:
```bash ```bash
# 模型相关 # 模型相关
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数 --batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数
--use_gpu: 是否使用GPU进行FineTune,默认为False --use_gpu: 是否使用GPU进行Fine-Tune,默认为False
--learning_rate: Finetune的最大学习率 --learning_rate: Fine-tune的最大学习率
--weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01 --weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01
--warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0 --warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0
--num_epoch: Finetune迭代的轮数 --num_epoch: Fine-tune迭代的轮数
--max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数 --max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数
# 任务相关 # 任务相关
...@@ -24,15 +34,38 @@ ...@@ -24,15 +34,38 @@
## 代码步骤 ## 代码步骤
使用PaddleHub Finetune API进行Finetune可以分为4个步骤 使用PaddleHub Fine-tune API进行Fine-tune可以分为4个步骤
### Step1: 加载预训练模型 ### Step1: 加载预训练模型
```python ```python
module = hub.Module(name="bert_uncased_L-12_H-768_A-12") module = hub.Module(name="ernie_v2_eng_base")
inputs, outputs, program = module.context(trainable=True, max_seq_len=128) inputs, outputs, program = module.context(trainable=True, max_seq_len=128)
``` ```
其中最大序列长度`max_seq_len`是可以调整的参数,建议值128,根据任务文本长度不同可以调整该值,但最大不超过512。
PaddleHub还提供BERT等模型可供选择, 模型对应的加载示例如下:
模型名 | PaddleHub Module
---------------------------------- | :------:
ERNIE, Chinese | `hub.Module(name='ernie')`
ERNIE tiny, Chinese | `hub.Module(name='ernie_tiny')`
ERNIE 2.0 Base, English | `hub.Module(name='ernie_v2_eng_base')`
ERNIE 2.0 Large, English | `hub.Module(name='ernie_v2_eng_large')`
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')`
BERT-wwm, Chinese | `hub.Module(name='bert_wwm_chinese_L-12_H-768_A-12')`
BERT-wwm-ext, Chinese | `hub.Module(name='bert_wwm_ext_chinese_L-12_H-768_A-12')`
RoBERTa-wwm-ext, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-12_H-768_A-12')`
RoBERTa-wwm-ext-large, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-24_H-1024_A-16')`
更多模型请参考[PaddleHub官网](https://www.paddlepaddle.org.cn/hub)
### Step2: 准备数据集并使用MultiLabelClassifyReader读取数据 ### Step2: 准备数据集并使用MultiLabelClassifyReader读取数据
```python ```python
dataset = hub.dataset.Toxic() dataset = hub.dataset.Toxic()
...@@ -54,6 +87,12 @@ MultiLabelClassifyReader中的`data_generator`会自动按照模型对应词表 ...@@ -54,6 +87,12 @@ MultiLabelClassifyReader中的`data_generator`会自动按照模型对应词表
**NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。 **NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。
#### 自定义数据集
如果想加载自定义数据集完成迁移学习,详细参见[自定义数据集](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%90\)
### Step3:选择优化策略和运行配置 ### Step3:选择优化策略和运行配置
```python ```python
...@@ -70,13 +109,15 @@ config = hub.RunConfig(use_cuda=True, use_data_parallel=True, use_pyreader=True, ...@@ -70,13 +109,15 @@ config = hub.RunConfig(use_cuda=True, use_data_parallel=True, use_pyreader=True,
#### 优化策略 #### 优化策略
针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy` 针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy`
* `learning_rate`: Finetune过程中的最大学习率; * `learning_rate`: Fine-tune过程中的最大学习率;
* `weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数; * `weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数;
* `warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate; * `warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate;
* `lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减; * `lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减;
PaddleHub提供了许多优化策略,如`AdamWeightDecayStrategy``ULMFiTStrategy``DefaultFinetuneStrategy`等,详细信息参见[策略](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Strategy)
#### 运行配置 #### 运行配置
`RunConfig` 主要控制Finetune的训练,包含以下可控制的参数: `RunConfig` 主要控制Fine-tune的训练,包含以下可控制的参数:
* `log_interval`: 进度日志打印间隔,默认每10个step打印一次 * `log_interval`: 进度日志打印间隔,默认每10个step打印一次
* `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集 * `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集
...@@ -85,12 +126,12 @@ config = hub.RunConfig(use_cuda=True, use_data_parallel=True, use_pyreader=True, ...@@ -85,12 +126,12 @@ config = hub.RunConfig(use_cuda=True, use_data_parallel=True, use_pyreader=True,
* use_pyreader: 是否使用pyreader,默认False * use_pyreader: 是否使用pyreader,默认False
* use_data_parallel: 是否使用并行计算,默认False。打开该功能依赖nccl库 * use_data_parallel: 是否使用并行计算,默认False。打开该功能依赖nccl库
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成 * `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: finetune的轮数 * `num_epoch`: Fine-tune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size * `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `enable_memory_optim`: 是否使用内存优化, 默认为True * `enable_memory_optim`: 是否使用内存优化, 默认为True
* `strategy`: Finetune优化策略 * `strategy`: Fine-tune优化策略
### Step4: 构建网络并创建分类迁移任务进行Finetune ### Step4: 构建网络并创建分类迁移任务进行Fine-tune
```python ```python
pooled_output = outputs["pooled_output"] pooled_output = outputs["pooled_output"]
...@@ -116,23 +157,50 @@ cls_task.finetune_and_eval() ...@@ -116,23 +157,50 @@ cls_task.finetune_and_eval()
2. `feed_list`中的inputs参数指名了ERNIE/BERT中的输入tensor的顺序,与MultiLabelClassifierTask返回的结果一致。 2. `feed_list`中的inputs参数指名了ERNIE/BERT中的输入tensor的顺序,与MultiLabelClassifierTask返回的结果一致。
3. `hub.MultiLabelClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于多标签分类的迁移任务`MultiLabelClassifierTask` 3. `hub.MultiLabelClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于多标签分类的迁移任务`MultiLabelClassifierTask`
#### 自定义迁移任务
如果想改变迁移任务组网,详细参见[自定义迁移任务](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub:-%E8%87%AA%E5%AE%9A%E4%B9%89Task)
## 可视化 ## 可视化
Finetune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令 Fine-tune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令
```bash ```bash
$ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM} $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM}
``` ```
其中${HOST_IP}为本机IP地址,${PORT_NUM}为可用端口号,如本机IP地址为192.168.0.1,端口号8040,用浏览器打开192.168.0.1:8040,即可看到训练过程中指标的变化情况 其中${HOST_IP}为本机IP地址,${PORT_NUM}为可用端口号,如本机IP地址为192.168.0.1,端口号8040,用浏览器打开192.168.0.1:8040,即可看到训练过程中指标的变化情况
## 模型预测 ## 模型预测
通过Finetune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。 通过Fine-tune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数 配置脚本参数
```
```shell
CKPT_DIR="./ckpt_toxic" CKPT_DIR="./ckpt_toxic"
python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128 python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128
``` ```
其中CKPT_DIR为Finetune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致*
其中CKPT_DIR为Fine-tune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致*
参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。 参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。
如需了解更多预测步骤,请参考`predict.py` 如需了解更多预测步骤,请参考`predict.py`
我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
|预训练模型|任务类型|数据集|AIStudio链接|备注|
|-|-|-|-|-|
|ResNet|图像分类|猫狗数据集DogCat|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216772)||
|ERNIE|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216764)||
|ERNIE|文本分类|中文新闻分类数据集THUNEWS|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216649)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成文本分类迁移学习。|
|ERNIE|序列标注|中文序列标注数据集MSRA_NER|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216787)||
|ERNIE|序列标注|中文快递单数据集Express|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216683)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成序列标注迁移学习。|
|ERNIE Tiny|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215599)||
|Senta|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216851)|本教程讲述了任何利用Senta和Fine-tune API完成情感分类迁移学习。|
|Senta|情感分析预测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216735)||
|LAC|词法分析|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215641)||
|Ultra-Light-Fast-Generic-Face-Detector-1MB|人脸检测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216749)||
## 超参优化AutoDL Finetuner
PaddleHub还提供了超参优化(Hyperparameter Tuning)功能, 自动搜索最优模型超参得到更好的模型效果。详细信息参见[AutoDL Finetuner超参优化功能教程](../../tutorial/autofinetune.md)[使用样例](../autofinetune)
...@@ -34,35 +34,33 @@ args = parser.parse_args() ...@@ -34,35 +34,33 @@ args = parser.parse_args()
# yapf: enable. # yapf: enable.
if __name__ == '__main__': if __name__ == '__main__':
# Load Paddlehub BERT pretrained model # Load Paddlehub ERNIE 2.0 pretrained model
module = hub.Module(name="ernie_v2_eng_base") module = hub.Module(name="ernie_v2_eng_base")
inputs, outputs, program = module.context( inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len) trainable=True, max_seq_len=args.max_seq_len)
# Setup feed list for data feeder
feed_list = [
inputs["input_ids"].name, inputs["position_ids"].name,
inputs["segment_ids"].name, inputs["input_mask"].name
]
# Download dataset and use MultiLabelReader to read dataset # Download dataset and use MultiLabelReader to read dataset
dataset = hub.dataset.Toxic() dataset = hub.dataset.Toxic()
reader = hub.reader.MultiLabelClassifyReader( reader = hub.reader.MultiLabelClassifyReader(
dataset=dataset, dataset=dataset,
vocab_path=module.get_vocab_path(), vocab_path=module.get_vocab_path(),
max_seq_len=args.max_seq_len) max_seq_len=args.max_seq_len)
# Setup feed list for data feeder
feed_list = [
inputs["input_ids"].name, inputs["position_ids"].name,
inputs["segment_ids"].name, inputs["input_mask"].name
]
# Construct transfer learning network # Construct transfer learning network
# Use "pooled_output" for classification tasks on an entire sentence. # Use "pooled_output" for classification tasks on an entire sentence.
pooled_output = outputs["pooled_output"] pooled_output = outputs["pooled_output"]
# Select finetune strategy, setup config and finetune # Select finetune strategy, setup config and finetune
strategy = hub.AdamWeightDecayStrategy( strategy = hub.AdamWeightDecayStrategy(
warmup_proportion=args.warmup_proportion,
weight_decay=args.weight_decay, weight_decay=args.weight_decay,
learning_rate=args.learning_rate, learning_rate=args.learning_rate)
lr_scheduler="linear_decay")
# Setup runing config for PaddleHub Finetune API # Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
......
...@@ -40,12 +40,18 @@ args = parser.parse_args() ...@@ -40,12 +40,18 @@ args = parser.parse_args()
# yapf: enable. # yapf: enable.
if __name__ == '__main__': if __name__ == '__main__':
# Load Paddlehub BERT pretrained model # Load Paddlehub ERNIE 2.0 pretrained model
module = hub.Module(name="ernie_v2_eng_base") module = hub.Module(name="ernie_v2_eng_base")
inputs, outputs, program = module.context( inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len) trainable=True, max_seq_len=args.max_seq_len)
# Download dataset and use MultiLabelReader to read dataset
dataset = hub.dataset.Toxic()
reader = hub.reader.MultiLabelClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path(),
max_seq_len=args.max_seq_len)
# Setup feed list for data feeder # Setup feed list for data feeder
feed_list = [ feed_list = [
inputs["input_ids"].name, inputs["input_ids"].name,
...@@ -54,14 +60,6 @@ if __name__ == '__main__': ...@@ -54,14 +60,6 @@ if __name__ == '__main__':
inputs["input_mask"].name, inputs["input_mask"].name,
] ]
# Download dataset and use MultiLabelReader to read dataset
dataset = hub.dataset.Toxic()
reader = hub.reader.MultiLabelClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path(),
max_seq_len=args.max_seq_len)
# Construct transfer learning network # Construct transfer learning network
# Use "pooled_output" for classification tasks on an entire sentence. # Use "pooled_output" for classification tasks on an entire sentence.
# Use "sequence_output" for token-level output. # Use "sequence_output" for token-level output.
...@@ -70,10 +68,8 @@ if __name__ == '__main__': ...@@ -70,10 +68,8 @@ if __name__ == '__main__':
# Setup runing config for PaddleHub Finetune API # Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
use_data_parallel=False, use_data_parallel=False,
use_pyreader=False,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
batch_size=args.batch_size, batch_size=args.batch_size,
enable_memory_optim=False,
checkpoint_dir=args.checkpoint_dir, checkpoint_dir=args.checkpoint_dir,
strategy=hub.finetune.strategy.DefaultFinetuneStrategy()) strategy=hub.finetune.strategy.DefaultFinetuneStrategy())
...@@ -85,7 +81,7 @@ if __name__ == '__main__': ...@@ -85,7 +81,7 @@ if __name__ == '__main__':
num_classes=dataset.num_labels, num_classes=dataset.num_labels,
config=config) config=config)
# Data to be prdicted # Data to be predicted
data = [ data = [
[ [
"Yes you did. And you admitted to doing it. See the Warren Kinsella talk page." "Yes you did. And you admitted to doing it. See the Warren Kinsella talk page."
...@@ -95,5 +91,4 @@ if __name__ == '__main__': ...@@ -95,5 +91,4 @@ if __name__ == '__main__':
], ],
] ]
index = 0
print(multi_label_cls_task.predict(data=data, return_result=True)) print(multi_label_cls_task.predict(data=data, return_result=True))
export FLAGS_eager_delete_tensor_gb=0.0 export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0 export CUDA_VISIBLE_DEVICES=0
# User can select chnsenticorp, nlpcc_dbqa, lcqmc for different task CKPT_DIR="./ckpt_toxic"
DATASET="toxic"
CKPT_DIR="./ckpt_${DATASET}"
# 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 multi_label_classifier.py \ python -u multi_label_classifier.py \
--batch_size=32 \ --batch_size=32 \
...@@ -16,4 +10,5 @@ python -u multi_label_classifier.py \ ...@@ -16,4 +10,5 @@ python -u multi_label_classifier.py \
--learning_rate=5e-5 \ --learning_rate=5e-5 \
--weight_decay=0.01 \ --weight_decay=0.01 \
--max_seq_len=128 \ --max_seq_len=128 \
--warmup_proportion=0.1 \
--num_epoch=3 --num_epoch=3
# PaddleHub 检索式问答任务 # PaddleHub 检索式问答任务
本示例将展示如何使用PaddleHub Finetune API以及Transformer类预训练模型在NLPCC-DBQA数据集上完成检索式问答任务。 本示例将展示如何使用PaddleHub Fine-tune API以及Transformer类预训练模型在NLPCC-DBQA数据集上完成检索式问答任务。
## 如何开始Finetune ## 如何开始Fine-tune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_classifier.sh`即可开始使用ERNIE对NLPCC-DBQA数据集进行Finetune。 在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_classifier.sh`即可开始使用ERNIE对NLPCC-DBQA数据集进行Fine-tune。
其中脚本参数说明如下: 其中脚本参数说明如下:
```bash ```bash
# 模型相关 # 模型相关
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数 --batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数
--learning_rate: Finetune的最大学习率 --learning_rate: Fine-tune的最大学习率
--weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01 --weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01
--warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0 --warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0
--num_epoch: Finetune迭代的轮数 --num_epoch: Fine-tune迭代的轮数
--max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数 --max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数
# 任务相关 # 任务相关
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
## 代码步骤 ## 代码步骤
使用PaddleHub Finetune API进行Finetune可以分为4个步骤 使用PaddleHub Fine-tune API进行Fine-tune可以分为4个步骤
### Step1: 加载预训练模型 ### Step1: 加载预训练模型
...@@ -51,6 +51,7 @@ BERT-wwm, Chinese | `hub.Module(name='bert_wwm_chinese_L-12_H-7 ...@@ -51,6 +51,7 @@ BERT-wwm, Chinese | `hub.Module(name='bert_wwm_chinese_L-12_H-7
BERT-wwm-ext, Chinese | `hub.Module(name='bert_wwm_ext_chinese_L-12_H-768_A-12')` BERT-wwm-ext, Chinese | `hub.Module(name='bert_wwm_ext_chinese_L-12_H-768_A-12')`
RoBERTa-wwm-ext, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-12_H-768_A-12')` RoBERTa-wwm-ext, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-12_H-768_A-12')`
RoBERTa-wwm-ext-large, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-24_H-1024_A-16')` RoBERTa-wwm-ext-large, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-24_H-1024_A-16')`
更多模型请参考[PaddleHub官网](https://www.paddlepaddle.org.cn/hub?filter=hot&value=1) 更多模型请参考[PaddleHub官网](https://www.paddlepaddle.org.cn/hub?filter=hot&value=1)
如果想尝试BERT模型,只需要更换Module中的`name`参数即可. 如果想尝试BERT模型,只需要更换Module中的`name`参数即可.
...@@ -80,6 +81,11 @@ ClassifyReader中的`data_generator`会自动按照模型对应词表对数据 ...@@ -80,6 +81,11 @@ ClassifyReader中的`data_generator`会自动按照模型对应词表对数据
**NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。 **NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。
#### 自定义数据集
如果想加载自定义数据集完成迁移学习,详细参见[自定义数据集](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)
### Step3:选择优化策略和运行配置 ### Step3:选择优化策略和运行配置
```python ```python
...@@ -94,15 +100,18 @@ config = hub.RunConfig(use_cuda=True, use_data_parallel=True, use_pyreader=True, ...@@ -94,15 +100,18 @@ config = hub.RunConfig(use_cuda=True, use_data_parallel=True, use_pyreader=True,
``` ```
#### 优化策略 #### 优化策略
PaddleHub提供了许多优化策略,如`AdamWeightDecayStrategy``ULMFiTStrategy``DefaultFinetuneStrategy`等,详细信息参见[策略](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Strategy)
针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy` 针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy`
* `learning_rate`: Finetune过程中的最大学习率; * `learning_rate`: Fine-tune过程中的最大学习率;
* `weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数; * `weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数;
* `warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate; * `warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate;
* `lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减; * `lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减;
#### 运行配置 #### 运行配置
`RunConfig` 主要控制Finetune的训练,包含以下可控制的参数: `RunConfig` 主要控制Fine-tune的训练,包含以下可控制的参数:
* `log_interval`: 进度日志打印间隔,默认每10个step打印一次 * `log_interval`: 进度日志打印间隔,默认每10个step打印一次
* `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集 * `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集
...@@ -111,12 +120,12 @@ config = hub.RunConfig(use_cuda=True, use_data_parallel=True, use_pyreader=True, ...@@ -111,12 +120,12 @@ config = hub.RunConfig(use_cuda=True, use_data_parallel=True, use_pyreader=True,
* `use_pyreader`: 是否使用pyreader,默认False。 * `use_pyreader`: 是否使用pyreader,默认False。
* `use_data_parallel`: 是否使用并行计算,默认False。打开该功能依赖nccl库。 * `use_data_parallel`: 是否使用并行计算,默认False。打开该功能依赖nccl库。
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成 * `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: finetune的轮数 * `num_epoch`: Fine-tune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size * `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `enable_memory_optim`: 是否使用内存优化, 默认为True * `enable_memory_optim`: 是否使用内存优化, 默认为True
* `strategy`: Finetune优化策略 * `strategy`: Fine-tune优化策略
### Step4: 构建网络并创建分类迁移任务进行Finetune ### Step4: 构建网络并创建分类迁移任务进行Fine-tune
```python ```python
pooled_output = outputs["pooled_output"] pooled_output = outputs["pooled_output"]
...@@ -142,9 +151,13 @@ cls_task.finetune_and_eval() ...@@ -142,9 +151,13 @@ cls_task.finetune_and_eval()
2. `feed_list`中的inputs参数指名了ERNIE/BERT中的输入tensor的顺序,与ClassifyReader返回的结果一致。 2. `feed_list`中的inputs参数指名了ERNIE/BERT中的输入tensor的顺序,与ClassifyReader返回的结果一致。
3. `hub.TextClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于文本分类的迁移任务`TextClassifierTask` 3. `hub.TextClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于文本分类的迁移任务`TextClassifierTask`
#### 自定义迁移任务
如果想改变迁移任务组网,详细参见[自定义迁移任务](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub:-%E8%87%AA%E5%AE%9A%E4%B9%89Task)
## 可视化 ## 可视化
Finetune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令 Fine-tune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令
```bash ```bash
$ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM} $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM}
``` ```
...@@ -152,13 +165,34 @@ $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_N ...@@ -152,13 +165,34 @@ $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_N
## 模型预测 ## 模型预测
通过Finetune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。 通过Fine-tune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数 配置脚本参数
``` ```
CKPT_DIR="./ckpt_qa" CKPT_DIR="./ckpt_qa"
python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128 python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128
``` ```
其中CKPT_DIR为Finetune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致* 其中CKPT_DIR为Fine-tune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致*
参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。 参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。
如需了解更多预测步骤,请参考`predict.py` 如需了解更多预测步骤,请参考`predict.py`
我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
|预训练模型|任务类型|数据集|AIStudio链接|备注|
|-|-|-|-|-|
|ResNet|图像分类|猫狗数据集DogCat|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216772)||
|ERNIE|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216764)||
|ERNIE|文本分类|中文新闻分类数据集THUNEWS|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216649)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成文本分类迁移学习。|
|ERNIE|序列标注|中文序列标注数据集MSRA_NER|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216787)||
|ERNIE|序列标注|中文快递单数据集Express|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216683)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成序列标注迁移学习。|
|ERNIE Tiny|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215599)||
|Senta|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216851)|本教程讲述了任何利用Senta和Fine-tune API完成情感分类迁移学习。|
|Senta|情感分析预测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216735)||
|LAC|词法分析|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215641)||
|Ultra-Light-Fast-Generic-Face-Detector-1MB|人脸检测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216749)||
## 超参优化AutoDL Finetuner
PaddleHub还提供了超参优化(Hyperparameter Tuning)功能, 自动搜索最优模型超参得到更好的模型效果。详细信息参见[AutoDL Finetuner超参优化功能教程](../../tutorial/autofinetune.md)[使用样例](../autofinetune)
...@@ -30,7 +30,6 @@ parser.add_argument("--warmup_proportion", type=float, default=0.0, help="Warmup ...@@ -30,7 +30,6 @@ parser.add_argument("--warmup_proportion", type=float, default=0.0, help="Warmup
parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint") 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("--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("--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.") parser.add_argument("--use_data_parallel", type=ast.literal_eval, default=False, help="Whether use data parallel.")
args = parser.parse_args() args = parser.parse_args()
# yapf: enable. # yapf: enable.
...@@ -38,13 +37,11 @@ args = parser.parse_args() ...@@ -38,13 +37,11 @@ args = parser.parse_args()
if __name__ == '__main__': if __name__ == '__main__':
# Load Paddlehub ERNIE pretrained model # Load Paddlehub ERNIE pretrained model
module = hub.Module(name="ernie") module = hub.Module(name="ernie")
# module = hub.Module(name="bert_chinese_L-12_H-768_A-12")
inputs, outputs, program = module.context( inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len) trainable=True, max_seq_len=args.max_seq_len)
# Download dataset and use ClassifyReader to read dataset # Download dataset and use ClassifyReader to read dataset
dataset = hub.dataset.NLPCC_DBQA() dataset = hub.dataset.NLPCC_DBQA()
reader = hub.reader.ClassifyReader( reader = hub.reader.ClassifyReader(
dataset=dataset, dataset=dataset,
vocab_path=module.get_vocab_path(), vocab_path=module.get_vocab_path(),
...@@ -66,14 +63,13 @@ if __name__ == '__main__': ...@@ -66,14 +63,13 @@ if __name__ == '__main__':
# Select finetune strategy, setup config and finetune # Select finetune strategy, setup config and finetune
strategy = hub.AdamWeightDecayStrategy( strategy = hub.AdamWeightDecayStrategy(
warmup_proportion=args.warmup_proportion,
weight_decay=args.weight_decay, weight_decay=args.weight_decay,
learning_rate=args.learning_rate, learning_rate=args.learning_rate)
lr_scheduler="linear_decay")
# Setup runing config for PaddleHub Finetune API # Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
use_data_parallel=args.use_data_parallel, use_data_parallel=args.use_data_parallel,
use_pyreader=args.use_pyreader,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
num_epoch=args.num_epoch, num_epoch=args.num_epoch,
batch_size=args.batch_size, batch_size=args.batch_size,
......
...@@ -34,7 +34,6 @@ parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory ...@@ -34,7 +34,6 @@ parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory
parser.add_argument("--batch_size", type=int, default=1, help="Total examples' number in batch for training.") 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("--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_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() args = parser.parse_args()
# yapf: enable. # yapf: enable.
...@@ -50,9 +49,6 @@ if __name__ == '__main__': ...@@ -50,9 +49,6 @@ if __name__ == '__main__':
vocab_path=module.get_vocab_path(), vocab_path=module.get_vocab_path(),
max_seq_len=args.max_seq_len) 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 # Construct transfer learning network
# Use "pooled_output" for classification tasks on an entire sentence. # Use "pooled_output" for classification tasks on an entire sentence.
# Use "sequence_output" for token-level output. # Use "sequence_output" for token-level output.
...@@ -70,10 +66,8 @@ if __name__ == '__main__': ...@@ -70,10 +66,8 @@ if __name__ == '__main__':
# Setup runing config for PaddleHub Finetune API # Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
use_data_parallel=False, use_data_parallel=False,
use_pyreader=args.use_pyreader,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
batch_size=args.batch_size, batch_size=args.batch_size,
enable_memory_optim=False,
checkpoint_dir=args.checkpoint_dir, checkpoint_dir=args.checkpoint_dir,
strategy=hub.finetune.strategy.DefaultFinetuneStrategy()) strategy=hub.finetune.strategy.DefaultFinetuneStrategy())
......
...@@ -2,10 +2,6 @@ export FLAGS_eager_delete_tensor_gb=0.0 ...@@ -2,10 +2,6 @@ export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0 export CUDA_VISIBLE_DEVICES=0
CKPT_DIR="./ckpt_qa" 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 \ python -u classifier.py \
--batch_size=24 \ --batch_size=24 \
...@@ -13,7 +9,7 @@ python -u classifier.py \ ...@@ -13,7 +9,7 @@ python -u classifier.py \
--checkpoint_dir=${CKPT_DIR} \ --checkpoint_dir=${CKPT_DIR} \
--learning_rate=5e-5 \ --learning_rate=5e-5 \
--weight_decay=0.01 \ --weight_decay=0.01 \
--warmup_proportion=0.1 \
--max_seq_len=128 \ --max_seq_len=128 \
--num_epoch=3 \ --num_epoch=3 \
--use_pyreader=False \ --use_data_parallel=True \
--use_data_parallel=False \
export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0
CKPT_DIR="./ckpt_cmrc2018"
dataset=cmrc2018
python -u predict.py \
--batch_size=8 \
--use_gpu=True \
--dataset=${dataset} \
--checkpoint_dir=${CKPT_DIR} \
--learning_rate=2.5e-5 \
--weight_decay=0.01 \
--warmup_proportion=0.1 \
--num_epoch=1 \
--max_seq_len=512 \
--use_pyreader=False \
--use_data_parallel=False
# PaddleHub 阅读理解 # PaddleHub 阅读理解
本示例将展示如何使用PaddleHub Finetune API以及BERT预训练模型完成阅读理解任务。 本示例将展示如何使用PaddleHub Fine-tune API以及BERT预训练模型完成阅读理解任务。
## 如何开始Finetune ## 如何开始Fine-tune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_finetune.sh`即可开始使用BERT对SQuAD数据集进行Finetune。 在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_finetune.sh`即可开始使用BERT对SQuAD数据集进行Fine-tune。
其中脚本参数说明如下: 其中脚本参数说明如下:
```bash ```bash
# 模型相关 # 模型相关
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数 --batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数
--learning_rate: Finetune的最大学习率 --learning_rate: Fine-tune的最大学习率
--weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01 --weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01
--warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0 --warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0
--num_epoch: Finetune迭代的轮数 --num_epoch: Fine-tune迭代的轮数
--max_seq_len: BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数 --max_seq_len: BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数
--use_data_parallel: 是否使用并行计算,默认False。打开该功能依赖nccl库。 --use_data_parallel: 是否使用并行计算,默认False。打开该功能依赖nccl库。
--use_pyreader: 是否使用pyreader,默认False。
# 任务相关 # 任务相关
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型 --checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型
--version_2_with_negative: 若version_2_with_negative=False,则使用SQuAD 1.1数据集;若version_2_with_negative=True,则使用SQuAD 2.0数据集;
``` ```
## 代码步骤 ## 代码步骤
使用PaddleHub Finetune API进行Finetune可以分为4个步骤 使用PaddleHub Fine-tune API进行Fine-tune可以分为4个步骤
### Step1: 加载预训练模型 ### Step1: 加载预训练模型
...@@ -36,6 +34,33 @@ inputs, outputs, program = module.context(trainable=True, max_seq_len=384) ...@@ -36,6 +34,33 @@ inputs, outputs, program = module.context(trainable=True, max_seq_len=384)
``` ```
其中最大序列长度`max_seq_len`是可以调整的参数,建议值384,根据任务文本长度不同可以调整该值,但最大不超过512。 其中最大序列长度`max_seq_len`是可以调整的参数,建议值384,根据任务文本长度不同可以调整该值,但最大不超过512。
PaddleHub还提供BERT等模型可供选择, 模型对应的加载示例如下:
模型名 | PaddleHub Module
---------------------------------- | :------:
ERNIE, Chinese | `hub.Module(name='ernie')`
ERNIE tiny, Chinese | `hub.Module(name='ernie_tiny')`
ERNIE 2.0 Base, English | `hub.Module(name='ernie_v2_eng_base')`
ERNIE 2.0 Large, English | `hub.Module(name='ernie_v2_eng_large')`
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')`
BERT-wwm, Chinese | `hub.Module(name='bert_wwm_chinese_L-12_H-768_A-12')`
BERT-wwm-ext, Chinese | `hub.Module(name='bert_wwm_ext_chinese_L-12_H-768_A-12')`
RoBERTa-wwm-ext, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-12_H-768_A-12')`
RoBERTa-wwm-ext-large, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-24_H-1024_A-16')`
更多模型请参考[PaddleHub官网](https://www.paddlepaddle.org.cn/hub?filter=hot&value=1)
如果想尝试BERT模型,只需要更换Module中的`name`参数即可.
```python
# 更换name参数即可无缝切换BERT中文模型, 代码示例如下
module = hub.Module(name="bert_chinese_L-12_H-768_A-12")
```
### Step2: 准备数据集并使用ReadingComprehensionReader读取数据 ### Step2: 准备数据集并使用ReadingComprehensionReader读取数据
```python ```python
dataset = hub.dataset.SQUAD( dataset = hub.dataset.SQUAD(
...@@ -43,14 +68,12 @@ dataset = hub.dataset.SQUAD( ...@@ -43,14 +68,12 @@ dataset = hub.dataset.SQUAD(
reader = hub.reader.ReadingComprehensionReader( reader = hub.reader.ReadingComprehensionReader(
dataset=dataset, dataset=dataset,
vocab_path=module.get_vocab_path(), vocab_path=module.get_vocab_path(),
max_seq_length=args.max_seq_len, max_seq_length=384)
doc_stride=128,
max_query_length=64)
``` ```
其中数据集的准备代码可以参考 [squad.py](https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.2/paddlehub/dataset/squad.py) 其中数据集的准备代码可以参考 [squad.py](https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.2/paddlehub/dataset/squad.py)
`hub.dataset.SQUAD()` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录 `hub.dataset.SQUAD(version_2_with_negative=False)` 会自动从网络下载数据集SQuAD v1.1并解压到用户目录下`$HOME/.paddlehub/dataset`目录;如果想选择数据集SQuAD v2.0,则只需version_2_with_negative=True
`module.get_vocab_path()` 会返回预训练模型对应的词表 `module.get_vocab_path()` 会返回预训练模型对应的词表
...@@ -60,44 +83,60 @@ ReadingComprehensionReader中的`data_generator`会自动按照模型对应词 ...@@ -60,44 +83,60 @@ ReadingComprehensionReader中的`data_generator`会自动按照模型对应词
**NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。 **NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。
PaddleHub还提供了其他的阅读理解数据集,具体信息如下表:
数据集 | API | 推荐预训练模型 |
------------- | ------------------------------------------------------------------- |--------------------------------------- |
SQuAD v1.1 | hub.dataset.SQUAD(version_2_with_negative=False) | bert_uncased_L-12_H-768_A-12 |
SQuAD v2.0 | hub.dataset.SQUAD(version_2_with_negative=True) | bert_uncased_L-12_H-768_A-12 |
DRCD | hub.dataset.DRCD() |roberta_wwm_ext_chinese_L-24_H-1024_A-16|
CMRC 2018 | hub.dataset.CMRC2018() |roberta_wwm_ext_chinese_L-24_H-1024_A-16|
更多数据集信息参考[Dataset](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Dataset)
#### 自定义数据集
如果想加载自定义数据集完成迁移学习,详细参见[自定义数据集](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)
### Step3:选择优化策略和运行配置 ### Step3:选择优化策略和运行配置
```python ```python
strategy = hub.AdamWeightDecayStrategy( strategy = hub.AdamWeightDecayStrategy(
learning_rate=5e-5, learning_rate=5e-5,
weight_decay=0.01, weight_decay=0.01,
warmup_proportion=0.0, warmup_proportion=0.1
lr_scheduler="linear_decay",
) )
config = hub.RunConfig(use_cuda=True, num_epoch=2, batch_size=12, strategy=strategy) config = hub.RunConfig(use_cuda=True, num_epoch=2, batch_size=12, strategy=strategy)
``` ```
#### 优化策略 #### 优化策略
针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy` 针对ERNIE/BERT类Transformer模型,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy`
`learning_rate`: Finetune过程中的最大学习率; `learning_rate`: Fine-tune过程中的最大学习率;
`weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数; `weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数;
`warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate; `warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate;
`lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减; `lr_scheduler`: 有两种策略可选(1)`linear_decay`策略学习率会在最高点后以线性方式衰减; (2)`noam_decay`策略学习率会在最高点以多项式形式衰减;
PaddleHub提供了许多优化策略,如`AdamWeightDecayStrategy``ULMFiTStrategy``DefaultFinetuneStrategy`等,详细信息参见[策略](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Strategy)
#### 运行配置 #### 运行配置
`RunConfig` 主要控制Finetune的训练,包含以下可控制的参数: `RunConfig` 主要控制Fine-tune的训练,包含以下可控制的参数:
* `log_interval`: 进度日志打印间隔,默认每10个step打印一次 * `log_interval`: 进度日志打印间隔,默认每10个step打印一次
* `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集 * `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集
* `save_ckpt_interval`: 模型保存间隔,请根据任务大小配置,默认只保存验证集效果最好的模型和训练结束的模型 * `save_ckpt_interval`: 模型保存间隔,请根据任务大小配置,默认只保存验证集效果最好的模型和训练结束的模型
* `use_cuda`: 是否使用GPU训练,默认为False * `use_cuda`: 是否使用GPU训练,默认为False
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成 * `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: finetune的轮数 * `num_epoch`: Fine-tune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size * `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `enable_memory_optim`: 是否使用内存优化, 默认为True * `enable_memory_optim`: 是否使用内存优化, 默认为True
* `strategy`: Finetune优化策略 * `strategy`: Fine-tune优化策略
### Step4: 构建网络并创建阅读理解迁移任务进行Finetune ### Step4: 构建网络并创建阅读理解迁移任务进行Fine-tune
```python ```python
seq_output = outputs["sequence_output"] seq_output = outputs["sequence_output"]
...@@ -113,17 +152,25 @@ reading_comprehension_task = hub.ReadingComprehensionTask( ...@@ -113,17 +152,25 @@ reading_comprehension_task = hub.ReadingComprehensionTask(
data_reader=reader, data_reader=reader,
feature=seq_output, feature=seq_output,
feed_list=feed_list, feed_list=feed_list,
config=config) config=config,
sub_task="squad")
reading_comprehension_task.finetune_and_eval() reading_comprehension_task.finetune_and_eval()
``` ```
**NOTE:** **NOTE:**
1. `outputs["sequence_output"]`返回了BERT模型输入单词的对应输出,可以用于单词的特征表达。 1. `outputs["sequence_output"]`返回了ERNIE/BERT模型输入单词的对应输出,可以用于单词的特征表达。
2. `feed_list`中的inputs参数指名了BERT中的输入tensor的顺序,与ClassifyReader返回的结果一致。 2. `feed_list`中的inputs参数指名了BERT中的输入tensor的顺序,与ReadingComprehensionReader返回的结果一致。
3. `sub_task`指明阅读理解数据集名称,可选{squad, squad2.0, cmrc2018, drcd}, 用于适配各个数据集的模型训练过程中的评估方法
4. `hub.ReadingComprehensionTask`通过输入特征、段落背景、问题和答案,可以生成适用于阅读理解迁移任务ReadingComprehensionTask
#### 自定义迁移任务
如果想改变迁移任务组网,详细参见[自定义迁移任务](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub:-%E8%87%AA%E5%AE%9A%E4%B9%89Task)
## 可视化 ## 可视化
Finetune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令 Fine-tune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令
```bash ```bash
$ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM} $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM}
``` ```
...@@ -131,17 +178,36 @@ $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_N ...@@ -131,17 +178,36 @@ $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_N
## 模型预测 ## 模型预测
通过Finetune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。 通过Fine-tune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数 配置脚本参数
```bash ```bash
CKPT_DIR=".ckpt_rc/" CKPT_DIR=".ckpt_rc/"
python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 384 --batch_size=12 --version_2_with_negative=False python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 384 --batch_size=1
``` ```
其中CKPT_DIR为Finetune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致* 其中CKPT_DIR为Fine-tune API保存最佳模型的路径, max_seq_len是ERNIE/BERT模型的最大序列长度,*请与训练时配置的参数保持一致*
参数配置正确后,请执行脚本`sh run_predict.sh`,预测时程序会自动调用官方评价脚本(version_2_with_negative=False调用evaluate_v1.py,version_2_with_negative=True调用evaluate_v2.py)即可看到SQuAD数据集的最终效果。 参数配置正确后,请执行脚本`sh run_predict.sh`,预测时程序会自动调用官方评价脚本即可看到SQuAD数据集的最终效果。
如需了解更多预测步骤,请参考`predict.py` 如需了解更多预测步骤,请参考`predict.py`
**NOTE:** **NOTE:**
运行预测脚本时,建议用单卡预测。 运行预测脚本时,建议用单卡预测。
我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
|预训练模型|任务类型|数据集|AIStudio链接|备注|
|-|-|-|-|-|
|ResNet|图像分类|猫狗数据集DogCat|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216772)||
|ERNIE|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216764)||
|ERNIE|文本分类|中文新闻分类数据集THUNEWS|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216649)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成文本分类迁移学习。|
|ERNIE|序列标注|中文序列标注数据集MSRA_NER|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216787)||
|ERNIE|序列标注|中文快递单数据集Express|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216683)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成序列标注迁移学习。|
|ERNIE Tiny|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215599)||
|Senta|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216851)|本教程讲述了任何利用Senta和Fine-tune API完成情感分类迁移学习。|
|Senta|情感分析预测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216735)||
|LAC|词法分析|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215641)||
|Ultra-Light-Fast-Generic-Face-Detector-1MB|人脸检测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216749)||
## 超参优化AutoDL Finetuner
PaddleHub还提供了超参优化(Hyperparameter Tuning)功能, 自动搜索最优模型超参得到更好的模型效果。详细信息参见[AutoDL Finetuner超参优化功能教程](../../tutorial/autofinetune.md)[使用样例](../autofinetune)
...@@ -21,51 +21,29 @@ from __future__ import print_function ...@@ -21,51 +21,29 @@ from __future__ import print_function
import argparse import argparse
import ast import ast
import paddlehub as hub import paddlehub as hub
hub.common.logger.logger.setLevel("INFO") hub.common.logger.logger.setLevel("INFO")
# yapf: disable # yapf: disable
parser = argparse.ArgumentParser(__doc__) parser = argparse.ArgumentParser(__doc__)
parser.add_argument("--num_epoch", type=int, default=1, help="Number of epoches for fine-tuning.") parser.add_argument("--num_epoch", type=int, default=1, help="Number of epoches for fine-tuning.")
parser.add_argument("--use_gpu", type=ast.literal_eval, default=True, help="Whether use GPU for finetuning, input should be True or False") parser.add_argument("--use_gpu", type=ast.literal_eval, default=True, help="Whether use GPU for finetuning, input should be True or False")
parser.add_argument("--learning_rate", type=float, default=4e-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("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint.")
parser.add_argument("--result_dir", type=str, default=None, help="Directory to predicted results to be written.")
parser.add_argument("--max_seq_len", type=int, default=384, help="Number of words of the longest seqence.") parser.add_argument("--max_seq_len", type=int, default=384, help="Number of words of the longest seqence.")
parser.add_argument("--batch_size", type=int, default=8, help="Total examples' number in batch for training.") parser.add_argument("--batch_size", type=int, default=8, 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=True, help="Whether use data parallel.")
parser.add_argument("--max_answer_length", type=int, default=30, help="Max answer length.")
parser.add_argument("--n_best_size", type=int, default=20, help="The total number of n-best predictions to generate in the nbest_predictions.json output file.")
parser.add_argument("--null_score_diff_threshold", type=float, default=0.0, help="If null_score - best_non_null is greater than the threshold predict null.")
parser.add_argument("--dataset", type=str, default="squad", help="Support squad, squad2.0, drcd and cmrc2018")
args = parser.parse_args() args = parser.parse_args()
# yapf: enable. # yapf: enable.
if __name__ == '__main__': if __name__ == '__main__':
# Download dataset and use ReadingComprehensionReader to read dataset # Load Paddlehub BERT pretrained model
if args.dataset == "squad": module = hub.Module(name="bert_uncased_L-12_H-768_A-12")
dataset = hub.dataset.SQUAD(version_2_with_negative=False)
module = hub.Module(name="bert_uncased_L-12_H-768_A-12")
elif args.dataset == "squad2.0" or args.dataset == "squad2":
args.dataset = "squad2.0"
dataset = hub.dataset.SQUAD(version_2_with_negative=True)
module = hub.Module(name="bert_uncased_L-12_H-768_A-12")
elif args.dataset == "drcd":
dataset = hub.dataset.DRCD()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
elif args.dataset == "cmrc2018":
dataset = hub.dataset.CMRC2018()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
else:
raise Exception(
"Only support datasets: squad, squad2.0, drcd and cmrc2018")
inputs, outputs, program = module.context( inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len) trainable=True, max_seq_len=args.max_seq_len)
# Download dataset and use ReadingComprehensionReader to read dataset
# If you wanna load SQuAD 2.0 dataset, just set version_2_with_negative as True
dataset = hub.dataset.SQUAD(version_2_with_negative=False)
# dataset = hub.dataset.SQUAD(version_2_with_negative=True)
reader = hub.reader.ReadingComprehensionReader( reader = hub.reader.ReadingComprehensionReader(
dataset=dataset, dataset=dataset,
vocab_path=module.get_vocab_path(), vocab_path=module.get_vocab_path(),
...@@ -84,25 +62,13 @@ if __name__ == '__main__': ...@@ -84,25 +62,13 @@ if __name__ == '__main__':
inputs["input_mask"].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,
warmup_proportion=args.warmup_proportion,
lr_scheduler="linear_decay")
# Setup runing config for PaddleHub Finetune API # Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
log_interval=10, use_data_parallel=False,
use_pyreader=args.use_pyreader,
use_data_parallel=args.use_data_parallel,
save_ckpt_interval=100,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
num_epoch=args.num_epoch,
batch_size=args.batch_size, batch_size=args.batch_size,
checkpoint_dir=args.checkpoint_dir, checkpoint_dir=args.checkpoint_dir,
enable_memory_optim=True, strategy=hub.AdamWeightDecayStrategy())
strategy=strategy)
# Define a reading comprehension finetune task by PaddleHub's API # Define a reading comprehension finetune task by PaddleHub's API
reading_comprehension_task = hub.ReadingComprehensionTask( reading_comprehension_task = hub.ReadingComprehensionTask(
...@@ -112,5 +78,5 @@ if __name__ == '__main__': ...@@ -112,5 +78,5 @@ if __name__ == '__main__':
config=config) config=config)
# Data to be predicted # Data to be predicted
data = dataset.dev_examples[97:98] data = dataset.dev_examples[:10]
print(reading_comprehension_task.predict(data=data, return_result=True)) print(reading_comprehension_task.predict(data=data, return_result=True))
...@@ -31,38 +31,22 @@ parser.add_argument("--weight_decay", type=float, default=0.01, help="Weight dec ...@@ -31,38 +31,22 @@ parser.add_argument("--weight_decay", type=float, default=0.01, help="Weight dec
parser.add_argument("--warmup_proportion", type=float, default=0.0, help="Warmup proportion params for warmup strategy") 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("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint")
parser.add_argument("--max_seq_len", type=int, default=384, help="Number of words of the longest seqence.") parser.add_argument("--max_seq_len", type=int, default=384, help="Number of words of the longest seqence.")
parser.add_argument("--null_score_diff_threshold", type=float, default=0.0, help="If null_score - best_non_null is greater than the threshold predict null.")
parser.add_argument("--n_best_size", type=int, default=20,help="The total number of n-best predictions to generate in the ""nbest_predictions.json output file.")
parser.add_argument("--max_answer_length", type=int, default=30,help="The maximum length of an answer that can be generated. This is needed ""because the start and end predictions are not conditioned on one another.")
parser.add_argument("--batch_size", type=int, default=8, help="Total examples' number in batch for training.") parser.add_argument("--batch_size", type=int, default=8, 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=True, help="Whether use data parallel.")
parser.add_argument("--use_data_parallel", type=ast.literal_eval, default=False, help="Whether use data parallel.")
parser.add_argument("--dataset", type=str, default="squad", help="Support squad, squad2.0, drcd and cmrc2018")
args = parser.parse_args() args = parser.parse_args()
# yapf: enable. # yapf: enable.
if __name__ == '__main__': if __name__ == '__main__':
# Download dataset and use ReadingComprehensionReader to read dataset # Load Paddlehub BERT pretrained model
if args.dataset == "squad": module = hub.Module(name="bert_uncased_L-12_H-768_A-12")
dataset = hub.dataset.SQUAD(version_2_with_negative=False)
module = hub.Module(name="bert_uncased_L-12_H-768_A-12")
elif args.dataset == "squad2.0" or args.dataset == "squad2":
args.dataset = "squad2.0"
dataset = hub.dataset.SQUAD(version_2_with_negative=True)
module = hub.Module(name="bert_uncased_L-12_H-768_A-12")
elif args.dataset == "drcd":
dataset = hub.dataset.DRCD()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
elif args.dataset == "cmrc2018":
dataset = hub.dataset.CMRC2018()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
else:
raise Exception(
"Only support datasets: squad, squad2.0, drcd and cmrc2018")
inputs, outputs, program = module.context( inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len) trainable=True, max_seq_len=args.max_seq_len)
# Download dataset and use ReadingComprehensionReader to read dataset
# If you wanna load SQuAD 2.0 dataset, just set version_2_with_negative as True
dataset = hub.dataset.SQUAD(version_2_with_negative=False)
# dataset = hub.dataset.SQUAD(version_2_with_negative=True)
reader = hub.reader.ReadingComprehensionReader( reader = hub.reader.ReadingComprehensionReader(
dataset=dataset, dataset=dataset,
vocab_path=module.get_vocab_path(), vocab_path=module.get_vocab_path(),
...@@ -84,19 +68,16 @@ if __name__ == '__main__': ...@@ -84,19 +68,16 @@ if __name__ == '__main__':
strategy = hub.AdamWeightDecayStrategy( strategy = hub.AdamWeightDecayStrategy(
weight_decay=args.weight_decay, weight_decay=args.weight_decay,
learning_rate=args.learning_rate, learning_rate=args.learning_rate,
warmup_proportion=args.warmup_proportion, warmup_proportion=args.warmup_proportion)
lr_scheduler="linear_decay")
# Setup runing config for PaddleHub Finetune API # Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
eval_interval=300, eval_interval=300,
use_pyreader=args.use_pyreader,
use_data_parallel=args.use_data_parallel, use_data_parallel=args.use_data_parallel,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
num_epoch=args.num_epoch, num_epoch=args.num_epoch,
batch_size=args.batch_size, batch_size=args.batch_size,
checkpoint_dir=args.checkpoint_dir, checkpoint_dir=args.checkpoint_dir,
enable_memory_optim=True,
strategy=strategy) strategy=strategy)
# Define a reading comprehension finetune task by PaddleHub's API # Define a reading comprehension finetune task by PaddleHub's API
...@@ -105,7 +86,7 @@ if __name__ == '__main__': ...@@ -105,7 +86,7 @@ if __name__ == '__main__':
feature=seq_output, feature=seq_output,
feed_list=feed_list, feed_list=feed_list,
config=config, config=config,
sub_task=args.dataset, sub_task="squad",
) )
# Finetune by PaddleHub's API # Finetune by PaddleHub's API
......
export FLAGS_eager_delete_tensor_gb=0.0 export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0 export CUDA_VISIBLE_DEVICES=0
# Recommending hyper parameters for difference task # The suggested hyper parameters for difference task
# squad: batch_size=8, weight_decay=0, num_epoch=3, max_seq_len=512, lr=5e-5 # squad: batch_size=8, weight_decay=0.01, num_epoch=3, max_seq_len=512, lr=3e-5
# squad2.0: batch_size=8, weight_decay=0, num_epoch=3, max_seq_len=512, lr=5e-5 # squad2.0: batch_size=8, weight_decay=0.01, num_epoch=3, max_seq_len=512, lr=3e-5
# cmrc2018: batch_size=8, weight_decay=0, num_epoch=2, max_seq_len=512, lr=2.5e-5 # cmrc2018: batch_size=8, weight_decay=0, num_epoch=2, max_seq_len=512, lr=2.5e-5
# drcd: batch_size=8, weight_decay=0, num_epoch=2, max_seq_len=512, lr=2.5e-5 # drcd: batch_size=8, weight_decay=0, num_epoch=2, max_seq_len=512, lr=2.5e-5
dataset=cmrc2018
python -u reading_comprehension.py \ python -u reading_comprehension.py \
--batch_size=8 \ --batch_size=8 \
--use_gpu=True \ --use_gpu=True \
--checkpoint_dir=./ckpt_${dataset} \ --checkpoint_dir="./ckpt_squad" \
--learning_rate=2.5e-5 \ --learning_rate=3e-5 \
--weight_decay=0.01 \ --weight_decay=0.01 \
--warmup_proportion=0.1 \ --warmup_proportion=0.1 \
--num_epoch=2 \ --num_epoch=2 \
--max_seq_len=512 \ --max_seq_len=512 \
--dataset=${dataset} --use_data_parallel=True
export FLAGS_eager_delete_tensor_gb=0.0 export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0 export CUDA_VISIBLE_DEVICES=0
python -u elmo_finetune.py \ python -u predict.py \
--batch_size=32 \ --batch_size=1 \
--use_gpu=True \ --use_gpu=True \
--checkpoint_dir="./ckpt_chnsenticorp" \ --checkpoint_dir="./ckpt_squad" \
--learning_rate=1e-4 \ --max_seq_len=512 \
--weight_decay=1 \
--num_epoch=3
# PaddleHub 回归任务 # PaddleHub 回归任务
本示例将展示如何使用PaddleHub Finetune API以及BERT预训练模型完成回归任务。 本示例将展示如何使用PaddleHub Fine-tune API以及Transformer类模型完成回归任务。
## 如何开始Finetune ## 如何开始Fine-tune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_regression.sh`即可开始使用BERT对GLUE-STSB数据集进行Finetune。 在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_regression.sh`即可开始使用BERT对GLUE-STSB数据集进行Fine-tune。
其中脚本参数说明如下: 其中脚本参数说明如下:
```bash ```bash
# 模型相关 # 模型相关
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数 --batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数
--learning_rate: Finetune的最大学习率 --learning_rate: Fine-tune的最大学习率
--weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01 --weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01
--warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0 --warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0
--num_epoch: Finetune迭代的轮数 --num_epoch: Fine-tune迭代的轮数
--max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数 --max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数
--use_data_parallel: 是否使用并行计算,默认False。打开该功能依赖nccl库。 --use_data_parallel: 是否使用并行计算,默认True。打开该功能依赖nccl库。
--use_pyreader: 是否使用pyreader,默认False。
# 任务相关 # 任务相关
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型 --checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型
...@@ -26,12 +25,12 @@ ...@@ -26,12 +25,12 @@
## 代码步骤 ## 代码步骤
使用PaddleHub Finetune API进行Finetune可以分为4个步骤 使用PaddleHub Fine-tune API进行Fine-tune可以分为4个步骤
### Step1: 加载预训练模型 ### Step1: 加载预训练模型
```python ```python
module = hub.Module(name="ernie") module = hub.Module(name="ernie_v2_eng_base")
inputs, outputs, program = module.context(trainable=True, max_seq_len=128) inputs, outputs, program = module.context(trainable=True, max_seq_len=128)
``` ```
其中最大序列长度`max_seq_len`是可以调整的参数,建议值128,根据任务文本长度不同可以调整该值,但最大不超过512。 其中最大序列长度`max_seq_len`是可以调整的参数,建议值128,根据任务文本长度不同可以调整该值,但最大不超过512。
...@@ -54,12 +53,13 @@ BERT-wwm, Chinese | `hub.Module(name='bert_wwm_chinese_L-12_H-7 ...@@ -54,12 +53,13 @@ BERT-wwm, Chinese | `hub.Module(name='bert_wwm_chinese_L-12_H-7
BERT-wwm-ext, Chinese | `hub.Module(name='bert_wwm_ext_chinese_L-12_H-768_A-12')` BERT-wwm-ext, Chinese | `hub.Module(name='bert_wwm_ext_chinese_L-12_H-768_A-12')`
RoBERTa-wwm-ext, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-12_H-768_A-12')` RoBERTa-wwm-ext, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-12_H-768_A-12')`
RoBERTa-wwm-ext-large, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-24_H-1024_A-16')` RoBERTa-wwm-ext-large, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-24_H-1024_A-16')`
更多模型请参考[PaddleHub官网](https://www.paddlepaddle.org.cn/hub?filter=hot&value=1) 更多模型请参考[PaddleHub官网](https://www.paddlepaddle.org.cn/hub?filter=hot&value=1)
如果想尝试BERT模型,只需要更换Module中的`name`参数即可. 如果想尝试BERT模型,只需要更换Module中的`name`参数即可.
```python ```python
# 更换name参数即可无缝切换BERT中文模型, 代码示例如下 # 更换name参数即可无缝切换BERT模型, 代码示例如下
module = hub.Module(name="bert_chinese_L-12_H-768_A-12") module = hub.Module(name="bert_cased_L-12_H-768_A-12")
``` ```
### Step2: 准备数据集并使用RegressionReader读取数据 ### Step2: 准备数据集并使用RegressionReader读取数据
...@@ -83,6 +83,10 @@ RegressionReader中的`data_generator`会自动按照模型对应词表对数据 ...@@ -83,6 +83,10 @@ RegressionReader中的`data_generator`会自动按照模型对应词表对数据
**NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。 **NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。
#### 自定义数据集
如果想加载自定义数据集完成迁移学习,详细参见[自定义数据集](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)
### Step3:选择优化策略和运行配置 ### Step3:选择优化策略和运行配置
```python ```python
...@@ -97,27 +101,30 @@ config = hub.RunConfig(use_cuda=True, num_epoch=3, batch_size=32, strategy=strat ...@@ -97,27 +101,30 @@ config = hub.RunConfig(use_cuda=True, num_epoch=3, batch_size=32, strategy=strat
``` ```
#### 优化策略 #### 优化策略
PaddleHub提供了许多优化策略,如`AdamWeightDecayStrategy``ULMFiTStrategy``DefaultFinetuneStrategy`等,详细信息参见[策略](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Strategy)
针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy` 针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy`
`learning_rate`: Finetune过程中的最大学习率; `learning_rate`: Fine-tune过程中的最大学习率;
`weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数; `weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数;
`warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate; `warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate;
`lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减; `lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减;
#### 运行配置 #### 运行配置
`RunConfig` 主要控制Finetune的训练,包含以下可控制的参数: `RunConfig` 主要控制Fine-tune的训练,包含以下可控制的参数:
* `log_interval`: 进度日志打印间隔,默认每10个step打印一次 * `log_interval`: 进度日志打印间隔,默认每10个step打印一次
* `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集 * `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集
* `save_ckpt_interval`: 模型保存间隔,请根据任务大小配置,默认只保存验证集效果最好的模型和训练结束的模型 * `save_ckpt_interval`: 模型保存间隔,请根据任务大小配置,默认只保存验证集效果最好的模型和训练结束的模型
* `use_cuda`: 是否使用GPU训练,默认为False * `use_cuda`: 是否使用GPU训练,默认为False
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成 * `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: finetune的轮数 * `num_epoch`: Fine-tune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size * `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `enable_memory_optim`: 是否使用内存优化, 默认为True * `enable_memory_optim`: 是否使用内存优化, 默认为True
* `strategy`: Finetune优化策略 * `strategy`: Fine-tune优化策略
### Step4: 构建网络并创建回归迁移任务进行Finetune ### Step4: 构建网络并创建回归迁移任务进行Fine-tune
```python ```python
pooled_output = outputs["pooled_output"] pooled_output = outputs["pooled_output"]
...@@ -138,12 +145,16 @@ reg_task = hub.RegressionTask( ...@@ -138,12 +145,16 @@ reg_task = hub.RegressionTask(
reg_task.finetune_and_eval() reg_task.finetune_and_eval()
``` ```
**NOTE:** **NOTE:**
1. `outputs["pooled_output"]`返回了BERT模型对应的[CLS]向量,可以用于句子或句对的特征表达。 1. `outputs["pooled_output"]`返回了ERNIE/BERT模型对应的[CLS]向量,可以用于句子或句对的特征表达。
2. `feed_list`中的inputs参数指名了BERT中的输入tensor的顺序,与RegressionReader返回的结果一致。 2. `feed_list`中的inputs参数指名了BERT中的输入tensor的顺序,与RegressionReader返回的结果一致。
#### 自定义迁移任务
如果想改变迁移任务组网,详细参见[自定义迁移任务](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub:-%E8%87%AA%E5%AE%9A%E4%B9%89Task)
## 可视化 ## 可视化
Finetune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令 Fine-tune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令
```bash ```bash
$ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM} $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM}
``` ```
...@@ -151,13 +162,33 @@ $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_N ...@@ -151,13 +162,33 @@ $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_N
## 模型预测 ## 模型预测
通过Finetune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。 通过Fine-tune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数 配置脚本参数
``` ```
CKPT_DIR="ckpt_STS-B/" CKPT_DIR="ckpt_stsb/"
python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128 python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128
``` ```
其中CKPT_DIR为Finetune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致* 其中CKPT_DIR为Fine-tune API保存最佳模型的路径, max_seq_len是ERNIE/BERT模型的最大序列长度,*请与训练时配置的参数保持一致*
参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下回归任务预测结果。 参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下回归任务预测结果。
如需了解更多预测步骤,请参考`predict.py` 如需了解更多预测步骤,请参考`predict.py`
我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
|预训练模型|任务类型|数据集|AIStudio链接|备注|
|-|-|-|-|-|
|ResNet|图像分类|猫狗数据集DogCat|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216772)||
|ERNIE|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216764)||
|ERNIE|文本分类|中文新闻分类数据集THUNEWS|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216649)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成文本分类迁移学习。|
|ERNIE|序列标注|中文序列标注数据集MSRA_NER|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216787)||
|ERNIE|序列标注|中文快递单数据集Express|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216683)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成序列标注迁移学习。|
|ERNIE Tiny|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215599)||
|Senta|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216851)|本教程讲述了任何利用Senta和Fine-tune API完成情感分类迁移学习。|
|Senta|情感分析预测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216735)||
|LAC|词法分析|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215641)||
|Ultra-Light-Fast-Generic-Face-Detector-1MB|人脸检测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216749)||
## 超参优化AutoDL Finetuner
PaddleHub还提供了超参优化(Hyperparameter Tuning)功能, 自动搜索最优模型超参得到更好的模型效果。详细信息参见[AutoDL Finetuner超参优化功能教程](../../tutorial/autofinetune.md)[使用样例](../autofinetune)
...@@ -34,29 +34,17 @@ parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory ...@@ -34,29 +34,17 @@ parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory
parser.add_argument("--batch_size", type=int, default=1, help="Total examples' number in batch for training.") 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=512, help="Number of words of the longest seqence.") parser.add_argument("--max_seq_len", type=int, default=512, 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_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.")
parser.add_argument("--dataset", type=str, default="STS-B", help="Directory to model checkpoint")
args = parser.parse_args() args = parser.parse_args()
# yapf: enable. # yapf: enable.
if __name__ == '__main__': if __name__ == '__main__':
dataset = None # Load Paddlehub ERNIE 2.0 pretrained model
metrics_choices = [] module = hub.Module(name="ernie_v2_eng_base")
# Download dataset and use ClassifyReader to read dataset
if args.dataset.lower() == "sts-b":
dataset = hub.dataset.GLUE("STS-B")
module = hub.Module(name="bert_uncased_L-12_H-768_A-12")
metrics_choices = ["acc"]
else:
raise ValueError("%s dataset is not defined" % args.dataset)
support_metrics = ["acc", "f1", "matthews"]
for metric in metrics_choices:
if metric not in support_metrics:
raise ValueError("\"%s\" metric is not defined" % metric)
inputs, outputs, program = module.context( inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len) trainable=True, max_seq_len=args.max_seq_len)
# Download dataset and use RegressionReader to read dataset
dataset = hub.dataset.GLUE("STS-B")
reader = hub.reader.RegressionReader( reader = hub.reader.RegressionReader(
dataset=dataset, dataset=dataset,
vocab_path=module.get_vocab_path(), vocab_path=module.get_vocab_path(),
...@@ -79,21 +67,20 @@ if __name__ == '__main__': ...@@ -79,21 +67,20 @@ if __name__ == '__main__':
# Setup runing config for PaddleHub Finetune API # Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
use_data_parallel=False, use_data_parallel=False,
use_pyreader=args.use_pyreader,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
batch_size=args.batch_size, batch_size=args.batch_size,
enable_memory_optim=False,
checkpoint_dir=args.checkpoint_dir, checkpoint_dir=args.checkpoint_dir,
strategy=hub.finetune.strategy.DefaultFinetuneStrategy()) strategy=hub.AdamWeightDecayStrategy())
# Define a regression finetune task by PaddleHub's API # Define a regression finetune task by PaddleHub's API
reg_task = hub.RegressionTask( reg_task = hub.RegressionTask(
data_reader=reader, data_reader=reader,
feature=pooled_output, feature=pooled_output,
feed_list=feed_list, feed_list=feed_list,
config=config) config=config,
)
# Data to be prdicted # Data to be prdicted
data = [[d.text_a, d.text_b] for d in dataset.get_predict_examples()[:3]] data = [[d.text_a, d.text_b] for d in dataset.get_predict_examples()[:10]]
print(reg_task.predict(data=data, return_result=True)) print(reg_task.predict(data=data, return_result=True))
...@@ -24,30 +24,25 @@ import paddlehub as hub ...@@ -24,30 +24,25 @@ import paddlehub as hub
parser = argparse.ArgumentParser(__doc__) parser = argparse.ArgumentParser(__doc__)
parser.add_argument("--num_epoch", type=int, default=3, help="Number of epoches for fine-tuning.") 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("--use_gpu", type=ast.literal_eval, default=False, help="Whether use GPU for finetuning, input should be True or False")
parser.add_argument("--dataset", type=str, default="STS-B", help="Directory to model checkpoint")
parser.add_argument("--learning_rate", type=float, default=5e-5, help="Learning rate used to train with warmup.") 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("--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("--warmup_proportion", type=float, default=0.1, help="Warmup proportion params for warmup strategy")
parser.add_argument("--data_dir", type=str, default=None, help="Path to training data.")
parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint") 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("--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("--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.") parser.add_argument("--use_data_parallel", type=ast.literal_eval, default=False, help="Whether use data parallel.")
args = parser.parse_args() args = parser.parse_args()
# yapf: enable. # yapf: enable.
if __name__ == '__main__': if __name__ == '__main__':
dataset = None
# Download dataset and use ClassifyReader to read dataset
if args.dataset.lower() == "sts-b":
dataset = hub.dataset.GLUE("STS-B")
module = hub.Module(name="ernie_v2_eng_base")
else:
raise ValueError("%s dataset is not defined" % args.dataset)
# Load Paddlehub ERNIE 2.0 pretrained model
module = hub.Module(name="ernie_v2_eng_base")
inputs, outputs, program = module.context( inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len) trainable=True, max_seq_len=args.max_seq_len)
# Download dataset and use RegressionReader to read dataset
dataset = hub.dataset.GLUE("STS-B")
reader = hub.reader.RegressionReader( reader = hub.reader.RegressionReader(
dataset=dataset, dataset=dataset,
vocab_path=module.get_vocab_path(), vocab_path=module.get_vocab_path(),
...@@ -69,14 +64,14 @@ if __name__ == '__main__': ...@@ -69,14 +64,14 @@ if __name__ == '__main__':
# Select finetune strategy, setup config and finetune # Select finetune strategy, setup config and finetune
strategy = hub.AdamWeightDecayStrategy( strategy = hub.AdamWeightDecayStrategy(
warmup_proportion=args.warmup_proportion,
weight_decay=args.weight_decay, weight_decay=args.weight_decay,
learning_rate=args.learning_rate, learning_rate=args.learning_rate)
lr_scheduler="linear_decay")
# Setup runing config for PaddleHub Finetune API # Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
eval_interval=300,
use_data_parallel=args.use_data_parallel, use_data_parallel=args.use_data_parallel,
use_pyreader=args.use_pyreader,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
num_epoch=args.num_epoch, num_epoch=args.num_epoch,
batch_size=args.batch_size, batch_size=args.batch_size,
......
export FLAGS_eager_delete_tensor_gb=0.0 export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0 export CUDA_VISIBLE_DEVICES=0
# User can select chnsenticorp, nlpcc_dbqa, lcqmc and so on for different task CKPT_DIR="./ckpt_stsb"
DATASET="STS-B"
CKPT_DIR="./ckpt_${DATASET}"
# STS-B: batch_size=32, max_seq_len=128
python -u predict.py --checkpoint_dir $CKPT_DIR \ python -u predict.py --checkpoint_dir ${CKPT_DIR} \
--max_seq_len 128 \ --max_seq_len 128 \
--use_gpu True \ --use_gpu True \
--dataset=${DATASET} \ --batch_size=1 \
--batch_size=32 \
export FLAGS_eager_delete_tensor_gb=0.0 export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0 export CUDA_VISIBLE_DEVICES=0
DATASET="STS-B" CKPT_DIR="./ckpt_stsb"
CKPT_DIR="./ckpt_${DATASET}"
# Recommending hyper parameters for difference task
# STS-B: batch_size=32, weight_decay=0.1, num_epoch=3, max_seq_len=128, lr=4e-5
python -u regression.py \ python -u regression.py \
--batch_size=32 \ --batch_size=32 \
--use_gpu=True \ --use_gpu=True \
--dataset=${DATASET} \
--checkpoint_dir=${CKPT_DIR} \ --checkpoint_dir=${CKPT_DIR} \
--learning_rate=4e-5 \ --learning_rate=4e-5 \
--warmup_proportion=0.1 \
--weight_decay=0.1 \ --weight_decay=0.1 \
--max_seq_len=128 \ --max_seq_len=128 \
--num_epoch=3 \ --num_epoch=3 \
--use_pyreader=True \ --use_data_parallel=False
--use_data_parallel=True
# PaddleHub Senta # Senta 情感分析
## 关于 本示例展示如何使用PaddleHub Senta预训练模型进行预测。
本示例展示如何使用PaddleHub Senta Module进行预测 Senta是百度NLP开放的中文情感分析模型,可以用于进行中文句子的情感分析,输出结果为`{正向/中性/负向}`中的一个,关于模型更多信息参见[Senta](https://www.paddlepaddle.org.cn/hubdetail?name=senta_bilstm&en_category=SentimentAnalysis), 本示例代码选择的是Senta-BiLSTM模型
Senta是百度NLP开放的中文情感分析模型,可以用于进行中文句子的情感分析,输出结果为`{正向/中性/负向}`中的一个,关于模型的结构细节,请查看[Senta](https://github.com/baidu/senta), 本示例代码选择的是Senta-BiLSTM模型。 ## 命令行方式预测
## 准备工作
在运行本目录的脚本前,需要先安装1.3.0版本以上的PaddlePaddle(如果您本地已经安装了符合条件的PaddlePaddle版本,那么可以跳过`准备工作`这一步)。
如果您的机器支持GPU,我们建议下载GPU版本的PaddlePaddle,使用GPU进行训练和预测的效率都比使用CPU要高。
```shell
# 安装GPU版本的PaddlePaddle
$ pip install --upgrade paddlepaddle-gpu
```
如果您的机器不支持GPU,可以通过下面的命令来安装CPU版本的PaddlePaddle
```shell ```shell
# 安装CPU版本的PaddlePaddle $ hub run senta_bilstm --input_text "这家餐厅很好吃"
$ pip install --upgrade paddlepaddle $ hub run senta_bilstm --input_file test.txt
``` ```
在安装过程中如果遇到问题,您可以到[Paddle官方网站](http://www.paddlepaddle.org/)上查看解决方案。 test.txt 存放待预测文本, 如:
## 命令行方式预测
`cli_demo.sh`给出了使用命令行接口 (Command Line Interface) 调用Module预测的示例脚本
通过以下命令体验下效果
```shell ```text
$ sh cli_demo.sh 这家餐厅很好吃
这部电影真的很差劲
``` ```
## 通过python API预测 ## 通过python API预测
...@@ -43,9 +27,162 @@ $ sh cli_demo.sh ...@@ -43,9 +27,162 @@ $ sh cli_demo.sh
python senta_demo.py python senta_demo.py
``` ```
## 通过PaddleHub Finetune API微调 ## 通过PaddleHub Fine-tune API微调
`senta_finetune.py` 给出了如何使用Senta模型的句子特征进行Fine-tuning的实例代码。 `senta_finetune.py` 给出了如何使用Senta模型的句子特征进行Fine-tuning的实例代码。
可以运行以下命令在ChnSentiCorp数据集上进行Fine-tuning. 可以运行以下命令在ChnSentiCorp数据集上进行Fine-tuning。
```shell ```shell
$ sh run_finetune.sh $ sh run_finetune.sh
``` ```
其中脚本参数说明如下:
```bash
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型
--num_epoch: Fine-tune迭代的轮数
--use_gpu: 是否使用GPU进行训练,如果机器支持GPU且安装了GPU版本的PaddlePaddle,我们建议您打开这个开关
```
使用PaddleHub Fine-tune API进行Fine-tune可以分为4个步骤
### Step1: 加载预训练模型
```python
module = hub.Module(name="senta_bilstm")
inputs, outputs, program = module.context(trainable=True)
```
PaddleHub提供Senta一列模型可供选择, 模型对应的加载示例如下:
模型名 | PaddleHub Module
---------------------------------- | :------:
senta_bilstm | `hub.Module(name='senta_bilstm')`
senta_bow | `hub.Module(name='senta_bow')`
senta_gru | `hub.Module(name='senta_gru')`
senta_lstm | `hub.Module(name='senta_lstm')`
senta_cnn | `hub.Module(name='senta_cnn')`
更多模型请参考[PaddleHub官网](https://www.paddlepaddle.org.cn/hub?filter=hot&value=1)
如果想尝GRU模型,只需要更换Module中的`name`参数即可.
```python
# 更换name参数即可无缝切换GRU模型, 代码示例如下
module = hub.Module(name="senta_gru")
```
### Step2: 准备数据集并使用LACClassifyReader读取数据
```python
dataset = hub.dataset.ChnSentiCorp()
reader = hub.reader.LACClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path())
```
`hub.dataset.ChnSentiCorp()` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录
`module.get_vocab_path()` 会返回预训练模型对应的词表
LACClassifyReader中的`data_generator`会自动按照模型对应词表对数据进行切词,以迭代器的方式返回Senta所需要的word id。
更多数据集信息参考[Dataset](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Dataset)
#### 自定义数据集
如果想加载自定义数据集完成迁移学习,详细参见[自定义数据集](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)
### Step3:选择优化策略和运行配置
```python
strategy = hub.AdamWeightDecayStrategy(
learning_rate=1e-5,
weight_decay=0.01,
warmup_proportion=0.1,
lr_scheduler="linear_decay",
)
config = hub.RunConfig(use_cuda=True, num_epoch=3, batch_size=32, strategy=strategy)
```
#### 优化策略
PaddleHub提供了许多优化策略,如`AdamWeightDecayStrategy``ULMFiTStrategy``DefaultFinetuneStrategy`等,详细信息参见[策略](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Strategy)
其中`AdamWeightDecayStrategy`
* `learning_rate`: Fine-tune过程中的最大学习率;
* `weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数;
* `warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate;
* `lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减;
#### 运行配置
`RunConfig` 主要控制Fine-tune的训练,包含以下可控制的参数:
* `use_cuda`: 是否使用GPU训练,默认为False
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: Fine-tune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `strategy`: Fine-tune优化策略
### Step4: 构建网络并创建分类迁移任务进行Fine-tune
```python
sent_feature = outputs["sentence_feature"]
feed_list = [inputs["words"].name]
cls_task = hub.TextClassifierTask(
data_reader=reader,
feature=sent_feature,
feed_list=feed_list,
num_classes=dataset.num_labels,
config=config)
cls_task.finetune_and_eval()
```
**NOTE:**
1. `outputs["sentence_feature"]`返回了senta模型对应的句子特征,可以用于句子的特征表达。
2. `feed_list`中的inputs参数指名了senta中的输入tensor的顺序,与LACClassifyReader返回的结果一致。
3. `hub.TextClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于文本分类的迁移任务`TextClassifierTask`
## 可视化
Fine-tune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令
```bash
$ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM}
```
其中${HOST_IP}为本机IP地址,${PORT_NUM}为可用端口号,如本机IP地址为192.168.0.1,端口号8040,用浏览器打开192.168.0.1:8040,即可看到训练过程中指标的变化情况
## 模型预测
通过Fine-tune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数
```
CKPT_DIR="ckpt_chnsentiment/"
python predict.py --checkpoint_dir $CKPT_DIR
```
其中CKPT_DIR为Fine-tune API保存最佳模型的路径
参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。
如需了解更多预测步骤,请参考`predict.py`
我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
|预训练模型|任务类型|数据集|AIStudio链接|备注|
|-|-|-|-|-|
|ResNet|图像分类|猫狗数据集DogCat|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216772)||
|ERNIE|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216764)||
|ERNIE|文本分类|中文新闻分类数据集THUNEWS|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216649)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成文本分类迁移学习。|
|ERNIE|序列标注|中文序列标注数据集MSRA_NER|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216787)||
|ERNIE|序列标注|中文快递单数据集Express|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216683)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成序列标注迁移学习。|
|ERNIE Tiny|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215599)||
|Senta|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216851)|本教程讲述了任何利用Senta和Fine-tune API完成情感分类迁移学习。|
|Senta|情感分析预测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216735)||
|LAC|词法分析|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215641)||
|Ultra-Light-Fast-Generic-Face-Detector-1MB|人脸检测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216749)||
## 超参优化AutoDL Finetuner
PaddleHub还提供了超参优化(Hyperparameter Tuning)功能, 自动搜索最优模型超参得到更好的模型效果。详细信息参见[AutoDL Finetuner超参优化功能教程](../../tutorial/autofinetune.md)[使用样例](../autofinetune)
python ../../paddlehub/commands/hub.py run senta_bilstm --input_file test/test.txt
...@@ -17,6 +17,7 @@ import paddlehub as hub ...@@ -17,6 +17,7 @@ import paddlehub as hub
parser = argparse.ArgumentParser(__doc__) parser = argparse.ArgumentParser(__doc__)
parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint") parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint")
parser.add_argument("--use_gpu", type=ast.literal_eval, default=True, help="Whether use GPU for finetuning, input should be True or False") parser.add_argument("--use_gpu", type=ast.literal_eval, default=True, help="Whether use GPU for finetuning, input should be True or False")
parser.add_argument("--batch_size", type=int, default=1, help="Total examples' number in batch when the program predicts.")
args = parser.parse_args() args = parser.parse_args()
# yapf: enable. # yapf: enable.
...@@ -25,31 +26,26 @@ if __name__ == '__main__': ...@@ -25,31 +26,26 @@ if __name__ == '__main__':
module = hub.Module(name="senta_bilstm") module = hub.Module(name="senta_bilstm")
inputs, outputs, program = module.context(trainable=True) inputs, outputs, program = module.context(trainable=True)
# Sentence classification dataset reader # Download dataset and use LACClassifyReader to read dataset
dataset = hub.dataset.ChnSentiCorp() dataset = hub.dataset.ChnSentiCorp()
reader = hub.reader.LACClassifyReader( reader = hub.reader.LACClassifyReader(
dataset=dataset, vocab_path=module.get_vocab_path()) dataset=dataset, vocab_path=module.get_vocab_path())
strategy = hub.AdamWeightDecayStrategy( sent_feature = outputs["sentence_feature"]
weight_decay=0.01,
warmup_proportion=0.1, # Setup feed list for data feeder
learning_rate=5e-5, # Must feed all the tensor of senta's module need
lr_scheduler="linear_decay", feed_list = [inputs["words"].name]
optimizer_name="adam")
# Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
use_data_parallel=False, use_data_parallel=False,
use_pyreader=False,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
batch_size=1, batch_size=args.batch_size,
enable_memory_optim=False,
checkpoint_dir=args.checkpoint_dir, checkpoint_dir=args.checkpoint_dir,
strategy=strategy) strategy=hub.AdamWeightDecayStrategy())
sent_feature = outputs["sentence_feature"]
feed_list = [inputs["words"].name]
# Define a classfication finetune task by PaddleHub's API
cls_task = hub.TextClassifierTask( cls_task = hub.TextClassifierTask(
data_reader=reader, data_reader=reader,
feature=sent_feature, feature=sent_feature,
...@@ -57,6 +53,7 @@ if __name__ == '__main__': ...@@ -57,6 +53,7 @@ if __name__ == '__main__':
num_classes=dataset.num_labels, num_classes=dataset.num_labels,
config=config) config=config)
# Data to be predicted
data = ["这家餐厅很好吃", "这部电影真的很差劲"] data = ["这家餐厅很好吃", "这部电影真的很差劲"]
print(cls_task.predict(data=data, return_result=True)) print(cls_task.predict(data=data, return_result=True))
export FLAGS_eager_delete_tensor_gb=0.0 export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0 export CUDA_VISIBLE_DEVICES=0
DATASET="chnsenticorp" CKPT_DIR="./ckpt_chnsenticorp"
CKPT_DIR="./ckpt_${DATASET}"
python -u senta_finetune.py \ python -u senta_finetune.py \
--batch_size=24 \ --batch_size=24 \
--use_gpu=False \ --use_gpu=True \
--checkpoint_dir=${CKPT_DIR} \ --checkpoint_dir=${CKPT_DIR} \
--num_epoch=3 --num_epoch=3
export FLAGS_eager_delete_tensor_gb=0.0 export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0 export CUDA_VISIBLE_DEVICES=0
CKPT_DIR="./ckpt_chnsenticorp/best_model" CKPT_DIR="./ckpt_chnsenticorp "
python -u predict.py --checkpoint_dir $CKPT_DIR --use_gpu False python -u predict.py --checkpoint_dir $CKPT_DIR --use_gpu True
...@@ -11,10 +11,11 @@ if __name__ == "__main__": ...@@ -11,10 +11,11 @@ if __name__ == "__main__":
# Load Senta-BiLSTM module # Load Senta-BiLSTM module
senta = hub.Module(name="senta_bilstm") senta = hub.Module(name="senta_bilstm")
# Data to be predicted
test_text = ["这家餐厅很好吃", "这部电影真的很差劲"] test_text = ["这家餐厅很好吃", "这部电影真的很差劲"]
# execute predict and print the result
input_dict = {"text": test_text} input_dict = {"text": test_text}
results = senta.sentiment_classify(data=input_dict) results = senta.sentiment_classify(data=input_dict)
for index, text in enumerate(test_text): for index, text in enumerate(test_text):
......
...@@ -15,13 +15,12 @@ args = parser.parse_args() ...@@ -15,13 +15,12 @@ args = parser.parse_args()
# yapf: enable. # yapf: enable.
if __name__ == '__main__': if __name__ == '__main__':
# Step1: load Paddlehub senta pretrained model # Load Paddlehub senta pretrained model
module = hub.Module(name="senta_bilstm") module = hub.Module(name="senta_bilstm")
inputs, outputs, program = module.context(trainable=True) inputs, outputs, program = module.context(trainable=True)
# Step2: Download dataset and use LACClassifyReader to read dataset # Download dataset and use LACClassifyReader to read dataset
dataset = hub.dataset.ChnSentiCorp() dataset = hub.dataset.ChnSentiCorp()
reader = hub.reader.LACClassifyReader( reader = hub.reader.LACClassifyReader(
dataset=dataset, vocab_path=module.get_vocab_path()) dataset=dataset, vocab_path=module.get_vocab_path())
...@@ -31,16 +30,15 @@ if __name__ == '__main__': ...@@ -31,16 +30,15 @@ if __name__ == '__main__':
# Must feed all the tensor of senta's module need # Must feed all the tensor of senta's module need
feed_list = [inputs["words"].name] feed_list = [inputs["words"].name]
strategy = hub.finetune.strategy.AdamWeightDecayStrategy( # Setup runing config for PaddleHub Finetune API
learning_rate=1e-4, weight_decay=0.01, warmup_proportion=0.05)
config = hub.RunConfig( config = hub.RunConfig(
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
use_pyreader=False,
use_data_parallel=False,
num_epoch=args.num_epoch, num_epoch=args.num_epoch,
batch_size=args.batch_size, batch_size=args.batch_size,
checkpoint_dir=args.checkpoint_dir, checkpoint_dir=args.checkpoint_dir,
use_pyreader=False, strategy=hub.AdamWeightDecayStrategy())
strategy=strategy)
# Define a classfication finetune task by PaddleHub's API # Define a classfication finetune task by PaddleHub's API
cls_task = hub.TextClassifierTask( cls_task = hub.TextClassifierTask(
......
# Word2vec # 句子相似度
## 关于 本示例展示如何使用[word2vec_skipgram](https://www.paddlepaddle.org.cn/hubdetail?name=word2vec_skipgram&en_category=SemanticModel)模型进行句子相似度预测。
本示例展示如何使用word2vec_skipgram Module进行句子相似度预测。 该示例运用最简单的方法,将一个句子中所有单词的word embedding叠加,得到句子向量。之后计算余弦相似度。
word2vec_skipgram是对中文词语的向量表示,可以用于各类NLP下游任务等。
## 准备工作
在运行本目录的脚本前,需要先安装1.4.0版本以上的PaddlePaddle(如果您本地已经安装了符合条件的PaddlePaddle版本,那么可以跳过`准备工作`这一步)。
```shell
# 安装GPU版本的PaddlePaddle
$ pip install --upgrade paddlepaddle-gpu
```
如果您的机器不支持GPU,可以通过下面的命令来安装CPU版本的PaddlePaddle
```shell
# 安装CPU版本的PaddlePaddle
$ pip install --upgrade paddlepaddle
```
在安装过程中如果遇到问题,您可以到[Paddle官方网站](http://www.paddlepaddle.org/)上查看解决方案。
## 预测 ## 预测
......
# PaddleHub 序列标注 # PaddleHub 序列标注
## 如何开始Finetune ## 如何开始Fine-tune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_sequence_label.sh`即可开始使用ERNIE对MSRA_NER数据集进行Finetune。 在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_sequence_label.sh`即可开始使用ERNIE对MSRA_NER数据集进行Fine-tune。
其中脚本参数说明如下: 其中脚本参数说明如下:
...@@ -10,13 +10,12 @@ ...@@ -10,13 +10,12 @@
# 模型相关 # 模型相关
--use_gpu: 是否使用GPU,默认为False --use_gpu: 是否使用GPU,默认为False
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数 --batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数
--learning_rate: Finetune的最大学习率 --learning_rate: Fine-tune的最大学习率
--weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01 --weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01
--warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0 --warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0
--num_epoch: Finetune迭代的轮数 --num_epoch: Fine-tune迭代的轮数
--max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数。 --max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数。
--use_data_parallel: 是否使用并行计算,默认False。打开该功能依赖nccl库。 --use_data_parallel: 是否使用并行计算,默认True。打开该功能依赖nccl库。
--use_pyreader: 是否使用pyreader,默认False。
# 任务相关 # 任务相关
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型 --checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型
...@@ -24,7 +23,7 @@ ...@@ -24,7 +23,7 @@
## 代码步骤 ## 代码步骤
使用PaddleHub Finetune API进行Finetune可以分为4个步骤 使用PaddleHub Fine-tune API进行Fine-tune可以分为4个步骤
### Step1: 加载预训练模型 ### Step1: 加载预训练模型
...@@ -52,6 +51,7 @@ BERT-wwm, Chinese | `hub.Module(name='bert_wwm_chinese_L-12_H-7 ...@@ -52,6 +51,7 @@ BERT-wwm, Chinese | `hub.Module(name='bert_wwm_chinese_L-12_H-7
BERT-wwm-ext, Chinese | `hub.Module(name='bert_wwm_ext_chinese_L-12_H-768_A-12')` BERT-wwm-ext, Chinese | `hub.Module(name='bert_wwm_ext_chinese_L-12_H-768_A-12')`
RoBERTa-wwm-ext, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-12_H-768_A-12')` RoBERTa-wwm-ext, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-12_H-768_A-12')`
RoBERTa-wwm-ext-large, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-24_H-1024_A-16')` RoBERTa-wwm-ext-large, Chinese | `hub.Module(name='roberta_wwm_ext_chinese_L-24_H-1024_A-16')`
更多模型请参考[PaddleHub官网](https://www.paddlepaddle.org.cn/hub?filter=hot&value=1) 更多模型请参考[PaddleHub官网](https://www.paddlepaddle.org.cn/hub?filter=hot&value=1)
如果想尝试BERT模型,只需要更换Module中的`name`参数即可. 如果想尝试BERT模型,只需要更换Module中的`name`参数即可.
...@@ -79,13 +79,17 @@ reader = hub.reader.SequenceLabelReader( ...@@ -79,13 +79,17 @@ reader = hub.reader.SequenceLabelReader(
`max_seq_len` 需要与Step1中context接口传入的序列长度保持一致 `max_seq_len` 需要与Step1中context接口传入的序列长度保持一致
`module.sp_model_path` 若module为ernie_tiny则返回对应的子词切分模型,否则返回None `module.sp_model_path``module.word_dict_path` 用于 ERNIE Tiny 中文sub-word中文切词技术
`module.word_dict_path` 若module为ernie_tiny则返回对应的词语切分模型,否则返回None
SequenceLabelReader中的`data_generator`会自动按照模型对应词表对数据进行切词,以迭代器的方式返回ERNIE/BERT所需要的Tensor格式,包括`input_ids``position_ids``segment_id`与序列对应的mask `input_mask`. SequenceLabelReader中的`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这一顺序返回。 **NOTE**:
* Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。
* 如果选择的预训练模型不是ERNIE Tiny,则无需设定sp_model_path和word_dict_path参数
#### 自定义数据集
如果想加载自定义数据集完成迁移学习,详细参见[自定义数据集](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)
### Step3:选择优化策略和运行配置 ### Step3:选择优化策略和运行配置
...@@ -100,27 +104,30 @@ strategy = hub.AdamWeightDecayStrategy( ...@@ -100,27 +104,30 @@ strategy = hub.AdamWeightDecayStrategy(
config = hub.RunConfig(use_cuda=True, num_epoch=3, batch_size=32, strategy=strategy) config = hub.RunConfig(use_cuda=True, num_epoch=3, batch_size=32, strategy=strategy)
``` ```
#### 优化策略 #### 优化策略
PaddleHub提供了许多优化策略,如`AdamWeightDecayStrategy``ULMFiTStrategy``DefaultFinetuneStrategy`等,详细信息参见[策略](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Strategy)
针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy` 针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy`
`learning_rate`: Finetune过程中的最大学习率; `learning_rate`: fine-tune过程中的最大学习率;
`weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数; `weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数;
`warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate; `warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate;
`lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减; `lr_scheduler`: 有两种策略可选(1)`linear_decay`策略学习率会在最高点后以线性方式衰减;(2) `noam_decay`策略学习率会在最高点以多项式形式衰减;
#### 运行配置 #### 运行配置
`RunConfig` 主要控制Finetune的训练,包含以下可控制的参数: `RunConfig` 主要控制fine-tune的训练,包含以下可控制的参数:
* `log_interval`: 进度日志打印间隔,默认每10个step打印一次 * `log_interval`: 进度日志打印间隔,默认每10个step打印一次
* `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集 * `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集
* `save_ckpt_interval`: 模型保存间隔,请根据任务大小配置,默认只保存验证集效果最好的模型和训练结束的模型 * `save_ckpt_interval`: 模型保存间隔,请根据任务大小配置,默认只保存验证集效果最好的模型和训练结束的模型
* `use_cuda`: 是否使用GPU训练,默认为False * `use_cuda`: 是否使用GPU训练,默认为False
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成 * `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: finetune的轮数 * `num_epoch`: fine-tune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size * `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `enable_memory_optim`: 是否使用内存优化, 默认为True * `enable_memory_optim`: 是否使用内存优化, 默认为True
* `strategy`: Finetune优化策略 * `strategy`: fine-tune优化策略
### Step4: 构建网络并创建序列标注迁移任务进行Finetune ### Step4: 构建网络并创建序列标注迁移任务进行fine-tune
```python ```python
sequence_output = outputs["sequence_output"] sequence_output = outputs["sequence_output"]
...@@ -149,9 +156,13 @@ seq_label_task.finetune_and_eval() ...@@ -149,9 +156,13 @@ seq_label_task.finetune_and_eval()
3. `hub.SequenceLabelTask`通过输入特征,迁移的类别数,可以生成适用于序列标注的迁移任务`SequenceLabelTask` 3. `hub.SequenceLabelTask`通过输入特征,迁移的类别数,可以生成适用于序列标注的迁移任务`SequenceLabelTask`
4. `hub.SequenceLabelTask`通过add_crf, 选择是否加入crf作为decoder。如果add_crf=True, 则在预训练模型计算图加入fc+crf层,否则只在在预训练模型计算图加入fc层。 4. `hub.SequenceLabelTask`通过add_crf, 选择是否加入crf作为decoder。如果add_crf=True, 则在预训练模型计算图加入fc+crf层,否则只在在预训练模型计算图加入fc层。
#### 自定义迁移任务
如果想改变迁移任务组网,详细参见[自定义迁移任务](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub:-%E8%87%AA%E5%AE%9A%E4%B9%89Task)
## 可视化 ## 可视化
Finetune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令 Fine-tune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令
```bash ```bash
$ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM} $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM}
``` ```
...@@ -159,16 +170,33 @@ $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_N ...@@ -159,16 +170,33 @@ $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_N
## 模型预测 ## 模型预测
通过Finetune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。 通过Fine-tune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数 配置脚本参数
``` ```
CKPT_DIR="ckpt_sequence_label/" CKPT_DIR="ckpt_sequence_label/"
python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128 python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128
``` ```
其中CKPT_DIR为Finetune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致* 其中CKPT_DIR为Fine-tune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致*
参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。 参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。
如需了解更多预测步骤,请参考`predict.py` 如需了解更多预测步骤,请参考`predict.py`
``` 我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
text=它折射出华夏文明的绚丽光环,使这片古老的土地更加异彩纷呈,充满魅力。 label=OOOOB-LOCI-LOCOOOOOOOOOOOOOOOOOOOOOOOOOOOO predict=OOOOOB-LOCI-LOCOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
|预训练模型|任务类型|数据集|AIStudio链接|备注|
|-|-|-|-|-|
|ResNet|图像分类|猫狗数据集DogCat|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216772)||
|ERNIE|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216764)||
|ERNIE|文本分类|中文新闻分类数据集THUNEWS|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216649)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成文本分类迁移学习。|
|ERNIE|序列标注|中文序列标注数据集MSRA_NER|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216787)||
|ERNIE|序列标注|中文快递单数据集Express|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216683)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成序列标注迁移学习。|
|ERNIE Tiny|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215599)||
|Senta|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216851)|本教程讲述了任何利用Senta和Fine-tune API完成情感分类迁移学习。|
|Senta|情感分析预测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216735)||
|LAC|词法分析|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215641)||
|Ultra-Light-Fast-Generic-Face-Detector-1MB|人脸检测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216749)||
## 超参优化AutoDL Finetuner
PaddleHub还提供了超参优化(Hyperparameter Tuning)功能, 自动搜索最优模型超参得到更好的模型效果。详细信息参见[AutoDL Finetuner超参优化功能教程](../../tutorial/autofinetune.md)[使用样例](../autofinetune)
...@@ -35,7 +35,6 @@ parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory ...@@ -35,7 +35,6 @@ parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory
parser.add_argument("--max_seq_len", type=int, default=512, help="Number of words of the longest seqence.") 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=1, help="Total examples' number in batch for training.") parser.add_argument("--batch_size", type=int, default=1, help="Total examples' number in batch for training.")
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_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() args = parser.parse_args()
# yapf: enable. # yapf: enable.
...@@ -52,10 +51,8 @@ if __name__ == '__main__': ...@@ -52,10 +51,8 @@ if __name__ == '__main__':
max_seq_len=args.max_seq_len, max_seq_len=args.max_seq_len,
sp_model_path=module.get_spm_path(), sp_model_path=module.get_spm_path(),
word_dict_path=module.get_word_dict_path()) word_dict_path=module.get_word_dict_path())
inv_label_map = {val: key for key, val in reader.label_map.items()}
place = fluid.CUDAPlace(0) if args.use_gpu else fluid.CPUPlace() inv_label_map = {val: key for key, val in reader.label_map.items()}
exe = fluid.Executor(place)
# Construct transfer learning network # Construct transfer learning network
# Use "sequence_output" for token-level output. # Use "sequence_output" for token-level output.
...@@ -73,10 +70,8 @@ if __name__ == '__main__': ...@@ -73,10 +70,8 @@ if __name__ == '__main__':
# Setup runing config for PaddleHub Finetune API # Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
use_data_parallel=False, use_data_parallel=False,
use_pyreader=args.use_pyreader,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
batch_size=args.batch_size, batch_size=args.batch_size,
enable_memory_optim=False,
checkpoint_dir=args.checkpoint_dir, checkpoint_dir=args.checkpoint_dir,
strategy=hub.finetune.strategy.DefaultFinetuneStrategy()) strategy=hub.finetune.strategy.DefaultFinetuneStrategy())
...@@ -91,7 +86,7 @@ if __name__ == '__main__': ...@@ -91,7 +86,7 @@ if __name__ == '__main__':
config=config, config=config,
add_crf=True) add_crf=True)
# test data # Data to be predicted
data = [ data = [
["我们变而以书会友,以书结缘,把欧美、港台流行的食品类图谱、画册、工具书汇集一堂。"], ["我们变而以书会友,以书结缘,把欧美、港台流行的食品类图谱、画册、工具书汇集一堂。"],
["为了跟踪国际最新食品工艺、流行趋势,大量搜集海外专业书刊资料是提高技艺的捷径。"], ["为了跟踪国际最新食品工艺、流行趋势,大量搜集海外专业书刊资料是提高技艺的捷径。"],
......
...@@ -9,5 +9,5 @@ python -u sequence_label.py \ ...@@ -9,5 +9,5 @@ python -u sequence_label.py \
--checkpoint_dir $CKPT_DIR \ --checkpoint_dir $CKPT_DIR \
--max_seq_len 128 \ --max_seq_len 128 \
--learning_rate 5e-5 \ --learning_rate 5e-5 \
--use_pyreader True \ --warmup_proportion 0.1 \
--use_data_parallel True --use_data_parallel True
...@@ -26,17 +26,16 @@ parser.add_argument("--num_epoch", type=int, default=3, help="Number of epoches ...@@ -26,17 +26,16 @@ parser.add_argument("--num_epoch", type=int, default=3, help="Number of epoches
parser.add_argument("--use_gpu", type=ast.literal_eval, default=True, help="Whether use GPU for finetuning, input should be True or False") parser.add_argument("--use_gpu", type=ast.literal_eval, default=True, 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("--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("--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("--warmup_proportion", type=float, default=0.1, help="Warmup proportion params for warmup strategy")
parser.add_argument("--max_seq_len", type=int, default=512, help="Number of words of the longest seqence.") 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("--batch_size", type=int, default=32, help="Total examples' number in batch for training.")
parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint") parser.add_argument("--checkpoint_dir", type=str, default=None, help="Directory to model checkpoint")
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.") parser.add_argument("--use_data_parallel", type=ast.literal_eval, default=False, help="Whether use data parallel.")
args = parser.parse_args() args = parser.parse_args()
# yapf: enable. # yapf: enable.
if __name__ == '__main__': if __name__ == '__main__':
# Load Paddlehub ERNIE pretrained model # Load Paddlehub ERNIE Tiny pretrained model
module = hub.Module(name="ernie_tiny") module = hub.Module(name="ernie_tiny")
inputs, outputs, program = module.context( inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len) trainable=True, max_seq_len=args.max_seq_len)
...@@ -55,8 +54,7 @@ if __name__ == '__main__': ...@@ -55,8 +54,7 @@ if __name__ == '__main__':
sequence_output = outputs["sequence_output"] sequence_output = outputs["sequence_output"]
# Setup feed list for data feeder # Setup feed list for data feeder
# Must feed all the tensor of ERNIE's module need # Must feed all the tensor of module need
# Compared to classification task, we need add seq_len tensor to feedlist
feed_list = [ feed_list = [
inputs["input_ids"].name, inputs["position_ids"].name, inputs["input_ids"].name, inputs["position_ids"].name,
inputs["segment_ids"].name, inputs["input_mask"].name inputs["segment_ids"].name, inputs["input_mask"].name
...@@ -64,15 +62,13 @@ if __name__ == '__main__': ...@@ -64,15 +62,13 @@ if __name__ == '__main__':
# Select a finetune strategy # Select a finetune strategy
strategy = hub.AdamWeightDecayStrategy( strategy = hub.AdamWeightDecayStrategy(
warmup_proportion=args.warmup_proportion,
weight_decay=args.weight_decay, weight_decay=args.weight_decay,
learning_rate=args.learning_rate, learning_rate=args.learning_rate)
lr_scheduler="linear_decay",
)
# Setup runing config for PaddleHub Finetune API # Setup runing config for PaddleHub Finetune API
config = hub.RunConfig( config = hub.RunConfig(
use_data_parallel=args.use_data_parallel, use_data_parallel=args.use_data_parallel,
use_pyreader=args.use_pyreader,
use_cuda=args.use_gpu, use_cuda=args.use_gpu,
num_epoch=args.num_epoch, num_epoch=args.num_epoch,
batch_size=args.batch_size, batch_size=args.batch_size,
...@@ -80,7 +76,7 @@ if __name__ == '__main__': ...@@ -80,7 +76,7 @@ if __name__ == '__main__':
strategy=strategy) strategy=strategy)
# Define a sequence labeling finetune task by PaddleHub's API # Define a sequence labeling finetune task by PaddleHub's API
# if add crf, the network use crf as decoder # If add crf, the network use crf as decoder
seq_label_task = hub.SequenceLabelTask( seq_label_task = hub.SequenceLabelTask(
data_reader=reader, data_reader=reader,
feature=sequence_output, feature=sequence_output,
......
# PaddleHub SSD # SSD 目标检测
## 关于 本示例展示如何使用[SSD](https://www.paddlepaddle.org.cn/hubdetail?name=ssd_mobilenet_v1_pascal&en_category=ObjectDetection)预训练模型进行目标检测预测。
本示例展示如何使用SSD Module进行预测。 SSD是一个目标检测模型,可以检测出图片中的实物的类别和位置,PaddleHub发布的SSD模型通过pascalvoc数据集训练,支持20个数据类别的检测。
SSD是一个目标检测模型,可以检测出图片中的实物的类别和位置,PaddleHub发布的SSD模型通过pascalvoc数据集训练,支持20个数据类别的检测,关于模型的训练细节,请查看[SSD](https://github.com/PaddlePaddle/models/tree/release/v1.2/PaddleCV/object_detection)
## 准备工作
在运行本目录的脚本前,需要先安装1.3.0版本以上的PaddlePaddle(如果您本地已经安装了符合条件的PaddlePaddle版本,那么可以跳过`准备工作`这一步)。
如果您的机器支持GPU,我们建议下载GPU版本的PaddlePaddle,使用GPU进行训练和预测的效率都比使用CPU要高。
```shell
# 安装GPU版本的PaddlePaddle
$ pip install --upgrade paddlepaddle-gpu
```
如果您的机器不支持GPU,可以通过下面的命令来安装CPU版本的PaddlePaddle
```shell
# 安装CPU版本的PaddlePaddle
$ pip install --upgrade paddlepaddle
```
在安装过程中如果遇到问题,您可以到[Paddle官方网站](http://www.paddlepaddle.org/)上查看解决方案。
## 命令行方式预测 ## 命令行方式预测
`cli_demo.sh`给出了使用命令行调用Module预测的示例脚本
通过以下命令试验下效果
```shell ```shell
$ sh cli_demo.sh $ hub run ssd_mobilenet_v1_pascal --input_path "/PATH/TO/IMAGE"
$ hub run ssd_mobilenet_v1_pascal --input_file test.txt
``` ```
test.txt 存放待检测图片的存放路径
## 通过python API预测 ## 通过python API预测
`ssd_demo.py`给出了使用python API调用Module预测的示例代码 `ssd_demo.py`给出了使用python API调用SSD预测的示例代码
通过以下命令试验下效果 通过以下命令试验下效果
```shell ```shell
......
python ../../paddlehub/commands/hub.py run ssd_mobilenet_v1_pascal --input_file test/test.txt
#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=512, 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.")
parser.add_argument("--dataset", type=str, default="chnsenticorp", help="The choice of dataset")
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__':
dataset = None
metrics_choices = []
# Download dataset and use ClassifyReader to read dataset
if args.dataset.lower() == "chnsenticorp":
dataset = hub.dataset.ChnSentiCorp()
module = hub.Module(name="ernie_tiny")
metrics_choices = ["acc"]
elif args.dataset.lower() == "tnews":
dataset = hub.dataset.TNews()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == "nlpcc_dbqa":
dataset = hub.dataset.NLPCC_DBQA()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == "lcqmc":
dataset = hub.dataset.LCQMC()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == 'inews':
dataset = hub.dataset.INews()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == 'bq':
dataset = hub.dataset.BQ()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == 'thucnews':
dataset = hub.dataset.THUCNEWS()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == 'iflytek':
dataset = hub.dataset.IFLYTEK()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == "mrpc":
dataset = hub.dataset.GLUE("MRPC")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["f1", "acc"]
# The first metric will be choose to eval. Ref: task.py:799
elif args.dataset.lower() == "qqp":
dataset = hub.dataset.GLUE("QQP")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["f1", "acc"]
elif args.dataset.lower() == "sst-2":
dataset = hub.dataset.GLUE("SST-2")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["acc"]
elif args.dataset.lower() == "cola":
dataset = hub.dataset.GLUE("CoLA")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["matthews", "acc"]
elif args.dataset.lower() == "qnli":
dataset = hub.dataset.GLUE("QNLI")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["acc"]
elif args.dataset.lower() == "rte":
dataset = hub.dataset.GLUE("RTE")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["acc"]
elif args.dataset.lower() == "mnli" or args.dataset.lower() == "mnli_m":
dataset = hub.dataset.GLUE("MNLI_m")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["acc"]
elif args.dataset.lower() == "mnli_mm":
dataset = hub.dataset.GLUE("MNLI_mm")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["acc"]
elif args.dataset.lower().startswith("xnli"):
dataset = hub.dataset.XNLI(language=args.dataset.lower()[-2:])
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
else:
raise ValueError("%s dataset is not defined" % args.dataset)
support_metrics = ["acc", "f1", "matthews"]
for metric in metrics_choices:
if metric not in support_metrics:
raise ValueError("\"%s\" metric is not defined" % metric)
inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len)
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,
]
# 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,
metrics_choices=metrics_choices)
# Data to be prdicted
data = [[d.text_a, d.text_b] for d in dataset.get_dev_examples()[:3]]
print(cls_task.predict(data=data, return_result=True))
export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0
# User can select chnsenticorp, nlpcc_dbqa, lcqmc and so on for different task
# Support ChnSentiCorp NLPCC_DBQA LCQMC MRPC QQP SST-2
# CoLA QNLI RTE MNLI (or MNLI_m) MNLI_mm) XNLI
# for XNLI: Specify the language with an underscore like xnli_zh.
# ar: Arabic bg: Bulgarian de: German
# el: Greek en: English es: Spanish
# fr: French hi: Hindi ru: Russian
# sw: Swahili th: Thai tr: Turkish
# ur: Urdu vi: Vietnamese zh: Chinese (Simplified)
DATASET="ChnSentiCorp"
CKPT_DIR="./ckpt_${DATASET}"
python -u predict.py --checkpoint_dir=$CKPT_DIR \
--max_seq_len=128 \
--use_gpu=True \
--dataset=${DATASET} \
--batch_size=32 \
#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=True, help="Whether use GPU for finetuning, input should be True or False")
parser.add_argument("--dataset", type=str, default="chnsenticorp", help="The choice of dataset")
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("--data_dir", type=str, default=None, help="Path to training data.")
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__':
dataset = None
metrics_choices = []
# Download dataset and use ClassifyReader to read dataset
if args.dataset.lower() == "chnsenticorp":
dataset = hub.dataset.ChnSentiCorp()
module = hub.Module(name="ernie_tiny")
metrics_choices = ["acc"]
elif args.dataset.lower() == "tnews":
dataset = hub.dataset.TNews()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == "nlpcc_dbqa":
dataset = hub.dataset.NLPCC_DBQA()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == "lcqmc":
dataset = hub.dataset.LCQMC()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == 'inews':
dataset = hub.dataset.INews()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == 'bq':
dataset = hub.dataset.BQ()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == 'thucnews':
dataset = hub.dataset.THUCNEWS()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == 'iflytek':
dataset = hub.dataset.IFLYTEK()
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
elif args.dataset.lower() == "mrpc":
dataset = hub.dataset.GLUE("MRPC")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["f1", "acc"]
# The first metric will be choose to eval. Ref: task.py:799
elif args.dataset.lower() == "qqp":
dataset = hub.dataset.GLUE("QQP")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["f1", "acc"]
elif args.dataset.lower() == "sst-2":
dataset = hub.dataset.GLUE("SST-2")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["acc"]
elif args.dataset.lower() == "cola":
dataset = hub.dataset.GLUE("CoLA")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["matthews", "acc"]
elif args.dataset.lower() == "qnli":
dataset = hub.dataset.GLUE("QNLI")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["acc"]
elif args.dataset.lower() == "rte":
dataset = hub.dataset.GLUE("RTE")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["acc"]
elif args.dataset.lower() == "mnli" or args.dataset.lower() == "mnli_m":
dataset = hub.dataset.GLUE("MNLI_m")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["acc"]
elif args.dataset.lower() == "mnli_mm":
dataset = hub.dataset.GLUE("MNLI_mm")
module = hub.Module(name="ernie_v2_eng_base")
metrics_choices = ["acc"]
elif args.dataset.lower().startswith("xnli"):
dataset = hub.dataset.XNLI(language=args.dataset.lower()[-2:])
module = hub.Module(name="roberta_wwm_ext_chinese_L-24_H-1024_A-16")
metrics_choices = ["acc"]
else:
raise ValueError("%s dataset is not defined" % args.dataset)
# Check metric
support_metrics = ["acc", "f1", "matthews"]
for metric in metrics_choices:
if metric not in support_metrics:
raise ValueError("\"%s\" metric is not defined" % metric)
# Start preparing parameters for reader and task accoring to module
# For ernie_v2, it has an addition embedding named task_id
# For ernie_v2_chinese_tiny, it use an addition sentence_piece_vocab to tokenize
inputs, outputs, program = module.context(
trainable=True, 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 module need
feed_list = [
inputs["input_ids"].name,
inputs["position_ids"].name,
inputs["segment_ids"].name,
inputs["input_mask"].name,
]
# Finish preparing parameter for reader and task accoring to modul
# Define reader
reader = hub.reader.ClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path(),
max_seq_len=args.max_seq_len,
sp_model_path=module.get_spm_path(),
word_dict_path=module.get_word_dict_path())
# 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,
metrics_choices=metrics_choices)
# Finetune and evaluate by PaddleHub's API
# will finish training, evaluation, testing, save model automatically
cls_task.finetune_and_eval()
# PaddleHub 文本分类 # PaddleHub 文本分类
本示例将展示如何使用PaddleHub Finetune API以及Transformer类预训练模型完成分类任务。 本示例将展示如何使用PaddleHub Fine-tune API以及Transformer类预训练模型(ERNIE/BERT/RoBERTa)完成分类任务。
其中分类任务可以分为两大类:
## 如何开始Fine-tune
* **单句分类**
- ChineseGLUE-IFLYTEK 在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_classifier.sh`即可开始使用ERNIE对ChnSentiCorp数据集进行Fine-tune。
- ChineseGLUE-THUCNEWS
- GLUE-Cola
- GLUE-SST2
- ChnSentiCorp
* **句对分类**
- ChineseGLUE-LCQMC
- ChineseGLUE-INEWS
- ChineseGLUE-TNEWS
- ChinesGLUE-BQ
- ChineseGLUE-XNLI_zh
- GLUE-MNLI
- GLUE-QQP
- GLUE-QNLI
- GLUE-STS-B
- GLUE-MRPC
- GLUE-RTE
- NLPCC-DBQA
- XNLI
## 如何开始Finetune
在完成安装PaddlePaddle与PaddleHub后,通过执行脚本`sh run_classifier.sh`即可开始使用ERNIE对ChnSentiCorp数据集进行Finetune。
其中脚本参数说明如下: 其中脚本参数说明如下:
```bash ```bash
# 模型相关
--batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数 --batch_size: 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数
--learning_rate: Finetune的最大学习率 --learning_rate: Fine-tune的最大学习率
--weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01 --weight_decay: 控制正则项力度的参数,用于防止过拟合,默认为0.01
--warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0 --warmup_proportion: 学习率warmup策略的比例,如果0.1,则学习率会在前10%训练step的过程中从0慢慢增长到learning_rate, 而后再缓慢衰减,默认为0
--num_epoch: Finetune迭代的轮数 --num_epoch: Fine-tune迭代的轮数
--max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数 --max_seq_len: ERNIE/BERT模型使用的最大序列长度,最大不能超过512, 若出现显存不足,请适当调低这一参数
--use_data_parallel: 是否使用并行计算,默认False。打开该功能依赖nccl库。 --use_data_parallel: 是否使用并行计算,默认True。打开该功能依赖nccl库。
--use_pyreader: 是否使用pyreader,默认False。
# 任务相关
--checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型 --checkpoint_dir: 模型保存路径,PaddleHub会自动保存验证集上表现最好的模型
--dataset: 有以下数据集可选: chnsenticorp, lcqmc, nlpcc_dbqa, GLUE, XNLI
``` ```
## 代码步骤 ## 代码步骤
使用PaddleHub Finetune API进行Finetune可以分为4个步骤 使用PaddleHub Fine-tune API进行Fine-tune可以分为4个步骤
### Step1: 加载预训练模型 ### Step1: 加载预训练模型
...@@ -96,8 +69,6 @@ reader = hub.reader.ClassifyReader( ...@@ -96,8 +69,6 @@ reader = hub.reader.ClassifyReader(
metrics_choices = ["acc"] metrics_choices = ["acc"]
``` ```
其中数据集的准备代码可以参考 [chnsenticorp.py](https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.2/paddlehub/dataset/chnsenticorp.py)
`hub.dataset.ChnSentiCorp()` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录 `hub.dataset.ChnSentiCorp()` 会自动从网络下载数据集并解压到用户目录下`$HOME/.paddlehub/dataset`目录
`module.get_vocab_path()` 会返回预训练模型对应的词表 `module.get_vocab_path()` 会返回预训练模型对应的词表
...@@ -112,7 +83,35 @@ ClassifyReader中的`data_generator`会自动按照模型对应词表对数据 ...@@ -112,7 +83,35 @@ ClassifyReader中的`data_generator`会自动按照模型对应词表对数据
**NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。 **NOTE**: Reader返回tensor的顺序是固定的,默认按照input_ids, position_ids, segment_id, input_mask这一顺序返回。
同时,利用Accuracy作为评价指标。 PaddleHub还提供了其他的文本分类数据集,分两类(单句分类和句对分类),具体信息如下表
数据集 | API | 单句/句对 | 推荐预训练模型 | 推荐评价指标 |
---------------- | -----------------------------| ---------| ------------------------------ | -----------|
ChnSentiCorp | hub.dataset.ChnSentiCorp() | 单句 | ernie_tiny | accuracy |
LCQMC | hub.dataset.LCQMC() | 句对 | ernie_tiny | accuracy |
NLPCC-QBDA | hub.dataset.NLPCC_DBQA() | 句对 | ernie_tiny | accuracy |
GLUE-CoLA | hub.dataset.GLUE("CoLA") | 单句 | ernie_v2_eng_base | matthews |
GLUE-SST2 | hub.dataset.GLUE("SST-2") | 单句 | ernie_v2_eng_base | accuracy |
GLUE-CoLA | hub.dataset.GLUE("CoLA") | 单句 | ernie_v2_eng_base | accuracy |
GLUE-MNLI | hub.dataset.GLUE("MNLI_m") | 句对 | ernie_v2_eng_base | accuracy |
GLUE-QQP | hub.dataset.GLUE("QQP") | 句对 | ernie_v2_eng_base | accuracy |
GLUE-QNLI | hub.dataset.GLUE("QNLI") | 句对 | ernie_v2_eng_base | accuracy |
GLUE-STS-2 | hub.dataset.GLUE("SST-2"") | 句对 | ernie_v2_eng_base | accuracy |
GLUE-MRPC | hub.dataset.GLUE("MRPC") | 句对 | ernie_v2_eng_base | f1 |
GLUE-RTE | hub.dataset.GLUE("RTE") | 单句 | ernie_v2_eng_base | accuracy |
XNLI | hub.dataset.XNLI(language=zh)| 句对 | roberta_wwm_ext_chinese_L-24_H-1024_A-16 | accuracy |
ChineseGLUE-THUCNEWS | hub.dataset.THUCNEWS() | 单句 | roberta_wwm_ext_chinese_L-24_H-1024_A-16 | accuracy |
ChineseGLUE-IFLYTEK | hub.dataset.IFLYTEK() | 单句 | roberta_wwm_ext_chinese_L-24_H-1024_A-16 | accuracy |
ChineseGLUE-INEWS | hub.dataset.INews() | 句对 | roberta_wwm_ext_chinese_L-24_H-1024_A-16 | accuracy |
ChineseGLUE-TNEWS | hub.dataset.TNews() | 句对 | roberta_wwm_ext_chinese_L-24_H-1024_A-16 | accuracy |
ChinesGLUE-BQ | hub.dataset.BQ() | 句对 | roberta_wwm_ext_chinese_L-24_H-1024_A-16 | accuracy |
更多数据集信息参考[Dataset](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Dataset)
#### 自定义数据集
如果想加载自定义数据集完成迁移学习,详细参见[自定义数据集](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)
### Step3:选择优化策略和运行配置 ### Step3:选择优化策略和运行配置
...@@ -130,25 +129,21 @@ config = hub.RunConfig(use_cuda=True, num_epoch=3, batch_size=32, strategy=strat ...@@ -130,25 +129,21 @@ config = hub.RunConfig(use_cuda=True, num_epoch=3, batch_size=32, strategy=strat
#### 优化策略 #### 优化策略
针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy` 针对ERNIE与BERT类任务,PaddleHub封装了适合这一任务的迁移学习优化策略`AdamWeightDecayStrategy`
`learning_rate`: Finetune过程中的最大学习率; * `learning_rate`: Fine-tune过程中的最大学习率;
`weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数; * `weight_decay`: 模型的正则项参数,默认0.01,如果模型有过拟合倾向,可适当调高这一参数;
`warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate; * `warmup_proportion`: 如果warmup_proportion>0, 例如0.1, 则学习率会在前10%的steps中线性增长至最高值learning_rate;
`lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减; * `lr_scheduler`: 有两种策略可选(1) `linear_decay`策略学习率会在最高点后以线性方式衰减; `noam_decay`策略学习率会在最高点以多项式形式衰减;
#### 运行配置 #### 运行配置
`RunConfig` 主要控制Finetune的训练,包含以下可控制的参数: `RunConfig` 主要控制Fine-tune的训练,包含以下可控制的参数:
* `log_interval`: 进度日志打印间隔,默认每10个step打印一次
* `eval_interval`: 模型评估的间隔,默认每100个step评估一次验证集
* `save_ckpt_interval`: 模型保存间隔,请根据任务大小配置,默认只保存验证集效果最好的模型和训练结束的模型
* `use_cuda`: 是否使用GPU训练,默认为False * `use_cuda`: 是否使用GPU训练,默认为False
* `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成 * `checkpoint_dir`: 模型checkpoint保存路径, 若用户没有指定,程序会自动生成
* `num_epoch`: finetune的轮数 * `num_epoch`: Fine-tune的轮数
* `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size * `batch_size`: 训练的批大小,如果使用GPU,请根据实际情况调整batch_size
* `enable_memory_optim`: 是否使用内存优化, 默认为True * `strategy`: Fine-tune优化策略
* `strategy`: Finetune优化策略
### Step4: 构建网络并创建分类迁移任务进行Finetune ### Step4: 构建网络并创建分类迁移任务进行Fine-tune
```python ```python
pooled_output = outputs["pooled_output"] pooled_output = outputs["pooled_output"]
...@@ -174,9 +169,13 @@ cls_task.finetune_and_eval() ...@@ -174,9 +169,13 @@ cls_task.finetune_and_eval()
2. `feed_list`中的inputs参数指名了ERNIE/BERT中的输入tensor的顺序,与ClassifyReader返回的结果一致。 2. `feed_list`中的inputs参数指名了ERNIE/BERT中的输入tensor的顺序,与ClassifyReader返回的结果一致。
3. `hub.TextClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于文本分类的迁移任务`TextClassifierTask` 3. `hub.TextClassifierTask`通过输入特征,label与迁移的类别数,可以生成适用于文本分类的迁移任务`TextClassifierTask`
#### 自定义迁移任务
如果想改变迁移任务组网,详细参见[自定义迁移任务](https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub:-%E8%87%AA%E5%AE%9A%E4%B9%89Task)
## 可视化 ## 可视化
Finetune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令 Fine-tune API训练过程中会自动对关键训练指标进行打点,启动程序后执行下面命令
```bash ```bash
$ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM} $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_NUM}
``` ```
...@@ -184,18 +183,39 @@ $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_N ...@@ -184,18 +183,39 @@ $ tensorboard --logdir $CKPT_DIR/visualization --host ${HOST_IP} --port ${PORT_N
## 模型预测 ## 模型预测
通过Finetune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。 通过Fine-tune完成模型训练后,在对应的ckpt目录下,会自动保存验证集上效果最好的模型。
配置脚本参数 配置脚本参数
``` ```
CKPT_DIR="ckpt_chnsentiment/" CKPT_DIR="ckpt_chnsentiment/"
python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128 python predict.py --checkpoint_dir $CKPT_DIR --max_seq_len 128
``` ```
其中CKPT_DIR为Finetune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致* 其中CKPT_DIR为Fine-tune API保存最佳模型的路径, max_seq_len是ERNIE模型的最大序列长度,*请与训练时配置的参数保持一致*
参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。 参数配置正确后,请执行脚本`sh run_predict.sh`,即可看到以下文本分类预测结果, 以及最终准确率。
如需了解更多预测步骤,请参考`predict.py` 如需了解更多预测步骤,请参考`predict.py`
``` ```
text=键盘缝隙大进灰,装系统自己不会装,屏幕有点窄玩游戏人物有点变形 label=0 predict=0 这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般 predict=0
accuracy = 0.954267 交通方便;环境很好;服务态度很好 房间较小 predict=1
19天硬盘就罢工了~~~算上运来的一周都没用上15天~~~可就是不能换了~~~唉~~~~你说这算什么事呀~~~ predict=0
``` ```
我们在AI Studio上提供了IPython NoteBook形式的demo,您可以直接在平台上在线体验,链接如下:
|预训练模型|任务类型|数据集|AIStudio链接|备注|
|-|-|-|-|-|
|ResNet|图像分类|猫狗数据集DogCat|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216772)||
|ERNIE|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216764)||
|ERNIE|文本分类|中文新闻分类数据集THUNEWS|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216649)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成文本分类迁移学习。|
|ERNIE|序列标注|中文序列标注数据集MSRA_NER|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216787)||
|ERNIE|序列标注|中文快递单数据集Express|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216683)|本教程讲述了如何将自定义数据集加载,并利用Fine-tune API完成序列标注迁移学习。|
|ERNIE Tiny|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215599)||
|Senta|文本分类|中文情感分类数据集ChnSentiCorp|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216851)|本教程讲述了任何利用Senta和Fine-tune API完成情感分类迁移学习。|
|Senta|情感分析预测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216735)||
|LAC|词法分析|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/215641)||
|Ultra-Light-Fast-Generic-Face-Detector-1MB|人脸检测|N/A|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/216749)||
## 超参优化AutoDL Finetuner
PaddleHub还提供了超参优化(Hyperparameter Tuning)功能, 自动搜索最优模型超参得到更好的模型效果。详细信息参见[AutoDL Finetuner超参优化功能教程](../../tutorial/autofinetune.md)[使用样例](../autofinetune)
#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=512, 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_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 Tiny pretrained model
module = hub.Module(name="ernie_tiny")
inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len)
# Download dataset and use accuracy as metrics
# Choose dataset: GLUE/XNLI/ChinesesGLUE/NLPCC-DBQA/LCQMC
dataset = hub.dataset.ChnSentiCorp()
# For ernie_tiny, it use sub-word to tokenize chinese sentence
# If not ernie tiny, sp_model_path and word_dict_path should be set None
reader = hub.reader.ClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path(),
max_seq_len=args.max_seq_len,
sp_model_path=module.get_spm_path(),
word_dict_path=module.get_word_dict_path())
# 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 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=args.use_data_parallel,
use_cuda=args.use_gpu,
batch_size=args.batch_size,
checkpoint_dir=args.checkpoint_dir,
strategy=hub.AdamWeightDecayStrategy())
# 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 = [["这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般"], ["交通方便;环境很好;服务态度很好 房间较小"],
["19天硬盘就罢工了~~~算上运来的一周都没用上15天~~~可就是不能换了~~~唉~~~~你说这算什么事呀~~~"]]
print(cls_task.predict(data=data, return_result=True))
export FLAGS_eager_delete_tensor_gb=0.0 export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0 export CUDA_VISIBLE_DEVICES=0
# User can select chnsenticorp, nlpcc_dbqa, lcqmc and so on for different task CKPT_DIR="./ckpt_chnsenticorp"
DATASET="chnsenticorp"
CKPT_DIR="./ckpt_${DATASET}"
python -u text_classifier.py \ python -u text_classifier.py \
--batch_size=24 \ --batch_size=24 \
--use_gpu=True \ --use_gpu=True \
--dataset=${DATASET} \
--checkpoint_dir=${CKPT_DIR} \ --checkpoint_dir=${CKPT_DIR} \
--learning_rate=5e-5 \ --learning_rate=5e-5 \
--weight_decay=0.01 \ --weight_decay=0.01 \
--max_seq_len=128 \ --max_seq_len=128 \
--warmup_proportion=0.1 \
--num_epoch=3 \ --num_epoch=3 \
--use_pyreader=True \
--use_data_parallel=True --use_data_parallel=True
# Recommending hyper parameters for difference task # The sugguested hyper parameters for difference task
# for ChineseGLUE: # for ChineseGLUE:
# TNews: batch_size=32, weight_decay=0, num_epoch=3, max_seq_len=128, lr=5e-5 # TNews: batch_size=32, weight_decay=0, num_epoch=3, max_seq_len=128, lr=5e-5
# LCQMC: batch_size=32, weight_decay=0, num_epoch=3, max_seq_len=128, lr=5e-5 # LCQMC: batch_size=32, weight_decay=0, num_epoch=3, max_seq_len=128, lr=5e-5
......
...@@ -2,4 +2,8 @@ export FLAGS_eager_delete_tensor_gb=0.0 ...@@ -2,4 +2,8 @@ export FLAGS_eager_delete_tensor_gb=0.0
export CUDA_VISIBLE_DEVICES=0 export CUDA_VISIBLE_DEVICES=0
CKPT_DIR="./ckpt_chnsenticorp" CKPT_DIR="./ckpt_chnsenticorp"
python -u predict.py --checkpoint_dir $CKPT_DIR --use_gpu True
python -u predict.py --checkpoint_dir=$CKPT_DIR \
--max_seq_len=128 \
--use_gpu=True \
--batch_size=24 \
#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=True, 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.1, 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_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 Tiny pretrained model
module = hub.Module(name="ernie_tiny")
inputs, outputs, program = module.context(
trainable=True, max_seq_len=args.max_seq_len)
# Download dataset and use accuracy as metrics
# Choose dataset: GLUE/XNLI/ChinesesGLUE/NLPCC-DBQA/LCQMC
# metric should be acc, f1 or matthews
dataset = hub.dataset.ChnSentiCorp()
metrics_choices = ["acc"]
# For ernie_tiny, it use sub-word to tokenize chinese sentence
# If not ernie tiny, sp_model_path and word_dict_path should be set None
reader = hub.reader.ClassifyReader(
dataset=dataset,
vocab_path=module.get_vocab_path(),
max_seq_len=args.max_seq_len,
sp_model_path=module.get_spm_path(),
word_dict_path=module.get_word_dict_path())
# 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 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(
warmup_proportion=args.warmup_proportion,
weight_decay=args.weight_decay,
learning_rate=args.learning_rate)
# Setup runing config for PaddleHub Finetune API
config = hub.RunConfig(
use_data_parallel=args.use_data_parallel,
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,
metrics_choices=metrics_choices)
# Finetune and evaluate by PaddleHub's API
# will finish training, evaluation, testing, save model automatically
cls_task.finetune_and_eval()
...@@ -232,6 +232,6 @@ class SequenceLabelTask(BaseTask): ...@@ -232,6 +232,6 @@ class SequenceLabelTask(BaseTask):
for length in seq_lens: for length in seq_lens:
seq_infers = batch_infers[current_id:current_id + length] seq_infers = batch_infers[current_id:current_id + length]
seq_result = list(map(id2label.get, seq_infers[1:-1])) seq_result = list(map(id2label.get, seq_infers[1:-1]))
current_id += int(length) current_id += self.max_seq_len
results.append(seq_result) results.append(seq_result)
return results return results
...@@ -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 = "1.4.0" hub_version = "1.5.0"
module_proto_version = "1.0.0" module_proto_version = "1.0.0"
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册