Browse Source

Merge remote-tracking branch 'paddle/doc1105' into doc1105
add raspberry doc

wangsiyuan06 5 years ago
parent
commit
13b01eb18e
51 changed files with 1008 additions and 58 deletions
  1. 4 3
      .github/ISSUE_TEMPLATE/4_gui.md
  2. 1 1
      deploy/lite/export_lite.py
  3. 10 0
      docs/apis/slim.md
  4. 34 0
      docs/data/annotation/classification.md
  5. 13 0
      docs/data/annotation/index.rst
  6. 42 0
      docs/data/annotation/instance_segmentation.md
  7. 26 0
      docs/data/annotation/labelme.md
  8. 47 0
      docs/data/annotation/object_detection.md
  9. BIN
      docs/data/annotation/pics/detection1.png
  10. BIN
      docs/data/annotation/pics/detection2.png
  11. BIN
      docs/data/annotation/pics/detection3.png
  12. BIN
      docs/data/annotation/pics/detection4.png
  13. BIN
      docs/data/annotation/pics/detection5.png
  14. 42 0
      docs/data/annotation/semantic_segmentation.md
  15. 4 0
      docs/deploy/export_model.md
  16. 1 1
      docs/deploy/hub_serving.md
  17. 1 1
      docs/deploy/server/index.rst
  18. 13 7
      docs/gui/download.md
  19. 33 14
      docs/gui/how_to_use.md
  20. 1 1
      docs/gui/index.rst
  21. 41 0
      docs/gui/introduce.md
  22. 67 9
      docs/index.rst
  23. 0 1
      docs/train/index.rst
  24. 9 2
      paddlex/__init__.py
  25. 4 2
      paddlex/cv/models/base.py
  26. 54 12
      paddlex/cv/models/slim/prune.py
  27. 5 2
      paddlex/cv/models/slim/visualize.py
  28. 1 1
      setup.py
  29. 4 0
      tutorials/compress/README.md
  30. 1 1
      tutorials/compress/classification/cal_sensitivities_file.py
  31. 51 0
      tutorials/slim/prune/image_classification/README.md
  32. 44 0
      tutorials/slim/prune/image_classification/mobilenetv2_prune_train.py
  33. 41 0
      tutorials/slim/prune/image_classification/mobilenetv2_train.py
  34. 17 0
      tutorials/slim/prune/image_classification/params_analysis.py
  35. BIN
      tutorials/slim/prune/image_classification/sensitivities.png
  36. 3 0
      tutorials/slim/prune/image_classification/slim_visualize.py
  37. 50 0
      tutorials/slim/prune/object_detection/README.md
  38. 14 0
      tutorials/slim/prune/object_detection/params_analysis.py
  39. BIN
      tutorials/slim/prune/object_detection/sensitivities.png
  40. 3 0
      tutorials/slim/prune/object_detection/slim_visualize.py
  41. 54 0
      tutorials/slim/prune/object_detection/yolov3_prune_train.py
  42. 51 0
      tutorials/slim/prune/object_detection/yolov3_train.py
  43. 51 0
      tutorials/slim/prune/semantic_segmentation/README.md
  44. 14 0
      tutorials/slim/prune/semantic_segmentation/params_analysis.py
  45. BIN
      tutorials/slim/prune/semantic_segmentation/sensitivities.png
  46. 3 0
      tutorials/slim/prune/semantic_segmentation/slim_visualize.py
  47. 46 0
      tutorials/slim/prune/semantic_segmentation/unet_prune_train.py
  48. 43 0
      tutorials/slim/prune/semantic_segmentation/unet_train.py
  49. 16 0
      tutorials/slim/quant/image_classification/README.md
  50. 31 0
      tutorials/slim/quant/image_classification/mobilenetv2_quant.py
  51. 18 0
      tutorials/slim/quant/image_classification/paddlelite_export.py

+ 4 - 3
.github/ISSUE_TEMPLATE/4_gui.md

@@ -1,9 +1,10 @@
 ---
 ---
-name: 4. PaddleX GUI使用问题
-about: Paddle GUI客户端使用问题
+name: 4. PaddleX可视化客户端使用问题
+about: PaddleX可视化客户端使用问题
 ---
 ---
-问题类型:PaddleX GUI  
+问题类型:PaddleX可视化客户端  
 **问题描述**  
 **问题描述**  
 
 
 ===================================  
 ===================================  
+
 请在这里描述您在使用GUI过程中的问题
 请在这里描述您在使用GUI过程中的问题

+ 1 - 1
deploy/lite/export_lite.py

@@ -42,7 +42,7 @@ if __name__ == '__main__':
     parser.add_argument(
     parser.add_argument(
         "--save_file",
         "--save_file",
         type=str,
         type=str,
-        default="paddlex.onnx",
+        default="paddlex.nb",
         help="file name for storing the output files.",
         help="file name for storing the output files.",
         required=True)
         required=True)
     FLAGS = parser.parse_args()
     FLAGS = parser.parse_args()

+ 10 - 0
docs/apis/slim.md

@@ -1,6 +1,16 @@
 # 模型压缩
 # 模型压缩
 
 
