diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7aed9143a1ac7f5fb7c8768588e7354593a55a62..5a750a0aef715e1c89d6dfe7de51f41b8918950f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,6 +14,7 @@ - id: check-symlinks - id: check-added-large-files - repo: local + hooks: - id: copyright_checker name: copyright_checker @@ -21,3 +22,19 @@ language: system files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto|py)$ exclude: (?!.*third_party)^.*$ + + hooks: + - id: clang-format-with-version-check + name: clang-format + description: Format files with ClangFormat. + entry: bash ./tools/codestyle/clang_format.hook -i + language: system + files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto)$ + + hooks: + - id: cpplint-cpp-source + name: cpplint + description: Check C++ code style using cpplint.py. + entry: bash cpplint_pre_commit.hook + language: system + files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx)$ diff --git a/README.md b/README.md index a27e3ae5e61667618daf9d83b51ce6968fd02e51..4105c32ad8ec0462b16ea365937bf348bc45b903 100644 --- a/README.md +++ b/README.md @@ -11,18 +11,18 @@ PaddleX是基于飞桨核心框架、开发套件和工具组件的深度学习 ## 特点 -- **全流程打通** - - 数据准备:支持LabelMe,精灵标注等主流数据标注工具协议,同时无缝集成[EasyData智能数据服务平台](https://ai.baidu.com/easydata/), 助力开发者高效获取AI开发所需高质量数据。 - - 模型训练:基于飞桨核心框架集成[PaddleClas](https://github.com/PaddlePaddle/PaddleClas), [PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection), [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg)视觉开发套件,[VisualDL](https://github.com/PaddlePaddle/VisualDL)可视化分析组件,高效完成模型训练。 - - 多端部署:内置[PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim)模型压缩工具和AES模型加密SDK,结合Paddle Inference和[Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite)便捷完成高性能且可靠的多端部署。 +- **全流程打通** + - **数据准备**:支持[EasyData智能数据服务平台](https://ai.baidu.com/easydata/)数据协议,通过平台便捷完成智能标注,低质数据清洗工作, 同时兼容主流标注工具协议, 助力开发者更快完成数据准备工作。 + - **模型训练**:集成[PaddleClas](https://github.com/PaddlePaddle/PaddleClas), [PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection), [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg)视觉开发套件,丰富的高质量预训练模型,更快实现工业级模型效果。 + - **模型调优**:内置模型可解释性模块、[VisualDL](https://github.com/PaddlePaddle/VisualDL)可视化分析组件, 提供丰富的信息更好地理解模型,优化模型。 + - **多端安全部署**:内置[PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim)模型压缩工具和**模型加密部署模块**,结合Paddle Inference或[Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite)便捷完成高性能的多端安全部署。 -- **融合产业实践** +- **融合产业实践** - 精选飞桨产业实践的成熟模型结构,开放案例实践教程,加速开发者产业落地。 - - 通过[PaddleHub](https://github.com/PaddlePaddle/Paddle)内置丰富的飞桨高质量预训练模型,助力开发者高效实现飞桨Master模式。 - **易用易集成** - - PadldeX提供简洁易用的全流程API,几行代码即可实现上百种数据增强、模型可解释性、C++模型部署等功能。 - - 提供以PaddleX API为核心集成的跨平台GUI界面,降低深度学习全流程应用门槛。 + - 统一易用的全流程API,5步完成模型训练,10行代码实现Python/C++高性能部署。 + - 提供以PaddleX为核心集成的跨平台可视化工具PaddleX-GUI,快速体验飞桨深度学习全流程。 ## 安装 @@ -31,7 +31,7 @@ PaddleX提供两种开发模式,满足不同场景和用户需求: - **Python开发模式:** 通过Python API方式完成全流程使用或集成,该模型提供全面、灵活、开放的深度学习功能,有更高的定制化空间。 -- **GUI开发模式:** 以PaddleX API为核心集成的跨平台GUI客户端,支持`Python开发模式`下的常用功能,以更低门槛的方式快速完成产业验证的模型训练。 +- **Padlde-GUI模式:** PaddleX-GUI支持`Python开发模式`下的常用功能,以更低门槛的方式快速完成产业验证的模型训练。 开发者可根据自身需要按需选择不同的模式进行安装使用。 @@ -47,21 +47,21 @@ PaddleX提供两种开发模式,满足不同场景和用户需求: ``` pip install paddlex -i https://mirror.baidu.com/pypi/simple ``` +安装的相关问题参考[PaddleX安装](https://paddlex.readthedocs.io/zh_CN/latest/install.html) -### GUI开发模式安装 +### PaddleX-GUI安装 进入PaddleX官网[下载使用](https://www.paddlepaddle.org.cn/paddle/paddlex),申请下载绿色安装包,开箱即用。 -GUI模式的使用教程可参考[PaddleX GUI模式使用教程](https://paddlex.readthedocs.io/zh_CN/latest/paddlex_gui/index.html) +Paddle-GUI的使用教程可参考[PaddleX-GUI模式使用教程](https://paddlex.readthedocs.io/zh_CN/latest/paddlex_gui/index.html) -## 使用文档 +## 使用文档 推荐访问[PaddleX在线使用文档](https://paddlex.readthedocs.io/zh_CN/latest/index.html),快速查阅读使用教程和API文档说明。 -- [10分钟快速上手](https://paddlex.readthedocs.io/zh_CN/latest/quick_start.html) -- [PaddleX模型训练](https://paddlex.readthedocs.io/zh_CN/latest/tutorials/train/index.html#id1) -- [PaddleX模型压缩](https://paddlex.readthedocs.io/zh_CN/latest/slim/index.html#id1) -- [PaddleX模型库](https://paddlex.readthedocs.io/zh_CN/latest/model_zoo.html#id1) -- [PaddleX多端部署](docs/deploy.md) +- [10分钟快速上手使用](https://paddlex.readthedocs.io/zh_CN/latest/quick_start.html) +- [PaddleX全流程开发教程](https://paddlex.readthedocs.io/zh_CN/latest/tutorials/index.html) +- [PaddleX视觉方案介绍](https://paddlex.readthedocs.io/zh_CN/latest/cv_solutions.html) +- [PaddleX API参考文档](https://paddlex.readthedocs.io/zh_CN/latest/apis/index.html) ## 在线教程 @@ -74,12 +74,16 @@ GUI模式的使用教程可参考[PaddleX GUI模式使用教程](https://paddlex ## 交流与反馈 - 项目官网: https://www.paddlepaddle.org.cn/paddle/paddlex -- PaddleX用户QQ群: 1045148026 (手机QQ扫描如下二维码快速加入) +- PaddleX用户交流群: 1045148026 (手机QQ扫描如下二维码快速加入) QQGroup ## FAQ ## 更新日志 +* 2020.05.20 + + **`v1.0.0`** + * 正式版本发布。 ## 贡献代码 diff --git a/deploy/README.md b/deploy/README.md index 1a9efe9d8ef9810592bd05e2e9fbd06842303c49..515b1a16878efe8b1d18622aa811a335a285cdac 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -1,6 +1,7 @@ -# 模型部署 +# 多端安全部署 -本目录为PaddleX模型部署代码, 编译和使用的教程参考: +本目录为PaddleX模型部署代码,编译和使用教程参考: -- [C++部署文档](../docs/tutorials/deploy/deploy.md#C部署) -- [OpenVINO部署文档](../docs/tutorials/deploy/deploy.md#openvino部署) +- [服务端部署(支持Python部署、C++部署、模型加密部署)](../docs/tutorials/deploy/deploy_server/) +- [OpenVINO部署](../docs/tutorials/deploy/deploy_openvino.md) +- [移动端部署](../docs/tutorials/deploy/deploy_lite.md) diff --git a/deploy/lite/export_lite.py b/deploy/lite/export_lite.py new file mode 100644 index 0000000000000000000000000000000000000000..b56aee9ee803b943473178b67f38c0f8d41a00da --- /dev/null +++ b/deploy/lite/export_lite.py @@ -0,0 +1,48 @@ +#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +#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. + +import paddlelite.lite as lite +import os +import argparse + + +def export_lite(): + opt = lite.Opt() + model_file = os.path.join(FLAGS.model_path, '__model__') + params_file = os.path.join(FLAGS.model_path, '__params__') + opt.run_optimize("", model_file, params_file, FLAGS.place, FLAGS.save_dir) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--model_path", + type=str, + default="", + help="model path.", + required=True) + parser.add_argument( + "--place", + type=str, + default="arm", + help="preprocess config path.", + required=True) + parser.add_argument( + "--save_dir", + type=str, + default="paddlex.onnx", + help="Directory for storing the output visualization files.", + required=True) + FLAGS = parser.parse_args() + export_lite() diff --git a/docs/FAQ.md b/docs/FAQ.md index d96e35c886cf582ee57b699aa2baf549e0d56a09..8da14f32e428f868f637a395223855aa66371bbf 100755 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -1,22 +1,25 @@ # 常见问题 -## 1. 训练过程因显存不够出错 +## 1. 训练参数如何调整 +> 参考[参数调整文档](appendix/parameters.md) + +## 2. 训练过程因显存不够出错 > 通过使用在终端`nvidia-smi`命令,查看GPU是否被其它任务占用,尝试清除其它任务; > 调低训练时的`batch_size`参数,从而降低显存的要求,注意需等比例调低`learning_rate`等参数; > 选用更小的模型或backbone。 -## 2. 是否有更小的模型,适用于更低配置的设备上运行 +## 3. 是否有更小的模型,适用于更低配置的设备上运行 > 可以使用模型裁剪,参考文档[模型裁剪使用教程](slim/prune.md),通过调整裁剪参数,可以控制模型裁剪后的大小,在实际实验中,如VOC检测数据,使用yolov3-mobilenet,原模型大小为XXM,裁剪后为XX M,精度基本保持不变 -## 3. 如何配置训练时GPU的卡数 +## 4. 如何配置训练时GPU的卡数 > 通过在终端export环境变量,或在Python代码中设置,可参考文档[CPU/多卡GPU训练](gpu_configure.md) -## 4. 想将之前训练的模型参数上继续训练 +## 5. 想将之前训练的模型参数上继续训练 > 在训练调用`train`接口时,将`pretrain_weights`设为之前的模型保存路径即可 -## 5. PaddleX保存的模型分为正常训练过程中产生、裁剪训练产生、导出为部署模型和量化保存这么多种,有什么差别,怎么区分 +## 6. PaddleX保存的模型分为正常训练过程中产生、裁剪训练产生、导出为部署模型和量化保存这么多种,有什么差别,怎么区分 **不同模型的功能差异** @@ -40,20 +43,20 @@ >> 通过模型目录下model.yml文件中`status`字段来区别不同的模型类型, 'Normal'、'Prune'、'Infer'、'Quant'分别表示正常模型训练保存、裁剪训练保存、导出的部署模型、量化保存模型 -## 6. 模型训练需要太久时间,或者训练速度太慢,怎么提速 +## 7. 模型训练需要太久时间,或者训练速度太慢,怎么提速 > 1.模型训练速度与用户选定的模型大小,和设定的`batch_size`相关,模型大小可直接参考[模型库](model_zoo.md)中的指标,一般而言,模型越大,训练速度就越慢; > 2.在模型速度之外,模型训练完成所需的时间又与用户设定的`num_epochs`迭代轮数相关,用户可以通过观察模型在验证集上的指标来决定是否提示结束掉训练进程(训练时设定`save_interval_epochs`参数,训练过程会每间隔`save_interval_epochs`轮数在验证集上计算指标,并保存模型); -## 7. 如何设定迭代的轮数 +## 8. 如何设定迭代的轮数 > 1. 用户自行训练时,如不确定迭代的轮数,可以将轮数设高一些,同时注意设置`save_interval_epochs`,这样模型迭代每间隔相应轮数就会在验证集上进行评估和保存,可以根据不同轮数模型在验证集上的评估指标,判断模型是否已经收敛,若模型已收敛,可以自行结束训练进程 > -## 8. 只有CPU,没有GPU,如何提升训练速度 +## 9. 只有CPU,没有GPU,如何提升训练速度 > 当没有GPU时,可以根据自己的CPU配置,选择是否使用多CPU进行训练,具体配置方式可以参考文档[多卡CPU/GPU训练](gpu_configure.md) > -## 9. 电脑不能联网,训练时因为下载预训练模型失败,如何解决 +## 10. 电脑不能联网,训练时因为下载预训练模型失败,如何解决 > 可以预先通过其它方式准备好预训练模型,然后训练时自定义`pretrain_weights`即可,可参考文档[无联网模型训练](how_to_offline_run.md) -## 10. 每次训练新的模型,都需要重新下载预训练模型,怎样可以下载一次就搞定 +## 11. 每次训练新的模型,都需要重新下载预训练模型,怎样可以下载一次就搞定 > 1.可以按照9的方式来解决这个问题 > 2.每次训练前都设定`paddlex.pretrain_dir`路径,如设定`paddlex.pretrain_dir='/usrname/paddlex`,如此下载完的预训练模型会存放至`/usrname/paddlex`目录下,而已经下载在该目录的模型也不会再次重复下载 diff --git a/docs/apis/visualize.md b/docs/apis/visualize.md index 8a253fc04310f43b8e424729e7d75f2712e8dc19..069913274580f1e8bd5fdb5ee6e6e642c977b3ce 100755 --- a/docs/apis/visualize.md +++ b/docs/apis/visualize.md @@ -114,27 +114,54 @@ pdx.slim.visualize(model, 'mobilenetv2.sensitivities', save_dir='./') # 可视化结果保存在./sensitivities.png ``` -## 可解释性结果可视化 +## LIME可解释性结果可视化 ``` -paddlex.interpret.visualize(img_file, - model, - dataset=None, - algo='lime', - num_samples=3000, - batch_size=50, - save_dir='./') +paddlex.interpret.lime(img_file, + model, + num_samples=3000, + batch_size=50, + save_dir='./') ``` -将模型预测结果的可解释性可视化,目前只支持分类模型。 +使用LIME算法将模型预测结果的可解释性可视化。 +LIME表示与模型无关的局部可解释性,可以解释任何模型。LIME的思想是以输入样本为中心,在其附近的空间中进行随机采样,每个采样通过原模型得到新的输出,这样得到一系列的输入和对应的输出,LIME用一个简单的、可解释的模型(比如线性回归模型)来拟合这个映射关系,得到每个输入维度的权重,以此来解释模型。 + +**注意:** 可解释性结果可视化目前只支持分类模型。 ### 参数 >* **img_file** (str): 预测图像路径。 >* **model** (paddlex.cv.models): paddlex中的模型。 ->* **dataset** (paddlex.datasets): 数据集读取器,默认为None。 ->* **algo** (str): 可解释性方式,当前可选'lime'和'normlime'。 >* **num_samples** (int): LIME用于学习线性模型的采样数,默认为3000。 >* **batch_size** (int): 预测数据batch大小,默认为50。 >* **save_dir** (str): 可解释性可视化结果(保存为png格式文件)和中间文件存储路径。 ### 使用示例 -> 对预测可解释性结果可视化的过程可参见[代码](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/interpret/interpret.py)。 +> 对预测可解释性结果可视化的过程可参见[代码](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/interpret/lime.py)。 + + +## NormLIME可解释性结果可视化 +``` +paddlex.interpret.normlime(img_file, + model, + dataset=None, + num_samples=3000, + batch_size=50, + save_dir='./') +``` +使用NormLIME算法将模型预测结果的可解释性可视化。 +NormLIME是利用一定数量的样本来出一个全局的解释。NormLIME会提前计算一定数量的测试样本的LIME结果,然后对相同的特征进行权重的归一化,这样来得到一个全局的输入和输出的关系。 + +**注意:** 可解释性结果可视化目前只支持分类模型。 + +### 参数 +>* **img_file** (str): 预测图像路径。 +>* **model** (paddlex.cv.models): paddlex中的模型。 +>* **dataset** (paddlex.datasets): 数据集读取器,默认为None。 +>* **num_samples** (int): LIME用于学习线性模型的采样数,默认为3000。 +>* **batch_size** (int): 预测数据batch大小,默认为50。 +>* **save_dir** (str): 可解释性可视化结果(保存为png格式文件)和中间文件存储路径。 + +**注意:** dataset`读取的是一个数据集,该数据集不宜过大,否则计算时间会较长,但应包含所有类别的数据。 +### 使用示例 +> 对预测可解释性结果可视化的过程可参见[代码](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/interpret/normlime.py)。 + diff --git a/docs/appendix/index.rst b/docs/appendix/index.rst index b914b5b00337cbf3f5a4386b176fa2968829b568..c3198420d394372a359eba151fd58812d635c58a 100755 --- a/docs/appendix/index.rst +++ b/docs/appendix/index.rst @@ -8,13 +8,7 @@ model_zoo.md metrics.md + parameters.md how_to_convert_dataset.md datasets.md - -* PaddleX版本: v0.1.7 -* 项目官网: http://www.paddlepaddle.org.cn/paddle/paddlex -* 项目GitHub: https://github.com/PaddlePaddle/PaddleX/tree/develop -* 官方QQ用户群: 1045148026 -* GitHub Issue反馈: http://www.github.com/PaddlePaddle/PaddleX/issues - diff --git a/docs/appendix/parameters.md b/docs/appendix/parameters.md new file mode 100644 index 0000000000000000000000000000000000000000..732535dd08f2cc16e16e14fe2a45cd655706dc4c --- /dev/null +++ b/docs/appendix/parameters.md @@ -0,0 +1,25 @@ +# 训练参数调整 + +PaddleX所有训练接口中,内置的参数均为根据单GPU卡相应batch_size下的较优参数,用户在自己的数据上训练模型,涉及到参数调整时,如无太多参数调优经验,则可参考如下方式 + +## 1.Epoch数的调整 +Epoch数是模型训练过程,迭代的轮数,用户可以设置较大的数值,根据模型迭代过程在验证集上的指标表现,来判断模型是否收敛,进而提前终止训练。此外也可以使用`train`接口中的`early_stop`策略,模型在训练过程会自动判断模型是否收敛自动中止。 + +## 2.Batch Size的调整 +Batch Size指模型在训练过程中,一次性处理的样本数量, 如若使用多卡训练, batch_size会均分到各张卡上(因此需要让batch size整除卡数)。这个参数跟机器的显存/内存高度相关,`batch_size`越高,所消耗的显存/内存就越高。PaddleX在各个`train`接口中均配置了默认的batch size,如若用户调整batch size,则也注意需要对应调整其它参数,如下表所示展示YOLOv3在训练时的参数配置 + +| 参数 | 默认值 | 调整比例 | 示例 | +|:---------------- | :------------ | :------------------ | :------------ | +| train_batch_size | 8 | 调整为 8*alpha | 16 | +| learning_rate | 1.0/8000 | 调整为 alpha/8000 | 2.0/8000 | +| warmup_steps | 1000 | 调整为 1000/alpha
(该参数也可以自行根据数据情况调整) | 500 | +| lr_decay_epochs | [213, 240] | 不变 | [213, 240] | + + +更多训练接口可以参考 +- [分类模型-train](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/classification.html#train) +- [目标检测检测FasterRCNN-train](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/detection.html#id2) +- [目标检测YOLOv3-train](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/detection.html#train) +- [实例分割MaskRCNN-train](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/instance_segmentation.html#train) +- [语义分割DeepLabv3p-train](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/semantic_segmentation.html#train) +- [语义分割UNet](https://paddlex.readthedocs.io/zh_CN/latest/apis/models/semantic_segmentation.html#id2) diff --git a/docs/cv_solutions.md b/docs/cv_solutions.md index 5bf084870ba3cbf581c89657daeaff0bebb2d66e..cb96c2d9e71ac6e98ee036364b8700ec9656411a 100755 --- a/docs/cv_solutions.md +++ b/docs/cv_solutions.md @@ -11,10 +11,10 @@ PaddleX目前提供了4种视觉任务解决方案,分别为图像分类、目 | 模型 | 模型大小 | GPU预测速度 | CPU预测速度 | ARM芯片预测速度 | 准确率 | 备注 | | :--------- | :------ | :---------- | :-----------| :------------- | :----- | :--- | -| MobileNetV3_small_ssld | 12M | ? | ? | ? | 71.3% |适用于移动端场景 | -| MobileNetV3_large_ssld | 21M | ? | ? | ? | 79.0% | 适用于移动端/服务端场景 | -| ResNet50_vd_ssld | 102.8MB | ? | ? | ? | 82.4% | 适用于服务端场景 | -| ResNet101_vd_ssld | 179.2MB | ? | ? | ? |83.7% | 适用于服务端场景 | +| MobileNetV3_small_ssld | 12M | - | - | - | 71.3% |适用于移动端场景 | +| MobileNetV3_large_ssld | 21M | - | - | - | 79.0% | 适用于移动端/服务端场景 | +| ResNet50_vd_ssld | 102.8MB | - | - | - | 82.4% | 适用于服务端场景 | +| ResNet101_vd_ssld | 179.2MB | - | - | - |83.7% | 适用于服务端场景 | 除上述模型外,PaddleX还支持近20种图像分类模型,模型列表可参考[PaddleX模型库](../appendix/model_zoo.md) @@ -28,10 +28,10 @@ PaddleX目前提供了4种视觉任务解决方案,分别为图像分类、目 | 模型 | 模型大小 | GPU预测速度 | CPU预测速度 |ARM芯片预测速度 | BoxMAP | 备注 | | :------- | :------- | :--------- | :---------- | :------------- | :----- | :--- | -| YOLOv3-MobileNetV1 | 101.2M | ? | ? | ? | 29.3 | | -| YOLOv3-MobileNetV3 | 94.6M | ? | ? | ? | 31.6 | | -| YOLOv3-ResNet34 | 169.7M | ? | ? | ? | 36.2 | | -| YOLOv3-DarkNet53 | 252.4 | ? | ? | ? | 38.9 | | +| YOLOv3-MobileNetV1 | 101.2M | - | - | - | 29.3 | | +| YOLOv3-MobileNetV3 | 94.6M | - | - | - | 31.6 | | +| YOLOv3-ResNet34 | 169.7M | - | - | - | 36.2 | | +| YOLOv3-DarkNet53 | 252.4 | - | - | - | 38.9 | | 除YOLOv3模型外,PaddleX同时也支持FasterRCNN模型,支持FPN结构和5种backbone网络,详情可参考[PaddleX模型库](../appendix/model_zoo.md) @@ -44,8 +44,8 @@ PaddleX目前提供了实例分割MaskRCNN模型,支持5种不同的backbone | 模型 | 模型大小 | GPU预测速度 | CPU预测速度 | ARM芯片预测速度 | BoxMAP | SegMAP | 备注 | | :---- | :------- | :---------- | :---------- | :------------- | :----- | :----- | :--- | -| MaskRCNN-ResNet50_vd-FPN | 185.5M | ? | ? | ? | 39.8 | 35.4 | | -| MaskRCNN-ResNet101_vd-FPN | 268.6M | ? | ? | ? | 41.4 | 36.8 | | +| MaskRCNN-ResNet50_vd-FPN | 185.5M | - | - | - | 39.8 | 35.4 | | +| MaskRCNN-ResNet101_vd-FPN | 268.6M | - | - | - | 41.4 | 36.8 | | ## 语义分割 @@ -57,7 +57,7 @@ PaddleX目前提供了实例分割MaskRCNN模型,支持5种不同的backbone | 模型 | 模型大小 | GPU预测速度 | CPU预测速度 | ARM芯片预测速度 | mIOU | 备注 | | :---- | :------- | :---------- | :---------- | :------------- | :----- | :----- | -| DeepLabv3p-MobileNetV2_x0.25 | | ? | ? | ? | ? | ? | -| DeepLabv3p-MobileNetV2_x1.0 | | ? | ? | ? | ? | ? | -| DeepLabv3p-Xception65 | | ? | ? | ? | ? | ? | -| UNet | | ? | ? | ? | ? | ? | +| DeepLabv3p-MobileNetV2_x0.25 | | - | - | - | - | - | +| DeepLabv3p-MobileNetV2_x1.0 | | - | - | - | - | - | +| DeepLabv3p-Xception65 | | - | - | - | - | - | +| UNet | | - | - | - | - | - | diff --git a/docs/index.rst b/docs/index.rst index 3e4c80103288de087952261e623295041e96770a..c3276f301bcd54846ba3639441572a26a5dd0f6a 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,19 +3,18 @@ PaddleX是基于飞桨核心框架、开发套件和工具组件的深度学习全流程开发工具。具备 **全流程打通** 、**融合产业实践** 、**易用易集成** 三大特点。 - 全流程打通 - | - **数据准备**: 支持LabelMe,精灵标注等主流数据标注工具协议,同时无缝集成 `EasyData智能数据服务平台 `_ ,助力开发者高效获取AI开发所需高质量数据。 - | - **模型训练**: 基于飞桨核心框架集成 `PaddleClas `_ ,`PaddleDetection `_ ,`PaddleSeg `_ 视觉开发套件 ,`VisualDL `_ 可视化分析组件,高效完成模型训练。 - | _ **多端部署**: 内置 `PaddleSlim `_ 模型压缩工具和AES模型加密SDK,结合Paddle Inference和 `Paddle Lite `_ 便捷完成高性能且可靠的多端部署。 + | - **数据准备**: 支持 `EasyData智能数据服务平台数据协议 `_ ,通过平台便捷完成智能标注,低质数据清洗工作;同时兼容主流标注工具协议, 助力开发者更快完成数据准备工作。 + | - **模型训练**: 基于飞桨核心框架集成 `PaddleClas `_ ,`PaddleDetection `_ ,`PaddleSeg `_ 视觉开发套件,丰富的高质量预训练模型,更快实现工业级模型训练。 + | - **模型调优**: 内置模型可解释性模块、`VisualDL `_ 可视化分析组件,提供丰富的信息更好地理解模型,优化模型。 + | - **多端安全部署**: 内置 `PaddleSlim `_ 模型压缩工具和AES模型加密SDK,结合Paddle Inference和 `Paddle Lite `_ 便捷完成高性能的多端安全部署。 融合产业实践 | - 精选飞桨产业实践的成熟模型结构,开放案例实践教程,加速开发者产业落地。 - | - 通过 `PaddleHub `_ 内置丰富的飞桨高质量预训练模型,助力开发者高效实现飞桨Master模式。 易用易集成 - | - PadldeX提供简洁易用的全流程API,几行代码即可实现上百种数据增强、模型可解释性、C++模型部署等功能。 - | - 提供以PaddleX API为核心集成的跨平台GUI界面,降低深度学习全流程应用门槛。 + | - 统一易用的全流程API,5步完成模型训练,10行代码实现Python/C++高性能部署。 + | - 提供以PaddleX为核心集成的跨平台可视化开发工具PaddleX-GUI,更低门槛快速体验飞桨深度学习全流程。 .. toctree:: :maxdepth: 2 @@ -31,7 +30,7 @@ PaddleX是基于飞桨核心框架、开发套件和工具组件的深度学习 FAQ.md appendix/index.rst -* PaddleX版本: v0.1.7 +* PaddleX版本: v1.0.0 * 项目官网: http://www.paddlepaddle.org.cn/paddle/paddlex * 项目GitHub: https://github.com/PaddlePaddle/PaddleX/tree/develop * 官方QQ用户群: 1045148026 diff --git a/docs/test.cpp b/docs/test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f9bc680b74ee4a33ba65236d944592a832f835d --- /dev/null +++ b/docs/test.cpp @@ -0,0 +1,20 @@ +// Copyright (c) 2020 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. + +#include + +int main() { + std::cout << "haha" << std::endl; + return 0; +} diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md deleted file mode 100755 index b2453e23ff6f086bf6229cf5599ab8f5a648ac56..0000000000000000000000000000000000000000 --- a/docs/tutorials/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# PaddleX使用教程 - -- [模型训练](./train) -- [模型裁剪](./compress) diff --git a/docs/tutorials/deploy/deploy_lite.md b/docs/tutorials/deploy/deploy_lite.md new file mode 100644 index 0000000000000000000000000000000000000000..392e945dea2465ca4f6f40f2a131f7cad19db03a --- /dev/null +++ b/docs/tutorials/deploy/deploy_lite.md @@ -0,0 +1,23 @@ +# 移动端部署 + +step 1: 安装PaddleLite + +``` +pip install paddlelite +``` + +step 2: 将PaddleX模型导出为inference模型 + +参考[导出inference模型](deploy_server/deploy_python.html#inference)将模型导出为inference格式模型。 + +step 3: 将inference模型转换成PaddleLite模型 + +``` +python /path/to/PaddleX/deploy/lite/export_lite.py --model_path /path/to/inference_model --save_dir /path/to/onnx_model +``` + +`--model_path`用于指定inference模型的路径,`--save_dir`用于指定Lite模型的保存路径。 + +step 4: 预测 + +Lite模型预测正在集成中,即将开源... diff --git a/docs/tutorials/deploy/depoly_openvino.md b/docs/tutorials/deploy/deploy_openvino.md similarity index 65% rename from docs/tutorials/deploy/depoly_openvino.md rename to docs/tutorials/deploy/deploy_openvino.md index 30a0c3fee0a8a1052a601b0dddea3d7886a1e063..7011ca2cd78a366cb5aaebbe8e95fc18101a6e4b 100644 --- a/docs/tutorials/deploy/depoly_openvino.md +++ b/docs/tutorials/deploy/deploy_openvino.md @@ -1,16 +1,45 @@ -# OpenVINO 分类demo编译 - -## 说明 +# OpenVINO部署 + +## 方案简介 +OpenVINO部署方案位于目录`PaddleX/deploy/openvino/`下,且独立于PaddleX其他模块,该方案目前支持在 **Linux** 完成编译和部署运行。 + +PaddleX到OpenVINO的部署流程如下: + +> PaddleX --> ONNX --> OpenVINO IR --> OpenVINO Inference Engine + +|目前支持OpenVINO部署的PaddleX模型| +|-----| +|ResNet18| +|ResNet34| +|ResNet50| +|ResNet101| +|ResNet50_vd| +|ResNet101_vd| +|ResNet50_vd_ssld| +|ResNet101_vd_ssld| +|DarkNet53| +|MobileNetV1| +|MobileNetV2| +|DenseNet121| +|DenseNet161| +|DenseNet201| + +## 部署流程 + +### 说明 本文档在 `Ubuntu`使用`GCC 4.8.5` 进行了验证,如果需要使用更多G++版本和平台的OpenVino编译,请参考: [OpenVINO](https://github.com/openvinotoolkit/openvino/blob/2020/build-instruction.md)。 -## 验证环境 + +### 验证环境 * Ubuntu* 16.04 (64-bit) with GCC* 4.8.5 * CMake 3.12 * Python 2.7 or higher 请确保系统已经安装好上述基本软件,**下面所有示例以工作目录 `/root/projects/`演示**。 - `git clone https://github.com/PaddlePaddle/PaddleX.git` +``` + git clone https://github.com/PaddlePaddle/PaddleX.git +``` **说明**:其中`C++`预测代码在`/root/projects/PaddleX/deploy/openvino` 目录,该目录不依赖任何`PaddleX`下其他目录。 @@ -29,7 +58,7 @@ - ngraph: 说明:openvino编译的过程中会生成ngraph的lib文件,位于{openvino根目录}/bin/intel64/Release/lib/下。 -### Step2: 编译demo +### Step2: 编译 编译`cmake`的命令在`scripts/build.sh`中,请根据Step1中编译软件的实际情况修改主要参数,其主要内容说明如下: @@ -51,7 +80,7 @@ cmake .. \ -DOPENCV_DIR=${OPENCV_DIR} \ -DGFLAGS_DIR=${GFLAGS_DIR} \ -DOPENVINO_DIR=${OPENVINO_DIR} \ - -DNGRAPH_LIB=${NGRAPH_LIB} + -DNGRAPH_LIB=${NGRAPH_LIB} make ``` @@ -62,10 +91,17 @@ make ### Step3: 模型转换 -将[]()生成的onnx文件转换为OpencVINO支持的格式,请参考:[Model Optimizer文档](https://docs.openvinotoolkit.org/latest/_docs_MO_DG_Deep_Learning_Model_Optimizer_DevGuide.html) +将PaddleX模型转换成ONNX模型: + +``` +paddlex --export_onnx --model_dir=/path/to/xiaoduxiong_epoch_12 --save_dir=/path/to/onnx_model +``` + +将生成的onnx模型转换为OpenVINO支持的格式,请参考:[Model Optimizer文档](https://docs.openvinotoolkit.org/latest/_docs_MO_DG_Deep_Learning_Model_Optimizer_DevGuide.html) ### Step4: 预测 -编译成功后,预测demo的可执行程序分别为`build/classifer`,其主要命令参数说明如下: + +编译成功后,分类任务的预测可执行程序为`classifier`,其主要命令参数说明如下: | 参数 | 说明 | | ---- | ---- | @@ -74,17 +110,14 @@ make | --image_list | 按行存储图片路径的.txt文件 | | --device | 运行的平台, 默认值为"CPU" | - -## 样例 - -可使用[小度熊识别模型](deploy.md#导出inference模型)中导出的`inference_model`和测试图片进行预测。 +#### 样例 `样例一`: 测试图片 `/path/to/xiaoduxiong.jpeg` ```shell -./build/classifier --model_dir=/path/to/inference_model --image=/path/to/xiaoduxiong.jpeg +./build/classifier --model_dir=/path/to/openvino_model --image=/path/to/xiaoduxiong.jpeg ``` @@ -97,7 +130,7 @@ make ... /path/to/images/xiaoduxiongn.jpeg ``` + ```shell -./build/classifier --model_dir=/path/to/models/inference_model --image_list=/root/projects/images_list.txt - +./build/classifier --model_dir=/path/to/models/openvino_model --image_list=/root/projects/images_list.txt ``` - diff --git a/docs/tutorials/deploy/deploy_cpp_linux.md b/docs/tutorials/deploy/deploy_server/deploy_cpp/deploy_cpp_linux.md similarity index 96% rename from docs/tutorials/deploy/deploy_cpp_linux.md rename to docs/tutorials/deploy/deploy_server/deploy_cpp/deploy_cpp_linux.md index dbce8580534fa68f8836bd2660937de8dbb5f5d0..b4edf3510ae992d72ea60e1078f22e12d54357c2 100755 --- a/docs/tutorials/deploy/deploy_cpp_linux.md +++ b/docs/tutorials/deploy/deploy_server/deploy_cpp/deploy_cpp_linux.md @@ -1,4 +1,4 @@ -# Linux平台编译指南 +# Linux平台部署 ## 说明 本文档在 `Linux`平台使用`GCC 4.8.5` 和 `GCC 4.9.4`测试过,如果需要使用更高G++版本编译使用,则需要重新编译Paddle预测库,请参考: [从源码编译Paddle预测库](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/advanced_guide/inference_deployment/inference/build_and_install_lib_cn.html#id12)。 @@ -103,6 +103,9 @@ make ``` ### Step5: 预测及可视化 + +参考[导出inference模型](../deploy_python.html#inference)将模型导出为inference格式模型。 + 编译成功后,预测demo的可执行程序分别为`build/demo/detector`,`build/demo/classifer`,`build/demo/segmenter`,用户可根据自己的模型类型选择,其主要命令参数说明如下: | 参数 | 说明 | @@ -117,7 +120,7 @@ make ## 样例 -可使用[小度熊识别模型](deploy.md#导出inference模型)中导出的`inference_model`和测试图片进行预测。 +可使用[小度熊识别模型](../deploy_python.html#inference)中导出的`inference_model`和测试图片进行预测。 `样例一`: diff --git a/docs/tutorials/deploy/deploy_cpp_win_vs2019.md b/docs/tutorials/deploy/deploy_server/deploy_cpp/deploy_cpp_win_vs2019.md similarity index 85% rename from docs/tutorials/deploy/deploy_cpp_win_vs2019.md rename to docs/tutorials/deploy/deploy_server/deploy_cpp/deploy_cpp_win_vs2019.md index 2572236c5113fa7552bf13929391bc6538d61edd..2f7c62766291410ec8e48a77b7e814edeb1523bb 100755 --- a/docs/tutorials/deploy/deploy_cpp_win_vs2019.md +++ b/docs/tutorials/deploy/deploy_server/deploy_cpp/deploy_cpp_win_vs2019.md @@ -1,4 +1,4 @@ -# Visual Studio 2019 Community CMake 编译指南 +# Windows平台部署 ## 说明 Windows 平台下,我们使用`Visual Studio 2019 Community` 进行了测试。微软从`Visual Studio 2017`开始即支持直接管理`CMake`跨平台编译项目,但是直到`2019`才提供了稳定和完全的支持,所以如果你想使用CMake管理项目编译构建,我们推荐你使用`Visual Studio 2019`环境下构建。 @@ -62,19 +62,19 @@ PaddlePaddle C++ 预测库针对不同的`CPU`,`CUDA`,以及是否支持Tens 1. 打开Visual Studio 2019 Community,点击`继续但无需代码` -![step2](images/vs2019_step1.png) +![step2](../../images/vs2019_step1.png) 2. 点击: `文件`->`打开`->`CMake` -![step2.1](images/vs2019_step2.png) +![step2.1](../../images/vs2019_step2.png) 选择项目代码所在路径,并打开`CMakeList.txt`: -![step2.2](images/vs2019_step3.png) +![step2.2](../../images/vs2019_step3.png) 3. 点击:`项目`->`PADDLEX_INFERENCE的CMake设置` -![step3](images/vs2019_step4.png) +![step3](../../images/vs2019_step4.png) 4. 点击`浏览`,分别设置编译选项指定`CUDA`、`OpenCV`、`Paddle预测库`的路径 @@ -88,17 +88,19 @@ PaddlePaddle C++ 预测库针对不同的`CPU`,`CUDA`,以及是否支持Tens **注意:** 1. 使用`CPU`版预测库,请把`WITH_GPU`的`值`去掉勾 2. 如果使用的是`openblas`版本,请把`WITH_MKL`的`值`去掉勾 -![step4](images/vs2019_step5.png) +![step4](../../images/vs2019_step5.png) **设置完成后**, 点击上图中`保存并生成CMake缓存以加载变量`。 5. 点击`生成`->`全部生成` -![step6](images/vs2019_step6.png) +![step6](../../images/vs2019_step6.png) ### Step5: 预测及可视化 +参考[导出inference模型](../deploy_python.html#inference)将模型导出为inference格式模型。 + 上述`Visual Studio 2019`编译产出的可执行文件在`out\build\x64-Release`目录下,打开`cmd`,并切换到该目录: ``` @@ -106,7 +108,7 @@ d: cd D:\projects\PaddleX\deploy\cpp\out\build\x64-Release ``` -编译成功后,预测demo的入口程序为`demo\detector`,`demo\classifer`,`demo\segmenter`,用户可根据自己的模型类型选择,其主要命令参数说明如下: +编译成功后,预测demo的入口程序为`paddlex_inference\detector.exe`,`paddlex_inference\classifer.exe`,`paddlex_inference\segmenter.exe`,用户可根据自己的模型类型选择,其主要命令参数说明如下: | 参数 | 说明 | | ---- | ---- | @@ -120,14 +122,14 @@ cd D:\projects\PaddleX\deploy\cpp\out\build\x64-Release ## 样例 -可使用[小度熊识别模型](deploy.md#导出inference模型)中导出的`inference_model`和测试图片进行预测。 +可使用[小度熊识别模型](../deploy_python.html#inference)中导出的`inference_model`和测试图片进行预测。 `样例一`: 不使用`GPU`测试图片 `\\path\\to\\xiaoduxiong.jpeg` ```shell -.\detector --model_dir=\\path\\to\\inference_model --image=D:\\images\\xiaoduxiong.jpeg --save_dir=output +.\\paddlex_inference\\detector.exe --model_dir=\\path\\to\\inference_model --image=D:\\images\\xiaoduxiong.jpeg --save_dir=output ``` 图片文件`可视化预测结果`会保存在`save_dir`参数设置的目录下。 @@ -143,6 +145,6 @@ cd D:\projects\PaddleX\deploy\cpp\out\build\x64-Release \\path\\to\\images\\xiaoduxiongn.jpeg ``` ```shell -.\detector --model_dir=\\path\\to\\inference_model --image_list=\\path\\to\\images_list.txt --use_gpu=1 --save_dir=output +.\\paddlex_inference\\detector.exe --model_dir=\\path\\to\\inference_model --image_list=\\path\\to\\images_list.txt --use_gpu=1 --save_dir=output ``` 图片文件`可视化预测结果`会保存在`save_dir`参数设置的目录下。 diff --git a/docs/tutorials/deploy/deploy_server/deploy_cpp/index.rst b/docs/tutorials/deploy/deploy_server/deploy_cpp/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..36a066b6eb269a00be34f8401e1083b9f61a91bd --- /dev/null +++ b/docs/tutorials/deploy/deploy_server/deploy_cpp/index.rst @@ -0,0 +1,11 @@ +C++部署 +============== + + +C++部署方案位于目录PaddleX/deploy/cpp/下,且独立于PaddleX其他模块。该方案支持在 Windows 和 Linux 完成编译、二次开发集成和部署运行,支持在Linux上完成加密部署。 + +.. toctree:: + :maxdepth: 1 + + deploy_cpp_win_vs2019.md + deploy_cpp_linux.md diff --git a/docs/tutorials/deploy/deploy.md b/docs/tutorials/deploy/deploy_server/deploy_python.md old mode 100755 new mode 100644 similarity index 55% rename from docs/tutorials/deploy/deploy.md rename to docs/tutorials/deploy/deploy_server/deploy_python.md index 7193dc3de315b43c85f3aa3d8ff24c7b02f98f3b..c597f87cdbbc208ad2b72a8305642da41b9be5cd --- a/docs/tutorials/deploy/deploy.md +++ b/docs/tutorials/deploy/deploy_server/deploy_python.md @@ -1,10 +1,7 @@ -# 模型预测部署 +# Python部署 +PaddleX已经集成了基于Python的高性能预测接口,在安装PaddleX后,可参照如下代码示例,进行预测。相关的接口文档可参考[paddlex.deploy](../../../apis/deploy.md) -本文档指引用户如何采用更高性能地方式来部署使用PaddleX训练的模型。使用本文档模型部署方式,会在模型运算过程中,对模型计算图进行优化,同时减少内存操作,相对比普通的paddlepaddle模型加载和预测方式,预测速度平均可提升1倍,具体各模型性能对比见[预测性能对比](#预测性能对比) - -## 服务端部署 - -### 导出inference模型 +## 导出inference模型 在服务端部署的模型需要首先将模型导出为inference格式模型,导出的模型将包括`__model__`、`__params__`和`model.yml`三个文名,分别为模型的网络结构,模型权重和模型的配置文件(包括数据预处理参数等等)。在安装完PaddleX后,在命令行终端使用如下命令导出模型到当前目录`inferece_model`下。 > 可直接下载小度熊分拣模型测试本文档的流程[xiaoduxiong_epoch_12.tar.gz](https://bj.bcebos.com/paddlex/models/xiaoduxiong_epoch_12.tar.gz) @@ -22,59 +19,17 @@ paddlex --export_inference --model_dir=./xiaoduxiong_epoch_12 --save_dir=./infer paddlex --export_inference --model_dir=./xiaoduxiong_epoch_12 --save_dir=./inference_model --fixed_input_shape=[640,960] ``` -### Python部署 -PaddleX已经集成了基于Python的高性能预测接口,在安装PaddleX后,可参照如下代码示例,进行预测。相关的接口文档可参考[paddlex.deploy](apis/deploy.md) +## 预测部署 > 点击下载测试图片 [xiaoduxiong_test_image.tar.gz](https://bj.bcebos.com/paddlex/datasets/xiaoduxiong_test_image.tar.gz) ``` import paddlex as pdx -predictor = pdx.deploy.create_predictor('./inference_model') +predictor = pdx.deploy.Predictor('./inference_model') result = predictor.predict(image='xiaoduxiong_test_image/JPEGImages/WeChatIMG110.jpeg') ``` -### C++部署 - -C++部署方案位于目录`deploy/cpp/`下,且独立于PaddleX其他模块。该方案支持在 Windows 和 Linux 完成编译、二次开发集成和部署运行。具体使用方法和编译: - -- Linux平台:[linux](deploy_cpp_linux.md) -- window平台:[windows](deploy_cpp_win_vs2019.md) - -### OpenVINO部署demo - -OpenVINO部署demo位于目录`deploy/openvino/`下,且独立于PaddleX其他模块,该demo目前支持在 Linux 完成编译和部署运行。目前PaddleX到OpenVINO的部署流程如下: - -graph LR - PaddleX --> ONNX --> OpenVINO IR --> OpenVINO Inference Engine -#### step1 - -PaddleX输出ONNX模型方法如下: - -``` -paddlex --export_onnx --model_dir=./xiaoduxiong_epoch_12 --save_dir=./onnx_model -``` - -|目前支持的模型| -|-----| -|ResNet18| -|ResNet34| -|ResNet50| -|ResNet101| -|ResNet50_vd| -|ResNet101_vd| -|ResNet50_vd_ssld| -|ResNet101_vd_ssld -|DarkNet53| -|MobileNetV1| -|MobileNetV2| -|DenseNet121| -|DenseNet161| -|DenseNet201| - -得到ONNX模型后,OpenVINO的部署参考:[OpenVINO部署](deploy_openvino.md) - -### 预测性能对比 - -#### 测试环境 +## 预测性能对比 +### 测试环境 - CUDA 9.0 - CUDNN 7.5 @@ -84,6 +39,9 @@ paddlex --export_onnx --model_dir=./xiaoduxiong_epoch_12 --save_dir=./onnx_model - Executor 指采用paddlepaddle普通的python预测方式 - Batch Size均为1,耗时单位为ms/image,只计算模型运行时间,不包括数据的预处理和后处理 +### 性能对比 + + | 模型 | AnalysisPredictor耗时 | Executor耗时 | 输入图像大小 | | :---- | :--------------------- | :------------ | :------------ | | resnet50 | 4.84 | 7.57 | 224*224 | @@ -95,7 +53,3 @@ paddlex --export_onnx --model_dir=./xiaoduxiong_epoch_12 --save_dir=./onnx_model | faster_rcnn_r50_1x | 326.11 | 347.22 | 800*1067 | | mask_rcnn_r50_fpn_1x | 67.49 | 91.02 | 800*1088 | | mask_rcnn_r50_1x | 326.11 | 350.94 | 800*1067 | - -## 移动端部署 - -> Lite模型导出正在集成中,即将开源... diff --git a/docs/tutorials/deploy/deploy_server/encryption.md b/docs/tutorials/deploy/deploy_server/encryption.md new file mode 100644 index 0000000000000000000000000000000000000000..71b07048ed8372b4c4b9aa0b2082dc9ed9f2f9a0 --- /dev/null +++ b/docs/tutorials/deploy/deploy_server/encryption.md @@ -0,0 +1,110 @@ +# 模型加密部署 + +PaddleX提供一个轻量级的模型加密部署方案,通过PaddleX内置的模型加密工具对推理模型进行加密,预测部署SDK支持直接加载密文模型并完成推理,提升AI模型部署的安全性。 + +**注意:目前加密方案仅支持Linux系统** + +## 1. 方案简介 + +### 1.1 简介 + +(1)加密算法的选择和支持的库 + +一般使用OpenSSL库来支持数据的加解密,OpenSSL提供了大量的加解密算法,包括对称加密算法(AES等)和非对称加密算法(RSA等)。 + +两种算法使用的场景不同,非对称加密算法一般应用于数字签名和密钥协商的场景下,而对称加密算法一般应用于纯数据加密场景,性能更优。在对模型的加密过程中使用对称加密算法。 + +以下对模型加密场景实现的说明中以开发一个C/C++库为基础,采用AES对称加密算法,为了加解密前后能够快速判断解密是否成功,使用AES-GCM加解密模式,在密钥的安全性上使用长度为256位的密钥数据。 + +(2)实现模型保护的一般步骤: + +![](../images/encryption_process.png) + +下面是对提供的C/C++加解密库内部实现的中文描述,参考以下步骤可以实现 一套加解密库 来适应自己的场景并通过内存数据load到paddlepaddle中(c/c++预测服务) + +> 1)考虑到加密的模型文件解密后需要从内存加载数据,使用conbine的模式生成模型文件和参数文件。 +> +> 2)项目集成OpenSSL,使用静态库的形式。 +> +> 3)实现AES算法接口,借助OpenSSL提供的EVP接口,在EVP接口中指定算法类型,算法使用对称加解密算法中的AES,加解密模式使用AES-GCM, 密钥长度为256位,AES-GCM的实现可以参考官方提供的例子自己进行封装接口:https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption。 +> +> 4)利用OpenSSL库实现SHA256摘要算法,这部分下面有用(可选)。关于SHA256的hash计算可以参考OpenSSL提供的example:https://wiki.openssl.org/index.php/EVP_Message_Digests +> +> 5)在模型加密环节直接对model文件和params文件的数据内容进行加密后保存到新的文件,为了新的文件能够被区分和可迭代,除了加密后的数据外还添加了头部信息,比如为了判断该文件类型使用固定的魔数作为文件的开头;为了便于后面需求迭代写入版本号以示区别;为了能够在解密时判断是否采用了相同的密钥将加密时的密钥进行SHA256计算后存储;这三部分构成了目前加密后文件的头部信息。加密后的文件包含头部信息 + 密文信息。 +> +> 6)在模型解密环节根据加密后的文件读取相关的加密数据到内存中,对内存数据使用AES算法进行解密,注意解密时需要采用与加密时一致的加密算法和加密的模式,以及密钥的数据和长度,否则会导致解密后数据错误。 +> +> 7)集成模型预测的C/C++库,在具体使用paddlepaddle预测时一般涉及paddle::AnalysisConfig和paddle:Predictor,为了能够从内存数据中直接load解密后的模型明文数据(避免模型解密后创建临时文件),这里需要将AnalysisConfig的模型加载函数从SetModel替换为SetModelBuffer来实现从内存中加载模型数据。 + +需要注意的是,在本方案中,密钥集成在上层预测服务的代码中。故模型的安全强度等同于代码抵御逆向调试的强度。为了保护密钥和模型的安全,开发者还需对自己的应用进行加固保护。常见的应用加固手段有:代码混淆,二进制文件加壳 等等,亦或将加密机制更改为AES白盒加密技术来保护密钥。这类技术领域内有大量商业和开源产品可供选择,此处不一一赘述。 + +### 1.2 加密工具 + +[PaddleX模型加密工具](https://bj.bcebos.com/paddlex/tools/paddlex-encryption.zip)。在编译部署代码时,编译脚本会自动下载加密工具,您也可以选择手动下载。 + +加密工具包含内容为: +``` +paddlex-encryption +├── include # 头文件:paddle_model_decrypt.h(解密)和paddle_model_encrypt.h(加密) +| +├── lib # libpmodel-encrypt.so和libpmodel-decrypt.so动态库 +| +└── tool # paddlex_encrypt_tool +``` + +### 1.3 加密PaddleX模型 + +对模型完成加密后,加密工具会产生随机密钥信息(用于AES加解密使用),需要在后续加密部署时传入该密钥来用于解密。 +> 密钥由32字节key + 16字节iv组成, 注意这里产生的key是经过base64编码后的,这样可以扩充key的选取范围 + +``` +./paddlex-encryption/tool/paddlex_encrypt_tool -model_dir /path/to/paddlex_inference_model -save_dir /path/to/paddlex_encrypted_model +``` + +`-model_dir`用于指定inference模型路径(参考[导出inference模型](deploy_python.html#inference)将模型导出为inference格式模型),可使用[导出小度熊识别模型](deploy_python.html#inference)中导出的`inference_model`。加密完成后,加密过的模型会保存至指定的`-save_dir`下,包含`__model__.encrypted`、`__params__.encrypted`和`model.yml`三个文件,同时生成密钥信息,命令输出如下图所示,密钥为`kLAl1qOs5uRbFt0/RrIDTZW2+tOf5bzvUIaHGF8lJ1c=` + +![](../images/encrypt.png) + +## 2. PaddleX C++加密部署 + +参考[Linux平台编译指南](deploy_cpp/deploy_cpp_linux.html#linux)编译C++部署代码。编译成功后,预测demo的可执行程序分别为`build/demo/detector`,`build/demo/classifer`,`build/demo/segmenter`,用户可根据自己的模型类型选择,其主要命令参数说明如下: + +| 参数 | 说明 | +| ---- | ---- | +| model_dir | 导出的预测模型所在路径 | +| image | 要预测的图片文件路径 | +| image_list | 按行存储图片路径的.txt文件 | +| use_gpu | 是否使用 GPU 预测, 支持值为0或1(默认值为0) | +| use_trt | 是否使用 TensorTr 预测, 支持值为0或1(默认值为0) | +| gpu_id | GPU 设备ID, 默认值为0 | +| save_dir | 保存可视化结果的路径, 默认值为"output",classifier无该参数 | +| key | 加密过程中产生的密钥信息,默认值为""表示加载的是未加密的模型 | + + +## 样例 + +可使用[导出小度熊识别模型](deploy_python.html#inference)中的测试图片进行预测。 + +`样例一`: + +不使用`GPU`测试图片 `/path/to/xiaoduxiong.jpeg` + +```shell +./build/demo/detector --model_dir=/path/to/inference_model --image=/path/to/xiaoduxiong.jpeg --save_dir=output --key=kLAl1qOs5uRbFt0/RrIDTZW2+tOf5bzvUIaHGF8lJ1c= +``` +`--key`传入加密工具输出的密钥,例如`kLAl1qOs5uRbFt0/RrIDTZW2+tOf5bzvUIaHGF8lJ1c=`, 图片文件`可视化预测结果`会保存在`save_dir`参数设置的目录下。 + + +`样例二`: + +使用`GPU`预测多个图片`/path/to/image_list.txt`,image_list.txt内容的格式如下: +``` +/path/to/images/xiaoduxiong1.jpeg +/path/to/images/xiaoduxiong2.jpeg +... +/path/to/images/xiaoduxiongn.jpeg +``` +```shell +./build/demo/detector --model_dir=/path/to/models/inference_model --image_list=/root/projects/images_list.txt --use_gpu=1 --save_dir=output --key=kLAl1qOs5uRbFt0/RrIDTZW2+tOf5bzvUIaHGF8lJ1c= +``` +`--key`传入加密工具输出的密钥,例如`kLAl1qOs5uRbFt0/RrIDTZW2+tOf5bzvUIaHGF8lJ1c=`, 图片文件`可视化预测结果`会保存在`save_dir`参数设置的目录下。 diff --git a/docs/tutorials/deploy/deploy_server/index.rst b/docs/tutorials/deploy/deploy_server/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..e9635c0532bc56f3073a78f615c21019a699c68f --- /dev/null +++ b/docs/tutorials/deploy/deploy_server/index.rst @@ -0,0 +1,9 @@ +服务端部署 +============== + +.. toctree:: + :maxdepth: 2 + + deploy_python.md + deploy_cpp/index.rst + encryption.md diff --git a/docs/tutorials/deploy/encryption.md b/docs/tutorials/deploy/encryption.md deleted file mode 100644 index 74d4dd450e5b1920989d807f073abc76bb923f22..0000000000000000000000000000000000000000 --- a/docs/tutorials/deploy/encryption.md +++ /dev/null @@ -1,77 +0,0 @@ -# Paddle模型加密方案 - -飞桨团队推出模型加密方案,使用业内主流的AES加密技术对最终模型进行加密。飞桨用户可以通过PaddleX导出模型后,使用该方案对模型进行加密,预测时使用解密SDK进行模型解密并完成推理,大大提升AI应用安全性和开发效率。 - -**注意:目前加密方案仅支持Linux系统** - -## 1. 方案简介 - -### 1.1 加密工具 - -[PaddleX模型加密工具](https://bj.bcebos.com/paddlex/tools/paddlex-encryption.zip)。在编译部署代码时,编译脚本会自动下载加密工具,您也可以选择手动下载。 - -加密工具包含内容为: -``` -paddlex-encryption -├── include # 头文件:paddle_model_decrypt.h(解密)和paddle_model_encrypt.h(加密) -| -├── lib # libpmodel-encrypt.so和libpmodel-decrypt.so动态库 -| -└── tool # paddlex_encrypt_tool -``` - -### 1.2 加密PaddleX模型 - -对模型完成加密后,加密工具会产生随机密钥信息(用于AES加解密使用),需要在后续加密部署时传入该密钥来用于解密。 -> 密钥由32字节key + 16字节iv组成, 注意这里产生的key是经过base64编码后的,这样可以扩充key的选取范围 - -``` -./paddlex-encryption/tool/paddlex_encrypt_tool -model_dir /path/to/paddlex_inference_model -save_dir /path/to/paddlex_encrypted_model -``` - -`-model_dir`用于指定inference模型路径,可使用[导出小度熊识别模型](deploy.md#导出inference模型)中导出的`inference_model`。加密完成后,加密过的模型会保存至指定的`-save_dir`下,包含`__model__.encrypted`、`__params__.encrypted`和`model.yml`三个文件,同时生成密钥信息,命令输出如下图所示,密钥为`kLAl1qOs5uRbFt0/RrIDTZW2+tOf5bzvUIaHGF8lJ1c=` -![](images/encryt.png) - -## 2. PaddleX C++加密部署 - -参考[Linux平台编译指南](deploy_cpp_linux.md)编译C++部署代码。编译成功后,预测demo的可执行程序分别为`build/demo/detector`,`build/demo/classifer`,`build/demo/segmenter`,用户可根据自己的模型类型选择,其主要命令参数说明如下: - -| 参数 | 说明 | -| ---- | ---- | -| model_dir | 导出的预测模型所在路径 | -| image | 要预测的图片文件路径 | -| image_list | 按行存储图片路径的.txt文件 | -| use_gpu | 是否使用 GPU 预测, 支持值为0或1(默认值为0) | -| use_trt | 是否使用 TensorTr 预测, 支持值为0或1(默认值为0) | -| gpu_id | GPU 设备ID, 默认值为0 | -| save_dir | 保存可视化结果的路径, 默认值为"output",classfier无该参数 | -| key | 加密过程中产生的密钥信息,默认值为""表示加载的是未加密的模型 | - - -## 样例 - -可使用[导出小度熊识别模型](deploy.md#导出inference模型)中的测试图片进行预测。 - -`样例一`: - -不使用`GPU`测试图片 `/path/to/xiaoduxiong.jpeg` - -```shell -./build/demo/detector --model_dir=/path/to/inference_model --image=/path/to/xiaoduxiong.jpeg --save_dir=output --key=kLAl1qOs5uRbFt0/RrIDTZW2+tOf5bzvUIaHGF8lJ1c= -``` -`--key`传入加密工具输出的密钥,例如`kLAl1qOs5uRbFt0/RrIDTZW2+tOf5bzvUIaHGF8lJ1c=`, 图片文件`可视化预测结果`会保存在`save_dir`参数设置的目录下。 - - -`样例二`: - -使用`GPU`预测多个图片`/path/to/image_list.txt`,image_list.txt内容的格式如下: -``` -/path/to/images/xiaoduxiong1.jpeg -/path/to/images/xiaoduxiong2.jpeg -... -/path/to/images/xiaoduxiongn.jpeg -``` -```shell -./build/demo/detector --model_dir=/path/to/models/inference_model --image_list=/root/projects/images_list.txt --use_gpu=1 --save_dir=output --key=kLAl1qOs5uRbFt0/RrIDTZW2+tOf5bzvUIaHGF8lJ1c= -``` -`--key`传入加密工具输出的密钥,例如`kLAl1qOs5uRbFt0/RrIDTZW2+tOf5bzvUIaHGF8lJ1c=`, 图片文件`可视化预测结果`会保存在`save_dir`参数设置的目录下。 diff --git a/docs/tutorials/deploy/images/encryption_process.png b/docs/tutorials/deploy/images/encryption_process.png new file mode 100644 index 0000000000000000000000000000000000000000..25d3fac458e5cbdd2e211a62147698ac081b9f32 Binary files /dev/null and b/docs/tutorials/deploy/images/encryption_process.png differ diff --git a/docs/tutorials/deploy/images/vs2019_step4.png b/docs/tutorials/deploy/images/vs2019_step4.png old mode 100755 new mode 100644 index 102cb81ac911c810bdf24e86b42ece307ffd1f8a..74fe7b224dc9b3533066111ab2a9cd877a5bbc68 Binary files a/docs/tutorials/deploy/images/vs2019_step4.png and b/docs/tutorials/deploy/images/vs2019_step4.png differ diff --git a/docs/tutorials/deploy/index.rst b/docs/tutorials/deploy/index.rst index 2aa5e1d61db4fa3901da833b2b3c2bb112fce491..ebeb36ffb9227ff610f1f82ab9eccb16b82a89f8 100644 --- a/docs/tutorials/deploy/index.rst +++ b/docs/tutorials/deploy/index.rst @@ -1,8 +1,13 @@ -多端部署 +多端安全部署 ============== +本文档指引用户如何采用更高性能地方式来部署使用PaddleX训练的模型。本文档模型部署采用Paddle Inference高性能部署方式,在模型运算过程中,对模型计算图进行优化,同时减少内存操作,具体各模型性能对比见服务端Python部署的预测性能对比章节。 + +同时结合产业实践开发者对模型知识产权的保护需求,提供了轻量级模型加密部署的方案,提升深度学习模型部署的安全性。 + .. toctree:: :maxdepth: 2 - :caption: 文档目录: - + deploy_server/index.rst + deploy_openvino.md + deploy_lite.md diff --git a/paddlex/__init__.py b/paddlex/__init__.py index 96650dbb5be87bb12642327b39339f98cd70fba8..c9a52a5888d9d0ec716f9b8f09381632861e3652 100644 --- a/paddlex/__init__.py +++ b/paddlex/__init__.py @@ -53,4 +53,4 @@ log_level = 2 from . import interpret -__version__ = '0.2.0.github' +__version__ = '1.0.1.github' diff --git a/paddlex/cls.py b/paddlex/cls.py index 750e1bce59c18aa3cea7be77d7d4db767f296aa5..e440c726b639ac6d78cc3c62dd8ef2df7bf8a327 100644 --- a/paddlex/cls.py +++ b/paddlex/cls.py @@ -1,4 +1,4 @@ -# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/paddlex/command.py b/paddlex/command.py index 07b0e68020a2ce37be043603a705ee6180dee066..8198291180b92a061dd633eae863f8ddb17727cb 100644 --- a/paddlex/command.py +++ b/paddlex/command.py @@ -1,3 +1,17 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + from six import text_type as _text_type import argparse import sys diff --git a/paddlex/convertor.py b/paddlex/convertor.py index fa74f49cac68fb7cbacadb6e38e7493c28857a92..a6888ae1ef9bd764d213125142d355e7e2ca2428 100644 --- a/paddlex/convertor.py +++ b/paddlex/convertor.py @@ -1,16 +1,16 @@ -#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. -# -#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. +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. from __future__ import absolute_import import paddle.fluid as fluid diff --git a/paddlex/cv/models/utils/pretrain_weights.py b/paddlex/cv/models/utils/pretrain_weights.py index 3f41838b7d3e1529558ced1db23e84292bdd5270..81790a20144d8c255601b8a778eebf02c409c55d 100644 --- a/paddlex/cv/models/utils/pretrain_weights.py +++ b/paddlex/cv/models/utils/pretrain_weights.py @@ -1,5 +1,5 @@ import paddlex -#import paddlehub as hub +import paddlehub as hub import os import os.path as osp @@ -85,53 +85,49 @@ def get_pretrain_weights(flag, model_type, backbone, save_dir): backbone = 'DetResNet50' assert backbone in image_pretrain, "There is not ImageNet pretrain weights for {}, you may try COCO.".format( backbone) - url = image_pretrain[backbone] - fname = osp.split(url)[-1].split('.')[0] - paddlex.utils.download_and_decompress(url, path=new_save_dir) - return osp.join(new_save_dir, fname) -# try: -# hub.download(backbone, save_path=new_save_dir) -# except Exception as e: -# if isinstance(e, hub.ResourceNotFoundError): -# raise Exception( -# "Resource for backbone {} not found".format(backbone)) -# elif isinstance(e, hub.ServerConnectionError): -# raise Exception( -# "Cannot get reource for backbone {}, please check your internet connecgtion" -# .format(backbone)) -# else: -# raise Exception( -# "Unexpected error, please make sure paddlehub >= 1.6.2") -# return osp.join(new_save_dir, backbone) + # url = image_pretrain[backbone] + # fname = osp.split(url)[-1].split('.')[0] + # paddlex.utils.download_and_decompress(url, path=new_save_dir) + # return osp.join(new_save_dir, fname) + try: + hub.download(backbone, save_path=new_save_dir) + except Exception as e: + if isinstance(e, hub.ResourceNotFoundError): + raise Exception("Resource for backbone {} not found".format( + backbone)) + elif isinstance(e, hub.ServerConnectionError): + raise Exception( + "Cannot get reource for backbone {}, please check your internet connecgtion" + .format(backbone)) + else: + raise Exception( + "Unexpected error, please make sure paddlehub >= 1.6.2") + return osp.join(new_save_dir, backbone) elif flag == 'COCO': new_save_dir = save_dir if hasattr(paddlex, 'pretrain_dir'): new_save_dir = paddlex.pretrain_dir url = coco_pretrain[backbone] fname = osp.split(url)[-1].split('.')[0] - paddlex.utils.download_and_decompress(url, path=new_save_dir) - return osp.join(new_save_dir, fname) - + # paddlex.utils.download_and_decompress(url, path=new_save_dir) + # return osp.join(new_save_dir, fname) -# new_save_dir = save_dir -# if hasattr(paddlex, 'pretrain_dir'): -# new_save_dir = paddlex.pretrain_dir -# assert backbone in coco_pretrain, "There is not COCO pretrain weights for {}, you may try ImageNet.".format( -# backbone) -# try: -# hub.download(backbone, save_path=new_save_dir) -# except Exception as e: -# if isinstance(hub.ResourceNotFoundError): -# raise Exception( -# "Resource for backbone {} not found".format(backbone)) -# elif isinstance(hub.ServerConnectionError): -# raise Exception( -# "Cannot get reource for backbone {}, please check your internet connecgtion" -# .format(backbone)) -# else: -# raise Exception( -# "Unexpected error, please make sure paddlehub >= 1.6.2") -# return osp.join(new_save_dir, backbone) + assert backbone in coco_pretrain, "There is not COCO pretrain weights for {}, you may try ImageNet.".format( + backbone) + try: + hub.download(backbone, save_path=new_save_dir) + except Exception as e: + if isinstance(hub.ResourceNotFoundError): + raise Exception("Resource for backbone {} not found".format( + backbone)) + elif isinstance(hub.ServerConnectionError): + raise Exception( + "Cannot get reource for backbone {}, please check your internet connecgtion" + .format(backbone)) + else: + raise Exception( + "Unexpected error, please make sure paddlehub >= 1.6.2") + return osp.join(new_save_dir, backbone) else: raise Exception( "pretrain_weights need to be defined as directory path or `IMAGENET` or 'COCO' (download pretrain weights automatically)." diff --git a/paddlex/interpret/__init__.py b/paddlex/interpret/__init__.py index 00a70c496d67194f22ef3b92d579da8f02792b14..1b8ae70a0c581bb24a9402e6a73ad7a4cb55fca6 100644 --- a/paddlex/interpret/__init__.py +++ b/paddlex/interpret/__init__.py @@ -15,4 +15,5 @@ from __future__ import absolute_import from . import visualize -visualize = visualize.visualize \ No newline at end of file +lime = visualize.lime +normlime = visualize.normlime \ No newline at end of file diff --git a/paddlex/interpret/core/interpretation_algorithms.py b/paddlex/interpret/core/interpretation_algorithms.py index eafb4850f5141dc86507fa12f0a345da8d713993..32dd72375fd01172a7dee8ed26fc607884a18f70 100644 --- a/paddlex/interpret/core/interpretation_algorithms.py +++ b/paddlex/interpret/core/interpretation_algorithms.py @@ -242,7 +242,13 @@ class NormLIME(object): self.label_names = label_names def predict_cluster_labels(self, feature_map, segments): - return self.kmeans_model.predict(get_feature_for_kmeans(feature_map, segments)) + X = get_feature_for_kmeans(feature_map, segments) + try: + cluster_labels = self.kmeans_model.predict(X) + except AttributeError: + from sklearn.metrics import pairwise_distances_argmin_min + cluster_labels, _ = pairwise_distances_argmin_min(X, self.kmeans_model.cluster_centers_) + return cluster_labels def predict_using_normlime_weights(self, pred_labels, predicted_cluster_labels): # global weights diff --git a/paddlex/interpret/core/lime_base.py b/paddlex/interpret/core/lime_base.py index 57844baa1737bb9f656eaf43a4c1f267c421c262..23969b91fc29a1324fff1a48a41de3b7c2450d8c 100644 --- a/paddlex/interpret/core/lime_base.py +++ b/paddlex/interpret/core/lime_base.py @@ -30,17 +30,10 @@ The code in this file (lime_base.py) is modified from https://github.com/marcotc import numpy as np import scipy as sp -import sklearn -import sklearn.preprocessing -from skimage.color import gray2rgb -from sklearn.linear_model import Ridge, lars_path -from sklearn.utils import check_random_state import tqdm import copy from functools import partial -from skimage.segmentation import quickshift -from skimage.measure import regionprops class LimeBase(object): @@ -59,6 +52,7 @@ class LimeBase(object): generate random numbers. If None, the random state will be initialized using the internal numpy seed. """ + from sklearn.utils import check_random_state self.kernel_fn = kernel_fn self.verbose = verbose self.random_state = check_random_state(random_state) @@ -75,6 +69,7 @@ class LimeBase(object): (alphas, coefs), both are arrays corresponding to the regularization parameter and coefficients, respectively """ + from sklearn.linear_model import lars_path x_vector = weighted_data alphas, _, coefs = lars_path(x_vector, weighted_labels, @@ -106,6 +101,7 @@ class LimeBase(object): def feature_selection(self, data, labels, weights, num_features, method): """Selects features for the model. see interpret_instance_with_data to understand the parameters.""" + from sklearn.linear_model import Ridge if method == 'none': return np.array(range(data.shape[1])) elif method == 'forward_selection': @@ -213,7 +209,7 @@ class LimeBase(object): score is the R^2 value of the returned interpretation local_pred is the prediction of the interpretation model on the original instance """ - + from sklearn.linear_model import Ridge weights = self.kernel_fn(distances) labels_column = neighborhood_labels[:, label] used_features = self.feature_selection(neighborhood_data, @@ -376,6 +372,7 @@ class LimeImageInterpreter(object): generate random numbers. If None, the random state will be initialized using the internal numpy seed. """ + from sklearn.utils import check_random_state kernel_width = float(kernel_width) if kernel is None: @@ -422,6 +419,10 @@ class LimeImageInterpreter(object): An ImageIinterpretation object (see lime_image.py) with the corresponding interpretations. """ + import sklearn + from skimage.measure import regionprops + from skimage.segmentation import quickshift + from skimage.color import gray2rgb if len(image.shape) == 2: image = gray2rgb(image) diff --git a/paddlex/interpret/core/normlime_base.py b/paddlex/interpret/core/normlime_base.py index c1ae902f33a39a3488bf6e9fd5035c295e4ac45f..df470b6f218f1591f6b648eb86189f425ef294e5 100644 --- a/paddlex/interpret/core/normlime_base.py +++ b/paddlex/interpret/core/normlime_base.py @@ -17,6 +17,7 @@ import numpy as np import glob from paddlex.interpret.as_data_reader.readers import read_image +import paddlex.utils.logging as logging from . import lime_base from ._session_preparation import compute_features_for_kmeans, h_pre_models_kmeans @@ -113,11 +114,10 @@ def precompute_lime_weights(list_data_, predict_fn, num_samples, batch_size, sav save_path = os.path.join(save_dir, save_path) if os.path.exists(save_path): - print(f'{save_path} exists, not computing this one.') + logging.info(save_path + ' exists, not computing this one.', use_color=True) continue - - print('processing', each_data_ if isinstance(each_data_, str) else data_index, - f', {data_index}/{len(list_data_)}') + img_file_name = each_data_ if isinstance(each_data_, str) else data_index + logging.info('processing '+ img_file_name + ' [{}/{}]'.format(data_index, len(list_data_)), use_color=True) image_show = read_image(each_data_) result = predict_fn(image_show) @@ -149,9 +149,12 @@ def precompute_lime_weights(list_data_, predict_fn, num_samples, batch_size, sav interpreter = algo.interpret_instance(image_show[0], predict_fn, pred_label, 0, num_samples=num_samples, batch_size=batch_size) - cluster_labels = kmeans_model.predict( - get_feature_for_kmeans(compute_features_for_kmeans(image_show).transpose((1, 2, 0)), interpreter.segments) - ) + X = get_feature_for_kmeans(compute_features_for_kmeans(image_show).transpose((1, 2, 0)), interpreter.segments) + try: + cluster_labels = kmeans_model.predict(X) + except AttributeError: + from sklearn.metrics import pairwise_distances_argmin_min + cluster_labels, _ = pairwise_distances_argmin_min(X, kmeans_model.cluster_centers_) save_one_lime_predict_and_kmean_labels( interpreter.local_weights, pred_label, cluster_labels, diff --git a/paddlex/interpret/visualize.py b/paddlex/interpret/visualize.py index 1b2e12110efef909abe18a18463bc8e2417d83df..de8e9151b9417fd3307c74d7bb67767bed1845c7 100644 --- a/paddlex/interpret/visualize.py +++ b/paddlex/interpret/visualize.py @@ -22,20 +22,65 @@ from .interpretation_predict import interpretation_predict from .core.interpretation import Interpretation from .core.normlime_base import precompute_normlime_weights from .core._session_preparation import gen_user_home - -def visualize(img_file, + +def lime(img_file, + model, + num_samples=3000, + batch_size=50, + save_dir='./'): + """使用LIME算法将模型预测结果的可解释性可视化。 + + LIME表示与模型无关的局部可解释性,可以解释任何模型。LIME的思想是以输入样本为中心, + 在其附近的空间中进行随机采样,每个采样通过原模型得到新的输出,这样得到一系列的输入 + 和对应的输出,LIME用一个简单的、可解释的模型(比如线性回归模型)来拟合这个映射关系, + 得到每个输入维度的权重,以此来解释模型。 + + 注意:LIME可解释性结果可视化目前只支持分类模型。 + + Args: + img_file (str): 预测图像路径。 + model (paddlex.cv.models): paddlex中的模型。 + num_samples (int): LIME用于学习线性模型的采样数,默认为3000。 + batch_size (int): 预测数据batch大小,默认为50。 + save_dir (str): 可解释性可视化结果(保存为png格式文件)和中间文件存储路径。 + """ + assert model.model_type == 'classifier', \ + 'Now the interpretation visualize only be supported in classifier!' + if model.status != 'Normal': + raise Exception('The interpretation only can deal with the Normal model') + if not osp.exists(save_dir): + os.makedirs(save_dir) + model.arrange_transforms( + transforms=model.test_transforms, mode='test') + tmp_transforms = copy.deepcopy(model.test_transforms) + tmp_transforms.transforms = tmp_transforms.transforms[:-2] + img = tmp_transforms(img_file)[0] + img = np.around(img).astype('uint8') + img = np.expand_dims(img, axis=0) + interpreter = None + interpreter = get_lime_interpreter(img, model, num_samples=num_samples, batch_size=batch_size) + img_name = osp.splitext(osp.split(img_file)[-1])[0] + interpreter.interpret(img, save_dir=save_dir) + + +def normlime(img_file, model, dataset=None, - algo='lime', num_samples=3000, batch_size=50, save_dir='./'): - """可解释性可视化。 + """使用NormLIME算法将模型预测结果的可解释性可视化。 + + NormLIME是利用一定数量的样本来出一个全局的解释。NormLIME会提前计算一定数量的测 + 试样本的LIME结果,然后对相同的特征进行权重的归一化,这样来得到一个全局的输入和输出的关系。 + + 注意1:dataset读取的是一个数据集,该数据集不宜过大,否则计算时间会较长,但应包含所有类别的数据。 + 注意2:NormLIME可解释性结果可视化目前只支持分类模型。 + Args: img_file (str): 预测图像路径。 model (paddlex.cv.models): paddlex中的模型。 dataset (paddlex.datasets): 数据集读取器,默认为None。 - algo (str): 可解释性方式,当前可选'lime'和'normlime'。 num_samples (int): LIME用于学习线性模型的采样数,默认为3000。 batch_size (int): 预测数据batch大小,默认为50。 save_dir (str): 可解释性可视化结果(保存为png格式文件)和中间文件存储路径。 @@ -54,21 +99,16 @@ def visualize(img_file, img = np.around(img).astype('uint8') img = np.expand_dims(img, axis=0) interpreter = None - if algo == 'lime': - interpreter = get_lime_interpreter(img, model, dataset, num_samples=num_samples, batch_size=batch_size) - elif algo == 'normlime': - if dataset is None: - raise Exception('The dataset is None. Cannot implement this kind of interpretation') - interpreter = get_normlime_interpreter(img, model, dataset, - num_samples=num_samples, batch_size=batch_size, + if dataset is None: + raise Exception('The dataset is None. Cannot implement this kind of interpretation') + interpreter = get_normlime_interpreter(img, model, dataset, + num_samples=num_samples, batch_size=batch_size, save_dir=save_dir) - else: - raise Exception('The {} interpretation method is not supported yet!'.format(algo)) img_name = osp.splitext(osp.split(img_file)[-1])[0] interpreter.interpret(img, save_dir=save_dir) -def get_lime_interpreter(img, model, dataset, num_samples=3000, batch_size=50): +def get_lime_interpreter(img, model, num_samples=3000, batch_size=50): def predict_func(image): image = image.astype('float32') for i in range(image.shape[0]): @@ -79,8 +119,8 @@ def get_lime_interpreter(img, model, dataset, num_samples=3000, batch_size=50): model.test_transforms.transforms = tmp_transforms return out[0] labels_name = None - if dataset is not None: - labels_name = dataset.labels + if hasattr(model, 'labels'): + labels_name = model.labels interpreter = Interpretation('lime', predict_func, labels_name, diff --git a/setup.py b/setup.py index ffc6377b6800138e615e7bf918ef918b0185f60e..55d8a5b91392960db6b6defd86bfe51fd30eb11d 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ long_description = "PaddleX. A end-to-end deeplearning model development toolkit setuptools.setup( name="paddlex", - version='0.2.0', + version='1.0.1', author="paddlex", author_email="paddlex@baidu.com", description=long_description, @@ -30,7 +30,7 @@ setuptools.setup( setup_requires=['cython', 'numpy'], install_requires=[ "pycocotools;platform_system!='Windows'", 'pyyaml', 'colorama', 'tqdm', - 'paddleslim==1.0.1', 'visualdl>=2.0.0a2' + 'paddleslim==1.0.1', 'visualdl>=2.0.0b', 'paddlehub>=1.6.2' ], classifiers=[ "Programming Language :: Python :: 3", diff --git a/tutorials/compress/classification/cal_sensitivities_file.py b/tutorials/compress/classification/cal_sensitivities_file.py index bfe17385c41dd4b4d49d0efa968ea8ccf1cfa4a9..b762ec26031d4b971d6311f13ef79ce721ecb670 100644 --- a/tutorials/compress/classification/cal_sensitivities_file.py +++ b/tutorials/compress/classification/cal_sensitivities_file.py @@ -1,16 +1,16 @@ -#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. -# -#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. +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. import argparse import os diff --git a/tutorials/compress/classification/mobilenetv2.py b/tutorials/compress/classification/mobilenetv2.py index 7ab2a6049fc006f8932e78372f6f421b42f9c1e5..86fb3795c9103def6b72daede56856a8ce9388cd 100644 --- a/tutorials/compress/classification/mobilenetv2.py +++ b/tutorials/compress/classification/mobilenetv2.py @@ -1,16 +1,16 @@ -#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. -# -#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. +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. import argparse import os diff --git a/tutorials/interpret/lime.py b/tutorials/interpret/lime.py new file mode 100644 index 0000000000000000000000000000000000000000..ae862aa9e41f4ad95c335c8e2a6de5a3b76a4ea2 --- /dev/null +++ b/tutorials/interpret/lime.py @@ -0,0 +1,23 @@ +import os +# 选择使用0号卡 +os.environ['CUDA_VISIBLE_DEVICES'] = '0' + +import os.path as osp +import paddlex as pdx + +# 下载和解压Imagenet果蔬分类数据集 +veg_dataset = 'https://bj.bcebos.com/paddlex/interpret/mini_imagenet_veg.tar.gz' +pdx.utils.download_and_decompress(veg_dataset, path='./') + +# 下载和解压已训练好的MobileNetV2模型 +model_file = 'https://bj.bcebos.com/paddlex/interpret/mini_imagenet_veg_mobilenetv2.tar.gz' +pdx.utils.download_and_decompress(model_file, path='./') + +# 加载模型 +model = pdx.load_model('mini_imagenet_veg_mobilenetv2') + +# 可解释性可视化 +pdx.interpret.lime( + 'mini_imagenet_veg/mushroom/n07734744_1106.JPEG', + model, + save_dir='./') diff --git a/tutorials/interpret/interpret.py b/tutorials/interpret/normlime.py similarity index 81% rename from tutorials/interpret/interpret.py rename to tutorials/interpret/normlime.py index f52d1053f5dcb1b2f1a585f50e9e0f2b1cb13ef2..3e501388e44aeab8548ae123831bc3211b08cea7 100644 --- a/tutorials/interpret/interpret.py +++ b/tutorials/interpret/normlime.py @@ -24,15 +24,8 @@ test_dataset = pdx.datasets.ImageNet( transforms=model.test_transforms) # 可解释性可视化 -pdx.interpret.visualize( - 'mini_imagenet_veg/mushroom/n07734744_1106.JPEG', - model, - test_dataset, - algo='lime', - save_dir='./') -pdx.interpret.visualize( +pdx.interpret.normlime( 'mini_imagenet_veg/mushroom/n07734744_1106.JPEG', model, test_dataset, - algo='normlime', save_dir='./')