+## paddlex.slim.prune.analysis
+> **计算参数敏感度**
+```
+paddlex.slim.prune.analysis(model, dataset, batch_size, save_file='model.sensi.data')
+```
+此函数接口与`paddlex.slim.cal_params_sensitivites`接口功能一致,仅修改了函数名,参数名,顺序和默认值,推荐使用此接口。
+
+使用示例参考[教程-模型裁剪训练](https://github.com/PaddlePaddle/PaddleX/tree/develop/tutorials/slim/prune)
+
 ## paddlex.slim.cal_params_sensitivities
 ## paddlex.slim.cal_params_sensitivities
+> 此函数接口与`paddlex.slim.prune.analysis`功能一致,推荐使用`paddlex.slim.prune.analysis`接口  
 > **计算参数敏感度**  
 > **计算参数敏感度**  
 ```
 ```
 paddlex.slim.cal_params_sensitivities(model, save_file, eval_dataset, batch_size=8)
 paddlex.slim.cal_params_sensitivities(model, save_file, eval_dataset, batch_size=8)

+ 34 - 0
docs/data/annotation/classification.md

@@ -0,0 +1,34 @@
+# 图像分类
+
+图像分类标注是一项最基础,最简单的标注任务,用户只需将属于同一类的图片放在同一个文件夹下即可,例如下所示目录结构,
+```
+MyDataset/ # 图像分类数据集根目录
+|--dog/ # 当前文件夹所有图片属于dog类别
+|  |--d1.jpg
+|  |--d2.jpg
+|  |--...
+|  |--...
+|
+|--...
+|
+|--snake/ # 当前文件夹所有图片属于snake类别
+|  |--s1.jpg
+|  |--s2.jpg
+|  |--...
+|  |--...
+```
+
+## 数据划分
+
+在模型进行训练时,我们需要划分训练集,验证集和测试集,因此需要对如上数据进行划分,直接使用paddlex命令即可将数据集随机划分成70%训练集,20%验证集和10%测试集
+```
+paddlex --split_dataset ImageNet --dataset_dir MyDataset --val_value 0.2 --test_value 0.1
+```
+
+划分好的数据集会额外生成`labels.txt`, `train_list.txt`, `val_list.txt`, `test_list.txt`四个文件,之后可直接进行训练。
+
+> 注:如您使用PaddleX可视化客户端进行模型训练,数据集划分功能集成在客户端内,无需自行使用命令划分
+
+
+- [图像分类任务训练示例代码](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/image_classification/mobilenetv2.py)
+

+ 13 - 0
docs/data/annotation/index.rst

@@ -0,0 +1,13 @@
+数据标注、转换、划分
+=======================================
+
+
+.. toctree::
+   :maxdepth: 1
+   :caption: 目录:
+
+   classification.md
+   object_detection.md
+   instance_segmentation.md
+   semantic_segmentation.md
+   labelme.md

+ 42 - 0
docs/data/annotation/instance_segmentation.md

@@ -0,0 +1,42 @@
+# 实例分割
+
+实例分割数据的标注推荐使用LabelMe标注工具,如您先前并无安装,那么LabelMe的安装可参考[LabelMe安装和启动](labelme.md)
+
+**注意:LabelMe对于中文支持不够友好,因此请不要在如下的路径以及文件名中出现中文字符!**
+
+## 准备工作     
+
+1. 将收集的图像存放于`JPEGImages`文件夹下,例如存储在`D:\MyDataset\JPEGImages`
+2. 创建与图像文件夹相对应的文件夹`Annotations`,用于存储标注的json文件,如`D:MyDataset\Annotations`
+3. 打开LabelMe,点击”Open Dir“按钮,选择需要标注的图像所在的文件夹打开,则”File List“对话框中会显示所有图像所对应的绝对路径,接着便可以开始遍历每张图像,进行标注工作      
+
+## 目标边缘标注    
+
+1. 打开多边形标注工具(右键菜单->Create Polygon)以打点的方式圈出目标的轮廓,并在弹出的对话框中写明对应label(当label已存在时点击即可,此处请注意label勿使用中文),具体如下提所示,当框标注错误时,可点击左侧的“Edit Polygons”再点击标注框,通过拖拉进行修改,也可再点击“Delete Polygon”进行删除。
+![](./pics/detection2.png)
+
+2. 点击右侧”Save“,将标注结果保存到中创建的文件夹Annotations目录中
+
+## 格式转换
+
+LabelMe标注后的数据还需要进行转换为MSCOCO格式,才可以用于实例分割任务的训练,创建保存目录`D:\dataset_seg`,在python环境中安装paddlex后,使用如下命令即可
+```
+paddlex --data_conversion --source labelme --to MSCOCO \
+        --pics D:\MyDataset\JPEGImages \
+        --annotations D:\MyDataset\Annotations \
+        --save_dir D:\dataset_coco
+```
+
+## 数据集划分
+
+转换完数据后,为了进行训练,还需要将数据划分为训练集、验证集和测试集,同样在安装paddlex后,使用如下命令即可将数据划分为70%训练集,20%验证集和10%的测试集
+```
+paddlex --split_dataset --format COCO --dataset_dir D:\MyDataset --val_value 0.2 --test_value 0.1
+```
+执行上面命令行,会在`D:\MyDataset`下生成`train.json`, `val.json`, `test.json`,分别存储训练样本信息,验证样本信息,测试样本信息
+
+> 注:如您使用PaddleX可视化客户端进行模型训练,数据集划分功能集成在客户端内,无需自行使用命令划分
+
+
+- [实例分割任务训练示例代码](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/instance_segmentation/mask_rcnn_r50_fpn.py)
+

+ 26 - 0
docs/data/annotation/labelme.md

@@ -0,0 +1,26 @@
+# LabelMe的安装和启动
+
+LabelMe可用于标注目标检测、实例分割、语义分割数据集,是一款开源的标注工具。
+
+## 1. 安装Anaconda
+
+推荐使用Anaconda安装python依赖,有经验的开发者可以跳过此步骤。安装Anaconda的方式可以参考[文档](../../appendix/anaconda_install.md)。
+
+在安装Anaconda,并创建环境之后,再进行接下来的步骤
+
+## 2. 安装LabelMe
+
+进入Python环境后,执行如下命令即可
+```
+conda activate my_paddlex
+conda install pyqt
+pip install labelme
+```
+
+## 3. 启动LabelMe
+
+进入安装了LabelMe的Python环境,执行如下命令即可启动LabelMe
+```
+conda activate my_paddlex
+labelme
+```

+ 47 - 0
docs/data/annotation/object_detection.md

@@ -0,0 +1,47 @@
+# 目标检测
+
+目标检测数据的标注推荐使用LabelMe标注工具,如您先前并无安装,那么LabelMe的安装可参考[LabelMe安装和启动](labelme.md)
+
+**注意:LabelMe对于中文支持不够友好,因此请不要在如下的路径以及文件名中出现中文字符!**
+
+## 准备工作     
+
+1. 将收集的图像存放于`JPEGImages`文件夹下,例如存储在`D:\MyDataset\JPEGImages`
+2. 创建与图像文件夹相对应的文件夹`Annotations`,用于存储标注的json文件,如`D:MyDataset\Annotations`
+3. 打开LabelMe,点击”Open Dir“按钮,选择需要标注的图像所在的文件夹打开,则”File List“对话框中会显示所有图像所对应的绝对路径,接着便可以开始遍历每张图像,进行标注工作      
+
+## 目标框标注    
+
+1. 打开矩形框标注工具(右键菜单->Create Rectangle),具体如下图所示     
+![](./pics/detection1.png)
+
+2. 使用拖拉的方式对目标物体进行标识,并在弹出的对话框中写明对应label(当label已存在时点击即可, 此处请注意label勿使用中文),具体如下图所示,当框标注错误时,可点击左侧的“Edit Polygons”再点击标注框,通过拖拉进行修改,也可再点击“Delete Polygon”进行删除。    
+![](./pics/detection3.png)
+
+3. 点击右侧”Save“,将标注结果保存到中创建的文件夹Annotations目录中
+
+## 格式转换
+
+LabelMe标注后的数据还需要进行转换为PascalVOC或MSCOCO格式,才可以用于目标检测任务的训练,创建`D:\dataset_voc`目录,在python环境中安装paddlex后,使用如下命令即可
+```
+paddlex --data_conversion --source labelme --to PascalVOC \
+        --pics D:\MyDataset\JPEGImages \
+        --annotations D:\MyDataset\Annotations \
+        --save_dir D:\dataset_voc
+```
+
+> 注:此文档中以LabelMe为示例,展示了格式转换,如您使用的是数据标注精灵工具,则可在标注完后,选择直接保存为PascalVOC格式
+
+## 数据集划分
+
+转换完数据后,为了进行训练,还需要将数据划分为训练集、验证集和测试集,同样在安装paddlex后,使用如下命令即可将数据划分为70%训练集,20%验证集和10%的测试集
+```
+paddlex --split_dataset --format VOC --dataset_dir D:\MyDataset --val_value 0.2 --test_value 0.1
+```
+执行上面命令行,会在`D:\MyDataset`下生成`labels.txt`, `train_list.txt`, `val_list.txt`和`test_list.txt`,分别存储类别信息,训练样本列表,验证样本列表,测试样本列表
+
+> 注:如您使用PaddleX可视化客户端进行模型训练,数据集划分功能集成在客户端内,无需自行使用命令划分
+
+
+- [目标检测任务训练示例代码](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/object_detection/yolov3_mobilenetv1.py)
+

BIN
docs/data/annotation/pics/detection1.png


BIN
docs/data/annotation/pics/detection2.png


BIN
docs/data/annotation/pics/detection3.png


BIN
docs/data/annotation/pics/detection4.png


BIN
docs/data/annotation/pics/detection5.png


+ 42 - 0
docs/data/annotation/semantic_segmentation.md

@@ -0,0 +1,42 @@
+# 语义分割
+
+语义数据的标注推荐使用LabelMe标注工具,如您先前并无安装,那么LabelMe的安装可参考[LabelMe安装和启动](labelme.md),语义分割的标注与实例分割类似,流程如下
+
+**注意:LabelMe对于中文支持不够友好,因此请不要在如下的路径以及文件名中出现中文字符!**
+
+## 准备工作     
+
+1. 将收集的图像存放于`JPEGImages`文件夹下,例如存储在`D:\MyDataset\JPEGImages`
+2. 创建与图像文件夹相对应的文件夹`Annotations`,用于存储标注的json文件,如`D:MyDataset\Annotations`
+3. 打开LabelMe,点击”Open Dir“按钮,选择需要标注的图像所在的文件夹打开,则”File List“对话框中会显示所有图像所对应的绝对路径,接着便可以开始遍历每张图像,进行标注工作      
+
+## 目标边缘标注    
+
+1. 打开多边形标注工具(右键菜单->Create Polygon)以打点的方式圈出目标的轮廓,并在弹出的对话框中写明对应label(当label已存在时点击即可,此处请注意label勿使用中文),具体如下提所示,当框标注错误时,可点击左侧的“Edit Polygons”再点击标注框,通过拖拉进行修改,也可再点击“Delete Polygon”进行删除。
+![](./pics/detection2.png)
+
+2. 点击右侧”Save“,将标注结果保存到中创建的文件夹Annotations目录中
+
+## 格式转换
+
+LabelMe标注后的数据还需要进行转换为SEG格式,才可以用于实例分割任务的训练,创建保存目录`D:\dataset_seg`,在python环境中安装paddlex后,使用如下命令即可
+```
+paddlex --data_conversion --source labelme --to SEG \
+        --pics D:\MyDataset\JPEGImages \
+        --annotations D:\MyDataset\Annotations \
+        --save_dir D:\dataset_seg
+```
+
+## 数据集划分
+
+转换完数据后,为了进行训练,还需要将数据划分为训练集、验证集和测试集,同样在安装paddlex后,使用如下命令即可将数据划分为70%训练集,20%验证集和10%的测试集
+```
+paddlex --split_dataset --format SEG --dataset_dir D:\MyDataset --val_value 0.2 --test_value 0.1
+```
+执行上面命令行,会在`D:\MyDataset`下生成`train_list.txt`, `val_list.txt`, `test_list.txt`,分别存储训练样本信息,验证样本信息,测试样本信息
+
+> 注:如您使用PaddleX可视化客户端进行模型训练,数据集划分功能集成在客户端内,无需自行使用命令划分
+
+
+- [语义分割任务训练示例代码](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/semantic_segmentation/deeplabv3p_xception65.py)
+

+ 4 - 0
docs/deploy/export_model.md

@@ -1,5 +1,7 @@
 # 部署模型导出
 # 部署模型导出
 
 
+**注:所有涉及到模型部署,均需要参考本文档,进行部署模型导出**  
+
 在服务端部署模型时需要将训练过程中保存的模型导出为inference格式模型,导出的inference格式模型包括`__model__`、`__params__`和`model.yml`三个文件,分别表示模型的网络结构、模型权重和模型的配置文件(包括数据预处理参数等)。
 在服务端部署模型时需要将训练过程中保存的模型导出为inference格式模型,导出的inference格式模型包括`__model__`、`__params__`和`model.yml`三个文件,分别表示模型的网络结构、模型权重和模型的配置文件(包括数据预处理参数等)。
 
 
 > **检查你的模型文件夹**,如果里面是`model.pdparams`, `model.pdmodel`和`model.yml`3个文件时,那么就需要按照下面流程进行模型导出
 > **检查你的模型文件夹**,如果里面是`model.pdparams`, `model.pdmodel`和`model.yml`3个文件时,那么就需要按照下面流程进行模型导出
@@ -22,7 +24,9 @@ paddlex --export_inference --model_dir=./xiaoduxiong_epoch_12 --save_dir=./infer
 
 
 **注意**:
 **注意**:
 - 分类模型的固定输入大小请保持与训练时的输入大小一致;
 - 分类模型的固定输入大小请保持与训练时的输入大小一致;
+- 检测模型模型中YOLO系列请保存w与h一致,且为32的倍数大小;RCNN类无此限制,按需设定即可
 - 指定[w,h]时,w和h中间逗号隔开,不允许存在空格等其他字符。
 - 指定[w,h]时,w和h中间逗号隔开,不允许存在空格等其他字符。
+- 需要注意的,w,h设得越大,模型在预测过程中所需要的耗时和内存/显存占用越高;设得太小,会影响模型精度
 
 
 ```
 ```
 paddlex --export_inference --model_dir=./xiaoduxiong_epoch_12 --save_dir=./inference_model --fixed_input_shape=[640,960]
 paddlex --export_inference --model_dir=./xiaoduxiong_epoch_12 --save_dir=./inference_model --fixed_input_shape=[640,960]

+ 1 - 1
docs/deploy/hub_serving.md

@@ -1,4 +1,4 @@
-# 轻量级服务化部署
+# PaddleHub轻量级服务化部署
 ## 简介
 ## 简介
 借助`PaddleHub-Serving`,可以将`PaddleX`的`Inference Model`进行快速部署,以提供在线预测的能力。
 借助`PaddleHub-Serving`,可以将`PaddleX`的`Inference Model`进行快速部署,以提供在线预测的能力。
 
 

+ 1 - 1
docs/deploy/server/index.rst

@@ -1,4 +1,4 @@
-服务端部署
+CPU/GPU(加密)部署
 =======================================
 =======================================
 
 
 
 

+ 13 - 7
docs/gui/download.md

@@ -1,15 +1,22 @@
-## PaddleX GUI安装
+# 下载安装
 
 
- PaddleX GUI是提升项目开发效率的核心模块,开发者可快速完成深度学习模型全流程开发。我们诚挚地邀请您前往 [官网](https://www.paddlepaddle.org.cn/paddle/paddleX)下载试用PaddleX GUI可视化前端,并获得您宝贵的意见或开源项目贡献。
+下载地址:https://www.paddlepaddle.org.cn/paddle/paddleXPaddleX 
 
 
 
 
+## 安装方式
 
 
-### 安装推荐环境
+**注意:安装/解压路径请务必在不包含中文和空格的路径下,否则会导致可能无法正确训练模型**
+
+- Windows下载后双击后选择安装路径即可
+- Mac/Ubuntu下载后解压即可
+
+
+## 安装推荐环境
 
 
 * **操作系统**:
 * **操作系统**:
-  * Windows7/8/10(推荐Windows 10);
+  * Windows 10;
   * Mac OS 10.13+;
   * Mac OS 10.13+;
-  * Ubuntu 18.04+;
+  * Ubuntu 18.04(Ubuntu暂只支持18.04)
 
 
 ***注:处理器需为x86_64架构,支持MKL。***
 ***注:处理器需为x86_64架构,支持MKL。***
 
 
@@ -24,5 +31,4 @@
   * **内存**:建议8G以上  
   * **内存**:建议8G以上  
   * **硬盘空间**:建议SSD剩余空间1T以上(非必须)  
   * **硬盘空间**:建议SSD剩余空间1T以上(非必须)  
 
 
-***注:PaddleX在Mac OS系统只支持单卡模型。Windows系统暂不支持NCCL。***
-
+***注:PaddleX在Mac OS系统只支持CPU训练。Windows系统只支持单GPU卡训练。***

+ 33 - 14
docs/gui/how_to_use.md

@@ -1,14 +1,16 @@
-# PaddleX GUI使用教程
+# 使用方法
 
 
 *注:如果你的系统是 Mac OS 10.15.5及以上,在双击客户端icon后,需要在Terminal中执行 sudo xattr -r -d com.apple.quarantine /Users/username/PaddleX ,并稍等几秒来启动客户端,其中 /Users/username/PaddleX 为您保存PaddleX的文件夹路径*
 *注:如果你的系统是 Mac OS 10.15.5及以上,在双击客户端icon后,需要在Terminal中执行 sudo xattr -r -d com.apple.quarantine /Users/username/PaddleX ,并稍等几秒来启动客户端,其中 /Users/username/PaddleX 为您保存PaddleX的文件夹路径*
 
 
-**第一步:准备数据**
+## 准备和导入数据
 
 
-在开始模型训练前,您需要根据不同的任务类型,将数据标注为相应的格式。目前PaddleX支持【图像分类】、【目标检测】、【语义分割】、【实例分割】四种任务类型。不同类型任务的数据处理方式可查看[数据标注方式](https://paddlex.readthedocs.io/zh_CN/latest/appendix/datasets.html)。
+**第一步: 准备数据**
+在开始模型训练前,您需要根据不同的任务类型,将数据标注为相应的格式。目前PaddleX支持【图像分类】、【目标检测】、【语义分割】、【实例分割】四种任务类型。  
+开发者可以参考PaddleX使用文档中的[2.数据准备-数据标注](../data/annotations/index.html)来进行数据标注和转换工作。 如若开发者自行准备数据,请注意数据格式与PaddleX支持四种数据格式是否一致。
 
 
- 
 
 
-**第二步:导入我的数据集**
+
+**第二步:导入的据集**
 
 
 ①数据标注完成后,您需要根据不同的任务,将数据和标注文件,按照客户端提示更名并保存到正确的文件中。
 ①数据标注完成后,您需要根据不同的任务,将数据和标注文件,按照客户端提示更名并保存到正确的文件中。
 
 
@@ -22,7 +24,10 @@
 
 
 ![](images/dataset2.jpg)
 ![](images/dataset2.jpg)
 
 
-**第三步:创建项目**
+
+## 创建项目和任务
+
+**第一步:创建项目**
 
 
 ① 在完成数据导入后,您可以点击「新建项目」创建一个项目。
 ① 在完成数据导入后,您可以点击「新建项目」创建一个项目。
 
 
@@ -32,7 +37,7 @@
 
 
 
 
 
 
-**第步:项目开发**
+**第步:项目开发**
 
 
 ① **数据选择**:项目创建完成后,您需要选择已载入客户端并校验后的数据集,并点击下一步,进入参数配置页面。
 ① **数据选择**:项目创建完成后,您需要选择已载入客户端并校验后的数据集,并点击下一步,进入参数配置页面。
 
 
@@ -42,9 +47,11 @@
 
 
 ![](images/project2.jpg)
 ![](images/project2.jpg)
 
 
+## 任务模型训练
+
 参数配置完成后,点击启动训练,模型开始训练并进行效果评估。
 参数配置完成后,点击启动训练,模型开始训练并进行效果评估。
 
 
- **训练可视化**:在训练过程中,您可通过VisualDL查看模型训练过程参数变化、日志详情,及当前最优的训练集和验证集训练指标。模型在训练过程中通过点击"中止训练"随时中止训练过程。
+ **训练可视化**:在训练过程中,您可通过VisualDL查看模型训练过程参数变化、日志详情,及当前最优的训练集和验证集训练指标。模型在训练过程中通过点击"中止训练"随时中止训练过程。
 
 
 ![](images/visualization1.jpg)
 ![](images/visualization1.jpg)
 
 
@@ -52,11 +59,24 @@
 
 
 ![](images/visualization2.jpg)
 ![](images/visualization2.jpg)
 
 
-④ **模型裁剪**:如果开发者希望减少模型的体积、计算量,提升模型在设备上的预测性能,可以采用PaddleX提供的模型裁剪策略。裁剪过程将对模型各卷积层的敏感度信息进行分析,根据各参数对模型效果的影响进行不同比例的裁剪,再进行精调训练获得最终裁剪后的模型。
+> 模型训练是最容易出错的步骤,经常遇到的原因为电脑无法联网下载预训练模型、显存不够。训练检测模型\实例分割模型对于显存要求较高,**建议用户通过在Windows/Mac/Ubuntu的命令行终端(Windows的Cmd命令终端)执行`nvidia-smi`命令**查看显存情况,请不要使用系统自带的任务管理器查看。  
+
+## 任务模型裁剪训练
+
+此步骤可选,模型裁剪训练相对比普通的任务模型训练,需要消耗更多的时间,需要在正常任务模型训练的基础上,增加『**模型裁剪分类**』和『**模型裁剪训练**』两个步骤。  
+
+裁剪过程将对模型各卷积层的敏感度信息进行分析,根据各参数对模型效果的影响进行不同比例的裁剪,再进行精调训练获得最终裁剪后的模型。  
+裁剪训练后的模型体积,计算量都会减少,并且可以提升模型在低性能设备的预测速度,如移动端,边缘设备,CPU。
+
+在可视化客户端上,**用户训练好模型后**,在训练界面,
+- 首先,点击『模型裁剪分析』,此过程将会消耗较长的时间
+- 接着,点击『开始模型裁剪训练』,客户端会创建一个新的任务,无需修改参数,直接再启动训练即可
 
 
 ![](images/visualization3.jpg)
 ![](images/visualization3.jpg)
 
 
-⑤ **模型评估**:在模型评估页面,您可查看训练后的模型效果。评估方法包括混淆矩阵、精度、召回率等。
+## 模型效果评估
+
+在模型评估页面,您可查看训练后的模型效果。评估方法包括混淆矩阵、精度、召回率等。
 
 
 ![](images/visualization4.jpg)
 ![](images/visualization4.jpg)
 
 
@@ -64,11 +84,10 @@
 
 
 ![](images/visualization5.jpg)
 ![](images/visualization5.jpg)
 
 
+## 模型发布
 
 
-
-**第五步:模型发布**
-
-当模型效果满意后,您可根据实际的生产环境需求,选择将模型发布为需要的版本。
+当模型效果满意后,您可根据实际的生产环境需求,选择将模型发布为需要的版本。  
+> 如若要部署到移动端/边缘设备,对于部分支持量化的模型,还可以根据需求选择是否量化。量化可以压缩模型体积,提升预测速度
 
 
 ![](images/publish.jpg)
 ![](images/publish.jpg)
 
 

+ 1 - 1
docs/gui/index.rst

@@ -47,7 +47,7 @@ PaddleX GUI覆盖深度学习模型开发必经的 **数据处理** 、 **超参
    :caption: 文档目录
    :caption: 文档目录
    
    
    download.md
    download.md
-   how_to_use.md
+   usage/index
    faq.md
    faq.md
 
 
 
 

+ 41 - 0
docs/gui/introduce.md

@@ -0,0 +1,41 @@
+# 介绍
+
+PaddleX可视化客户端基于PaddleX开发的可视化深度学习模型训练套件,目前支持训练视觉领域的图像分类、目标检测、实例分割和语义分割四大任务,同时支持模型裁剪、模型量化两种方式压缩模型。开发者以点选、键入的方式快速体验深度学习模型开发的全流程。可以作为您提升深度学习模型开发效率的工具。
+
+PaddleX GUI 当前提供Windows,Mac,Ubuntu三种版本一键绿色安装的方式。请至飞桨官网:https://www.paddlepaddle.org.cn/paddle/paddleX 下载您需要的版本。
+
+## 功能
+PaddleX可视化客户端是PaddleX API的衍生品,它在集成API功能的基础上,额外提供了可视化分析、评估等附加功能,致力于为开发者带来极致顺畅的开发体验。其拥有以下独特的功能:
+
+### 全流程打通
+
+PaddleX GUI覆盖深度学习模型开发必经的 **数据处理** 、 **超参配置** 、 **模型训练及优化** 、 **模型发布** 全流程,无需开发一行代码,即可得到高性深度学习推理模型。
+
+### 数据集智能分析
+
+详细的数据结构说明,并提供 **数据标签自动校验** 。支持 **可视化数据预览** 、 **数据分布图表展示** 、 **一键数据集切分** 等实用功能
+
+### 自动超参推荐
+
+集成飞桨团队长时间产业实践经验,根据用户选择的模型类别、骨架网络等,提供多种针对性优化的 **预训练模型** ,并 **提供推荐超参配置** ,可 **一键开启多种优化策略**
+
+### 可视化模型评估
+
+集成 **可视化分析工具:VisualDL** , 以线性图表的形式展示acc、lr等关键参数在训练过程中的变化趋势。提供 **混淆矩阵** 等实用方法,帮助快速定位问题,加速调参。模型评估报告一键导出,方便项目复盘分析。
+
+### 模型裁剪及量化
+
+一键启动模型裁剪、量化,在不同阶段为开发者提供模型优化的策略,满足不同环境对模型性能的需求。
+
+### 预训练模型管理
+
+可对历史训练模型进行保存及管理,未进行裁剪的模型可以保存为预训练模型,在后续任务中使用。
+
+### 可视化模型测试
+
+客户端直接展示模型预测效果,无需上线即可进行效果评估
+
+### 模型多端部署
+
+点选式选择模型发布平台、格式,一键导出预测模型,并匹配完善的模型预测部署说明文档,贴心助力产业端到端项目落地
+

+ 67 - 9
docs/index.rst

@@ -8,18 +8,76 @@ PaddleX是基于飞桨核心框架、开发套件和工具组件的深度学习
 * 官方QQ用户群: 1045148026  
 * 官方QQ用户群: 1045148026  
 * GitHub Issue反馈: http://www.github.com/PaddlePaddle/PaddleX/issues
 * GitHub Issue反馈: http://www.github.com/PaddlePaddle/PaddleX/issues
 
 
+1. 注:本使用手册在打印为pdf后,可能会存在部分格式的兼容问题;
+2. 注:本文档持续在http://paddlex.readthedocs.io/进行更新。
+
 
 
 .. toctree::
 .. toctree::
-   :maxdepth: 2
-   :caption: PaddleX使用文档目录
+   :maxdepth: 1
+   :caption: 1. 快速了解PaddleX
 
 
    quick_start.md
    quick_start.md
    install.md
    install.md
-   data/index
+
+
+.. toctree::
+   :maxdepth: 1
+   :caption: 2. 数据准备
+
+   data/annotation/index
+   data/format/index
+
+.. toctree::
+   :maxdepth: 1
+   :caption: 3. 模型训练与参数调整
+
    train/index
    train/index
-   deploy/index
-   examples/index
-   gui/index
-   apis/index
-   change_log.md
-   appendix/index
+   train/prediction.md
+   appendix/parameters.md
+
+.. toctree::
+   :maxdepth: 1
+   :caption: 4. 模型压缩优化
+
+   slim/prune.md
+   slim/quant.md
+
+.. toctree::
+   :maxdepth: 1
+   :caption: 5. 模型多端安全部署
+
+   deploy/export_model.md
+   deploy/hub_serving.md
+   deploy/server/index
+   deploy/nvidia-jetson.md
+   deploy/paddlelite/android.md
+   deploy/raspberry/index
+   deploy/openvino/index
+
+.. toctree::
+   :maxdepth: 1
+   :caption: 6. 产业案例集
+
+   examples/meter_reader.md
+   examples/human_segmentation.md
+   examples/remote_sensing.md
+   examples/multi-channel_remote_sensing/README.md
+   examples/change_detection.md
+
+.. toctree::
+   :maxdepth: 1
+   :caption: 7. 可视化客户端使用
+
+   gui/introduce.md
+   gui/download.md
+   gui/how_to_use.md
+
+.. toctree::
+   :maxdepth: 1
+   :caption: 8. 附录
+
+   apis/index.rst
+   appendix/model_zoo.md
+   appendix/metrics.md
+   appendix/interpret.md
+   appendix/how_to_offline_run.md

+ 0 - 1
docs/train/index.rst

@@ -12,5 +12,4 @@ PaddleX集成了PaddleClas、PaddleDetection和PaddleSeg三大CV工具套件中
    object_detection.md
    object_detection.md
    instance_segmentation.md
    instance_segmentation.md
    semantic_segmentation.md
    semantic_segmentation.md
-   prediction.md
    visualdl.md
    visualdl.md

+ 9 - 2
paddlex/__init__.py

@@ -14,6 +14,8 @@
 
 
 from __future__ import absolute_import
 from __future__ import absolute_import
 
 
+__version__ = '1.2.3'
+
 import os
 import os
 if 'FLAGS_eager_delete_tensor_gb' not in os.environ:
 if 'FLAGS_eager_delete_tensor_gb' not in os.environ:
     os.environ['FLAGS_eager_delete_tensor_gb'] = '0.0'
     os.environ['FLAGS_eager_delete_tensor_gb'] = '0.0'
@@ -23,6 +25,13 @@ if "CUDA_VISIBLE_DEVICES" in os.environ:
     if os.environ["CUDA_VISIBLE_DEVICES"].count("-1") > 0:
     if os.environ["CUDA_VISIBLE_DEVICES"].count("-1") > 0:
         os.environ["CUDA_VISIBLE_DEVICES"] = ""
         os.environ["CUDA_VISIBLE_DEVICES"] = ""
 
 
+import paddle
+version = paddle.__version__.strip().split('.')
+if version[0] != '1' and version[1] != '8':
+    raise Exception(
+        "For running paddlex(v{}), Version of paddlepaddle should be greater than 1.8.3 and less than 2.0.0".
+        format(__version__))
+
 from .utils.utils import get_environ_info
 from .utils.utils import get_environ_info
 from . import cv
 from . import cv
 from . import det
 from . import det
@@ -51,5 +60,3 @@ transforms = cv.transforms
 log_level = 2
 log_level = 2
 
 
 from . import interpret
 from . import interpret
-
-__version__ = '1.2.2'

+ 4 - 2
paddlex/cv/models/base.py

@@ -151,10 +151,11 @@ class BaseAPI:
         is_use_cache_file = True
         is_use_cache_file = True
         if cache_dir is None:
         if cache_dir is None:
             is_use_cache_file = False
             is_use_cache_file = False
+        quant_prog = self.test_prog.clone(for_test=True)
         post_training_quantization = PaddleXPostTrainingQuantization(
         post_training_quantization = PaddleXPostTrainingQuantization(
             executor=self.exe,
             executor=self.exe,
             dataset=dataset,
             dataset=dataset,
-            program=self.test_prog,
+            program=quant_prog,
             inputs=self.test_inputs,
             inputs=self.test_inputs,
             outputs=self.test_outputs,
             outputs=self.test_outputs,
             batch_size=batch_size,
             batch_size=batch_size,
@@ -366,6 +367,7 @@ class BaseAPI:
     def export_inference_model(self, save_dir):
     def export_inference_model(self, save_dir):
         test_input_names = [var.name for var in list(self.test_inputs.values())]
         test_input_names = [var.name for var in list(self.test_inputs.values())]
         test_outputs = list(self.test_outputs.values())
         test_outputs = list(self.test_outputs.values())
+        save_prog = self.test_prog.clone(for_test=True)
         with fluid.scope_guard(self.scope):
         with fluid.scope_guard(self.scope):
             fluid.io.save_inference_model(
             fluid.io.save_inference_model(
                 dirname=save_dir,
                 dirname=save_dir,
@@ -373,7 +375,7 @@ class BaseAPI:
                 params_filename='__params__',
                 params_filename='__params__',
                 feeded_var_names=test_input_names,
                 feeded_var_names=test_input_names,
                 target_vars=test_outputs,
                 target_vars=test_outputs,
-                main_program=self.test_prog)
+                main_program=save_prog)
         model_info = self.get_model_info()
         model_info = self.get_model_info()
         model_info['status'] = 'Infer'
         model_info['status'] = 'Infer'
 
 

+ 54 - 12
paddlex/cv/models/slim/prune.py

@@ -21,9 +21,6 @@ import os.path as osp
 from functools import reduce
 from functools import reduce
 import paddle.fluid as fluid
 import paddle.fluid as fluid
 from multiprocessing import Process, Queue
 from multiprocessing import Process, Queue
-import paddleslim
-from paddleslim.prune import Pruner, load_sensitivities
-from paddleslim.core import GraphWrapper
 from .prune_config import get_prune_params
 from .prune_config import get_prune_params
 import paddlex.utils.logging as logging
 import paddlex.utils.logging as logging
 from paddlex.utils import seconds_to_hms
 from paddlex.utils import seconds_to_hms
@@ -36,6 +33,10 @@ def sensitivity(program,
                 sensitivities_file=None,
                 sensitivities_file=None,
                 pruned_ratios=None,
                 pruned_ratios=None,
                 scope=None):
                 scope=None):
+    import paddleslim
+    from paddleslim.prune import Pruner, load_sensitivities
+    from paddleslim.core import GraphWrapper
+
     if scope is None:
     if scope is None:
         scope = fluid.global_scope()
         scope = fluid.global_scope()
     else:
     else:
@@ -104,7 +105,12 @@ def sensitivity(program,
     return sensitivities
     return sensitivities
 
 
 
 
-def channel_prune(program, prune_names, prune_ratios, place, only_graph=False, scope=None):
+def channel_prune(program,
+                  prune_names,
+                  prune_ratios,
+                  place,
+                  only_graph=False,
+                  scope=None):
     """通道裁剪。
     """通道裁剪。
 
 
     Args:
     Args:
@@ -119,6 +125,10 @@ def channel_prune(program, prune_names, prune_ratios, place, only_graph=False, s
     Returns:
     Returns:
         paddle.fluid.Program: 裁剪后的Program。
         paddle.fluid.Program: 裁剪后的Program。
     """
     """
+    import paddleslim
+    from paddleslim.prune import Pruner, load_sensitivities
+    from paddleslim.core import GraphWrapper
+
     prog_var_shape_dict = {}
     prog_var_shape_dict = {}
     for var in program.list_vars():
     for var in program.list_vars():
         try:
         try:
@@ -163,6 +173,10 @@ def prune_program(model, prune_params_ratios=None):
         prune_params_ratios (dict): 由裁剪参数名和裁剪率组成的字典,当为None时
         prune_params_ratios (dict): 由裁剪参数名和裁剪率组成的字典,当为None时
             使用默认裁剪参数名和裁剪率。默认为None。
             使用默认裁剪参数名和裁剪率。默认为None。
     """
     """
+    import paddleslim
+    from paddleslim.prune import Pruner, load_sensitivities
+    from paddleslim.core import GraphWrapper
+
     assert model.status == 'Normal', 'Only the models saved while training are supported!'
     assert model.status == 'Normal', 'Only the models saved while training are supported!'
     place = model.places[0]
     place = model.places[0]
     train_prog = model.train_prog
     train_prog = model.train_prog
@@ -175,10 +189,15 @@ def prune_program(model, prune_params_ratios=None):
     prune_ratios = [
     prune_ratios = [
         prune_params_ratios[prune_name] for prune_name in prune_names
         prune_params_ratios[prune_name] for prune_name in prune_names
     ]
     ]
-    model.train_prog = channel_prune(train_prog, prune_names, prune_ratios,
-                                     place, scope=model.scope)
+    model.train_prog = channel_prune(
+        train_prog, prune_names, prune_ratios, place, scope=model.scope)
     model.test_prog = channel_prune(
     model.test_prog = channel_prune(
-        eval_prog, prune_names, prune_ratios, place, only_graph=True, scope=model.scope)
+        eval_prog,
+        prune_names,
+        prune_ratios,
+        place,
+        only_graph=True,
+        scope=model.scope)
 
 
 
 
 def update_program(program, model_dir, place, scope=None):
 def update_program(program, model_dir, place, scope=None):
@@ -193,6 +212,10 @@ def update_program(program, model_dir, place, scope=None):
     Returns:
     Returns:
         paddle.fluid.Program: 更新后的Program。
         paddle.fluid.Program: 更新后的Program。
     """
     """
+    import paddleslim
+    from paddleslim.prune import Pruner, load_sensitivities
+    from paddleslim.core import GraphWrapper
+
     graph = GraphWrapper(program)
     graph = GraphWrapper(program)
     with open(osp.join(model_dir, "prune.yml")) as f:
     with open(osp.join(model_dir, "prune.yml")) as f:
         shapes = yaml.load(f.read(), Loader=yaml.Loader)
         shapes = yaml.load(f.read(), Loader=yaml.Loader)
@@ -203,11 +226,9 @@ def update_program(program, model_dir, place, scope=None):
     for block in program.blocks:
     for block in program.blocks:
         for param in block.all_parameters():
         for param in block.all_parameters():
             if param.name in shapes:
             if param.name in shapes:
-                param_tensor = scope.find_var(
-                    param.name).get_tensor()
+                param_tensor = scope.find_var(param.name).get_tensor()
                 param_tensor.set(
                 param_tensor.set(
-                    np.zeros(list(shapes[param.name])).astype('float32'),
-                    place)
+                    np.zeros(list(shapes[param.name])).astype('float32'), place)
     graph.update_groups_of_conv()
     graph.update_groups_of_conv()
     graph.infer_shape()
     graph.infer_shape()
     return program
     return program
@@ -243,6 +264,10 @@ def cal_params_sensitivities(model, save_file, eval_dataset, batch_size=8):
 
 
             其中``weight_0``是卷积Kernel名;``sensitivities['weight_0']``是一个字典,key是裁剪率,value是敏感度。
             其中``weight_0``是卷积Kernel名;``sensitivities['weight_0']``是一个字典,key是裁剪率,value是敏感度。
     """
     """
+    import paddleslim
+    from paddleslim.prune import Pruner, load_sensitivities
+    from paddleslim.core import GraphWrapper
+
     assert model.status == 'Normal', 'Only the models saved while training are supported!'
     assert model.status == 'Normal', 'Only the models saved while training are supported!'
     if os.path.exists(save_file):
     if os.path.exists(save_file):
         os.remove(save_file)
         os.remove(save_file)
@@ -268,6 +293,11 @@ def cal_params_sensitivities(model, save_file, eval_dataset, batch_size=8):
     return sensitivitives
     return sensitivitives
 
 
 
 
+def analysis(model, dataset, batch_size=8, save_file='./model.sensi.data'):
+    return cal_params_sensitivities(
+        model, eval_dataset=dataset, batch_size=batch_size, save_file=save_file)
+
+
 def get_params_ratios(sensitivities_file, eval_metric_loss=0.05):
 def get_params_ratios(sensitivities_file, eval_metric_loss=0.05):
     """根据设定的精度损失容忍度metric_loss_thresh和计算保存的模型参数敏感度信息文件sensetive_file,
     """根据设定的精度损失容忍度metric_loss_thresh和计算保存的模型参数敏感度信息文件sensetive_file,
         获取裁剪的参数配置。
         获取裁剪的参数配置。
@@ -288,6 +318,10 @@ def get_params_ratios(sensitivities_file, eval_metric_loss=0.05):
 
 
             其中key是卷积Kernel名;value是裁剪率。
             其中key是卷积Kernel名;value是裁剪率。
     """
     """
+    import paddleslim
+    from paddleslim.prune import Pruner, load_sensitivities
+    from paddleslim.core import GraphWrapper
+
     if not osp.exists(sensitivities_file):
     if not osp.exists(sensitivities_file):
         raise Exception('The sensitivities file is not exists!')
         raise Exception('The sensitivities file is not exists!')
     sensitivitives = paddleslim.prune.load_sensitivities(sensitivities_file)
     sensitivitives = paddleslim.prune.load_sensitivities(sensitivities_file)
@@ -296,7 +330,11 @@ def get_params_ratios(sensitivities_file, eval_metric_loss=0.05):
     return params_ratios
     return params_ratios
 
 
 
 
-def cal_model_size(program, place, sensitivities_file, eval_metric_loss=0.05, scope=None):
+def cal_model_size(program,
+                   place,
+                   sensitivities_file,
+                   eval_metric_loss=0.05,
+                   scope=None):
     """在可容忍的精度损失下,计算裁剪后模型大小相对于当前模型大小的比例。
     """在可容忍的精度损失下,计算裁剪后模型大小相对于当前模型大小的比例。
 
 
     Args:
     Args:
@@ -309,6 +347,10 @@ def cal_model_size(program, place, sensitivities_file, eval_metric_loss=0.05, sc
     Returns:
     Returns:
         float: 裁剪后模型大小相对于当前模型大小的比例。
         float: 裁剪后模型大小相对于当前模型大小的比例。
     """
     """
+    import paddleslim
+    from paddleslim.prune import Pruner, load_sensitivities
+    from paddleslim.core import GraphWrapper
+
     prune_params_ratios = get_params_ratios(sensitivities_file,
     prune_params_ratios = get_params_ratios(sensitivities_file,
                                             eval_metric_loss)
                                             eval_metric_loss)
     prog_var_shape_dict = {}
     prog_var_shape_dict = {}

+ 5 - 2
paddlex/cv/models/slim/visualize.py

@@ -16,7 +16,6 @@ import os.path as osp
 import tqdm
 import tqdm
 import numpy as np
 import numpy as np
 from .prune import cal_model_size
 from .prune import cal_model_size
-from paddleslim.prune import load_sensitivities
 
 
 
 
 def visualize(model, sensitivities_file, save_dir='./'):
 def visualize(model, sensitivities_file, save_dir='./'):
@@ -42,7 +41,11 @@ def visualize(model, sensitivities_file, save_dir='./'):
     y = list()
     y = list()
     for loss_thresh in tqdm.tqdm(list(np.arange(0.05, 1, 0.05))):
     for loss_thresh in tqdm.tqdm(list(np.arange(0.05, 1, 0.05))):
         prune_ratio = 1 - cal_model_size(
         prune_ratio = 1 - cal_model_size(
-            program, place, sensitivities_file, eval_metric_loss=loss_thresh, scope=model.scope)
+            program,
+            place,
+            sensitivities_file,
+            eval_metric_loss=loss_thresh,
+            scope=model.scope)
         x.append(prune_ratio)
         x.append(prune_ratio)
         y.append(loss_thresh)
         y.append(loss_thresh)
     plt.plot(x, y, color='green', linewidth=0.5, marker='o', markersize=3)
     plt.plot(x, y, color='green', linewidth=0.5, marker='o', markersize=3)

+ 1 - 1
setup.py

@@ -19,7 +19,7 @@ long_description = "PaddlePaddle Entire Process Development Toolkit"
 
 
 setuptools.setup(
 setuptools.setup(
     name="paddlex",
     name="paddlex",
-    version='1.2.2',
+    version='1.2.3',
     author="paddlex",
     author="paddlex",
     author_email="paddlex@baidu.com",
     author_email="paddlex@baidu.com",
     description=long_description,
     description=long_description,

+ 4 - 0
tutorials/compress/README.md

@@ -1,4 +1,8 @@
 # 使用教程——模型压缩
 # 使用教程——模型压缩
+
+本目录下教程已更新至[tutorials/slim/prune](../slim/prune),请参考该目录下教程使用。
+
+
 本目录下整理了使用PaddleX进行模型剪裁训练的代码,代码均会自动下载数据,并使用单张GPU卡进行训练。
 本目录下整理了使用PaddleX进行模型剪裁训练的代码,代码均会自动下载数据,并使用单张GPU卡进行训练。
 
 
 PaddleX提供了两种剪裁训练方式,  
 PaddleX提供了两种剪裁训练方式,  

+ 1 - 1
tutorials/compress/classification/cal_sensitivities_file.py

@@ -39,7 +39,7 @@ if __name__ == '__main__':
     parser = argparse.ArgumentParser(description=__doc__)
     parser = argparse.ArgumentParser(description=__doc__)
     parser.add_argument(
     parser.add_argument(
         "--model_dir",
         "--model_dir",
-        default="./output/mobilenet/best_model",
+        default="./output/mobilenetv2/best_model",
         type=str,
         type=str,
         help="The model path.")
         help="The model path.")
     parser.add_argument(
     parser.add_argument(

+ 51 - 0
tutorials/slim/prune/image_classification/README.md

@@ -0,0 +1,51 @@
+# 图像分类模型裁剪训练
+
+## 第一步 正常训练图像分类模型
+
+```
+python mobilenetv2_train.py
+```
+
+在此步骤中,训练的模型会保存在`output/mobilenetv2`目录下
+
+## 第二步 分析模型参数信息
+
+```
+python param_analysis.py
+```
+参数分析完后,会得到`mobilenetv2.sensi.data`文件,此文件保存了各参数的敏感度信息。  
+
+> 我们可以继续加载模型和敏感度文件,进行可视化,如下命令所示
+> ```
+> python slim_visualize.py
+> ```
+> 可视化结果出下图
+纵轴为`eval_metric_loss`(接下来第三步需要配置的参数),横轴为模型被裁剪的比例,从图中可以看到,  
+- 当`eval_metric_loss`设0.05时,模型被裁掉68.4%(剩余31.6%)  
+- 当`eval_metric_loss`设0.1时,模型被裁掉78.5%(剩余21.5%)
+
+![](./sensitivities.png)
+
+## 第三步 模型进行裁剪训练
+
+```
+python mobilenetv2_prune_train.py
+```
+此步骤的代码与第一步的代码基本一致,唯一的区别是在最后的train函数中,`mobilenetv2_prune_train.py`修改了里面的`pretrain_weights`、`save_dir`、`sensitivities_file`和`eval_metric_loss`四个参数
+
+- pretrain_weights: 在裁剪训练中,设置为之前训练好的模型
+- save_dir: 模型训练过程中,模型的保存位置
+- sensitivities_file: 在第二步中分析得到的参数敏感度信息文件
+- eval_metric_loss: 第二步中可视化的相关参数,通过此参数可相应的改变最终模型被裁剪的比例
+
+
+## 裁剪效果
+
+在本示例数据上,裁剪效果对比如下,其中预测采用**CPU,关闭MKLDNN**进行预测,预测时间不包含数据的预处理和结果的后处理。  
+可以看到在模型被裁剪掉64%后,模型精度还有上升,单张图片的预测用时减少了37%。
+
+
+| 模型 | 参数文件大小 | 预测速度 | 准确率 |
+| :--- | :----------  | :------- | :--- |
+| MobileNetV2 |    8.7M       |   0.057s  | 0.92 |
+| MobileNetV2(裁掉68%) | 2.8M | 0.036s | 0.99 |

+ 44 - 0
tutorials/slim/prune/image_classification/mobilenetv2_prune_train.py

@@ -0,0 +1,44 @@
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+from paddlex.cls import transforms
+import paddlex as pdx
+
+veg_dataset = 'https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz'
+pdx.utils.download_and_decompress(veg_dataset, path='./')
+
+train_transforms = transforms.Compose([
+    transforms.RandomCrop(crop_size=224), transforms.RandomHorizontalFlip(),
+    transforms.Normalize()
+])
+eval_transforms = transforms.Compose([
+    transforms.ResizeByShort(short_size=256),
+    transforms.CenterCrop(crop_size=224), transforms.Normalize()
+])
+
+train_dataset = pdx.datasets.ImageNet(
+    data_dir='vegetables_cls',
+    file_list='vegetables_cls/train_list.txt',
+    label_list='vegetables_cls/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.ImageNet(
+    data_dir='vegetables_cls',
+    file_list='vegetables_cls/val_list.txt',
+    label_list='vegetables_cls/labels.txt',
+    transforms=eval_transforms)
+
+model = pdx.cls.MobileNetV2(num_classes=len(train_dataset.labels))
+
+model.train(
+    num_epochs=10,
+    train_dataset=train_dataset,
+    train_batch_size=32,
+    eval_dataset=eval_dataset,
+    lr_decay_epochs=[4, 6, 8],
+    learning_rate=0.025,
+    pretrain_weights='output/mobilenetv2/best_model',
+    save_dir='output/mobilenetv2_prune',
+    sensitivities_file='./mobilenetv2.sensi.data',
+    eval_metric_loss=0.05,
+    use_vdl=True)

+ 41 - 0
tutorials/slim/prune/image_classification/mobilenetv2_train.py

@@ -0,0 +1,41 @@
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+from paddlex.cls import transforms
+import paddlex as pdx
+
+veg_dataset = 'https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz'
+pdx.utils.download_and_decompress(veg_dataset, path='./')
+
+train_transforms = transforms.Compose([
+    transforms.RandomCrop(crop_size=224), transforms.RandomHorizontalFlip(),
+    transforms.Normalize()
+])
+eval_transforms = transforms.Compose([
+    transforms.ResizeByShort(short_size=256),
+    transforms.CenterCrop(crop_size=224), transforms.Normalize()
+])
+
+train_dataset = pdx.datasets.ImageNet(
+    data_dir='vegetables_cls',
+    file_list='vegetables_cls/train_list.txt',
+    label_list='vegetables_cls/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.ImageNet(
+    data_dir='vegetables_cls',
+    file_list='vegetables_cls/val_list.txt',
+    label_list='vegetables_cls/labels.txt',
+    transforms=eval_transforms)
+
+model = pdx.cls.MobileNetV2(num_classes=len(train_dataset.labels))
+
+model.train(
+    num_epochs=10,
+    train_dataset=train_dataset,
+    train_batch_size=32,
+    eval_dataset=eval_dataset,
+    lr_decay_epochs=[4, 6, 8],
+    learning_rate=0.025,
+    save_dir='output/mobilenetv2',
+    use_vdl=True)

+ 17 - 0
tutorials/slim/prune/image_classification/params_analysis.py

@@ -0,0 +1,17 @@
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+import paddlex as pdx
+
+model = pdx.load_model('output/mobilenetv2/best_model')
+
+eval_dataset = pdx.datasets.ImageNet(
+    data_dir='vegetables_cls',
+    file_list='vegetables_cls/val_list.txt',
+    label_list='vegetables_cls/labels.txt',
+    transforms=model.eval_transforms)
+
+pdx.slim.prune.analysis(
+    model,
+    dataset=eval_dataset,
+    batch_size=16,
+    save_file='mobilenetv2.sensi.data')

BIN
tutorials/slim/prune/image_classification/sensitivities.png


+ 3 - 0
tutorials/slim/prune/image_classification/slim_visualize.py

@@ -0,0 +1,3 @@
+import paddlex as pdx
+model = pdx.load_model('output/mobilenetv2/best_model')
+pdx.slim.visualize(model, 'mobilenetv2.sensi.data', save_dir='./')

+ 50 - 0
tutorials/slim/prune/object_detection/README.md

@@ -0,0 +1,50 @@
+# 目标检测模型裁剪训练
+
+## 第一步 正常训练目标检测模型
+
+```
+python yolov3_train.py
+```
+
+在此步骤中,训练的模型会保存在`output/yolov3_mobilenetv1`目录下
+
+## 第二步 分析模型参数信息
+
+```
+python param_analysis.py
+```
+参数分析完后,会得到`yolov3.sensi.data`文件,此文件保存了各参数的敏感度信息。  
+
+> 我们可以继续加载模型和敏感度文件,进行可视化,如下命令所示
+> ```
+> python slim_visualize.py
+> ```
+> 可视化结果出下图
+纵轴为`eval_metric_loss`(接下来第三步需要配置的参数),横轴为模型被裁剪的比例,从图中可以看到,  
+- 当`eval_metric_loss`设0.05时,模型被裁掉63.1%(剩余36.9%)  
+- 当`eval_metric_loss`设0.1时,模型被裁掉68.6%(剩余31.4%)
+
+![](./sensitivities.png)
+
+## 第三步 模型进行裁剪训练
+
+```
+python yolov3_prune_train.py
+```
+此步骤的代码与第一步的代码基本一致,唯一的区别是在最后的train函数中,`yolov3_prune_train.py`修改了里面的`pretrain_weights`、`save_dir`、`sensitivities_file`和`eval_metric_loss`四个参数
+
+- pretrain_weights: 在裁剪训练中,设置为之前训练好的模型
+- save_dir: 模型训练过程中,模型的保存位置
+- sensitivities_file: 在第二步中分析得到的参数敏感度信息文件
+- eval_metric_loss: 第二步中可视化的相关参数,通过此参数可相应的改变最终模型被裁剪的比例
+
+## 裁剪效果
+
+在本示例数据上,裁剪效果对比如下,其中预测采用**CPU,关闭MKLDNN**进行预测,预测时间不包含数据的预处理和结果的后处理。  
+可以看到在模型被裁剪掉63%后,模型精度还有上升,单张图片的预测用时减少了30%。
+
+
+| 模型 | 参数文件大小 | 预测速度 | MAP |
+| :--- | :----------  | :------- | :--- |
+| YOLOv3-MobileNetV1 |    93M       |   1.045s  | 0.635 |
+| YOLOv3-MobileNetV1(裁掉63%) | 35M | 0.735s | 0.735 |

+ 14 - 0
tutorials/slim/prune/object_detection/params_analysis.py

@@ -0,0 +1,14 @@
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+import paddlex as pdx
+
+model = pdx.load_model('output/yolov3_mobilenetv1/best_model')
+
+eval_dataset = pdx.datasets.VOCDetection(
+    data_dir='insect_det',
+    file_list='insect_det/val_list.txt',
+    label_list='insect_det/labels.txt',
+    transforms=model.eval_transforms)
+
+pdx.slim.prune.analysis(
+    model, dataset=eval_dataset, batch_size=8, save_file='yolov3.sensi.data')

BIN
tutorials/slim/prune/object_detection/sensitivities.png


+ 3 - 0
tutorials/slim/prune/object_detection/slim_visualize.py

@@ -0,0 +1,3 @@
+import paddlex as pdx
+model = pdx.load_model('output/yolov3_mobilenetv1/best_model')
+pdx.slim.visualize(model, 'yolov3.sensi.data', save_dir='./')

+ 54 - 0
tutorials/slim/prune/object_detection/yolov3_prune_train.py

@@ -0,0 +1,54 @@
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+from paddlex.det import transforms
+import paddlex as pdx
+
+insect_dataset = 'https://bj.bcebos.com/paddlex/datasets/insect_det.tar.gz'
+pdx.utils.download_and_decompress(insect_dataset, path='./')
+
+train_transforms = transforms.Compose([
+    transforms.MixupImage(mixup_epoch=250),
+    transforms.RandomDistort(),
+    transforms.RandomExpand(),
+    transforms.RandomCrop(),
+    transforms.Resize(
+        target_size=608, interp='RANDOM'),
+    transforms.RandomHorizontalFlip(),
+    transforms.Normalize(),
+])
+
+eval_transforms = transforms.Compose([
+    transforms.Resize(
+        target_size=608, interp='CUBIC'),
+    transforms.Normalize(),
+])
+
+train_dataset = pdx.datasets.VOCDetection(
+    data_dir='insect_det',
+    file_list='insect_det/train_list.txt',
+    label_list='insect_det/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.VOCDetection(
+    data_dir='insect_det',
+    file_list='insect_det/val_list.txt',
+    label_list='insect_det/labels.txt',
+    transforms=eval_transforms)
+
+num_classes = len(train_dataset.labels)
+
+model = pdx.det.YOLOv3(num_classes=num_classes, backbone='MobileNetV1')
+
+model.train(
+    num_epochs=270,
+    train_dataset=train_dataset,
+    train_batch_size=8,
+    eval_dataset=eval_dataset,
+    learning_rate=0.000125,
+    lr_decay_epochs=[210, 240],
+    pretrain_weights='output/yolov3_mobilenetv1/best_model',
+    save_dir='output/yolov3_mobilenetv1_prune',
+    sensitivities_file='./yolov3.sensi.data',
+    eval_metric_loss=0.05,
+    use_vdl=True)

+ 51 - 0
tutorials/slim/prune/object_detection/yolov3_train.py

@@ -0,0 +1,51 @@
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+from paddlex.det import transforms
+import paddlex as pdx
+
+insect_dataset = 'https://bj.bcebos.com/paddlex/datasets/insect_det.tar.gz'
+pdx.utils.download_and_decompress(insect_dataset, path='./')
+
+train_transforms = transforms.Compose([
+    transforms.MixupImage(mixup_epoch=250),
+    transforms.RandomDistort(),
+    transforms.RandomExpand(),
+    transforms.RandomCrop(),
+    transforms.Resize(
+        target_size=608, interp='RANDOM'),
+    transforms.RandomHorizontalFlip(),
+    transforms.Normalize(),
+])
+
+eval_transforms = transforms.Compose([
+    transforms.Resize(
+        target_size=608, interp='CUBIC'),
+    transforms.Normalize(),
+])
+
+train_dataset = pdx.datasets.VOCDetection(
+    data_dir='insect_det',
+    file_list='insect_det/train_list.txt',
+    label_list='insect_det/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.VOCDetection(
+    data_dir='insect_det',
+    file_list='insect_det/val_list.txt',
+    label_list='insect_det/labels.txt',
+    transforms=eval_transforms)
+
+num_classes = len(train_dataset.labels)
+
+model = pdx.det.YOLOv3(num_classes=num_classes, backbone='MobileNetV1')
+
+model.train(
+    num_epochs=270,
+    train_dataset=train_dataset,
+    train_batch_size=8,
+    eval_dataset=eval_dataset,
+    learning_rate=0.000125,
+    lr_decay_epochs=[210, 240],
+    save_dir='output/yolov3_mobilenetv1',
+    use_vdl=True)

+ 51 - 0
tutorials/slim/prune/semantic_segmentation/README.md

@@ -0,0 +1,51 @@
+# 语义分割模型裁剪训练
+
+## 第一步 正常训练语义分割模型
+
+```
+python unet_train.py
+```
+
+在此步骤中,训练的模型会保存在`output/unet`目录下
+
+## 第二步 分析模型参数信息
+
+```
+python param_analysis.py
+```
+参数分析完后,会得到`unet.sensi.data`文件,此文件保存了各参数的敏感度信息。  
+
+> 我们可以继续加载模型和敏感度文件,进行可视化,如下命令所示
+> ```
+> python slim_visualize.py
+> ```
+> 可视化结果出下图
+纵轴为`eval_metric_loss`(接下来第三步需要配置的参数),横轴为模型被裁剪的比例,从图中可以看到,  
+- 当`eval_metric_loss`设0.05时,模型被裁掉64.1%(剩余35.9%)  
+- 当`eval_metric_loss`设0.1时,模型被裁掉70.9%(剩余29.1%)
+
+![](./sensitivities.png)
+
+## 第三步 模型进行裁剪训练
+
+```
+python unet_prune_train.py
+```
+此步骤的代码与第一步的代码基本一致,唯一的区别是在最后的train函数中,`unet_prune_train.py`修改了里面的`pretrain_weights`、`save_dir`、`sensitivities_file`和`eval_metric_loss`四个参数
+
+- pretrain_weights: 在裁剪训练中,设置为之前训练好的模型
+- save_dir: 模型训练过程中,模型的保存位置
+- sensitivities_file: 在第二步中分析得到的参数敏感度信息文件
+- eval_metric_loss: 第二步中可视化的相关参数,通过此参数可相应的改变最终模型被裁剪的比例
+
+## 裁剪效果
+
+在本示例数据上,裁剪效果对比如下,其中预测采用**CPU,关闭MKLDNN**进行预测,预测时间不包含数据的预处理和结果的后处理。  
+可以看到在模型被裁剪掉64%后,模型精度基本保持不变,单张图片的预测用时降低了近50%。
+
+> 此处仅做对比,使用了UNet模型,实际上在低性能设备上,更建议使用deeplab-mobilenet或fastscnn等轻量级分割模型。
+
+| 模型 | 参数文件大小 | 预测速度 | mIOU |
+| :--- | :----------  | :------- | :--- |
+| UNet |    52M       |   9.85s  | 0.915 |
+| UNet(裁掉64%) | 19M | 4.80s | 0.911 |

+ 14 - 0
tutorials/slim/prune/semantic_segmentation/params_analysis.py

@@ -0,0 +1,14 @@
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+import paddlex as pdx
+
+model = pdx.load_model('output/unet/best_model')
+
+eval_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/val_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=model.eval_transforms)
+
+pdx.slim.prune.analysis(
+    model, dataset=eval_dataset, batch_size=4, save_file='unet.sensi.data')

BIN
tutorials/slim/prune/semantic_segmentation/sensitivities.png


+ 3 - 0
tutorials/slim/prune/semantic_segmentation/slim_visualize.py

@@ -0,0 +1,3 @@
+import paddlex as pdx
+model = pdx.load_model('output/unet/best_model')
+pdx.slim.visualize(model, 'unet.sensi.data', save_dir='./')

+ 46 - 0
tutorials/slim/prune/semantic_segmentation/unet_prune_train.py

@@ -0,0 +1,46 @@
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+import paddlex as pdx
+from paddlex.seg import transforms
+
+optic_dataset = 'https://bj.bcebos.com/paddlex/datasets/optic_disc_seg.tar.gz'
+pdx.utils.download_and_decompress(optic_dataset, path='./')
+
+train_transforms = transforms.Compose([
+    transforms.RandomHorizontalFlip(), transforms.ResizeRangeScaling(),
+    transforms.RandomPaddingCrop(crop_size=512), transforms.Normalize()
+])
+
+eval_transforms = transforms.Compose([
+    transforms.ResizeByLong(long_size=512), transforms.Padding(target_size=512),
+    transforms.Normalize()
+])
+
+train_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/train_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/val_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=eval_transforms)
+
+num_classes = len(train_dataset.labels)
+
+model = pdx.seg.UNet(num_classes=num_classes)
+
+model.train(
+    num_epochs=20,
+    train_dataset=train_dataset,
+    train_batch_size=4,
+    eval_dataset=eval_dataset,
+    learning_rate=0.01,
+    pretrain_weights='output/unet/best_model',
+    save_dir='output/unet_prune',
+    sensitivities_file='./unet.sensi.data',
+    eval_metric_loss=0.05,
+    use_vdl=True)

+ 43 - 0
tutorials/slim/prune/semantic_segmentation/unet_train.py

@@ -0,0 +1,43 @@
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+import paddlex as pdx
+from paddlex.seg import transforms
+
+optic_dataset = 'https://bj.bcebos.com/paddlex/datasets/optic_disc_seg.tar.gz'
+pdx.utils.download_and_decompress(optic_dataset, path='./')
+
+train_transforms = transforms.Compose([
+    transforms.RandomHorizontalFlip(), transforms.ResizeRangeScaling(),
+    transforms.RandomPaddingCrop(crop_size=512), transforms.Normalize()
+])
+
+eval_transforms = transforms.Compose([
+    transforms.ResizeByLong(long_size=512), transforms.Padding(target_size=512),
+    transforms.Normalize()
+])
+
+train_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/train_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.SegDataset(
+    data_dir='optic_disc_seg',
+    file_list='optic_disc_seg/val_list.txt',
+    label_list='optic_disc_seg/labels.txt',
+    transforms=eval_transforms)
+
+num_classes = len(train_dataset.labels)
+
+model = pdx.seg.UNet(num_classes=num_classes)
+
+model.train(
+    num_epochs=20,
+    train_dataset=train_dataset,
+    train_batch_size=4,
+    eval_dataset=eval_dataset,
+    learning_rate=0.01,
+    save_dir='output/unet',
+    use_vdl=True)

+ 16 - 0
tutorials/slim/quant/image_classification/README.md

@@ -0,0 +1,16 @@
+# 图像分类模型量化
+
+在此目录下提供了MobileNetV2模型的量化示例,执行如下命令即可
+
+## 第一步 量化模型
+```
+python mobilenetv2_quant.py
+```
+执行代码会自动下载模型和数据集
+
+## 第二步 导出为PaddleLite模型
+
+```
+python paddlelite_export.py
+```
+执行此脚本前,需安装paddlelite,在python环境中`pip install paddlelite`即可

+ 31 - 0
tutorials/slim/quant/image_classification/mobilenetv2_quant.py

@@ -0,0 +1,31 @@
+import paddlex as pdx
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+# 下载训练好的模型
+url = 'https://bj.bcebos.com/paddlex/models/mobilenetv2_vegetables.tar.gz'
+pdx.utils.download_and_decompress(url, path='.')
+
+# 下载相应的训练数据集
+url = 'https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz'
+pdx.utils.download_and_decompress(url, path='.')
+
+# 加载模型
+model = pdx.load_model('mobilenetv2_vegetables')
+
+# 将正常模型导出为部署格式,用于对比
+import time
+for i in range(60):
+    print('save', i)
+    time.sleep(1)
+    model.export_inference_model('server_mobilenet')
+
+# 加载数据集用于量化
+dataset = pdx.datasets.ImageNet(
+                data_dir='vegetables_cls',
+                file_list='vegetables_cls/train_list.txt',
+                label_list='vegetables_cls/labels.txt',
+                transforms=model.test_transforms)
+
+# 开始量化
+pdx.slim.export_quant_model(model, dataset, save_dir='./quant_mobilenet', cache_dir='./tmp')

+ 18 - 0
tutorials/slim/quant/image_classification/paddlelite_export.py

@@ -0,0 +1,18 @@
+# 需先安装paddlelite
+import paddlelite.lite as lite
+
+model_filename = 'server_mobilenet/__model__'
+params_filename = 'server_mobilenet/__params__'
+export_filename = 'mobilenetv2'
+
+opt = lite.Opt()
+# 将正常模型导出为Lite模型
+opt.run_optimize("", model_filename, params_filename, 'naive_buffer', 'arm', export_filename) 
+
+
+quant_model_filename = 'quant_mobilenet/__model__'
+quant_params_filename = 'quant_mobilenet/__params__'
+quant_export_filename = 'mobilenetv2_quant'
+
+# 将量化模型导出为Lite模型
+opt.run_optimize("", quant_model_filename, quant_params_filename, 'naive_buffer', 'arm', quant_export_filename)