diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 21bab1f7baea919e7548df5adbf4f312c7dacc75..7aed9143a1ac7f5fb7c8768588e7354593a55a62 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,8 @@ -- repo: local +- repo: https://github.com/PaddlePaddle/mirrors-yapf.git + sha: 0d79c0c469bab64f7229c9aca2b1186ef47f0e37 hooks: - id: yapf - name: yapf - entry: yapf - language: system - args: [-i, --style .style.yapf] files: \.py$ - - repo: https://github.com/pre-commit/pre-commit-hooks sha: a11d9314b22d8f8c7556443875b731ef05965464 hooks: diff --git a/README.md b/README.md index 1c5e93d11f427c81eb193be9dbe747ef36b50dda..a27e3ae5e61667618daf9d83b51ce6968fd02e51 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,45 @@ -PaddleX +

+ PaddleX +

[![License](https://img.shields.io/badge/license-Apache%202-red.svg)](LICENSE) [![Version](https://img.shields.io/github/release/PaddlePaddle/PaddleX.svg)](https://github.com/PaddlePaddle/PaddleX/releases) ![python version](https://img.shields.io/badge/python-3.6+-orange.svg) ![support os](https://img.shields.io/badge/os-linux%2C%20win%2C%20mac-yellow.svg) -PaddleX是基于飞桨开发套件和工具组件的深度学习全流程开发工具。具备易集成,易使用,全流程等特点。PaddleX作为深度学习开发工具,不仅提供了开源的内核代码,可供用户灵活使用或集成,同时也提供了配套的前端可视化客户端套件,让用户以可视化的方式进行模型开发,免去代码开发过程。 +PaddleX是基于飞桨核心框架、开发套件和工具组件的深度学习全流程开发工具。具备**全流程打通**、**融合产业实践**、**易用易集成**三大特点。 -访问[PaddleX官网](https://www.paddlepaddle.org.cn/paddle/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)便捷完成高性能且可靠的多端部署。 -PaddleX提供两种使用模式,满足不同的场景和用户需求: -- **开发模式:** pip安装后,开发者可通过Python API调用方式更灵活地完成模型的训练与软件集成。 -- **可视化模式:** 通过绿色安装的跨平台软件包,用户即可开箱即用,以可视化方式快速体验飞桨深度学习的全流程。 +- **融合产业实践** + - 精选飞桨产业实践的成熟模型结构,开放案例实践教程,加速开发者产业落地。 + - 通过[PaddleHub](https://github.com/PaddlePaddle/Paddle)内置丰富的飞桨高质量预训练模型,助力开发者高效实现飞桨Master模式。 -### 开发模式 +- **易用易集成** + - PadldeX提供简洁易用的全流程API,几行代码即可实现上百种数据增强、模型可解释性、C++模型部署等功能。 + - 提供以PaddleX API为核心集成的跨平台GUI界面,降低深度学习全流程应用门槛。 + + +## 安装 + +PaddleX提供两种开发模式,满足不同场景和用户需求: + +- **Python开发模式:** 通过Python API方式完成全流程使用或集成,该模型提供全面、灵活、开放的深度学习功能,有更高的定制化空间。 + +- **GUI开发模式:** 以PaddleX API为核心集成的跨平台GUI客户端,支持`Python开发模式`下的常用功能,以更低门槛的方式快速完成产业验证的模型训练。 + +开发者可根据自身需要按需选择不同的模式进行安装使用。 + + +### Python开发模式安装 **前置依赖** -* paddlepaddle >= 1.7.0 +* paddlepaddle >= 1.8.0 * python >= 3.5 * cython * pycocotools @@ -27,36 +48,39 @@ PaddleX提供两种使用模式,满足不同的场景和用户需求: pip install paddlex -i https://mirror.baidu.com/pypi/simple ``` -### 可视化模式 +### GUI开发模式安装 进入PaddleX官网[下载使用](https://www.paddlepaddle.org.cn/paddle/paddlex),申请下载绿色安装包,开箱即用。 +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分钟快速上手PaddleX模型训练](docs/quick_start.md) -- [PaddleX使用教程](docs/tutorials) -- [PaddleX模型库](docs/model_zoo.md) -- [模型多端部署](docs/deploy.md) -- [PaddleX可视化模式进行模型训练](docs/client_use.md) +- [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) + +## 在线教程 + +基于AIStudio平台,快速在线体验PaddleX的Python开发模式教程。 +- [PaddleX快速上手——MobileNetV3-ssld 化妆品分类](https://aistudio.baidu.com/aistudio/projectdetail/450220) +- [PaddleX快速上手——Faster-RCNN AI识虫](https://aistudio.baidu.com/aistudio/projectdetail/439888) +- [PaddleX快速上手——DeepLabv3+ 视盘分割](https://aistudio.baidu.com/aistudio/projectdetail/440197) -## 反馈 +## 交流与反馈 - 项目官网: https://www.paddlepaddle.org.cn/paddle/paddlex - PaddleX用户QQ群: 1045148026 (手机QQ扫描如下二维码快速加入) -QQGroup +QQGroup +## FAQ -## 飞桨技术生态 +## 更新日志 -PaddleX全流程开发工具依赖以下飞桨开发套件与工具组件 +## 贡献代码 -- [PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection) -- [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg) -- [PaddleClas](https://github.com/PaddlePaddle/PaddleClas) -- [PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim) -- [PaddleHub](https://github.com/PaddlePaddle/PaddleHub) -- [Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite) -- [VisualDL](https://github.com/PaddlePaddle/VisualDL) +我们非常欢迎您为PaddleX贡献代码或者提供使用建议。如果您可以修复某个issue或者增加一个新功能,欢迎给我们提交Pull Requests. diff --git a/deploy/README.md b/deploy/README.md index 37007ac7387c5ec808adfb1f3ed200ea41f9b8f8..1a9efe9d8ef9810592bd05e2e9fbd06842303c49 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -2,4 +2,5 @@ 本目录为PaddleX模型部署代码, 编译和使用的教程参考: -- [C++部署文档](../docs/deploy/deploy.md#C部署) +- [C++部署文档](../docs/tutorials/deploy/deploy.md#C部署) +- [OpenVINO部署文档](../docs/tutorials/deploy/deploy.md#openvino部署) diff --git a/deploy/cpp/CMakeLists.txt b/deploy/cpp/CMakeLists.txt index d04bf85183e7aaf64950cf56ab9ffe7a78ddb3fe..bd13a46713e1239380891e25c3ee7cb68f0f8d1e 100644 --- a/deploy/cpp/CMakeLists.txt +++ b/deploy/cpp/CMakeLists.txt @@ -5,12 +5,29 @@ option(WITH_MKL "Compile demo with MKL/OpenBlas support,defaultuseMKL." option(WITH_GPU "Compile demo with GPU/CPU, default use CPU." ON) option(WITH_STATIC_LIB "Compile demo with static/shared library, default use static." OFF) option(WITH_TENSORRT "Compile demo with TensorRT." OFF) +option(WITH_ENCRYPTION "Compile demo with encryption tool." OFF) -SET(TENSORRT_DIR "" CACHE PATH "Compile demo with TensorRT") +SET(TENSORRT_DIR "" CACHE PATH "Location of libraries") SET(PADDLE_DIR "" CACHE PATH "Location of libraries") SET(OPENCV_DIR "" CACHE PATH "Location of libraries") +SET(ENCRYPTION_DIR"" CACHE PATH "Location of libraries") SET(CUDA_LIB "" CACHE PATH "Location of libraries") +if (NOT WIN32) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/demo) +else() + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/paddlex_inference) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/paddlex_inference) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/paddlex_inference) +endif() + +if (NOT WIN32) + SET(YAML_BUILD_TYPE ON CACHE BOOL "yaml build shared library.") +else() + SET(YAML_BUILD_TYPE OFF CACHE BOOL "yaml build shared library.") +endif() include(cmake/yaml-cpp.cmake) include_directories("${CMAKE_SOURCE_DIR}/") @@ -27,6 +44,11 @@ macro(safe_set_static_flag) endforeach(flag_var) endmacro() + +if (WITH_ENCRYPTION) +add_definitions( -DWITH_ENCRYPTION=${WITH_ENCRYPTION}) +endif() + if (WITH_MKL) ADD_DEFINITIONS(-DUSE_MKL) endif() @@ -183,6 +205,7 @@ else() set(DEPS ${DEPS} ${MATH_LIB} ${MKLDNN_LIB} glog gflags_static libprotobuf zlibstatic xxhash libyaml-cppmt) + set(DEPS ${DEPS} libcmt shlwapi) if (EXISTS "${PADDLE_DIR}/third_party/install/snappy/lib") set(DEPS ${DEPS} snappy) @@ -207,21 +230,35 @@ if(WITH_GPU) endif() endif() +if(WITH_ENCRYPTION) + if(NOT WIN32) + include_directories("${ENCRYPTION_DIR}/include") + link_directories("${ENCRYPTION_DIR}/lib") + set(DEPS ${DEPS} ${ENCRYPTION_DIR}/lib/libpmodel-decrypt${CMAKE_SHARED_LIBRARY_SUFFIX}) + else() + message(FATAL_ERROR "Encryption Tool don't support WINDOWS") + endif() +endif() + if (NOT WIN32) set(EXTERNAL_LIB "-ldl -lrt -lgomp -lz -lm -lpthread") set(DEPS ${DEPS} ${EXTERNAL_LIB}) endif() set(DEPS ${DEPS} ${OpenCV_LIBS}) -add_executable(classifier src/classifier.cpp src/transforms.cpp src/paddlex.cpp) +add_library(paddlex_inference SHARED src/visualize src/transforms.cpp src/paddlex.cpp) +ADD_DEPENDENCIES(paddlex_inference ext-yaml-cpp) +target_link_libraries(paddlex_inference ${DEPS}) + +add_executable(classifier demo/classifier.cpp src/transforms.cpp src/paddlex.cpp) ADD_DEPENDENCIES(classifier ext-yaml-cpp) target_link_libraries(classifier ${DEPS}) -add_executable(detector src/detector.cpp src/transforms.cpp src/paddlex.cpp src/visualize.cpp) +add_executable(detector demo/detector.cpp src/transforms.cpp src/paddlex.cpp src/visualize.cpp) ADD_DEPENDENCIES(detector ext-yaml-cpp) target_link_libraries(detector ${DEPS}) -add_executable(segmenter src/segmenter.cpp src/transforms.cpp src/paddlex.cpp src/visualize.cpp) +add_executable(segmenter demo/segmenter.cpp src/transforms.cpp src/paddlex.cpp src/visualize.cpp) ADD_DEPENDENCIES(segmenter ext-yaml-cpp) target_link_libraries(segmenter ${DEPS}) @@ -252,3 +289,14 @@ if (WIN32 AND WITH_MKL) ) endif() + +file(COPY "${CMAKE_SOURCE_DIR}/include/paddlex/visualize.h" +DESTINATION "${CMAKE_BINARY_DIR}/include/" ) +file(COPY "${CMAKE_SOURCE_DIR}/include/paddlex/config_parser.h" +DESTINATION "${CMAKE_BINARY_DIR}/include/" ) +file(COPY "${CMAKE_SOURCE_DIR}/include/paddlex/transforms.h" +DESTINATION "${CMAKE_BINARY_DIR}/include/" ) +file(COPY "${CMAKE_SOURCE_DIR}/include/paddlex/results.h" +DESTINATION "${CMAKE_BINARY_DIR}/include/" ) +file(COPY "${CMAKE_SOURCE_DIR}/include/paddlex/paddlex.h" +DESTINATION "${CMAKE_BINARY_DIR}/include/" ) diff --git a/deploy/cpp/cmake/yaml-cpp.cmake b/deploy/cpp/cmake/yaml-cpp.cmake index 30d904dc76196cf106abccb47c003eed485691f1..caa8be513bcaaf7ff73c12c268b8137e5582672c 100644 --- a/deploy/cpp/cmake/yaml-cpp.cmake +++ b/deploy/cpp/cmake/yaml-cpp.cmake @@ -14,7 +14,7 @@ ExternalProject_Add( -DYAML_CPP_INSTALL=OFF -DYAML_CPP_BUILD_CONTRIB=OFF -DMSVC_SHARED_RT=OFF - -DBUILD_SHARED_LIBS=OFF + -DBUILD_SHARED_LIBS=${YAML_BUILD_TYPE} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} -DCMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG} diff --git a/deploy/cpp/src/classifier.cpp b/deploy/cpp/demo/classifier.cpp similarity index 94% rename from deploy/cpp/src/classifier.cpp rename to deploy/cpp/demo/classifier.cpp index a885ab6a09aa3996e7fc2c661b955754e813c92a..badb835132418098d332014a590d2dbb7a1e43fd 100644 --- a/deploy/cpp/src/classifier.cpp +++ b/deploy/cpp/demo/classifier.cpp @@ -25,6 +25,7 @@ DEFINE_string(model_dir, "", "Path of inference model"); DEFINE_bool(use_gpu, false, "Infering with GPU or CPU"); DEFINE_bool(use_trt, false, "Infering with TensorRT"); DEFINE_int32(gpu_id, 0, "GPU card id"); +DEFINE_string(key, "", "key of encryption"); DEFINE_string(image, "", "Path of test image file"); DEFINE_string(image_list, "", "Path of test image list file"); @@ -43,7 +44,7 @@ int main(int argc, char** argv) { // 加载模型 PaddleX::Model model; - model.Init(FLAGS_model_dir, FLAGS_use_gpu, FLAGS_use_trt, FLAGS_gpu_id); + model.Init(FLAGS_model_dir, FLAGS_use_gpu, FLAGS_use_trt, FLAGS_gpu_id, FLAGS_key); // 进行预测 if (FLAGS_image_list != "") { diff --git a/deploy/cpp/src/detector.cpp b/deploy/cpp/demo/detector.cpp similarity index 92% rename from deploy/cpp/src/detector.cpp rename to deploy/cpp/demo/detector.cpp index f31178b26f644eb6cb8c22de403f0c5758655ab7..e5fc2800e2678aa26a15c9fa78d2de9b2e6e58ea 100644 --- a/deploy/cpp/src/detector.cpp +++ b/deploy/cpp/demo/detector.cpp @@ -26,6 +26,7 @@ DEFINE_string(model_dir, "", "Path of inference model"); DEFINE_bool(use_gpu, false, "Infering with GPU or CPU"); DEFINE_bool(use_trt, false, "Infering with TensorRT"); DEFINE_int32(gpu_id, 0, "GPU card id"); +DEFINE_string(key, "", "key of encryption"); DEFINE_string(image, "", "Path of test image file"); DEFINE_string(image_list, "", "Path of test image list file"); DEFINE_string(save_dir, "output", "Path to save visualized image"); @@ -45,7 +46,7 @@ int main(int argc, char** argv) { // 加载模型 PaddleX::Model model; - model.Init(FLAGS_model_dir, FLAGS_use_gpu, FLAGS_use_trt, FLAGS_gpu_id); + model.Init(FLAGS_model_dir, FLAGS_use_gpu, FLAGS_use_trt, FLAGS_gpu_id, FLAGS_key); auto colormap = PaddleX::GenerateColorMap(model.labels.size()); std::string save_dir = "output"; @@ -74,7 +75,7 @@ int main(int argc, char** argv) { // 可视化 cv::Mat vis_img = - PaddleX::VisualizeDet(im, result, model.labels, colormap, 0.5); + PaddleX::Visualize(im, result, model.labels, colormap, 0.5); std::string save_path = PaddleX::generate_save_path(FLAGS_save_dir, image_path); cv::imwrite(save_path, vis_img); @@ -97,7 +98,7 @@ int main(int argc, char** argv) { // 可视化 cv::Mat vis_img = - PaddleX::VisualizeDet(im, result, model.labels, colormap, 0.5); + PaddleX::Visualize(im, result, model.labels, colormap, 0.5); std::string save_path = PaddleX::generate_save_path(FLAGS_save_dir, FLAGS_image); cv::imwrite(save_path, vis_img); diff --git a/deploy/cpp/src/segmenter.cpp b/deploy/cpp/demo/segmenter.cpp similarity index 90% rename from deploy/cpp/src/segmenter.cpp rename to deploy/cpp/demo/segmenter.cpp index d4b7aae37675ef96bae27e9fd0eba9a91d88c38b..0492ef803e15268022d869eb8b8e84969b1c8fad 100644 --- a/deploy/cpp/src/segmenter.cpp +++ b/deploy/cpp/demo/segmenter.cpp @@ -26,6 +26,7 @@ DEFINE_string(model_dir, "", "Path of inference model"); DEFINE_bool(use_gpu, false, "Infering with GPU or CPU"); DEFINE_bool(use_trt, false, "Infering with TensorRT"); DEFINE_int32(gpu_id, 0, "GPU card id"); +DEFINE_string(key, "", "key of encryption"); DEFINE_string(image, "", "Path of test image file"); DEFINE_string(image_list, "", "Path of test image list file"); DEFINE_string(save_dir, "output", "Path to save visualized image"); @@ -45,7 +46,7 @@ int main(int argc, char** argv) { // 加载模型 PaddleX::Model model; - model.Init(FLAGS_model_dir, FLAGS_use_gpu, FLAGS_use_trt, FLAGS_gpu_id); + model.Init(FLAGS_model_dir, FLAGS_use_gpu, FLAGS_use_trt, FLAGS_gpu_id, FLAGS_key); auto colormap = PaddleX::GenerateColorMap(model.labels.size()); // 进行预测 @@ -62,7 +63,7 @@ int main(int argc, char** argv) { model.predict(im, &result); // 可视化 cv::Mat vis_img = - PaddleX::VisualizeSeg(im, result, model.labels, colormap); + PaddleX::Visualize(im, result, model.labels, colormap); std::string save_path = PaddleX::generate_save_path(FLAGS_save_dir, image_path); cv::imwrite(save_path, vis_img); @@ -74,7 +75,7 @@ int main(int argc, char** argv) { cv::Mat im = cv::imread(FLAGS_image, 1); model.predict(im, &result); // 可视化 - cv::Mat vis_img = PaddleX::VisualizeSeg(im, result, model.labels, colormap); + cv::Mat vis_img = PaddleX::Visualize(im, result, model.labels, colormap); std::string save_path = PaddleX::generate_save_path(FLAGS_save_dir, FLAGS_image); cv::imwrite(save_path, vis_img); diff --git a/deploy/cpp/include/paddlex/paddlex.h b/deploy/cpp/include/paddlex/paddlex.h index 3e951f46c4ac295e35c3c2a211d09b2eead3fc46..d000728c763666e46271d4602b0e42c41dc130f1 100644 --- a/deploy/cpp/include/paddlex/paddlex.h +++ b/deploy/cpp/include/paddlex/paddlex.h @@ -28,9 +28,14 @@ #include "paddle_inference_api.h" // NOLINT -#include "include/paddlex/config_parser.h" -#include "include/paddlex/results.h" -#include "include/paddlex/transforms.h" +#include "config_parser.h" +#include "results.h" +#include "transforms.h" + +#ifdef WITH_ENCRYPTION +#include "paddle_model_decrypt.h" +#include "model_code.h" +#endif namespace PaddleX { @@ -39,14 +44,16 @@ class Model { void Init(const std::string& model_dir, bool use_gpu = false, bool use_trt = false, - int gpu_id = 0) { - create_predictor(model_dir, use_gpu, use_trt, gpu_id); + int gpu_id = 0, + std::string key = "") { + create_predictor(model_dir, use_gpu, use_trt, gpu_id, key); } void create_predictor(const std::string& model_dir, bool use_gpu = false, bool use_trt = false, - int gpu_id = 0); + int gpu_id = 0, + std::string key = ""); bool load_config(const std::string& model_dir); diff --git a/deploy/cpp/include/paddlex/visualize.h b/deploy/cpp/include/paddlex/visualize.h index ba928b705ddd004277971cea4350a0610cf1af2c..7a71f474d028795aa1dec3cd993f5480c0906ced 100644 --- a/deploy/cpp/include/paddlex/visualize.h +++ b/deploy/cpp/include/paddlex/visualize.h @@ -46,13 +46,13 @@ namespace PaddleX { // Generate visualization colormap for each class std::vector GenerateColorMap(int num_class); -cv::Mat VisualizeDet(const cv::Mat& img, +cv::Mat Visualize(const cv::Mat& img, const DetResult& results, const std::map& labels, const std::vector& colormap, float threshold = 0.5); -cv::Mat VisualizeSeg(const cv::Mat& img, +cv::Mat Visualize(const cv::Mat& img, const SegResult& result, const std::map& labels, const std::vector& colormap); diff --git a/deploy/cpp/scripts/build.sh b/deploy/cpp/scripts/build.sh index b6b0b5ca14106951571112df92abef38e9d497f4..52019280e5ec1b2bdb1cc84094a2e63a4f98393d 100644 --- a/deploy/cpp/scripts/build.sh +++ b/deploy/cpp/scripts/build.sh @@ -16,6 +16,11 @@ CUDA_LIB=/path/to/cuda/lib/ # CUDNN 的 lib 路径 CUDNN_LIB=/path/to/cudnn/lib/ +# 是否加载加密后的模型 +WITH_ENCRYPTION=OFF +# 加密工具的路径 +ENCRYPTION_DIR=/path/to/encryption_tool/ + # OPENCV 路径, 如果使用自带预编译版本可不修改 OPENCV_DIR=$(pwd)/deps/opencv3gcc4.8/ sh $(pwd)/scripts/bootstrap.sh @@ -28,10 +33,12 @@ cmake .. \ -DWITH_GPU=${WITH_GPU} \ -DWITH_MKL=${WITH_MKL} \ -DWITH_TENSORRT=${WITH_TENSORRT} \ + -DWITH_ENCRYPTION=${WITH_ENCRYPTION} \ -DTENSORRT_DIR=${TENSORRT_DIR} \ -DPADDLE_DIR=${PADDLE_DIR} \ -DWITH_STATIC_LIB=${WITH_STATIC_LIB} \ -DCUDA_LIB=${CUDA_LIB} \ -DCUDNN_LIB=${CUDNN_LIB} \ + -DENCRYPTION_DIR=${ENCRYPTION_DIR} \ -DOPENCV_DIR=${OPENCV_DIR} make diff --git a/deploy/cpp/src/paddlex.cpp b/deploy/cpp/src/paddlex.cpp index ddaecaa3f19788ceb3c57bf133f7f6a32f894f50..d10c3fd429202c57f074ffacb248fa7eb243cd3f 100644 --- a/deploy/cpp/src/paddlex.cpp +++ b/deploy/cpp/src/paddlex.cpp @@ -19,7 +19,8 @@ namespace PaddleX { void Model::create_predictor(const std::string& model_dir, bool use_gpu, bool use_trt, - int gpu_id) { + int gpu_id, + std::string key) { // 读取配置文件 if (!load_config(model_dir)) { std::cerr << "Parse file 'model.yml' failed!" << std::endl; @@ -28,7 +29,14 @@ void Model::create_predictor(const std::string& model_dir, paddle::AnalysisConfig config; std::string model_file = model_dir + OS_PATH_SEP + "__model__"; std::string params_file = model_dir + OS_PATH_SEP + "__params__"; - config.SetModel(model_file, params_file); +#ifdef WITH_ENCRYPTION + if (key != ""){ + paddle_security_load_model(&config, key.c_str(), model_file.c_str(), params_file.c_str()); + } +#endif + if (key == ""){ + config.SetModel(model_file, params_file); + } if (use_gpu) { config.EnableUseGpu(100, gpu_id); } else { diff --git a/deploy/cpp/src/visualize.cpp b/deploy/cpp/src/visualize.cpp index 28c7c3bcce51a3f26dfd6ab3ea377b644e259622..6ec09fd1c2b7a342ea3d31e784a80033d80f1014 100644 --- a/deploy/cpp/src/visualize.cpp +++ b/deploy/cpp/src/visualize.cpp @@ -31,7 +31,7 @@ std::vector GenerateColorMap(int num_class) { return colormap; } -cv::Mat VisualizeDet(const cv::Mat& img, +cv::Mat Visualize(const cv::Mat& img, const DetResult& result, const std::map& labels, const std::vector& colormap, @@ -105,7 +105,7 @@ cv::Mat VisualizeDet(const cv::Mat& img, return vis_img; } -cv::Mat VisualizeSeg(const cv::Mat& img, +cv::Mat Visualize(const cv::Mat& img, const SegResult& result, const std::map& labels, const std::vector& colormap) { diff --git a/deploy/openvino/CMakeLists.txt b/deploy/openvino/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..8e32a9592fce38918e46ad9ab9e4b2d1fc97cd6e --- /dev/null +++ b/deploy/openvino/CMakeLists.txt @@ -0,0 +1,111 @@ +cmake_minimum_required(VERSION 3.0) +project(PaddleX CXX C) + + +option(WITH_STATIC_LIB "Compile demo with static/shared library, default use static." OFF) + +SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +SET(OPENVINO_DIR "" CACHE PATH "Location of libraries") +SET(OPENCV_DIR "" CACHE PATH "Location of libraries") +SET(GFLAGS_DIR "" CACHE PATH "Location of libraries") +SET(NGRAPH_LIB "" CACHE PATH "Location of libraries") + +include(cmake/yaml-cpp.cmake) + +include_directories("${CMAKE_SOURCE_DIR}/") +link_directories("${CMAKE_CURRENT_BINARY_DIR}") +include_directories("${CMAKE_CURRENT_BINARY_DIR}/ext/yaml-cpp/src/ext-yaml-cpp/include") +link_directories("${CMAKE_CURRENT_BINARY_DIR}/ext/yaml-cpp/lib") + +macro(safe_set_static_flag) + foreach(flag_var + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if(${flag_var} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + endif(${flag_var} MATCHES "/MD") + endforeach(flag_var) +endmacro() + +if (NOT DEFINED OPENVINO_DIR OR ${OPENVINO_DIR} STREQUAL "") + message(FATAL_ERROR "please set OPENVINO_DIR with -DOPENVINO_DIR=/path/influence_engine") +endif() + +if (NOT DEFINED OPENCV_DIR OR ${OPENCV_DIR} STREQUAL "") + message(FATAL_ERROR "please set OPENCV_DIR with -DOPENCV_DIR=/path/opencv") +endif() + +if (NOT DEFINED GFLAGS_DIR OR ${GFLAGS_DIR} STREQUAL "") + message(FATAL_ERROR "please set GFLAGS_DIR with -DGFLAGS_DIR=/path/gflags") +endif() + +if (NOT DEFINED NGRAPH_LIB OR ${NGRAPH_LIB} STREQUAL "") + message(FATAL_ERROR "please set NGRAPH_DIR with -DNGRAPH_DIR=/path/ngraph") +endif() + +include_directories("${OPENVINO_DIR}") +link_directories("${OPENVINO_DIR}/lib") +include_directories("${OPENVINO_DIR}/include") +link_directories("${OPENVINO_DIR}/external/tbb/lib") +include_directories("${OPENVINO_DIR}/external/tbb/include/tbb") + +link_directories("${GFLAGS_DIR}/lib") +include_directories("${GFLAGS_DIR}/include") + +link_directories("${NGRAPH_LIB}") +link_directories("${NGRAPH_LIB}/lib") + +if (WIN32) + find_package(OpenCV REQUIRED PATHS ${OPENCV_DIR}/build/ NO_DEFAULT_PATH) + unset(OpenCV_DIR CACHE) +else () + find_package(OpenCV REQUIRED PATHS ${OPENCV_DIR}/share/OpenCV NO_DEFAULT_PATH) +endif () + +include_directories(${OpenCV_INCLUDE_DIRS}) + +if (WIN32) + add_definitions("/DGOOGLE_GLOG_DLL_DECL=") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /bigobj /MTd") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /bigobj /MT") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj /MTd") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /bigobj /MT") + if (WITH_STATIC_LIB) + safe_set_static_flag() + add_definitions(-DSTATIC_LIB) + endif() +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -o2 -fopenmp -std=c++11") + set(CMAKE_STATIC_LIBRARY_PREFIX "") +endif() + + +if(WITH_STATIC_LIB) + set(DEPS ${OPENVINO_DIR}/lib/intel64/libinference_engine${CMAKE_STATIC_LIBRARY_SUFFIX}) + set(DEPS ${DEPS} ${OPENVINO_DIR}/lib/intel64/libinference_engine_legacy${CMAKE_STATIC_LIBRARY_SUFFIX}) +else() + set(DEPS ${OPENVINO_DIR}/lib/intel64/libinference_engine${CMAKE_SHARED_LIBRARY_SUFFIX}) + set(DEPS ${DEPS} ${OPENVINO_DIR}/lib/intel64/libinference_engine_legacy${CMAKE_SHARED_LIBRARY_SUFFIX}) +endif() + +if (NOT WIN32) + set(DEPS ${DEPS} + glog gflags z yaml-cpp + ) +else() + set(DEPS ${DEPS} + glog gflags_static libprotobuf zlibstatic xxhash libyaml-cppmt) + set(DEPS ${DEPS} libcmt shlwapi) +endif(NOT WIN32) + + +if (NOT WIN32) + set(EXTERNAL_LIB "-ldl -lrt -lgomp -lz -lm -lpthread") + set(DEPS ${DEPS} ${EXTERNAL_LIB}) +endif() + +set(DEPS ${DEPS} ${OpenCV_LIBS}) +add_executable(classifier src/classifier.cpp src/transforms.cpp src/paddlex.cpp) +ADD_DEPENDENCIES(classifier ext-yaml-cpp) +target_link_libraries(classifier ${DEPS}) + diff --git a/deploy/openvino/CMakeSettings.json b/deploy/openvino/CMakeSettings.json new file mode 100644 index 0000000000000000000000000000000000000000..861839dbc67816aeb96ca1ab174d95ca7dd292ef --- /dev/null +++ b/deploy/openvino/CMakeSettings.json @@ -0,0 +1,27 @@ +{ + "configurations": [ + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "variables": [ + { + "name": "OPENCV_DIR", + "value": "C:/projects/opencv", + "type": "PATH" + }, + { + "name": "OPENVINO_LIB", + "value": "C:/projetcs/inference_engine", + "type": "PATH" + } + ] + } + ] +} diff --git a/deploy/openvino/cmake/yaml-cpp.cmake b/deploy/openvino/cmake/yaml-cpp.cmake new file mode 100644 index 0000000000000000000000000000000000000000..30d904dc76196cf106abccb47c003eed485691f1 --- /dev/null +++ b/deploy/openvino/cmake/yaml-cpp.cmake @@ -0,0 +1,30 @@ +find_package(Git REQUIRED) + +include(ExternalProject) + +message("${CMAKE_BUILD_TYPE}") + +ExternalProject_Add( + ext-yaml-cpp + URL https://bj.bcebos.com/paddlex/deploy/deps/yaml-cpp.zip + URL_MD5 9542d6de397d1fbd649ed468cb5850e6 + CMAKE_ARGS + -DYAML_CPP_BUILD_TESTS=OFF + -DYAML_CPP_BUILD_TOOLS=OFF + -DYAML_CPP_INSTALL=OFF + -DYAML_CPP_BUILD_CONTRIB=OFF + -DMSVC_SHARED_RT=OFF + -DBUILD_SHARED_LIBS=OFF + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} + -DCMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG} + -DCMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} + -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_BINARY_DIR}/ext/yaml-cpp/lib + -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=${CMAKE_BINARY_DIR}/ext/yaml-cpp/lib + PREFIX "${CMAKE_BINARY_DIR}/ext/yaml-cpp" + # Disable install step + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + LOG_BUILD 1 +) + diff --git a/deploy/openvino/include/paddlex/config_parser.h b/deploy/openvino/include/paddlex/config_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..5303e4da7ac0eb3de73bc57059617d361065f136 --- /dev/null +++ b/deploy/openvino/include/paddlex/config_parser.h @@ -0,0 +1,57 @@ +// 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. + +#pragma once + +#include +#include +#include +#include + +#include "yaml-cpp/yaml.h" + +#ifdef _WIN32 +#define OS_PATH_SEP "\\" +#else +#define OS_PATH_SEP "/" +#endif + +namespace PaddleX { + +// Inference model configuration parser +class ConfigPaser { + public: + ConfigPaser() {} + + ~ConfigPaser() {} + + bool load_config(const std::string& model_dir, + const std::string& cfg = "model.yml") { + // Load as a YAML::Node + YAML::Node config; + config = YAML::LoadFile(model_dir + OS_PATH_SEP + cfg); + + if (config["Transforms"].IsDefined()) { + YAML::Node transforms_ = config["Transforms"]; + } else { + std::cerr << "There's no field 'Transforms' in model.yml" << std::endl; + return false; + } + return true; + } + + YAML::Node Transforms_; +}; + +} // namespace PaddleDetection diff --git a/deploy/openvino/include/paddlex/paddlex.h b/deploy/openvino/include/paddlex/paddlex.h new file mode 100644 index 0000000000000000000000000000000000000000..be31df6823870c9503a327d0c3bc264f1a5ac0e7 --- /dev/null +++ b/deploy/openvino/include/paddlex/paddlex.h @@ -0,0 +1,64 @@ +// 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. + +#pragma once + +#include +#include +#include + +#include "yaml-cpp/yaml.h" + +#ifdef _WIN32 +#define OS_PATH_SEP "\\" +#else +#define OS_PATH_SEP "/" +#endif + +#include +#include "include/paddlex/config_parser.h" +#include "include/paddlex/results.h" +#include "include/paddlex/transforms.h" +using namespace InferenceEngine; + +namespace PaddleX { + +class Model { + public: + void Init(const std::string& model_dir, + const std::string& cfg_dir, + std::string device) { + create_predictor(model_dir, cfg_dir, device); + } + + void create_predictor(const std::string& model_dir, + const std::string& cfg_dir, + std::string device); + + bool load_config(const std::string& model_dir); + + bool preprocess(cv::Mat* input_im); + + bool predict(const cv::Mat& im, ClsResult* result); + + std::string type; + std::string name; + std::vector labels; + Transforms transforms_; + Blob::Ptr inputs_; + Blob::Ptr output_; + CNNNetwork network_; + ExecutableNetwork executable_network_; +}; +} // namespce of PaddleX diff --git a/deploy/openvino/include/paddlex/results.h b/deploy/openvino/include/paddlex/results.h new file mode 100644 index 0000000000000000000000000000000000000000..de90c4a85130f42c0201f0d671fd3e2d53b0f37d --- /dev/null +++ b/deploy/openvino/include/paddlex/results.h @@ -0,0 +1,71 @@ +// 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. + +#pragma once + +#include +#include +#include + +namespace PaddleX { + +template +struct Mask { + std::vector data; + std::vector shape; + void clear() { + data.clear(); + shape.clear(); + } +}; + +struct Box { + int category_id; + std::string category; + float score; + std::vector coordinate; + Mask mask; +}; + +class BaseResult { + public: + std::string type = "base"; +}; + +class ClsResult : public BaseResult { + public: + int category_id; + std::string category; + float score; + std::string type = "cls"; +}; + +class DetResult : public BaseResult { + public: + std::vector boxes; + int mask_resolution; + std::string type = "det"; + void clear() { boxes.clear(); } +}; + +class SegResult : public BaseResult { + public: + Mask label_map; + Mask score_map; + void clear() { + label_map.clear(); + score_map.clear(); + } +}; +} // namespce of PaddleX diff --git a/deploy/openvino/include/paddlex/transforms.h b/deploy/openvino/include/paddlex/transforms.h new file mode 100644 index 0000000000000000000000000000000000000000..fa76a82999173ea01c80b8ea3b67ca1bc4f95fc7 --- /dev/null +++ b/deploy/openvino/include/paddlex/transforms.h @@ -0,0 +1,104 @@ +// 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. + +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +using namespace InferenceEngine; + +namespace PaddleX { + +// Abstraction of preprocessing opration class +class Transform { + public: + virtual void Init(const YAML::Node& item) = 0; + virtual bool Run(cv::Mat* im) = 0; +}; + +class Normalize : public Transform { + public: + virtual void Init(const YAML::Node& item) { + mean_ = item["mean"].as>(); + std_ = item["std"].as>(); + } + + virtual bool Run(cv::Mat* im); + + private: + std::vector mean_; + std::vector std_; +}; + +class ResizeByShort : public Transform { + public: + virtual void Init(const YAML::Node& item) { + short_size_ = item["short_size"].as(); + if (item["max_size"].IsDefined()) { + max_size_ = item["max_size"].as(); + } else { + max_size_ = -1; + } + }; + virtual bool Run(cv::Mat* im); + + private: + float GenerateScale(const cv::Mat& im); + int short_size_; + int max_size_; +}; + + +class CenterCrop : public Transform { + public: + virtual void Init(const YAML::Node& item) { + if (item["crop_size"].IsScalar()) { + height_ = item["crop_size"].as(); + width_ = item["crop_size"].as(); + } else if (item["crop_size"].IsSequence()) { + std::vector crop_size = item["crop_size"].as>(); + width_ = crop_size[0]; + height_ = crop_size[1]; + } + } + virtual bool Run(cv::Mat* im); + + private: + int height_; + int width_; +}; + +class Transforms { + public: + void Init(const YAML::Node& node, bool to_rgb = true); + std::shared_ptr CreateTransform(const std::string& name); + bool Run(cv::Mat* im, Blob::Ptr blob); + + private: + std::vector> transforms_; + bool to_rgb_ = true; +}; + +} // namespace PaddleX diff --git a/deploy/openvino/scripts/bootstrap.sh b/deploy/openvino/scripts/bootstrap.sh new file mode 100644 index 0000000000000000000000000000000000000000..f9fc1d1edc327370f7b5d8e7494cb88d4fd4d12c --- /dev/null +++ b/deploy/openvino/scripts/bootstrap.sh @@ -0,0 +1,10 @@ +# download pre-compiled opencv lib +OPENCV_URL=https://paddleseg.bj.bcebos.com/deploy/docker/opencv3gcc4.8.tar.bz2 +if [ ! -d "./deps/opencv3gcc4.8" ]; then + mkdir -p deps + cd deps + wget -c ${OPENCV_URL} + tar xvfj opencv3gcc4.8.tar.bz2 + rm -rf opencv3gcc4.8.tar.bz2 + cd .. +fi diff --git a/deploy/openvino/scripts/build.sh b/deploy/openvino/scripts/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..17f988146a6147030be35bd4abee966b569caa5f --- /dev/null +++ b/deploy/openvino/scripts/build.sh @@ -0,0 +1,21 @@ +# openvino预编译库的路径 +OPENVINO_DIR=/path/to/inference_engine/ +# gflags预编译库的路径 +GFLAGS_DIR=/path/to/gflags +# ngraph lib的路径,编译openvino时通常会生成 +NGRAPH_LIB=/path/to/ngraph/lib/ + +# opencv预编译库的路径, 如果使用自带预编译版本可不修改 +OPENCV_DIR=$(pwd)/deps/opencv3gcc4.8/ +# 下载自带预编译版本 +sh $(pwd)/scripts/bootstrap.sh + +rm -rf build +mkdir -p build +cd build +cmake .. \ + -DOPENCV_DIR=${OPENCV_DIR} \ + -DGFLAGS_DIR=${GFLAGS_DIR} \ + -DOPENVINO_DIR=${OPENVINO_DIR} \ + -DNGRAPH_LIB=${NGRAPH_LIB} +make diff --git a/deploy/openvino/src/classifier.cpp b/deploy/openvino/src/classifier.cpp new file mode 100644 index 0000000000000000000000000000000000000000..38c0da9b86d8b6d9c7d248aeb8526dfe1deab148 --- /dev/null +++ b/deploy/openvino/src/classifier.cpp @@ -0,0 +1,77 @@ +// 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 + +#include +#include +#include +#include + +#include "include/paddlex/paddlex.h" + +DEFINE_string(model_dir, "", "Path of inference model"); +DEFINE_string(cfg_dir, "", "Path of inference model"); +DEFINE_string(device, "CPU", "Device name"); +DEFINE_string(image, "", "Path of test image file"); +DEFINE_string(image_list, "", "Path of test image list file"); + +int main(int argc, char** argv) { + // Parsing command-line + google::ParseCommandLineFlags(&argc, &argv, true); + + if (FLAGS_model_dir == "") { + std::cerr << "--model_dir need to be defined" << std::endl; + return -1; + } + if (FLAGS_cfg_dir == "") { + std::cerr << "--cfg_dir need to be defined" << std::endl; + return -1; + } + if (FLAGS_image == "" & FLAGS_image_list == "") { + std::cerr << "--image or --image_list need to be defined" << std::endl; + return -1; + } + + // 加载模型 + PaddleX::Model model; + model.Init(FLAGS_model_dir, FLAGS_cfg_dir, FLAGS_device); + + // 进行预测 + if (FLAGS_image_list != "") { + std::ifstream inf(FLAGS_image_list); + if (!inf) { + std::cerr << "Fail to open file " << FLAGS_image_list << std::endl; + return -1; + } + std::string image_path; + while (getline(inf, image_path)) { + PaddleX::ClsResult result; + cv::Mat im = cv::imread(image_path, 1); + model.predict(im, &result); + std::cout << "Predict label: " << result.category + << ", label_id:" << result.category_id + << ", score: " << result.score << std::endl; + } + } else { + PaddleX::ClsResult result; + cv::Mat im = cv::imread(FLAGS_image, 1); + model.predict(im, &result); + std::cout << "Predict label: " << result.category + << ", label_id:" << result.category_id + << ", score: " << result.score << std::endl; + } + + return 0; +} diff --git a/deploy/openvino/src/paddlex.cpp b/deploy/openvino/src/paddlex.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bdae99892735ccc67d2189e1b6dcc0a0789dcf95 --- /dev/null +++ b/deploy/openvino/src/paddlex.cpp @@ -0,0 +1,108 @@ +// 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 "include/paddlex/paddlex.h" + +using namespace InferenceEngine; + +namespace PaddleX { + +void Model::create_predictor(const std::string& model_dir, + const std::string& cfg_dir, + std::string device) { + Core ie; + network_ = ie.ReadNetwork(model_dir, model_dir.substr(0, model_dir.size() - 4) + ".bin"); + network_.setBatchSize(1); + InputInfo::Ptr input_info = network_.getInputsInfo().begin()->second; + + input_info->getPreProcess().setResizeAlgorithm(RESIZE_BILINEAR); + input_info->setLayout(Layout::NCHW); + input_info->setPrecision(Precision::FP32); + executable_network_ = ie.LoadNetwork(network_, device); + load_config(cfg_dir); +} + +bool Model::load_config(const std::string& cfg_dir) { + YAML::Node config = YAML::LoadFile(cfg_dir); + type = config["_Attributes"]["model_type"].as(); + name = config["Model"].as(); + bool to_rgb = true; + if (config["TransformsMode"].IsDefined()) { + std::string mode = config["TransformsMode"].as(); + if (mode == "BGR") { + to_rgb = false; + } else if (mode != "RGB") { + std::cerr << "[Init] Only 'RGB' or 'BGR' is supported for TransformsMode" + << std::endl; + return false; + } + } + // 构建数据处理流 + transforms_.Init(config["Transforms"], to_rgb); + // 读入label list + labels.clear(); + labels = config["_Attributes"]["labels"].as>(); + return true; +} + +bool Model::preprocess(cv::Mat* input_im) { + if (!transforms_.Run(input_im, inputs_)) { + return false; + } + return true; +} + +bool Model::predict(const cv::Mat& im, ClsResult* result) { + if (type == "detector") { + std::cerr << "Loading model is a 'detector', DetResult should be passed to " + "function predict()!" + << std::endl; + return false; + } else if (type == "segmenter") { + std::cerr << "Loading model is a 'segmenter', SegResult should be passed " + "to function predict()!" + << std::endl; + return false; + } + // 处理输入图像 + InferRequest infer_request = executable_network_.CreateInferRequest(); + std::string input_name = network_.getInputsInfo().begin()->first; + inputs_ = infer_request.GetBlob(input_name); + + auto im_clone = im.clone(); + if (!preprocess(&im_clone)) { + std::cerr << "Preprocess failed!" << std::endl; + return false; + } + + infer_request.Infer(); + + std::string output_name = network_.getOutputsInfo().begin()->first; + output_ = infer_request.GetBlob(output_name); + MemoryBlob::CPtr moutput = as(output_); + auto moutputHolder = moutput->rmap(); + float* outputs_data = moutputHolder.as(); + + // 对模型输出结果进行后处理 + auto ptr = std::max_element(outputs_data, outputs_data+sizeof(outputs_data)); + result->category_id = std::distance(outputs_data, ptr); + result->score = *ptr; + result->category = labels[result->category_id]; + //for (int i=0;i +#include +#include + +#include "include/paddlex/transforms.h" + +namespace PaddleX { + +std::map interpolations = {{"LINEAR", cv::INTER_LINEAR}, + {"NEAREST", cv::INTER_NEAREST}, + {"AREA", cv::INTER_AREA}, + {"CUBIC", cv::INTER_CUBIC}, + {"LANCZOS4", cv::INTER_LANCZOS4}}; + +bool Normalize::Run(cv::Mat* im){ + for (int h = 0; h < im->rows; h++) { + for (int w = 0; w < im->cols; w++) { + im->at(h, w)[0] = + (im->at(h, w)[0] / 255.0 - mean_[0]) / std_[0]; + im->at(h, w)[1] = + (im->at(h, w)[1] / 255.0 - mean_[1]) / std_[1]; + im->at(h, w)[2] = + (im->at(h, w)[2] / 255.0 - mean_[2]) / std_[2]; + } + } + return true; +} + +bool CenterCrop::Run(cv::Mat* im) { + int height = static_cast(im->rows); + int width = static_cast(im->cols); + if (height < height_ || width < width_) { + std::cerr << "[CenterCrop] Image size less than crop size" << std::endl; + return false; + } + int offset_x = static_cast((width - width_) / 2); + int offset_y = static_cast((height - height_) / 2); + cv::Rect crop_roi(offset_x, offset_y, width_, height_); + *im = (*im)(crop_roi); + return true; +} + + +float ResizeByShort::GenerateScale(const cv::Mat& im) { + int origin_w = im.cols; + int origin_h = im.rows; + int im_size_max = std::max(origin_w, origin_h); + int im_size_min = std::min(origin_w, origin_h); + float scale = + static_cast(short_size_) / static_cast(im_size_min); + if (max_size_ > 0) { + if (round(scale * im_size_max) > max_size_) { + scale = static_cast(max_size_) / static_cast(im_size_max); + } + } + return scale; +} + +bool ResizeByShort::Run(cv::Mat* im) { + float scale = GenerateScale(*im); + int width = static_cast(scale * im->cols); + int height = static_cast(scale * im->rows); + cv::resize(*im, *im, cv::Size(width, height), 0, 0, cv::INTER_LINEAR); + return true; +} + +void Transforms::Init(const YAML::Node& transforms_node, bool to_rgb) { + transforms_.clear(); + to_rgb_ = to_rgb; + for (const auto& item : transforms_node) { + std::string name = item.begin()->first.as(); + std::cout << "trans name: " << name << std::endl; + std::shared_ptr transform = CreateTransform(name); + transform->Init(item.begin()->second); + transforms_.push_back(transform); + } +} + +std::shared_ptr Transforms::CreateTransform( + const std::string& transform_name) { + if (transform_name == "Normalize") { + return std::make_shared(); + } else if (transform_name == "CenterCrop") { + return std::make_shared(); + } else if (transform_name == "ResizeByShort") { + return std::make_shared(); + } else { + std::cerr << "There's unexpected transform(name='" << transform_name + << "')." << std::endl; + exit(-1); + } +} + +bool Transforms::Run(cv::Mat* im, Blob::Ptr blob) { + // 按照transforms中预处理算子顺序处理图像 + if (to_rgb_) { + cv::cvtColor(*im, *im, cv::COLOR_BGR2RGB); + } + (*im).convertTo(*im, CV_32FC3); + + for (int i = 0; i < transforms_.size(); ++i) { + if (!transforms_[i]->Run(im)) { + std::cerr << "Apply transforms to image failed!" << std::endl; + return false; + } + } + + // 将图像由NHWC转为NCHW格式 + // 同时转为连续的内存块存储到Blob + SizeVector blobSize = blob->getTensorDesc().getDims(); + const size_t width = blobSize[3]; + const size_t height = blobSize[2]; + const size_t channels = blobSize[1]; + MemoryBlob::Ptr mblob = InferenceEngine::as(blob); + auto mblobHolder = mblob->wmap(); + float *blob_data = mblobHolder.as(); + for (size_t c = 0; c < channels; c++) { + for (size_t h = 0; h < height; h++) { + for (size_t w = 0; w < width; w++) { + blob_data[c * width * height + h * width + w] = + im->at(h, w)[c]; + } + } + } + return true; +} +} // namespace PaddleX diff --git a/docs/FAQ.md b/docs/FAQ.md old mode 100644 new mode 100755 diff --git a/docs/Makefile b/docs/Makefile old mode 100644 new mode 100755 diff --git a/docs/README.md b/docs/README.md old mode 100644 new mode 100755 diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html new file mode 100644 index 0000000000000000000000000000000000000000..76d4bb0c6da716dc75d363d226dadf9173342f3a --- /dev/null +++ b/docs/_templates/layout.html @@ -0,0 +1,8 @@ +{% extends "!layout.html" %} + {% block footer %} {{ super() }} + + + +{% endblock %} diff --git a/docs/apis/datasets.md b/docs/apis/datasets.md deleted file mode 100644 index b40637f2aef586c79bb92b5bce3c5deb4b00893e..0000000000000000000000000000000000000000 --- a/docs/apis/datasets.md +++ /dev/null @@ -1,141 +0,0 @@ -# 数据集-datasets - -## ImageNet类 -``` -paddlex.datasets.ImageNet(data_dir, file_list, label_list, transforms=None, num_workers=‘auto’, buffer_size=100, parallel_method='thread', shuffle=False) -``` -读取ImageNet格式的分类数据集,并对样本进行相应的处理。ImageNet数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) - -示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/classification/mobilenetv2.py#L25) - -### 参数 - -> * **data_dir** (str): 数据集所在的目录路径。 -> * **file_list** (str): 描述数据集图片文件和类别id的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 -> * **label_list** (str): 描述数据集包含的类别信息文件路径。 -> * **transforms** (paddlex.cls.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.cls.transforms](./transforms/cls_transforms.md)。 -> * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 -> * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 -> * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 -> * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 - -## VOCDetection类 - -``` -paddlex.datasets.VOCDetection(data_dir, file_list, label_list, transforms=None, num_workers=‘auto’, buffer_size=100, parallel_method='thread', shuffle=False) -``` - -读取PascalVOC格式的检测数据集,并对样本进行相应的处理。PascalVOC数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) - -示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/detection/yolov3_mobilenetv1.py#L29) - -### 参数 - -> * **data_dir** (str): 数据集所在的目录路径。 -> * **file_list** (str): 描述数据集图片文件和对应标注文件的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 -> * **label_list** (str): 描述数据集包含的类别信息文件路径。 -> * **transforms** (paddlex.det.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.det.transforms](./transforms/det_transforms.md)。 -> * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 -> * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 -> * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 -> * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 - -## CocoDetection类 - -``` -paddlex.datasets.CocoDetection(data_dir, ann_file, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False) -``` - -读取MSCOCO格式的检测数据集,并对样本进行相应的处理,该格式的数据集同样可以应用到实例分割模型的训练中。MSCOCO数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) - -示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/detection/mask_rcnn_r50_fpn.py#L27) - -### 参数 - -> * **data_dir** (str): 数据集所在的目录路径。 -> * **ann_file** (str): 数据集的标注文件,为一个独立的json格式文件。 -> * **transforms** (paddlex.det.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.det.transforms](./transforms/det_transforms.md)。 -> * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 -> * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 -> * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 -> * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 - -## SegDataset类 - -``` -paddlex.datasets.SegDataset(data_dir, file_list, label_list, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False) -``` - -读取语分分割任务数据集,并对样本进行相应的处理。语义分割任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) - -示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/segmentation/unet.py#L27) - -### 参数 - -> * **data_dir** (str): 数据集所在的目录路径。 -> * **file_list** (str): 描述数据集图片文件和对应标注文件的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 -> * **label_list** (str): 描述数据集包含的类别信息文件路径。 -> * **transforms** (paddlex.seg.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.seg.transforms](./transforms/seg_transforms.md)。 -> * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 -> * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 -> * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 -> * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 - -## EasyDataCls类 -``` -paddlex.datasets.SegDataset(data_dir, file_list, label_list, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False) -``` -读取EasyData图像分类数据集,并对样本进行相应的处理。EasyData图像分类任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) - - -### 参数 - -> * **data_dir** (str): 数据集所在的目录路径。 -> * **file_list** (str): 描述数据集图片文件和对应标注文件的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 -> * **label_list** (str): 描述数据集包含的类别信息文件路径。 -> * **transforms** (paddlex.seg.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.cls.transforms](./transforms/cls_transforms.md)。 -> * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 -> * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 -> * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 -> * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 - -## EasyDataDet类 - -``` -paddlex.datasets.EasyDataDet(data_dir, file_list, label_list, transforms=None, num_workers=‘auto’, buffer_size=100, parallel_method='thread', shuffle=False) -``` - -读取EasyData目标检测格式数据集,并对样本进行相应的处理,该格式的数据集同样可以应用到实例分割模型的训练中。EasyData目标检测或实例分割任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) - - -### 参数 - -> * **data_dir** (str): 数据集所在的目录路径。 -> * **file_list** (str): 描述数据集图片文件和对应标注文件的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 -> * **label_list** (str): 描述数据集包含的类别信息文件路径。 -> * **transforms** (paddlex.det.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.det.transforms](./transforms/det_transforms.md)。 -> * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 -> * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 -> * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 -> * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 - - -## EasyDataSeg类 - -``` -paddlex.datasets.EasyDataSeg(data_dir, file_list, label_list, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False) -``` - -读取EasyData语分分割任务数据集,并对样本进行相应的处理。EasyData语义分割任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) - - -### 参数 - -> * **data_dir** (str): 数据集所在的目录路径。 -> * **file_list** (str): 描述数据集图片文件和对应标注文件的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 -> * **label_list** (str): 描述数据集包含的类别信息文件路径。 -> * **transforms** (paddlex.seg.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.seg.transforms](./transforms/seg_transforms.md)。 -> * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 -> * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 -> * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 -> * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 \ No newline at end of file diff --git a/docs/apis/datasets/classification.md b/docs/apis/datasets/classification.md new file mode 100755 index 0000000000000000000000000000000000000000..104bdf2dab80acfa8f1de1ef8ee522a126ddb7cc --- /dev/null +++ b/docs/apis/datasets/classification.md @@ -0,0 +1,38 @@ +# 图像分类数据集 + +## ImageNet类 +``` +paddlex.datasets.ImageNet(data_dir, file_list, label_list, transforms=None, num_workers=‘auto’, buffer_size=100, parallel_method='thread', shuffle=False) +``` +读取ImageNet格式的分类数据集,并对样本进行相应的处理。ImageNet数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) + +示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/classification/mobilenetv2.py#L25) + +> **参数** + +> > * **data_dir** (str): 数据集所在的目录路径。 +> > * **file_list** (str): 描述数据集图片文件和类别id的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 +> > * **label_list** (str): 描述数据集包含的类别信息文件路径。 +> > * **transforms** (paddlex.cls.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.cls.transforms](./transforms/cls_transforms.md)。 +> > * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 +> > * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 +> > * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 +> > * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 + +## EasyDataCls类 +``` +paddlex.datasets.EasyDatasetCls(data_dir, file_list, label_list, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False) +``` + +> 读取EasyData平台标注图像分类数据集,并对样本进行相应的处理。EasyData图像分类任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md)。 + +> **参数** + +> > * **data_dir** (str): 数据集所在的目录路径。 +> > * **file_list** (str): 描述数据集图片文件和对应标注文件的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 +> > * **label_list** (str): 描述数据集包含的类别信息文件路径。 +> > * **transforms** (paddlex.seg.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.cls.transforms](./transforms/cls_transforms.md)。 +> > * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 +> > * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 +> > * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 +> > * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 diff --git a/docs/apis/datasets/detection.md b/docs/apis/datasets/detection.md new file mode 100755 index 0000000000000000000000000000000000000000..e660d7edfa9cfc41582902b92bcf0b0977766222 --- /dev/null +++ b/docs/apis/datasets/detection.md @@ -0,0 +1,63 @@ +# 检测和实例分割数据集 + +## VOCDetection类 + +``` +paddlex.datasets.VOCDetection(data_dir, file_list, label_list, transforms=None, num_workers=‘auto’, buffer_size=100, parallel_method='thread', shuffle=False) +``` + +> 仅用于**目标检测**。读取PascalVOC格式的检测数据集,并对样本进行相应的处理。PascalVOC数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) + +> 示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/detection/yolov3_mobilenetv1.py#L29) + +> **参数** + +> > * **data_dir** (str): 数据集所在的目录路径。 +> > * **file_list** (str): 描述数据集图片文件和对应标注文件的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 +> > * **label_list** (str): 描述数据集包含的类别信息文件路径。 +> > * **transforms** (paddlex.det.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.det.transforms](./transforms/det_transforms.md)。 +> > * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 +> > * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 +> > * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 +> > * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 + +## CocoDetection类 + +``` +paddlex.datasets.CocoDetection(data_dir, ann_file, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False) +``` + +> 用于**目标检测或实例分割**。读取MSCOCO格式的检测数据集,并对样本进行相应的处理,该格式的数据集同样可以应用到实例分割模型的训练中。MSCOCO数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) + +> 示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/detection/mask_rcnn_r50_fpn.py#L27) + +> **参数** + +> > * **data_dir** (str): 数据集所在的目录路径。 +> > * **ann_file** (str): 数据集的标注文件,为一个独立的json格式文件。 +> > * **transforms** (paddlex.det.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.det.transforms](./transforms/det_transforms.md)。 +> > * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 +> > * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 +> > * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 +> > * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 + +## EasyDataDet类 + +``` +paddlex.datasets.EasyDataDet(data_dir, file_list, label_list, transforms=None, num_workers=‘auto’, buffer_size=100, parallel_method='thread', shuffle=False) +``` + +> 用于**目标检测或实例分割**。读取EasyData目标检测格式数据集,并对样本进行相应的处理,该格式的数据集同样可以应用到实例分割模型的训练中。EasyData目标检测或实例分割任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) + + +> **参数** + +> > * **data_dir** (str): 数据集所在的目录路径。 +> > * **file_list** (str): 描述数据集图片文件和对应标注文件的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 +> > * **label_list** (str): 描述数据集包含的类别信息文件路径。 +> > * **transforms** (paddlex.det.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.det.transforms](./transforms/det_transforms.md)。 +> > * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 +> > * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 +> > * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 +> > * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 + diff --git a/docs/apis/datasets/index.rst b/docs/apis/datasets/index.rst new file mode 100755 index 0000000000000000000000000000000000000000..e04aa4582c6ab7e8ac83aefb7ad1f7c4c3186889 --- /dev/null +++ b/docs/apis/datasets/index.rst @@ -0,0 +1,31 @@ +数据集-datasets +============================ + +PaddleX目前支持主流的CV数据集格式和 `EasyData `_ 数据标注平台的标注数据格式,此外PaddleX也提升了数据格式转换工具API,支持包括LabelMe,精灵标注助手和EasyData平台数据格式的转换,可以参考PaddleX的tools API文档。 + +下表为各数据集格式与相应任务的对应关系, + ++------------------------+------------+----------+----------+----------+ +| 数据集格式 | 图像分类 | 目标检测 | 实例分割 | 语义分割 | ++========================+============+==========+==========+==========+ +| ImageNet | √ | - | - | - | ++------------------------+------------+----------+----------+----------+ +| VOCDetection | - | √ | - | - | ++------------------------+------------+----------+----------+----------+ +| CocoDetection | - | √ | √ | - | ++------------------------+------------+----------+----------+----------+ +| SegDataset | - | - | - | √ | ++------------------------+------------+----------+----------+----------+ +| EasyDataCls | √ | - | - | - | ++------------------------+------------+----------+----------+----------+ +| EasyDataDet | - | √ | √ | - | ++------------------------+------------+----------+----------+----------+ +| EasyDataSeg | - | - | - | √ | ++------------------------+------------+----------+----------+----------+ + +.. toctree:: + :maxdepth: 2 + + classification.md + detection.md + semantic_segmentation.md diff --git a/docs/apis/datasets/semantic_segmentation.md b/docs/apis/datasets/semantic_segmentation.md new file mode 100755 index 0000000000000000000000000000000000000000..7aa4c21af7e1ebee850b185dea4f5d052abad167 --- /dev/null +++ b/docs/apis/datasets/semantic_segmentation.md @@ -0,0 +1,42 @@ +# 语义分割数据集 + +## SegDataset类 + +``` +paddlex.datasets.SegDataset(data_dir, file_list, label_list, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False) +``` + +> 读取语义分割任务数据集,并对样本进行相应的处理。语义分割任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) + +> 示例:[代码文件](https://github.com/PaddlePaddle/PaddleX/blob/develop/tutorials/train/segmentation/unet.py#L27) + +> **参数** + +> > * **data_dir** (str): 数据集所在的目录路径。 +> > * **file_list** (str): 描述数据集图片文件和对应标注文件的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 +> > * **label_list** (str): 描述数据集包含的类别信息文件路径。 +> > * **transforms** (paddlex.seg.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.seg.transforms](./transforms/seg_transforms.md)。 +> > * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 +> > * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 +> > * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 +> > * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 + +## EasyDataSeg类 + +``` +paddlex.datasets.EasyDataSeg(data_dir, file_list, label_list, transforms=None, num_workers='auto', buffer_size=100, parallel_method='thread', shuffle=False) +``` + +> 读取EasyData语义分割任务数据集,并对样本进行相应的处理。EasyData语义分割任务数据集格式的介绍可查看文档:[数据集格式说明](../datasets.md) + + +> **参数** + +> > * **data_dir** (str): 数据集所在的目录路径。 +> > * **file_list** (str): 描述数据集图片文件和对应标注文件的文件路径(文本内每行路径为相对`data_dir`的相对路径)。 +> > * **label_list** (str): 描述数据集包含的类别信息文件路径。 +> > * **transforms** (paddlex.seg.transforms): 数据集中每个样本的预处理/增强算子,详见[paddlex.seg.transforms](./transforms/seg_transforms.md)。 +> > * **num_workers** (int|str):数据集中样本在预处理过程中的线程或进程数。默认为'auto'。当设为'auto'时,根据系统的实际CPU核数设置`num_workers`: 如果CPU核数的一半大于8,则`num_workers`为8,否则为CPU核数的一半。 +> > * **buffer_size** (int): 数据集中样本在预处理过程中队列的缓存长度,以样本数为单位。默认为100。 +> > * **parallel_method** (str): 数据集中样本在预处理过程中并行处理的方式,支持'thread'线程和'process'进程两种方式。默认为'process'(Windows和Mac下会强制使用thread,该参数无效)。 +> > * **shuffle** (bool): 是否需要对数据集中样本打乱顺序。默认为False。 diff --git a/docs/apis/deploy.md b/docs/apis/deploy.md old mode 100644 new mode 100755 diff --git a/docs/apis/images/insect_bbox_pr_curve(iou-0.5).png b/docs/apis/images/insect_bbox_pr_curve(iou-0.5).png old mode 100644 new mode 100755 diff --git a/docs/apis/index.rst b/docs/apis/index.rst old mode 100644 new mode 100755 index d281cc0dccb5e8407ad4e479cf098a160a330400..900e165170997ec97ef8ad93cbda7f6c47e24f2e --- a/docs/apis/index.rst +++ b/docs/apis/index.rst @@ -1,12 +1,12 @@ -接口说明 +PaddleX API说明文档 ============================ .. toctree:: :maxdepth: 2 transforms/index.rst - datasets.md - models.md + datasets/index.rst + models/index.rst slim.md load_model.md visualize.md diff --git a/docs/apis/load_model.md b/docs/apis/load_model.md old mode 100644 new mode 100755 diff --git a/docs/apis/models.md b/docs/apis/models.md deleted file mode 100644 index 009999edf630f38ef5af12a906f55b6c5f507865..0000000000000000000000000000000000000000 --- a/docs/apis/models.md +++ /dev/null @@ -1,501 +0,0 @@ -# 模型-models - -## 分类模型 - -### ResNet50类 - -```python -paddlex.cls.ResNet50(num_classes=1000) -``` - -构建ResNet50分类器,并实现其训练、评估和预测。 - -#### **参数:** - -> - **num_classes** (int): 类别数。默认为1000。 - -#### 分类器训练函数接口 - -> ```python -> train(self, num_epochs, train_dataset, train_batch_size=64, eval_dataset=None, save_interval_epochs=1, log_interval_steps=2, save_dir='output', pretrain_weights='IMAGENET', optimizer=None, learning_rate=0.025, lr_decay_epochs=[30, 60, 90], lr_decay_gamma=0.1, use_vdl=False, sensitivities_file=None, eval_metric_loss=0.05, early_stop=False, early_stop_patience=5, resume_checkpoint=None) -> ``` -> -> **参数:** -> -> > - **num_epochs** (int): 训练迭代轮数。 -> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 -> > - **train_batch_size** (int): 训练数据batch大小。同时作为验证数据batch大小。默认值为64。 -> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 -> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为1。 -> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代步数)。默认为2。 -> > - **save_dir** (str): 模型保存路径。 -> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在ImageNet图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认为'IMAGENET'。 -> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认优化器:fluid.layers.piecewise_decay衰减策略,fluid.optimizer.Momentum优化方法。 -> > - **learning_rate** (float): 默认优化器的初始学习率。默认为0.025。 -> > - **lr_decay_epochs** (list): 默认优化器的学习率衰减轮数。默认为[30, 60, 90]。 -> > - **lr_decay_gamma** (float): 默认优化器的学习率衰减率。默认为0.1。 -> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认值为False。 -> > - **sensitivities_file** (str): 若指定为路径时,则加载路径下敏感度信息进行裁剪;若为字符串'DEFAULT',则自动下载在ImageNet图片数据上获得的敏感度信息进行裁剪;若为None,则不进行裁剪。默认为None。 -> > - **eval_metric_loss** (float): 可容忍的精度损失。默认为0.05。 -> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 -> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 -> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 - -#### 分类器评估函数接口 - -> ```python -> evaluate(self, eval_dataset, batch_size=1, epoch_id=None, return_details=False) -> ``` -> -> **参数:** -> -> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 -> > - **batch_size** (int): 验证数据批大小。默认为1。 -> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 -> > - **return_details** (bool): 是否返回详细信息,默认False。 -> -> **返回值:** -> -> > - **dict**: 当return_details为False时,返回dict, 包含关键字:'acc1'、'acc5',分别表示最大值的accuracy、前5个最大值的accuracy。 -> > - **tuple** (metrics, eval_details): 当`return_details`为True时,增加返回dict,包含关键字:'true_labels'、'pred_scores',分别代表真实类别id、每个类别的预测得分。 - -#### 分类器预测函数接口 - -> ```python -> predict(self, img_file, transforms=None, topk=5) -> ``` -> -> **参数:** -> -> > - **img_file** (str): 预测图像路径。 -> > - **transforms** (paddlex.cls.transforms): 数据预处理操作。 -> > - **topk** (int): 预测时前k个最大值。 - -> **返回值:** -> -> > - **list**: 其中元素均为字典。字典的关键字为'category_id'、'category'、'score', -> > 分别对应预测类别id、预测类别标签、预测得分。 - -### 其它分类器类 - -除`ResNet50`外,`paddlex.cls`下还提供了`ResNet18`、`ResNet34`、`ResNet101`、`ResNet50_vd`、`ResNet101_vd`、`ResNet50_vd_ssld`、`ResNet101_vd_ssld`、`DarkNet53`、`MobileNetV1`、`MobileNetV2`、`MobileNetV3_small`、`MobileNetV3_large`、`MobileNetV3_small_ssld`、`MobileNetV3_large_ssld`、`Xception41`、`Xception65`、`Xception71`、`ShuffleNetV2`, 使用方式(包括函数接口和参数)均与`ResNet50`一致,各模型效果可参考[模型库](../model_zoo.md)中列表。 - - - -## 检测模型 - -### YOLOv3类 - -```python -paddlex.det.YOLOv3(num_classes=80, backbone='MobileNetV1', anchors=None, anchor_masks=None, ignore_threshold=0.7, nms_score_threshold=0.01, nms_topk=1000, nms_keep_topk=100, nms_iou_threshold=0.45, label_smooth=False, train_random_shapes=[320, 352, 384, 416, 448, 480, 512, 544, 576, 608]) -``` - -构建YOLOv3检测器,并实现其训练、评估和预测。 **注意在YOLOv3,num_classes不需要包含背景类,如目标包括human、dog两种,则num_classes设为2即可,这里与FasterRCNN/MaskRCNN有差别** - -**参数:** - -> - **num_classes** (int): 类别数。默认为80。 -> - **backbone** (str): YOLOv3的backbone网络,取值范围为['DarkNet53', 'ResNet34', 'MobileNetV1', 'MobileNetV3_large']。默认为'MobileNetV1'。 -> - **anchors** (list|tuple): anchor框的宽度和高度,为None时表示使用默认值 -> [[10, 13], [16, 30], [33, 23], [30, 61], [62, 45], -> [59, 119], [116, 90], [156, 198], [373, 326]]。 -> - **anchor_masks** (list|tuple): 在计算YOLOv3损失时,使用anchor的mask索引,为None时表示使用默认值 -> [[6, 7, 8], [3, 4, 5], [0, 1, 2]]。 -> - **ignore_threshold** (float): 在计算YOLOv3损失时,IoU大于`ignore_threshold`的预测框的置信度被忽略。默认为0.7。 -> - **nms_score_threshold** (float): 检测框的置信度得分阈值,置信度得分低于阈值的框应该被忽略。默认为0.01。 -> - **nms_topk** (int): 进行NMS时,根据置信度保留的最大检测框数。默认为1000。 -> - **nms_keep_topk** (int): 进行NMS后,每个图像要保留的总检测框数。默认为100。 -> - **nms_iou_threshold** (float): 进行NMS时,用于剔除检测框IOU的阈值。默认为0.45。 -> - **label_smooth** (bool): 是否使用label smooth。默认值为False。 -> - **train_random_shapes** (list|tuple): 训练时从列表中随机选择图像大小。默认值为[320, 352, 384, 416, 448, 480, 512, 544, 576, 608]。 - -#### YOLOv3训练函数接口 - -> ```python -> train(self, num_epochs, train_dataset, train_batch_size=8, eval_dataset=None, save_interval_epochs=20, log_interval_steps=2, save_dir='output', pretrain_weights='IMAGENET', optimizer=None, learning_rate=1.0/8000, warmup_steps=1000, warmup_start_lr=0.0, lr_decay_epochs=[213, 240], lr_decay_gamma=0.1, metric=None, use_vdl=False, sensitivities_file=None, eval_metric_loss=0.05, early_stop=False, early_stop_patience=5, resume_checkpoint=None) -> ``` -> -> **参数:** -> -> > - **num_epochs** (int): 训练迭代轮数。 -> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 -> > - **train_batch_size** (int): 训练数据batch大小。目前检测仅支持单卡评估,训练数据batch大小与显卡数量之商为验证数据batch大小。默认值为8。 -> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 -> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为20。 -> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代次数)。默认为2。 -> > - **save_dir** (str): 模型保存路径。默认值为'output'。 -> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在ImageNet图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认为None。 -> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认优化器:fluid.layers.piecewise_decay衰减策略,fluid.optimizer.Momentum优化方法。 -> > - **learning_rate** (float): 默认优化器的学习率。默认为1.0/8000。 -> > - **warmup_steps** (int): 默认优化器进行warmup过程的步数。默认为1000。 -> > - **warmup_start_lr** (int): 默认优化器warmup的起始学习率。默认为0.0。 -> > - **lr_decay_epochs** (list): 默认优化器的学习率衰减轮数。默认为[213, 240]。 -> > - **lr_decay_gamma** (float): 默认优化器的学习率衰减率。默认为0.1。 -> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认值为None。 -> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认值为False。 -> > - **sensitivities_file** (str): 若指定为路径时,则加载路径下敏感度信息进行裁剪;若为字符串'DEFAULT',则自动下载在PascalVOC数据上获得的敏感度信息进行裁剪;若为None,则不进行裁剪。默认为None。 -> > - **eval_metric_loss** (float): 可容忍的精度损失。默认为0.05。 -> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 -> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 -> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 - -#### YOLOv3评估函数接口 - -> ```python -> evaluate(self, eval_dataset, batch_size=1, epoch_id=None, metric=None, return_details=False) -> ``` -> -> **参数:** -> -> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 -> > - **batch_size** (int): 验证数据批大小。默认为1。 -> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 -> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认为None,根据用户传入的Dataset自动选择,如为VOCDetection,则`metric`为'VOC';如为COCODetection,则`metric`为'COCO'默认为None。 -> > - **return_details** (bool): 是否返回详细信息。默认值为False。 -> > -> **返回值:** -> -> > - **tuple** (metrics, eval_details) | **dict** (metrics): 当`return_details`为True时,返回(metrics, eval_details),当`return_details`为False时,返回metrics。metrics为dict,包含关键字:'bbox_mmap'或者’bbox_map‘,分别表示平均准确率平均值在各个阈值下的结果取平均值的结果(mmAP)、平均准确率平均值(mAP)。eval_details为dict,包含关键字:'bbox',对应元素预测结果列表,每个预测结果由图像id、预测框类别id、预测框坐标、预测框得分;’gt‘:真实标注框相关信息。 - -#### YOLOv3预测函数接口 - -> ```python -> predict(self, img_file, transforms=None) -> ``` -> -> **参数:** -> -> > - **img_file** (str): 预测图像路径。 -> > - **transforms** (paddlex.det.transforms): 数据预处理操作。 -> -> **返回值:** -> -> > - **list**: 预测结果列表,列表中每个元素均为一个dict,key'bbox', 'category', 'category_id', 'score',分别表示每个预测目标的框坐标信息、类别、类别id、置信度,其中框坐标信息为[xmin, ymin, w, h],即左上角x, y坐标和框的宽和高。 - -### FasterRCNN类 - -```python -paddlex.det.FasterRCNN(num_classes=81, backbone='ResNet50', with_fpn=True, aspect_ratios=[0.5, 1.0, 2.0], anchor_sizes=[32, 64, 128, 256, 512]) - -``` - -构建FasterRCNN检测器,并实现其训练、评估和预测。 **注意在FasterRCNN中,num_classes需要设置为类别数+背景类,如目标包括human、dog两种,则num_classes需设为3,多的一种为背景background类别** - -**参数:** - -> - **num_classes** (int): 包含了背景类的类别数。默认为81。 -> - **backbone** (str): FasterRCNN的backbone网络,取值范围为['ResNet18', 'ResNet50', 'ResNet50_vd', 'ResNet101', 'ResNet101_vd']。默认为'ResNet50'。 -> - **with_fpn** (bool): 是否使用FPN结构。默认为True。 -> - **aspect_ratios** (list): 生成anchor高宽比的可选值。默认为[0.5, 1.0, 2.0]。 -> - **anchor_sizes** (list): 生成anchor大小的可选值。默认为[32, 64, 128, 256, 512]。 - -#### FasterRCNN训练函数接口 - -> ```python -> train(self, num_epochs, train_dataset, train_batch_size=2, eval_dataset=None, save_interval_epochs=1, log_interval_steps=2,save_dir='output', pretrain_weights='IMAGENET', optimizer=None, learning_rate=0.0025, warmup_steps=500, warmup_start_lr=1.0/1200, lr_decay_epochs=[8, 11], lr_decay_gamma=0.1, metric=None, use_vdl=False, early_stop=False, early_stop_patience=5, resume_checkpoint=None) -> -> ``` -> -> **参数:** -> -> > - **num_epochs** (int): 训练迭代轮数。 -> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 -> > - **train_batch_size** (int): 训练数据batch大小。目前检测仅支持单卡评估,训练数据batch大小与显卡数量之商为验证数据batch大小。默认为2。 -> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 -> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为1。 -> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代次数)。默认为2。 -> > - **save_dir** (str): 模型保存路径。默认值为'output'。 -> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在ImageNet图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认为None。 -> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认优化器:fluid.layers.piecewise_decay衰减策略,fluid.optimizer.Momentum优化方法。 -> > - **learning_rate** (float): 默认优化器的初始学习率。默认为0.0025。 -> > - **warmup_steps** (int): 默认优化器进行warmup过程的步数。默认为500。 -> > - **warmup_start_lr** (int): 默认优化器warmup的起始学习率。默认为1.0/1200。 -> > - **lr_decay_epochs** (list): 默认优化器的学习率衰减轮数。默认为[8, 11]。 -> > - **lr_decay_gamma** (float): 默认优化器的学习率衰减率。默认为0.1。 -> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认值为None。 -> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认值为False。 -> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 -> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 -> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 - -#### FasterRCNN评估函数接口 - -> ```python -> evaluate(self, eval_dataset, batch_size=1, epoch_id=None, metric=None, return_details=False) -> -> ``` -> -> **参数:** -> -> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 -> > - **batch_size** (int): 验证数据批大小。默认为1。当前只支持设置为1。 -> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 -> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认为None,根据用户传入的Dataset自动选择,如为VOCDetection,则`metric`为'VOC'; 如为COCODetection,则`metric`为'COCO'。 -> > - **return_details** (bool): 是否返回详细信息。默认值为False。 -> > -> **返回值:** -> -> > - **tuple** (metrics, eval_details) | **dict** (metrics): 当`return_details`为True时,返回(metrics, eval_details),当`return_details`为False时,返回metrics。metrics为dict,包含关键字:'bbox_mmap'或者’bbox_map‘,分别表示平均准确率平均值在各个IoU阈值下的结果取平均值的结果(mmAP)、平均准确率平均值(mAP)。eval_details为dict,包含关键字:'bbox',对应元素预测结果列表,每个预测结果由图像id、预测框类别id、预测框坐标、预测框得分;’gt‘:真实标注框相关信息。 - -#### FasterRCNN预测函数接口 - -> ```python -> predict(self, img_file, transforms=None) -> -> ``` -> -> **参数:** -> -> > - **img_file** (str): 预测图像路径。 -> > - **transforms** (paddlex.det.transforms): 数据预处理操作。 -> -> **返回值:** -> -> > - **list**: 预测结果列表,列表中每个元素均为一个dict,key'bbox', 'category', 'category_id', 'score',分别表示每个预测目标的框坐标信息、类别、类别id、置信度,其中框坐标信息为[xmin, ymin, w, h],即左上角x, y坐标和框的宽和高。 - -### MaskRCNN类 - -```python -paddlex.det.MaskRCNN(num_classes=81, backbone='ResNet50', with_fpn=True, aspect_ratios=[0.5, 1.0, 2.0], anchor_sizes=[32, 64, 128, 256, 512]) - -``` - -构建MaskRCNN检测器,并实现其训练、评估和预测。**注意在MaskRCNN中,num_classes需要设置为类别数+背景类,如目标包括human、dog两种,则num_classes需设为3,多的一种为背景background类别** - -**参数:** - -> - **num_classes** (int): 包含了背景类的类别数。默认为81。 -> - **backbone** (str): MaskRCNN的backbone网络,取值范围为['ResNet18', 'ResNet50', 'ResNet50_vd', 'ResNet101', 'ResNet101_vd']。默认为'ResNet50'。 -> - **with_fpn** (bool): 是否使用FPN结构。默认为True。 -> - **aspect_ratios** (list): 生成anchor高宽比的可选值。默认为[0.5, 1.0, 2.0]。 -> - **anchor_sizes** (list): 生成anchor大小的可选值。默认为[32, 64, 128, 256, 512]。 - -#### MaskRCNN训练函数接口 - -> ```python -> train(self, num_epochs, train_dataset, train_batch_size=1, eval_dataset=None, save_interval_epochs=1, log_interval_steps=20, save_dir='output', pretrain_weights='IMAGENET', optimizer=None, learning_rate=1.0/800, warmup_steps=500, warmup_start_lr=1.0 / 2400, lr_decay_epochs=[8, 11], lr_decay_gamma=0.1, metric=None, use_vdl=False, early_stop=False, early_stop_patience=5, resume_checkpoint=None) -> -> ``` -> -> **参数:** -> -> > - **num_epochs** (int): 训练迭代轮数。 -> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 -> > - **train_batch_size** (int): 训练数据batch大小。目前检测仅支持单卡评估,训练数据batch大小与显卡数量之商为验证数据batch大小。默认为1。 -> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 -> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为1。 -> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代次数)。默认为2。 -> > - **save_dir** (str): 模型保存路径。默认值为'output'。 -> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在ImageNet图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认为None。 -> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认优化器:fluid.layers.piecewise_decay衰减策略,fluid.optimizer.Momentum优化方法。 -> > - **learning_rate** (float): 默认优化器的初始学习率。默认为0.00125。 -> > - **warmup_steps** (int): 默认优化器进行warmup过程的步数。默认为500。 -> > - **warmup_start_lr** (int): 默认优化器warmup的起始学习率。默认为1.0/2400。 -> > - **lr_decay_epochs** (list): 默认优化器的学习率衰减轮数。默认为[8, 11]。 -> > - **lr_decay_gamma** (float): 默认优化器的学习率衰减率。默认为0.1。 -> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认值为None。 -> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认值为False。 -> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 -> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 -> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 - -#### MaskRCNN评估函数接口 - -> ```python -> evaluate(self, eval_dataset, batch_size=1, epoch_id=None, metric=None, return_details=False) -> -> ``` -> -> **参数:** -> -> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 -> > - **batch_size** (int): 验证数据批大小。默认为1。当前只支持设置为1。 -> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 -> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认为None,根据用户传入的Dataset自动选择,如为VOCDetection,则`metric`为'VOC'; 如为COCODetection,则`metric`为'COCO'。 -> > - **return_details** (bool): 是否返回详细信息。默认值为False。 -> > -> **返回值:** -> -> > - **tuple** (metrics, eval_details) | **dict** (metrics): 当`return_details`为True时,返回(metrics, eval_details),当return_details为False时,返回metrics。metrics为dict,包含关键字:'bbox_mmap'和'segm_mmap'或者’bbox_map‘和'segm_map',分别表示预测框和分割区域平均准确率平均值在各个IoU阈值下的结果取平均值的结果(mmAP)、平均准确率平均值(mAP)。eval_details为dict,包含关键字:'bbox',对应元素预测框结果列表,每个预测结果由图像id、预测框类别id、预测框坐标、预测框得分;'mask',对应元素预测区域结果列表,每个预测结果由图像id、预测区域类别id、预测区域坐标、预测区域得分;’gt‘:真实标注框和标注区域相关信息。 - -#### MaskRCNN预测函数接口 - -> ```python -> predict(self, img_file, transforms=None) -> -> ``` -> -> **参数:** -> -> > - **img_file** (str): 预测图像路径。 -> > - **transforms** (paddlex.det.transforms): 数据预处理操作。 -> -> **返回值:** -> -> > - **list**: 预测结果列表,列表中每个元素均为一个dict,key'bbox', 'mask', 'category', 'category_id', 'score',分别表示每个预测目标的框坐标信息、Mask信息,类别、类别id、置信度,其中框坐标信息为[xmin, ymin, w, h],即左上角x, y坐标和框的宽和高。 - -## 分割模型 - -### DeepLabv3p类 - -```python -paddlex.seg.DeepLabv3p(num_classes=2, backbone='MobileNetV2_x1.0', output_stride=16, aspp_with_sep_conv=True, decoder_use_sep_conv=True, encoder_with_aspp=True, enable_decoder=True, use_bce_loss=False, use_dice_loss=False, class_weight=None, ignore_index=255) - -``` - -构建DeepLabv3p分割器,并实现其训练、评估和预测。 - -**参数:** - -> - **num_classes** (int): 类别数。 -> - **backbone** (str): DeepLabv3+的backbone网络,实现特征图的计算,取值范围为['Xception65', 'Xception41', 'MobileNetV2_x0.25', 'MobileNetV2_x0.5', 'MobileNetV2_x1.0', 'MobileNetV2_x1.5', 'MobileNetV2_x2.0'],'MobileNetV2_x1.0'。 -> - **output_stride** (int): backbone 输出特征图相对于输入的下采样倍数,一般取值为8或16。默认16。 -> - **aspp_with_sep_conv** (bool): decoder模块是否采用separable convolutions。默认True。 -> - **decoder_use_sep_conv** (bool): decoder模块是否采用separable convolutions。默认True。 -> - **encoder_with_aspp** (bool): 是否在encoder阶段采用aspp模块。默认True。 -> - **enable_decoder** (bool): 是否使用decoder模块。默认True。 -> - **use_bce_loss** (bool): 是否使用bce loss作为网络的损失函数,只能用于两类分割。可与dice loss同时使用。默认False。 -> - **use_dice_loss** (bool): 是否使用dice loss作为网络的损失函数,只能用于两类分割,可与bce loss同时使用,当`use_bce_loss`和`use_dice_loss`都为False时,使用交叉熵损失函数。默认False。 -> - **class_weight** (list/str): 交叉熵损失函数各类损失的权重。当`class_weight`为list的时候,长度应为`num_classes`。当`class_weight`为str时, weight.lower()应为'dynamic',这时会根据每一轮各类像素的比重自行计算相应的权重,每一类的权重为:每类的比例 * num_classes。class_weight取默认值None是,各类的权重1,即平时使用的交叉熵损失函数。 -> - **ignore_index** (int): label上忽略的值,label为`ignore_index`的像素不参与损失函数的计算。默认255。 - -#### DeepLabv3训练函数接口 - -> ```python -> train(self, num_epochs, train_dataset, train_batch_size=2, eval_dataset=None, eval_batch_size=1, save_interval_epochs=1, log_interval_steps=2, save_dir='output', pretrain_weights='IMAGENET', optimizer=None, learning_rate=0.01, lr_decay_power=0.9, use_vdl=False, sensitivities_file=None, eval_metric_loss=0.05, early_stop=False, early_stop_patience=5, resume_checkpoint=None): -> -> ``` -> -> **参数:** -> > -> > - **num_epochs** (int): 训练迭代轮数。 -> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 -> > - **train_batch_size** (int): 训练数据batch大小。同时作为验证数据batch大小。默认2。 -> > - **eval_dataset** (paddlex.datasets): 评估数据读取器。 -> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为1。 -> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代次数)。默认为2。 -> > - **save_dir** (str): 模型保存路径。默认'output' -> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在ImageNet图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认'IMAGENET'。 -> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认的优化器:使用fluid.optimizer.Momentum优化方法,polynomial的学习率衰减策略。 -> > - **learning_rate** (float): 默认优化器的初始学习率。默认0.01。 -> > - **lr_decay_power** (float): 默认优化器学习率衰减指数。默认0.9。 -> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认False。 -> > - **sensitivities_file** (str): 若指定为路径时,则加载路径下敏感度信息进行裁剪;若为字符串'DEFAULT',则自动下载在ImageNet图片数据上获得的敏感度信息进行裁剪;若为None,则不进行裁剪。默认为None。 -> > - **eval_metric_loss** (float): 可容忍的精度损失。默认为0.05。 -> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 -> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 -> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 - -#### DeepLabv3评估函数接口 - -> ```python -> evaluate(self, eval_dataset, batch_size=1, epoch_id=None, return_details=False): -> ``` - -> **参数:** -> > -> > - **eval_dataset** (paddlex.datasets): 评估数据读取器。 -> > - **batch_size** (int): 评估时的batch大小。默认1。 -> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 -> > - **return_details** (bool): 是否返回详细信息。默认False。 - -> **返回值:** -> > -> > - **dict**: 当`return_details`为False时,返回dict。包含关键字:'miou'、'category_iou'、'macc'、 -> > 'category_acc'和'kappa',分别表示平均iou、各类别iou、平均准确率、各类别准确率和kappa系数。 -> > - **tuple** (metrics, eval_details):当`return_details`为True时,增加返回dict (eval_details), -> > 包含关键字:'confusion_matrix',表示评估的混淆矩阵。 - -#### DeepLabv3预测函数接口 - -> ``` -> predict(self, im_file, transforms=None): -> ``` - -> **参数:** -> > -> > - **img_file** (str): 预测图像路径。 -> > - **transforms** (paddlex.seg.transforms): 数据预处理操作。 - -> **返回值:** -> > -> > - **dict**: 包含关键字'label_map'和'score_map', 'label_map'存储预测结果灰度图,像素值表示对应的类别,'score_map'存储各类别的概率,shape=(h, w, num_classes)。 - -### UNet类 - -```python -paddlex.seg.UNet(num_classes=2, upsample_mode='bilinear', use_bce_loss=False, use_dice_loss=False, class_weight=None, ignore_index=255) -``` - -构建UNet分割器,并实现其训练、评估和预测。 - - -**参数:** - -> - **num_classes** (int): 类别数。 -> - **upsample_mode** (str): UNet decode时采用的上采样方式,取值为'bilinear'时利用双线行差值进行上菜样,当输入其他选项时则利用反卷积进行上菜样,默认为'bilinear'。 -> - **use_bce_loss** (bool): 是否使用bce loss作为网络的损失函数,只能用于两类分割。可与dice loss同时使用。默认False。 -> - **use_dice_loss** (bool): 是否使用dice loss作为网络的损失函数,只能用于两类分割,可与bce loss同时使用。当use_bce_loss和use_dice_loss都为False时,使用交叉熵损失函数。默认False。 -> - **class_weight** (list/str): 交叉熵损失函数各类损失的权重。当`class_weight`为list的时候,长度应为`num_classes`。当`class_weight`为str时, weight.lower()应为'dynamic',这时会根据每一轮各类像素的比重自行计算相应的权重,每一类的权重为:每类的比例 * num_classes。class_weight取默认值None是,各类的权重1,即平时使用的交叉熵损失函数。 -> - **ignore_index** (int): label上忽略的值,label为`ignore_index`的像素不参与损失函数的计算。默认255。 - -#### Unet训练函数接口 - -> ```python -> train(self, num_epochs, train_dataset, train_batch_size=2, eval_dataset=None, eval_batch_size=1, save_interval_epochs=1, log_interval_steps=2, save_dir='output', pretrain_weights='COCO', optimizer=None, learning_rate=0.01, lr_decay_power=0.9, use_vdl=False, sensitivities_file=None, eval_metric_loss=0.05, early_stop=False, early_stop_patience=5, resume_checkpoint=None): -> ``` -> -> **参数:** -> > -> > - **num_epochs** (int): 训练迭代轮数。 -> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 -> > - **train_batch_size** (int): 训练数据batch大小。同时作为验证数据batch大小。默认2。 -> > - **eval_dataset** (paddlex.datasets): 评估数据读取器。 -> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为1。 -> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代次数)。默认为2。 -> > - **save_dir** (str): 模型保存路径。默认'output' -> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在COCO图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认'COCO'。 -> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认的优化器:使用fluid.optimizer.Momentum优化方法,polynomial的学习率衰减策略。 -> > - **learning_rate** (float): 默认优化器的初始学习率。默认0.01。 -> > - **lr_decay_power** (float): 默认优化器学习率衰减指数。默认0.9。 -> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认False。 -> > - **sensitivities_file** (str): 若指定为路径时,则加载路径下敏感度信息进行裁剪;若为字符串'DEFAULT',则自动下载在ImageNet图片数据上获得的敏感度信息进行裁剪;若为None,则不进行裁剪。默认为None。 -> > - **eval_metric_loss** (float): 可容忍的精度损失。默认为0.05。 -> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 -> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 -> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 - -#### Unet评估函数接口 - -> ``` -> evaluate(self, eval_dataset, batch_size=1, epoch_id=None, return_details=False): -> ``` - -> **参数:** -> > -> > - **eval_dataset** (paddlex.datasets): 评估数据读取器。 -> > - **batch_size** (int): 评估时的batch大小。默认1。 -> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 -> > - **return_details** (bool): 是否返回详细信息。默认False。 - -> **返回值:** -> > -> > - **dict**: 当return_details为False时,返回dict。包含关键字:'miou'、'category_iou'、'macc'、 -> > 'category_acc'和'kappa',分别表示平均iou、各类别iou、平均准确率、各类别准确率和kappa系数。 -> > - **tuple** (metrics, eval_details):当return_details为True时,增加返回dict (eval_details), -> > 包含关键字:'confusion_matrix',表示评估的混淆矩阵。 - -#### Unet预测函数接口 - -> ``` -> predict(self, im_file, transforms=None): -> ``` - -> **参数:** -> > -> > - **img_file** (str): 预测图像路径。 -> > - **transforms** (paddlex.seg.transforms): 数据预处理操作。 - -> **返回值:** -> > -> > - **dict**: 包含关键字'label_map'和'score_map', 'label_map'存储预测结果灰度图,像素值表示对应的类别,'score_map'存储各类别的概率,shape=(h, w, num_classes)。 diff --git a/docs/apis/models/classification.md b/docs/apis/models/classification.md new file mode 100755 index 0000000000000000000000000000000000000000..4fa083df17d5d87c1b9755e9c224bfd236ebc6b6 --- /dev/null +++ b/docs/apis/models/classification.md @@ -0,0 +1,188 @@ +# 图像分类 + +## ResNet50类 + +```python +paddlex.cls.ResNet50(num_classes=1000) +``` + +> 构建ResNet50分类器,并实现其训练、评估和预测。 + +**参数** + +> - **num_classes** (int): 类别数。默认为1000。 + +### train 训练接口 + +```python +train(self, num_epochs, train_dataset, train_batch_size=64, eval_dataset=None, save_interval_epochs=1, log_interval_steps=2, save_dir='output', pretrain_weights='IMAGENET', optimizer=None, learning_rate=0.025, lr_decay_epochs=[30, 60, 90], lr_decay_gamma=0.1, use_vdl=False, sensitivities_file=None, eval_metric_loss=0.05, early_stop=False, early_stop_patience=5, resume_checkpoint=None) +``` +> +> **参数** +> +> > - **num_epochs** (int): 训练迭代轮数。 +> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 +> > - **train_batch_size** (int): 训练数据batch大小。同时作为验证数据batch大小。默认值为64。 +> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 +> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为1。 +> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代步数)。默认为2。 +> > - **save_dir** (str): 模型保存路径。 +> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在ImageNet图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认为'IMAGENET'。 +> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认优化器:fluid.layers.piecewise_decay衰减策略,fluid.optimizer.Momentum优化方法。 +> > - **learning_rate** (float): 默认优化器的初始学习率。默认为0.025。 +> > - **lr_decay_epochs** (list): 默认优化器的学习率衰减轮数。默认为[30, 60, 90]。 +> > - **lr_decay_gamma** (float): 默认优化器的学习率衰减率。默认为0.1。 +> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认值为False。 +> > - **sensitivities_file** (str): 若指定为路径时,则加载路径下敏感度信息进行裁剪;若为字符串'DEFAULT',则自动下载在ImageNet图片数据上获得的敏感度信息进行裁剪;若为None,则不进行裁剪。默认为None。 +> > - **eval_metric_loss** (float): 可容忍的精度损失。默认为0.05。 +> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 +> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 +> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 + +### evaluate 评估接口 + +```python +evaluate(self, eval_dataset, batch_size=1, epoch_id=None, return_details=False) +``` +> +> **参数** +> +> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 +> > - **batch_size** (int): 验证数据批大小。默认为1。 +> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 +> > - **return_details** (bool): 是否返回详细信息,默认False。 +> +> **返回值** +> +> > - **dict**: 当return_details为False时,返回dict, 包含关键字:'acc1'、'acc5',分别表示最大值的accuracy、前5个最大值的accuracy。 +> > - **tuple** (metrics, eval_details): 当`return_details`为True时,增加返回dict,包含关键字:'true_labels'、'pred_scores',分别代表真实类别id、每个类别的预测得分。 + +### predict 预测接口 + +```python +predict(self, img_file, transforms=None, topk=5) +``` + +> 分类模型预测接口。需要注意的是,只有在训练过程中定义了eval_dataset,模型在保存时才会将预测时的图像处理流程保存在`ResNet50.test_transforms`和`ResNet50.eval_transforms`中。如未在训练时定义eval_dataset,那在调用预测`predict`接口时,用户需要再重新定义test_transforms传入给`predict`接口。 + +> **参数** +> +> > - **img_file** (str): 预测图像路径。 +> > - **transforms** (paddlex.cls.transforms): 数据预处理操作。 +> > - **topk** (int): 预测时前k个最大值。 + +> **返回值** +> +> > - **list**: 其中元素均为字典。字典的关键字为'category_id'、'category'、'score', +> > 分别对应预测类别id、预测类别标签、预测得分。 + +## 其它分类器类 + +PaddleX提供了共计22种分类器,所有分类器均提供同`ResNet50`相同的训练`train`,评估`evaluate`和预测`predict`接口,各模型效果可参考[模型库](../appendix/model_zoo.md)。 + +### ResNet18 +```python +paddlex.cls.ResNet18(num_classes=1000) +``` + +### ResNet34 +```python +paddlex.cls.ResNet34(num_classes=1000) +``` + + +### ResNet50 +```python +paddlex.cls.ResNet50(num_classes=1000) +``` + +### ResNet50_vd +```python +paddlex.cls.ResNet50_vd(num_classes=1000) +``` + +### ResNet50_vd_ssld +```python +paddlex.cls.ResNet50_vd_ssld(num_classes=1000) +``` + +### ResNet101 +```python +paddlex.cls.ResNet101(num_classes=1000) +``` + +### ResNet101_vd +```python +paddlex.cls.ResNet101_vdnum_classes=1000) +``` + +### ResNet101_vd_ssld +```python +paddlex.cls.ResNet101_vd_ssld(num_classes=1000) +``` + +### DarkNet53 +```python +paddlex.cls.DarkNet53(num_classes=1000) +``` + +### MobileNetV1 +```python +paddlex.cls.MobileNetV1(num_classes=1000) +``` + +### MobileNetV2 +```python +paddlex.cls.MobileNetV2(num_classes=1000) +``` + +### MobileNetV3_small +```python +paddlex.cls.MobileNetV3_small(num_classes=1000) +``` + +### MobileNetV3_small_ssld +```python +paddlex.cls.MobileNetV3_small_ssld(num_classes=1000) +``` + +### MobileNetV3_large +```python +paddlex.cls.MobileNetV3_large(num_classes=1000) +``` + +### MobileNetV3_large_ssld +```python +paddlex.cls.MobileNetV3_large_ssld(num_classes=1000) +``` + +### Xception65 +```python +paddlex.cls.Xception65(num_classes=1000) +``` + +### Xception71 +```python +paddlex.cls.Xception71(num_classes=1000) +``` + +### ShuffleNetV2 +```python +paddlex.cls.ShuffleNetV2(num_classes=1000) +``` + +### DenseNet121 +```python +paddlex.cls.DenseNet121(num_classes=1000) +``` + +### DenseNet161 +```python +paddlex.cls.DenseNet161(num_classes=1000) +``` + +### DenseNet201 +```python +paddlex.cls.DenseNet201(num_classes=1000) +``` + diff --git a/docs/apis/models/detection.md b/docs/apis/models/detection.md new file mode 100755 index 0000000000000000000000000000000000000000..2039be6db803d0f0c4335346e7b6127565c684af --- /dev/null +++ b/docs/apis/models/detection.md @@ -0,0 +1,180 @@ +# 目标检测 + +## YOLOv3类 + +```python +paddlex.det.YOLOv3(num_classes=80, backbone='MobileNetV1', anchors=None, anchor_masks=None, ignore_threshold=0.7, nms_score_threshold=0.01, nms_topk=1000, nms_keep_topk=100, nms_iou_threshold=0.45, label_smooth=False, train_random_shapes=[320, 352, 384, 416, 448, 480, 512, 544, 576, 608]) +``` + +> 构建YOLOv3检测器。**注意在YOLOv3,num_classes不需要包含背景类,如目标包括human、dog两种,则num_classes设为2即可,这里与FasterRCNN/MaskRCNN有差别** + +> **参数** +> +> > - **num_classes** (int): 类别数。默认为80。 +> > - **backbone** (str): YOLOv3的backbone网络,取值范围为['DarkNet53', 'ResNet34', 'MobileNetV1', 'MobileNetV3_large']。默认为'MobileNetV1'。 +> > - **anchors** (list|tuple): anchor框的宽度和高度,为None时表示使用默认值 +> > [[10, 13], [16, 30], [33, 23], [30, 61], [62, 45], +> [59, 119], [116, 90], [156, 198], [373, 326]]。 +> > - **anchor_masks** (list|tuple): 在计算YOLOv3损失时,使用anchor的mask索引,为None时表示使用默认值 +> > [[6, 7, 8], [3, 4, 5], [0, 1, 2]]。 +> > - **ignore_threshold** (float): 在计算YOLOv3损失时,IoU大于`ignore_threshold`的预测框的置信度被忽略。默认为0.7。 +> > - **nms_score_threshold** (float): 检测框的置信度得分阈值,置信度得分低于阈值的框应该被忽略。默认为0.01。 +> > - **nms_topk** (int): 进行NMS时,根据置信度保留的最大检测框数。默认为1000。 +> > - **nms_keep_topk** (int): 进行NMS后,每个图像要保留的总检测框数。默认为100。 +> > - **nms_iou_threshold** (float): 进行NMS时,用于剔除检测框IOU的阈值。默认为0.45。 +> > - **label_smooth** (bool): 是否使用label smooth。默认值为False。 +> > - **train_random_shapes** (list|tuple): 训练时从列表中随机选择图像大小。默认值为[320, 352, 384, 416, 448, 480, 512, 544, 576, 608]。 + +### train 训练接口 + +```python +train(self, num_epochs, train_dataset, train_batch_size=8, eval_dataset=None, save_interval_epochs=20, log_interval_steps=2, save_dir='output', pretrain_weights='IMAGENET', optimizer=None, learning_rate=1.0/8000, warmup_steps=1000, warmup_start_lr=0.0, lr_decay_epochs=[213, 240], lr_decay_gamma=0.1, metric=None, use_vdl=False, sensitivities_file=None, eval_metric_loss=0.05, early_stop=False, early_stop_patience=5, resume_checkpoint=None) +``` + +> YOLOv3模型的训练接口,函数内置了`piecewise`学习率衰减策略和`momentum`优化器。 + +> **参数** +> +> > - **num_epochs** (int): 训练迭代轮数。 +> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 +> > - **train_batch_size** (int): 训练数据batch大小。目前检测仅支持单卡评估,训练数据batch大小与显卡数量之商为验证数据batch大小。默认值为8。 +> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 +> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为20。 +> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代次数)。默认为2。 +> > - **save_dir** (str): 模型保存路径。默认值为'output'。 +> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在ImageNet图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认为None。 +> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认优化器:fluid.layers.piecewise_decay衰减策略,fluid.optimizer.Momentum优化方法。 +> > - **learning_rate** (float): 默认优化器的学习率。默认为1.0/8000。 +> > - **warmup_steps** (int): 默认优化器进行warmup过程的步数。默认为1000。 +> > - **warmup_start_lr** (int): 默认优化器warmup的起始学习率。默认为0.0。 +> > - **lr_decay_epochs** (list): 默认优化器的学习率衰减轮数。默认为[213, 240]。 +> > - **lr_decay_gamma** (float): 默认优化器的学习率衰减率。默认为0.1。 +> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认值为None。 +> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认值为False。 +> > - **sensitivities_file** (str): 若指定为路径时,则加载路径下敏感度信息进行裁剪;若为字符串'DEFAULT',则自动下载在PascalVOC数据上获得的敏感度信息进行裁剪;若为None,则不进行裁剪。默认为None。 +> > - **eval_metric_loss** (float): 可容忍的精度损失。默认为0.05。 +> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 +> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 +> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 + +### evaluate 评估接口 + +```python +evaluate(self, eval_dataset, batch_size=1, epoch_id=None, metric=None, return_details=False) +``` + +> YOLOv3模型的评估接口,模型评估后会返回在验证集上的指标`box_map`(metric指定为'VOC'时)或`box_mmap`(metric指定为`COCO`时)。 + +> **参数** +> +> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 +> > - **batch_size** (int): 验证数据批大小。默认为1。 +> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 +> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认为None,根据用户传入的Dataset自动选择,如为VOCDetection,则`metric`为'VOC';如为COCODetection,则`metric`为'COCO'默认为None, 如为EasyData类型数据集,同时也会使用'VOC'。 +> > - **return_details** (bool): 是否返回详细信息。默认值为False。 +> > +> **返回值** +> +> > - **tuple** (metrics, eval_details) | **dict** (metrics): 当`return_details`为True时,返回(metrics, eval_details),当`return_details`为False时,返回metrics。metrics为dict,包含关键字:'bbox_mmap'或者’bbox_map‘,分别表示平均准确率平均值在各个阈值下的结果取平均值的结果(mmAP)、平均准确率平均值(mAP)。eval_details为dict,包含关键字:'bbox',对应元素预测结果列表,每个预测结果由图像id、预测框类别id、预测框坐标、预测框得分;’gt‘:真实标注框相关信息。 + +### predict 预测接口 + +```python +predict(self, img_file, transforms=None) +``` + +> YOLOv3模型预测接口。需要注意的是,只有在训练过程中定义了eval_dataset,模型在保存时才会将预测时的图像处理流程保存在`YOLOv3.test_transforms`和`YOLOv3.eval_transforms`中。如未在训练时定义eval_dataset,那在调用预测`predict`接口时,用户需要再重新定义`test_transforms`传入给`predict`接口 + +> **参数** +> +> > - **img_file** (str): 预测图像路径。 +> > - **transforms** (paddlex.det.transforms): 数据预处理操作。 +> +> **返回值** +> +> > - **list**: 预测结果列表,列表中每个元素均为一个dict,key包括'bbox', 'category', 'category_id', 'score',分别表示每个预测目标的框坐标信息、类别、类别id、置信度,其中框坐标信息为[xmin, ymin, w, h],即左上角x, y坐标和框的宽和高。 + + +## FasterRCNN类 + +```python +paddlex.det.FasterRCNN(num_classes=81, backbone='ResNet50', with_fpn=True, aspect_ratios=[0.5, 1.0, 2.0], anchor_sizes=[32, 64, 128, 256, 512]) + +``` + +> 构建FasterRCNN检测器。 **注意在FasterRCNN中,num_classes需要设置为类别数+背景类,如目标包括human、dog两种,则num_classes需设为3,多的一种为背景background类别** + +> **参数** + +> > - **num_classes** (int): 包含了背景类的类别数。默认为81。 +> > - **backbone** (str): FasterRCNN的backbone网络,取值范围为['ResNet18', 'ResNet50', 'ResNet50_vd', 'ResNet101', 'ResNet101_vd']。默认为'ResNet50'。 +> > - **with_fpn** (bool): 是否使用FPN结构。默认为True。 +> > - **aspect_ratios** (list): 生成anchor高宽比的可选值。默认为[0.5, 1.0, 2.0]。 +> > - **anchor_sizes** (list): 生成anchor大小的可选值。默认为[32, 64, 128, 256, 512]。 + +### train 训练接口 + +```python +train(self, num_epochs, train_dataset, train_batch_size=2, eval_dataset=None, save_interval_epochs=1, log_interval_steps=2,save_dir='output', pretrain_weights='IMAGENET', optimizer=None, learning_rate=0.0025, warmup_steps=500, warmup_start_lr=1.0/1200, lr_decay_epochs=[8, 11], lr_decay_gamma=0.1, metric=None, use_vdl=False, early_stop=False, early_stop_patience=5, resume_checkpoint=None) +``` + +> FasterRCNN模型的训练接口,函数内置了`piecewise`学习率衰减策略和`momentum`优化器。 + +> **参数** +> +> > - **num_epochs** (int): 训练迭代轮数。 +> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 +> > - **train_batch_size** (int): 训练数据batch大小。目前检测仅支持单卡评估,训练数据batch大小与显卡数量之商为验证数据batch大小。默认为2。 +> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 +> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为1。 +> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代次数)。默认为2。 +> > - **save_dir** (str): 模型保存路径。默认值为'output'。 +> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在ImageNet图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认为None。 +> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认优化器:fluid.layers.piecewise_decay衰减策略,fluid.optimizer.Momentum优化方法。 +> > - **learning_rate** (float): 默认优化器的初始学习率。默认为0.0025。 +> > - **warmup_steps** (int): 默认优化器进行warmup过程的步数。默认为500。 +> > - **warmup_start_lr** (int): 默认优化器warmup的起始学习率。默认为1.0/1200。 +> > - **lr_decay_epochs** (list): 默认优化器的学习率衰减轮数。默认为[8, 11]。 +> > - **lr_decay_gamma** (float): 默认优化器的学习率衰减率。默认为0.1。 +> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认值为None。 +> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认值为False。 +> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 +> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 +> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 + +### evaluate 接口 + +```python +evaluate(self, eval_dataset, batch_size=1, epoch_id=None, metric=None, return_details=False) +``` + +> FasterRCNN模型的评估接口,模型评估后会返回在验证集上的指标box_map(metric指定为’VOC’时)或box_mmap(metric指定为COCO时)。 + +> **参数** +> +> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 +> > - **batch_size** (int): 验证数据批大小。默认为1。当前只支持设置为1。 +> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 +> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认为None,根据用户传入的Dataset自动选择,如为VOCDetection,则`metric`为'VOC'; 如为COCODetection,则`metric`为'COCO'。 +> > - **return_details** (bool): 是否返回详细信息。默认值为False。 +> > +> **返回值** +> +> > - **tuple** (metrics, eval_details) | **dict** (metrics): 当`return_details`为True时,返回(metrics, eval_details),当`return_details`为False时,返回metrics。metrics为dict,包含关键字:'bbox_mmap'或者’bbox_map‘,分别表示平均准确率平均值在各个IoU阈值下的结果取平均值的结果(mmAP)、平均准确率平均值(mAP)。eval_details为dict,包含关键字:'bbox',对应元素预测结果列表,每个预测结果由图像id、预测框类别id、预测框坐标、预测框得分;’gt‘:真实标注框相关信息。 + +### predict 预测接口 + +```python +predict(self, img_file, transforms=None) +``` + +> FasterRCNN模型预测接口。需要注意的是,只有在训练过程中定义了eval_dataset,模型在保存时才会将预测时的图像处理流程保存在`FasterRCNN.test_transforms`和`FasterRCNN.eval_transforms`中。如未在训练时定义eval_dataset,那在调用预测`predict`接口时,用户需要再重新定义test_transforms传入给`predict`接口。 + +> **参数** +> +> > - **img_file** (str): 预测图像路径。 +> > - **transforms** (paddlex.det.transforms): 数据预处理操作。 +> +> **返回值** +> +> > - **list**: 预测结果列表,列表中每个元素均为一个dict,key包括'bbox', 'category', 'category_id', 'score',分别表示每个预测目标的框坐标信息、类别、类别id、置信度,其中框坐标信息为[xmin, ymin, w, h],即左上角x, y坐标和框的宽和高。 diff --git a/docs/apis/models/index.rst b/docs/apis/models/index.rst new file mode 100755 index 0000000000000000000000000000000000000000..5e533189cd44759cb2002e64bf1a0a9b066cfc6e --- /dev/null +++ b/docs/apis/models/index.rst @@ -0,0 +1,12 @@ +模型集-models +============================ + +PaddleX目前支持 `四种视觉任务解决方案 <../../cv_solutions.html>`_ ,包括图像分类、目标检测、实例分割和语义分割。对于每种视觉任务,PaddleX又提供了1种或多种模型,用户可根据需求及应用场景选取。 + +.. toctree:: + :maxdepth: 2 + + classification.md + detection.md + instance_segmentation.md + semantic_segmentation.md diff --git a/docs/apis/models/instance_segmentation.md b/docs/apis/models/instance_segmentation.md new file mode 100755 index 0000000000000000000000000000000000000000..f08645478cdafa845431ed52b68387f672886d17 --- /dev/null +++ b/docs/apis/models/instance_segmentation.md @@ -0,0 +1,85 @@ +# 实例分割 + +## MaskRCNN类 + +```python +paddlex.det.MaskRCNN(num_classes=81, backbone='ResNet50', with_fpn=True, aspect_ratios=[0.5, 1.0, 2.0], anchor_sizes=[32, 64, 128, 256, 512]) + +``` + +> 构建MaskRCNN检测器。**注意在MaskRCNN中,num_classes需要设置为类别数+背景类,如目标包括human、dog两种,则num_classes需设为3,多的一种为背景background类别** + +> **参数** + +> > - **num_classes** (int): 包含了背景类的类别数。默认为81。 +> > - **backbone** (str): MaskRCNN的backbone网络,取值范围为['ResNet18', 'ResNet50', 'ResNet50_vd', 'ResNet101', 'ResNet101_vd']。默认为'ResNet50'。 +> > - **with_fpn** (bool): 是否使用FPN结构。默认为True。 +> > - **aspect_ratios** (list): 生成anchor高宽比的可选值。默认为[0.5, 1.0, 2.0]。 +> > - **anchor_sizes** (list): 生成anchor大小的可选值。默认为[32, 64, 128, 256, 512]。 + +#### train 训练接口 + +```python +train(self, num_epochs, train_dataset, train_batch_size=1, eval_dataset=None, save_interval_epochs=1, log_interval_steps=20, save_dir='output', pretrain_weights='IMAGENET', optimizer=None, learning_rate=1.0/800, warmup_steps=500, warmup_start_lr=1.0 / 2400, lr_decay_epochs=[8, 11], lr_decay_gamma=0.1, metric=None, use_vdl=False, early_stop=False, early_stop_patience=5, resume_checkpoint=None) +``` + +> MaskRCNN模型的训练接口,函数内置了`piecewise`学习率衰减策略和`momentum`优化器。 + +> **参数** +> +> > - **num_epochs** (int): 训练迭代轮数。 +> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 +> > - **train_batch_size** (int): 训练数据batch大小。目前检测仅支持单卡评估,训练数据batch大小与显卡数量之商为验证数据batch大小。默认为1。 +> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 +> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为1。 +> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代次数)。默认为2。 +> > - **save_dir** (str): 模型保存路径。默认值为'output'。 +> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在ImageNet图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认为None。 +> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认优化器:fluid.layers.piecewise_decay衰减策略,fluid.optimizer.Momentum优化方法。 +> > - **learning_rate** (float): 默认优化器的初始学习率。默认为0.00125。 +> > - **warmup_steps** (int): 默认优化器进行warmup过程的步数。默认为500。 +> > - **warmup_start_lr** (int): 默认优化器warmup的起始学习率。默认为1.0/2400。 +> > - **lr_decay_epochs** (list): 默认优化器的学习率衰减轮数。默认为[8, 11]。 +> > - **lr_decay_gamma** (float): 默认优化器的学习率衰减率。默认为0.1。 +> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认值为None。 +> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认值为False。 +> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 +> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 +> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 + +#### evaluate 评估接口 + +```python +evaluate(self, eval_dataset, batch_size=1, epoch_id=None, metric=None, return_details=False) +``` + +> MaskRCNN模型的评估接口,模型评估后会返回在验证集上的指标box_mmap(metric指定为COCO时)和相应的seg_mmap。 + +> **参数** +> +> > - **eval_dataset** (paddlex.datasets): 验证数据读取器。 +> > - **batch_size** (int): 验证数据批大小。默认为1。当前只支持设置为1。 +> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 +> > - **metric** (bool): 训练过程中评估的方式,取值范围为['COCO', 'VOC']。默认为None,根据用户传入的Dataset自动选择,如为VOCDetection,则`metric`为'VOC'; 如为COCODetection,则`metric`为'COCO'。 +> > - **return_details** (bool): 是否返回详细信息。默认值为False。 +> > +> **返回值** +> +> > - **tuple** (metrics, eval_details) | **dict** (metrics): 当`return_details`为True时,返回(metrics, eval_details),当return_details为False时,返回metrics。metrics为dict,包含关键字:'bbox_mmap'和'segm_mmap'或者’bbox_map‘和'segm_map',分别表示预测框和分割区域平均准确率平均值在各个IoU阈值下的结果取平均值的结果(mmAP)、平均准确率平均值(mAP)。eval_details为dict,包含关键字:'bbox',对应元素预测框结果列表,每个预测结果由图像id、预测框类别id、预测框坐标、预测框得分;'mask',对应元素预测区域结果列表,每个预测结果由图像id、预测区域类别id、预测区域坐标、预测区域得分;’gt‘:真实标注框和标注区域相关信息。 + +#### predict 预测接口 + +```python +predict(self, img_file, transforms=None) +``` + +> MaskRCNN模型预测接口。需要注意的是,只有在训练过程中定义了eval_dataset,模型在保存时才会将预测时的图像处理流程保存在FasterRCNN.test_transforms和FasterRCNN.eval_transforms中。如未在训练时定义eval_dataset,那在调用预测predict接口时,用户需要再重新定义test_transforms传入给predict接口。 + +> **参数** +> +> > - **img_file** (str): 预测图像路径。 +> > - **transforms** (paddlex.det.transforms): 数据预处理操作。 +> +> **返回值** +> +> > - **list**: 预测结果列表,列表中每个元素均为一个dict,key'bbox', 'mask', 'category', 'category_id', 'score',分别表示每个预测目标的框坐标信息、Mask信息,类别、类别id、置信度,其中框坐标信息为[xmin, ymin, w, h],即左上角x, y坐标和框的宽和高。 diff --git a/docs/apis/models/semantic_segmentation.md b/docs/apis/models/semantic_segmentation.md new file mode 100755 index 0000000000000000000000000000000000000000..12b54d8c6114466771e25bdd88d21466018ed5aa --- /dev/null +++ b/docs/apis/models/semantic_segmentation.md @@ -0,0 +1,175 @@ +# 语义分割 + +## DeepLabv3p类 + +```python +paddlex.seg.DeepLabv3p(num_classes=2, backbone='MobileNetV2_x1.0', output_stride=16, aspp_with_sep_conv=True, decoder_use_sep_conv=True, encoder_with_aspp=True, enable_decoder=True, use_bce_loss=False, use_dice_loss=False, class_weight=None, ignore_index=255) + +``` + +> 构建DeepLabv3p分割器。 + +> **参数** + +> > - **num_classes** (int): 类别数。 +> > - **backbone** (str): DeepLabv3+的backbone网络,实现特征图的计算,取值范围为['Xception65', 'Xception41', 'MobileNetV2_x0.25', 'MobileNetV2_x0.5', 'MobileNetV2_x1.0', 'MobileNetV2_x1.5', 'MobileNetV2_x2.0'],'MobileNetV2_x1.0'。 +> > - **output_stride** (int): backbone 输出特征图相对于输入的下采样倍数,一般取值为8或16。默认16。 +> > - **aspp_with_sep_conv** (bool): decoder模块是否采用separable convolutions。默认True。 +> > - **decoder_use_sep_conv** (bool): decoder模块是否采用separable convolutions。默认True。 +> > - **encoder_with_aspp** (bool): 是否在encoder阶段采用aspp模块。默认True。 +> > - **enable_decoder** (bool): 是否使用decoder模块。默认True。 +> > - **use_bce_loss** (bool): 是否使用bce loss作为网络的损失函数,只能用于两类分割。可与dice loss同时使用。默认False。 +> > - **use_dice_loss** (bool): 是否使用dice loss作为网络的损失函数,只能用于两类分割,可与bce loss同时使用,当`use_bce_loss`和`use_dice_loss`都为False时,使用交叉熵损失函数。默认False。 +> > - **class_weight** (list/str): 交叉熵损失函数各类损失的权重。当`class_weight`为list的时候,长度应为`num_classes`。当`class_weight`为str时, weight.lower()应为'dynamic',这时会根据每一轮各类像素的比重自行计算相应的权重,每一类的权重为:每类的比例 * num_classes。class_weight取默认值None是,各类的权重1,即平时使用的交叉熵损失函数。 +> > - **ignore_index** (int): label上忽略的值,label为`ignore_index`的像素不参与损失函数的计算。默认255。 + +### train 训练接口 + +```python +train(self, num_epochs, train_dataset, train_batch_size=2, eval_dataset=None, eval_batch_size=1, save_interval_epochs=1, log_interval_steps=2, save_dir='output', pretrain_weights='IMAGENET', optimizer=None, learning_rate=0.01, lr_decay_power=0.9, use_vdl=False, sensitivities_file=None, eval_metric_loss=0.05, early_stop=False, early_stop_patience=5, resume_checkpoint=None): +``` + +> DeepLabv3p模型的训练接口,函数内置了`polynomial`学习率衰减策略和`momentum`优化器。 + +> **参数** +> > +> > - **num_epochs** (int): 训练迭代轮数。 +> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 +> > - **train_batch_size** (int): 训练数据batch大小。同时作为验证数据batch大小。默认2。 +> > - **eval_dataset** (paddlex.datasets): 评估数据读取器。 +> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为1。 +> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代次数)。默认为2。 +> > - **save_dir** (str): 模型保存路径。默认'output' +> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在ImageNet图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认'IMAGENET'。 +> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认的优化器:使用fluid.optimizer.Momentum优化方法,polynomial的学习率衰减策略。 +> > - **learning_rate** (float): 默认优化器的初始学习率。默认0.01。 +> > - **lr_decay_power** (float): 默认优化器学习率衰减指数。默认0.9。 +> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认False。 +> > - **sensitivities_file** (str): 若指定为路径时,则加载路径下敏感度信息进行裁剪;若为字符串'DEFAULT',则自动下载在ImageNet图片数据上获得的敏感度信息进行裁剪;若为None,则不进行裁剪。默认为None。 +> > - **eval_metric_loss** (float): 可容忍的精度损失。默认为0.05。 +> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 +> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 +> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 + +### evaluate 评估接口 + +```python +evaluate(self, eval_dataset, batch_size=1, epoch_id=None, return_details=False): +``` + +> DeepLabv3p模型评估接口。 + +> **参数** +> > +> > - **eval_dataset** (paddlex.datasets): 评估数据读取器。 +> > - **batch_size** (int): 评估时的batch大小。默认1。 +> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 +> > - **return_details** (bool): 是否返回详细信息。默认False。 + +> **返回值** +> > +> > - **dict**: 当`return_details`为False时,返回dict。包含关键字:'miou'、'category_iou'、'macc'、 +> > 'category_acc'和'kappa',分别表示平均iou、各类别iou、平均准确率、各类别准确率和kappa系数。 +> > - **tuple** (metrics, eval_details):当`return_details`为True时,增加返回dict (eval_details), +> > 包含关键字:'confusion_matrix',表示评估的混淆矩阵。 + +### predict 预测接口 + +``` +predict(self, im_file, transforms=None): +``` + +> DeepLabv3p模型预测接口。需要注意的是,只有在训练过程中定义了eval_dataset,模型在保存时才会将预测时的图像处理流程保存在`DeepLabv3p.test_transforms`和`DeepLabv3p.eval_transforms`中。如未在训练时定义eval_dataset,那在调用预测`predict`接口时,用户需要再重新定义test_transforms传入给`predict`接口。 + +> **参数** +> > +> > - **img_file** (str): 预测图像路径。 +> > - **transforms** (paddlex.seg.transforms): 数据预处理操作。 + +> **返回值** +> > +> > - **dict**: 包含关键字'label_map'和'score_map', 'label_map'存储预测结果灰度图,像素值表示对应的类别,'score_map'存储各类别的概率,shape=(h, w, num_classes)。 + +## UNet类 + +```python +paddlex.seg.UNet(num_classes=2, upsample_mode='bilinear', use_bce_loss=False, use_dice_loss=False, class_weight=None, ignore_index=255) +``` + +> 构建UNet分割器。 + +> **参数** + +> > - **num_classes** (int): 类别数。 +> > - **upsample_mode** (str): UNet decode时采用的上采样方式,取值为'bilinear'时利用双线行差值进行上菜样,当输入其他选项时则利用反卷积进行上菜样,默认为'bilinear'。 +> > - **use_bce_loss** (bool): 是否使用bce loss作为网络的损失函数,只能用于两类分割。可与dice loss同时使用。默认False。 +> > - **use_dice_loss** (bool): 是否使用dice loss作为网络的损失函数,只能用于两类分割,可与bce loss同时使用。当use_bce_loss和use_dice_loss都为False时,使用交叉熵损失函数。默认False。 +> > - **class_weight** (list/str): 交叉熵损失函数各类损失的权重。当`class_weight`为list的时候,长度应为`num_classes`。当`class_weight`为str时, weight.lower()应为'dynamic',这时会根据每一轮各类像素的比重自行计算相应的权重,每一类的权重为:每类的比例 * num_classes。class_weight取默认值None是,各类的权重1,即平时使用的交叉熵损失函数。 +> > - **ignore_index** (int): label上忽略的值,label为`ignore_index`的像素不参与损失函数的计算。默认255。 + +### train 训练接口 + +```python +train(self, num_epochs, train_dataset, train_batch_size=2, eval_dataset=None, eval_batch_size=1, save_interval_epochs=1, log_interval_steps=2, save_dir='output', pretrain_weights='COCO', optimizer=None, learning_rate=0.01, lr_decay_power=0.9, use_vdl=False, sensitivities_file=None, eval_metric_loss=0.05, early_stop=False, early_stop_patience=5, resume_checkpoint=None): +``` + +> UNet模型训练接口。 + +> **参数** +> > +> > - **num_epochs** (int): 训练迭代轮数。 +> > - **train_dataset** (paddlex.datasets): 训练数据读取器。 +> > - **train_batch_size** (int): 训练数据batch大小。同时作为验证数据batch大小。默认2。 +> > - **eval_dataset** (paddlex.datasets): 评估数据读取器。 +> > - **save_interval_epochs** (int): 模型保存间隔(单位:迭代轮数)。默认为1。 +> > - **log_interval_steps** (int): 训练日志输出间隔(单位:迭代次数)。默认为2。 +> > - **save_dir** (str): 模型保存路径。默认'output' +> > - **pretrain_weights** (str): 若指定为路径时,则加载路径下预训练模型;若为字符串'IMAGENET',则自动下载在COCO图片数据上预训练的模型权重;若为None,则不使用预训练模型。默认'COCO'。 +> > - **optimizer** (paddle.fluid.optimizer): 优化器。当该参数为None时,使用默认的优化器:使用fluid.optimizer.Momentum优化方法,polynomial的学习率衰减策略。 +> > - **learning_rate** (float): 默认优化器的初始学习率。默认0.01。 +> > - **lr_decay_power** (float): 默认优化器学习率衰减指数。默认0.9。 +> > - **use_vdl** (bool): 是否使用VisualDL进行可视化。默认False。 +> > - **sensitivities_file** (str): 若指定为路径时,则加载路径下敏感度信息进行裁剪;若为字符串'DEFAULT',则自动下载在ImageNet图片数据上获得的敏感度信息进行裁剪;若为None,则不进行裁剪。默认为None。 +> > - **eval_metric_loss** (float): 可容忍的精度损失。默认为0.05。 +> > - **early_stop** (float): 是否使用提前终止训练策略。默认值为False。 +> > - **early_stop_patience** (int): 当使用提前终止训练策略时,如果验证集精度在`early_stop_patience`个epoch内连续下降或持平,则终止训练。默认值为5。 +> > - **resume_checkpoint** (str): 恢复训练时指定上次训练保存的模型路径。若为None,则不会恢复训练。默认值为None。 + +#### evaluate 评估接口 + +``` +evaluate(self, eval_dataset, batch_size=1, epoch_id=None, return_details=False): +``` + +> UNet模型评估接口。 + +> **参数** +> > +> > - **eval_dataset** (paddlex.datasets): 评估数据读取器。 +> > - **batch_size** (int): 评估时的batch大小。默认1。 +> > - **epoch_id** (int): 当前评估模型所在的训练轮数。 +> > - **return_details** (bool): 是否返回详细信息。默认False。 + +> **返回值** +> > +> > - **dict**: 当return_details为False时,返回dict。包含关键字:'miou'、'category_iou'、'macc'、 +> > 'category_acc'和'kappa',分别表示平均iou、各类别iou、平均准确率、各类别准确率和kappa系数。 +> > - **tuple** (metrics, eval_details):当return_details为True时,增加返回dict (eval_details), +> > 包含关键字:'confusion_matrix',表示评估的混淆矩阵。 + +#### predict 预测接口 + +``` +predict(self, im_file, transforms=None): +``` + +> UNet模型预测接口。需要注意的是,只有在训练过程中定义了eval_dataset,模型在保存时才会将预测时的图像处理流程保存在`UNet.test_transforms`和`UNet.eval_transforms`中。如未在训练时定义eval_dataset,那在调用预测`predict`接口时,用户需要再重新定义test_transforms传入给`predict`接口。 + +> **参数** +> > +> > - **img_file** (str): 预测图像路径。 +> > - **transforms** (paddlex.seg.transforms): 数据预处理操作。 + +> **返回值** +> > +> > - **dict**: 包含关键字'label_map'和'score_map', 'label_map'存储预测结果灰度图,像素值表示对应的类别,'score_map'存储各类别的概率,shape=(h, w, num_classes)。 diff --git a/docs/apis/slim.md b/docs/apis/slim.md old mode 100644 new mode 100755 index c0054c3459e48b3193d351188436a663cc2492bf..000336ed9ead2fdff30ebf8dd829a29d317089ed --- a/docs/apis/slim.md +++ b/docs/apis/slim.md @@ -2,7 +2,7 @@ ## 计算参数敏感度 ``` -paddlex.slim.cal_params_sensetives(model, save_file, eval_dataset, batch_size=8) +paddlex.slim.cal_params_sensitivities(model, save_file, eval_dataset, batch_size=8) ``` 计算模型中可裁剪参数在验证集上的敏感度,并将敏感度信息保存至文件`save_file` 1. 获取模型中可裁剪卷积Kernel的名称。 diff --git a/docs/apis/transforms/augment.md b/docs/apis/transforms/augment.md new file mode 100644 index 0000000000000000000000000000000000000000..bc37d4853034f42361edd23e2719c119cda5a9bb --- /dev/null +++ b/docs/apis/transforms/augment.md @@ -0,0 +1,66 @@ +# 数据增强与imgaug支持 + +数据增强操作可用于在模型训练时,增加训练样本的多样性,从而提升模型的泛化能力。 + +## PaddleX内置增强操作 + +PaddleX对于图像分类、目标检测、实例分割和语义分割内置了部分常见的数据增强操作,如下表所示, + +| 任务类型 | 增强方法 | +| :------- | :------------| +| 图像分类 | [RandomCrop](cls_transforms.html#randomcrop)、[RandomHorizontalFlip](cls_transforms.html#randomhorizontalflip)、[RandomVerticalFlip](cls_transforms.html#randomverticalflip)、
[RandomRotate](cls_transforms.html#randomratate)、 [RandomDistort](cls_transforms.html#randomdistort) | +|目标检测
实例分割| [RandomHorizontalFlip](det_transforms.html#randomhorizontalflip)、[RandomDistort](det_transforms.html#randomdistort)、[RandomCrop](det_transforms.html#randomcrop)、
[[MixupImage](det_transforms.html#mixupimage)(仅支持YOLOv3模型)、RandomExpand](det_transforms.html#randomexpand) | +|语义分割 | [RandomHorizontalFlip](seg_transforms.html#randomhorizontalflip)、[RandomVerticalFlip](seg_transforms.html#randomverticalflip)、[RandomRangeScaling](seg_transforms.html#randomrangescaling)、
[RandomStepScaling](seg_transforms.html#randomstepscaling)、[RandomPaddingCrop](seg_transforms.html#randompaddingcrop)、 [RandomBlur](seg_transforms.html#randomblur)、
[RandomRotation](seg_transforms.html#randomrotation)、[RandomScaleAspect](seg_transforms.html#randomscaleaspect)、[RandomDistort](seg_transforms.html#randomdistort) | + +## imgaug增强库的支持 + +PaddleX目前已适配imgaug图像增强库,用户可以直接在PaddleX构造`transforms`时,调用imgaug的方法, 如下示例 +``` +import paddlex as pdx +from paddlex.cls import transforms +import imgaug.augmenters as iaa +train_transforms = transforms.Compose([ + # 随机在[0.0 3.0]中选值对图像进行模糊 + iaa.blur.GaussianBlur(sigma=(0.0, 3.0)), + transforms.RandomCrop(crop_size=224), + transforms.Normalize() +]) +``` +除了上述用法,`Compose`接口中也支持imgaug的`Someof`、`Sometimes`、`Sequential`、`Oneof`等操作,开发者可以通过这些方法随意组合出增强流程。由于imgaug对于标注信息(目标检测框和实例分割mask)与PaddleX模型训练逻辑有部分差异,**目前在检测和分割中,只支持pixel-level的增强方法,(即在增强时,不对图像的大小和方向做改变) 其它方法仍在适配中**,详情可见下表, + +| 增强方法 | 图像分类 | 目标检测
实例分割 | 语义分割 | 备注 | +| :------ | :------- | :-------------------- | :------- | :--- | +| [imgaug.augmenters.arithmetic](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_arithmetic.html) |√ |√ |√ | Cutout, DropoutJpegCompression等| +| [imgaug.augmenters.artistic](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_artistic.html) |√ |√ |√ | 图像卡通化| +| [imgaug.augmenters.blur](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_blur.html) |√ |√ |√ | GaussianBlur, AverageBlur等| +| [imgaug.augmenters.collections](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_collections.html) |√ | | |提供了RandAugment方法 | +| [imgaug.augmenters.color](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_color.html) |√ |√ |√ | Brightness, Hue等色调的增强方法| +| [imgaug.augmenters.contrast](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_contrast.html) |√ |√ |√ | 多种对比度增强方式| +| [imgaug.augmenters.convolutional](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_convolutional.html) |√ |√ |√ | 应用卷积kernel到图像 | +| [imgaug.augmenters.edges](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_edges.html) |√ |√ |√ | 图像边缘化等方法| +| [imgaug.augmenters.flip](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_flip.html) |√ | | | Fliplr和Flipud翻转方法| +| [imgaug.augmenters.geometric](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_geometric.html) |√ | | | Affine、Rotate等增强方法| +| [imgaug.augmenters.imgcorruptlike](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_imgcorruptlike.html) |√ |√ |√ | GaussianNoise等图像噪声增强方法| +| [imgaug.augmenters.pillike](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_pillike.html) |√ | | | | +| [imgaug.augmenters.pooling](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_pooling.html) |√ | | |应用pooling操作到图像 | +| [imgaug.augmenters.segmentation](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_segmentation.html) |√ | | | 应用分割方法到图像| +| [imgaug.augmenters.size](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_size.html) |√ | | | Reisze、Crop、Pad等操作| +| [imgaug.augmenters.weather](https://imgaug.readthedocs.io/en/latest/source/api_augmenters_weather.html) |√ |√ |√ | 多种模拟天气等增强方法| + +需要注意的是,imgaug的基础方法中,如`imgaug.augmenters.blur`仅为图像处理操作,并无概率设置,而在CV模型训练中,增强操作往往是以一定概率应用在样本上,因此我们可以通过imgaug的`Someof`、`Sometimes`、`Sequential`、`Oneof`等操作来组合实现,如下代码所示, +> - `Someof` 执行定义增强方法列表中的部分方法 +> - `Sometimes` 以一定概率执行定义的增强方法列表 +> - `Sequential` 按顺序执行定义的增强方法列表 +``` +image imgaug.augmenters as iaa +from paddlex.cls import transforms +# 以0.6的概率对图像样本进行模糊 +img_augmenters = iaa.Sometimes(0.6, [ + iaa.blur.GaussianBlur(sigma=(0.0, 3.0)) +]) +train_transforms = transforms.Compose([ + img_augmenters, + transforms.RandomCrop(crop_size=224), + transforms.Normalize() +]) +``` diff --git a/docs/apis/transforms/cls_transforms.md b/docs/apis/transforms/cls_transforms.md old mode 100644 new mode 100755 index ff6a9ebff33a9938ef439dd881d5ba9c492da479..ccffc30292c7b5dea81ba6fe62a42a1810203ca9 --- a/docs/apis/transforms/cls_transforms.md +++ b/docs/apis/transforms/cls_transforms.md @@ -1,4 +1,4 @@ -# 分类-paddlex.cls.transforms +# 图像分类-cls.transforms 对图像分类任务的数据进行操作。可以利用[Compose](#compose)类将图像预处理/增强操作进行组合。 diff --git a/docs/apis/transforms/det_transforms.md b/docs/apis/transforms/det_transforms.md old mode 100644 new mode 100755 index 21212cedec6a88483393d7232583e87ccf749dc4..0ee6e57ee778769c0e363eaee9050b36d5f6eb5a --- a/docs/apis/transforms/det_transforms.md +++ b/docs/apis/transforms/det_transforms.md @@ -1,4 +1,4 @@ -# 检测-paddlex.det.transforms +# 检测和实例分割-det.transforms 对目标检测任务的数据进行操作。可以利用[Compose](#compose)类将图像预处理/增强操作进行组合。 diff --git a/docs/apis/transforms/index.rst b/docs/apis/transforms/index.rst old mode 100644 new mode 100755 index f6040978134ccf664d08ab39f55db197b752ac37..0a2be9860a32e56b6e1e6b31aa12ab22332e6785 --- a/docs/apis/transforms/index.rst +++ b/docs/apis/transforms/index.rst @@ -9,3 +9,4 @@ transforms为PaddleX的模型训练提供了数据的预处理和数据增强接 cls_transforms.md det_transforms.md seg_transforms.md + augment.md diff --git a/docs/apis/transforms/seg_transforms.md b/docs/apis/transforms/seg_transforms.md old mode 100644 new mode 100755 index d339f8c2048013cc73ac8d55984d5e6e5c98c20b..1708290680e767b3a06615f0b789279b716433ea --- a/docs/apis/transforms/seg_transforms.md +++ b/docs/apis/transforms/seg_transforms.md @@ -1,4 +1,4 @@ -# 分割-paddlex.seg.transforms +# 语义分割-seg.transforms 对用于分割任务的数据进行操作。可以利用[Compose](#compose)类将图像预处理/增强操作进行组合。 diff --git a/docs/apis/visualize.md b/docs/apis/visualize.md old mode 100644 new mode 100755 diff --git a/docs/anaconda_install.md b/docs/appendix/anaconda_install.md old mode 100644 new mode 100755 similarity index 84% rename from docs/anaconda_install.md rename to docs/appendix/anaconda_install.md index 84e2d07c1e2f3fda66f64c73816ed5b75dfa9f40..154be30928496da632ac5f67f3e7ee27fe05bc48 --- a/docs/anaconda_install.md +++ b/docs/appendix/anaconda_install.md @@ -3,11 +3,12 @@ Anaconda是一个开源的Python发行版本,其包含了conda、Python等180 ## Windows安装Anaconda ### 第一步 下载 -在Anaconda官网[(https://www.anaconda.com/products/individual)](https://www.anaconda.com/products/individual)选择下载Windows Python3.7 64-Bit版本 +- 在Anaconda官网[(https://www.anaconda.com/products/individual)](https://www.anaconda.com/products/individual)选择下载Windows Python3.7 64-Bit版本 +- 确保已经安装`Visual C++ Build Tools`(可以在开始菜单中找到),如未安装,请[点击下载](https://go.microsoft.com/fwlink/?LinkId=691126)安装。 ### 第二步 安装 运行下载的安装包(以.exe为后辍),根据引导完成安装, 用户可自行修改安装目录(如下图) -![](./images/anaconda_windows.png) +![](../images/anaconda_windows.png) ### 第三步 使用 - 点击Windows系统左下角的Windows图标,打开:所有程序->Anaconda3/2(64-bit)->Anaconda Prompt @@ -21,7 +22,7 @@ conda activate my_paddlex conda install git # 安装pycocotools pip install cython -pip install git+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI +pip install git+https://gitee.com/jiangjiajun/philferriere-cocoapi.git#subdirectory=PythonAPI # 安装paddlepaddle-gpu pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple # 安装paddlex diff --git a/docs/gpu_configure.md b/docs/appendix/gpu_configure.md old mode 100644 new mode 100755 similarity index 100% rename from docs/gpu_configure.md rename to docs/appendix/gpu_configure.md diff --git a/docs/how_to_offline_run.md b/docs/appendix/how_to_offline_run.md old mode 100644 new mode 100755 similarity index 100% rename from docs/how_to_offline_run.md rename to docs/appendix/how_to_offline_run.md diff --git a/docs/appendix/index.rst b/docs/appendix/index.rst new file mode 100755 index 0000000000000000000000000000000000000000..4e6438cdfa706ebfe982b4a76b10916caa2e506b --- /dev/null +++ b/docs/appendix/index.rst @@ -0,0 +1,17 @@ +附录 +======================================= + + +.. toctree:: + :maxdepth: 1 + :caption: 目录: + + model_zoo.md + metrics.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/metrics.md b/docs/appendix/metrics.md new file mode 100755 index 0000000000000000000000000000000000000000..dea5703650c57ce88011c50bc99916000693293f --- /dev/null +++ b/docs/appendix/metrics.md @@ -0,0 +1,145 @@ +# PaddleX指标及日志 + +PaddleX在模型训练、评估过程中,都会有相应的日志和指标反馈,本文档用于说明这些日志和指标的含义。 + +## 训练通用统计信息 + +PaddleX所有模型在训练过程中,输出的日志信息都包含了6个通用的统计信息,用于辅助用户进行模型训练,例如**分割模型**的训练日志,如下图所示。 + +![](../images/seg_train.png) + +各字段含义如下: + +| 字段 | 字段值示例 | 含义 | +| -------------- | -------------------- | ------------------------------------------------------------ | +| Epoch | Epoch=4/20 | [迭代轮数]所有训练数据会被训练20轮,当前处于第4轮 | +| Step | Step=62/66 | [迭代步数]所有训练数据被训练一轮所需要的迭代步数为66,当前处于第62步 | +| loss | loss=0.007226 | [损失函数值]参与当前迭代步数的训练样本的平均损失函数值loss,loss值越低,表明模型在训练集上拟合的效果越好(如上日志中第1行表示第4个epoch的第62个Batch的loss值为0.007226) | +| lr | lr=0.008215 | [学习率]当前模型迭代过程中的学习率 | +| time_each_step | time_each_step=0.41s | [每步迭代时间]训练过程计算得到的每步迭代平均用时 | +| eta | eta=0:9:44 | [剩余时间]模型训练完成所需剩余时间预估为0小时9分钟44秒 | +| | | | + +不同模型的日志中除了上述通用字段外,还有其它字段,这些字段含义可见文档后面对各任务模型的描述。 + +## 评估通用统计信息 + +PaddleX所有模型在训练过程中会根据用户设定的`save_interval_epochs`参数,每间隔一定轮数进行评估和保存。例如**分类模型**的评估日志,如下图所示。 + +![](../images/cls_eval.png) + +上图中第1行表明验证数据集中样本数为240,需要迭代8步才能评估完所有验证数据;第5行用于表明第2轮的模型已经完成保存操作;第6行则表明当前保存的模型中,第2轮的模型在验证集上指标最优(分类任务看`acc1`,此时`acc1`值为0.258333),最优模型会保存在`best_model`目录中。 + +## 分类特有统计信息 + +### 训练日志字段 + +分类任务的训练日志除了通用统计信息外,还包括`acc1`和`acc5`两个特有字段。 + +> 注: acck准确率是针对一张图片进行计算的:把模型在各个类别上的预测得分按从高往低进行排序,取出前k个预测类别,若这k个预测类别包含了真值类,则认为该图片分类正确。 + +![](../images/cls_train.png) + + +上图中第1行中的`acc1`表示参与当前迭代步数的训练样本的平均top1准确率,值越高代表模型越优;`acc5`表示参与当前迭代步数的训练样本的平均top5(若类别数n少于5,则为topn)准确率,值越高代表模型越优。第4行中的`loss`表示整个训练集的平均损失函数值,`acc1`表示整个训练集的平均top1准确率,`acc5`表示整个训练集的平均top5准确率。 + + +### 评估日志字段 + +![](../images/cls_eval.png) + +上图中第3行中的`acc1`表示整个验证集的平均top1准确率,`acc5`表示整个验证集的平均top5准确率。 + + +## 检测特有统计信息 + +### 训练日志字段 + +#### YOLOv3 + +YOLOv3的训练日志只包括训练通用统计信息(见上文训练通用统计信息)。 + +![](../images/yolo_train.png) + +上图中第5行`loss`表示整个训练集的平均损失函数loss值。 + +#### FasterRCNN + +FasterRCNN的训练日志除了通用统计信息外,还包括`loss_cls`、`loss_bbox`、`loss_rpn_cls`和`loss_rpn_bbox`,这些字段的含义如下: + +| 字段 | 含义 | +| -------------- | --------------------------------------------- | +| loss_cls | RCNN子网络中分类损失函数值 | +| loss_bbox | RCNN子网络中检测框回归损失函数值 | +| loss_rpn_cls | RPN子网络中分类损失函数值 | +| loss_rpn_bbox | RPN子网络中检测框回归损失函数值 | +| loss | 所有子网络损失函数值之和 | + +![](../images/faster_train.png) + +上图中第1行`loss`, `loss_cls`、`loss_bbox`、`loss_rpn_clss`、`loss_rpn_bbox`都是参与当前迭代步数的训练样本的损失值,而第7行是针整个训练集的损失函数值。 + +#### MaskRCNN + +MaskRCNN的训练日志除了通用统计信息外,还包括`loss_cls`、`loss_bbox`、`loss_mask`、`loss_rpn_cls`和`loss_rpn_bbox`,这些字段的含义如下: + + +| 字段 | 含义 | +| -------------- | --------------------------------------------- | +| loss_cls | RCNN子网络中分类损失函数值 | +| loss_bbox | RCNN子网络中检测框回归损失函数值 | +| loss_mask | RCNN子网络中Mask回归损失函数值 | +| loss_rpn_cls | RPN子网络中分类损失函数值 | +| loss_rpn_bbox | RPN子网络中检测框回归损失函数值 | +| loss | 所有子网络损失函数值之和 | + +![](../images/mask_train.png) + +上图中第1行`loss`, `loss_cls`、`loss_bbox`、`loss_mask`、`loss_rpn_clss`、`loss_rpn_bbox`都是参与当前迭代步数的训练样本的损失值,而第7行是针整个训练集的损失函数值。 + +### 评估日志字段 + +检测可以使用两种评估标准:VOC评估标准和COCO评估标准。 + +#### VOC评估标准 + +![](../images/voc_eval.png) + +> 注:`map`为平均准确率的平均值,即IoU(Intersection Over Union)取0.5时各个类别的准确率-召回率曲线下面积的平均值。 + +上图中第3行`bbox_map`表示检测任务中整个验证集的平均准确率平均值。 + +#### COCO评估标准 + +> 注:COCO评估指标可参见[COCO官网解释](http://cocodataset.org/#detection-eval)。PaddleX主要反馈`mmAP`,即AP at IoU=.50:.05:.95这项指标,为在各个IoU阈值下平均准确率平均值(mAP)的平均值。 + +COCO格式的数据集不仅可以用于训练目标检测模型,也可以用于训练实例分割模型。在目标检测中,PaddleX主要反馈针对检测框的`bbox_mmAP`指标;在实例分割中,还包括针对Mask的`seg_mmAP`指标。如下所示,第一张日志截图为目标检测的评估结果,第二张日志截图为实例分割的评估结果。 + +![](../images/faster_eval.png) + +上图中红框标注的`bbox_mmap`表示整个验证集的检测框平均准确率平均值。 + +![](../images/mask_eval.png) +上图中红框标注的`bbox_mmap`和`seg_mmap`分别表示整个验证集的检测框平均准确率平均值、Mask平均准确率平均值。 + +## 分割特有统计信息 + +### 训练日志字段 + +语义分割的训练日志只包括训练通用统计信息(见上文训练通用统计信息)。 + +![](../images/seg_train.png) + +### 评估日志字段 + +语义分割的评估日志包括了`miou`、`category_iou`、`macc`、`category_acc`、`kappa`,这些字段的含义如下: + +| 字段 | 含义 | +| -------------- | --------------------------------------------- | +| miou | 各类IoU(Intersection Over Union)的平均值 | +| category_iou | 各类别的IoU | +| macc | 平均准确率,即预测正确的像素数/总像素数 | +| category_acc | 各类别的准确率,即各类别预测正确的像素数/预测为该类别的总像素数 | +| kappa | kappa系数,用于一致性检验 | + +![](../images/seg_eval.png) diff --git a/docs/appendix/model_zoo.md b/docs/appendix/model_zoo.md new file mode 100644 index 0000000000000000000000000000000000000000..f48ea51361f85c6fdeb22c6c03e8d6f982fbd439 --- /dev/null +++ b/docs/appendix/model_zoo.md @@ -0,0 +1,52 @@ +# PaddleX模型库 + +## 图像分类模型 +> 表中模型相关指标均为在ImageNet数据集上使用PaddlePaddle Python预测接口测试得到(测试GPU型号为Nvidia Tesla P40),预测速度为每张图片预测用时(不包括预处理和后处理),表中符号`-`表示相关指标暂未测试。 + + +| 模型 | 模型大小 | 预测速度(毫秒) | Top1准确率(%) | Top5准确率(%) | +| :----| :------- | :----------- | :--------- | :--------- | +| ResNet18| 46.9MB | 1.499 | 71.0 | 89.9 | +| ResNet34| 87.5MB | 2.272 | 74.6 | 92.1 | +| ResNet50| 102.7MB | 2.939 | 76.5 | 93.0 | +| ResNet101 |179.1MB | 5.314 | 77.6 | 93.6 | +| ResNet50_vd |102.8MB | 3.165 | 79.1 | 94.4 | +| ResNet101_vd| 179.2MB | 5.252 | 80.2 | 95.0 | +| ResNet50_vd_ssld |102.8MB | 3.165 | 82.4 | 96.1 | +| ResNet101_vd_ssld| 179.2MB | 5.252 | 83.7 | 96.7 | +| DarkNet53|166.9MB | 3.139 | 78.0 | 94.1 | +| MobileNetV1 | 16.0MB | 32.523 | 71.0 | 89.7 | +| MobileNetV2 | 14.0MB | 23.318 | 72.2 | 90.7 | +| MobileNetV3_large| 21.0MB | 19.308 | 75.3 | 93.2 | +| MobileNetV3_small | 12.0MB | 6.546 | 68.2 | 88.1 | +| MobileNetV3_large_ssld| 21.0MB | 19.308 | 79.0 | 94.5 | +| MobileNetV3_small_ssld | 12.0MB | 6.546 | 71.3 | 90.1 | +| Xception41 |92.4MB | 4.408 | 79.6 | 94.4 | +| Xception65 | 144.6MB | 6.464 | 80.3 | 94.5 | +| DenseNet121 | 32.8MB | 4.371 | 75.7 | 92.6 | +| DenseNet161|116.3MB | 8.863 | 78.6 | 94.1 | +| DenseNet201| 84.6MB | 8.173 | 77.6 | 93.7 | +| ShuffleNetV2 | 9.0MB | 10.941 | 68.8 | 88.5 | + +## 目标检测模型 + +> 表中模型相关指标均为在MSCOCO数据集上使用PaddlePaddle Python预测接口测试得到(测试GPU型号为Nvidia Tesla V100测试得到,表中符号`-`表示相关指标暂未测试。 + +| 模型 | 模型大小 | 预测时间(毫秒) | BoxAP(%) | +|:-------|:-----------|:-------------|:----------| +|FasterRCNN-ResNet50|135.6MB| 78.450 | 35.2 | +|FasterRCNN-ResNet50_vd| 135.7MB | 79.523 | 36.4 | +|FasterRCNN-ResNet101| 211.7MB | 107.342 | 38.3 | +|FasterRCNN-ResNet50-FPN| 167.2MB | 44.897 | 37.2 | +|FasterRCNN-ResNet50_vd-FPN|168.7MB | 45.773 | 38.9 | +|FasterRCNN-ResNet101-FPN| 251.7MB | 55.782 | 38.7 | +|FasterRCNN-ResNet101_vd-FPN |252MB | 58.785 | 40.5 | +|YOLOv3-DarkNet53|252.4MB | 21.944 | 38.9 | +|YOLOv3-MobileNetv1 |101.2MB | 12.771 | 29.3 | +|YOLOv3-MobileNetv3|94.6MB | - | 31.6 | +| YOLOv3-ResNet34|169.7MB | 15.784 | 36.2 | + +## 实例分割模型 + +> 表中模型相关指标均为在MSCOCO数据集上测试得到。 + diff --git a/docs/client_use.md b/docs/client_use.md deleted file mode 100644 index bb0fbf88ccc95b10b193aaee0be0705ef6277113..0000000000000000000000000000000000000000 --- a/docs/client_use.md +++ /dev/null @@ -1,75 +0,0 @@ -# 使用PaddleX客户端进行模型训练 - -**第一步:下载PaddleX客户端** - -您需要前往 [官网](https://www.paddlepaddle.org.cn/paddle/paddlex)填写基本信息后下载试用PaddleX客户端 - - -**第二步:准备数据** - -在开始模型训练前,您需要根据不同的任务类型,将数据标注为相应的格式。目前PaddleX支持【图像分类】、【目标检测】、【语义分割】、【实例分割】四种任务类型。不同类型任务的数据处理方式可查看[数据标注方式](https://github.com/PaddlePaddle/PaddleX/tree/master/DataAnnotation/AnnotationNote)。 - - -**第三步:导入我的数据集** - -① 数据标注完成后,您需要根据不同的任务,将数据和标注文件,按照客户端提示更名并保存到正确的文件中。 - -② 在客户端新建数据集,选择与数据集匹配的任务类型,并选择数据集对应的路径,将数据集导入。 - -![](./images/00_loaddata.png) - -③ 选定导入数据集后,客户端会自动校验数据及标注文件是否合规,校验成功后,您可根据实际需求,将数据集按比例划分为训练集、验证集、测试集。 - -④ 您可在「数据分析」模块按规则预览您标注的数据集,双击单张图片可放大查看。 - -![](./images/01_datasplit.png) - - - -**第四步:创建项目** - -① 在完成数据导入后,您可以点击「新建项目」创建一个项目。 - -② 您可根据实际任务需求选择项目的任务类型,需要注意项目所采用的数据集也带有任务类型属性,两者需要进行匹配。 - -![](./images/02_newproject.png) - - - -**第五步:项目开发** - -① **数据选择**:项目创建完成后,您需要选择已载入客户端并校验后的数据集,并点击下一步,进入参数配置页面。 - -![](./images/03_choosedata.png) - -② **参数配置**:主要分为**模型参数**、**训练参数**、**优化策略**三部分。您可根据实际需求选择模型结构及对应的训练参数、优化策略,使得任务效果最佳。 - -![](./images/04_parameter.png) - -参数配置完成后,点击启动训练,模型开始训练并进行效果评估。 - -③ **训练可视化**: - -在训练过程中,您可通过VisualDL查看模型训练过程时的参数变化、日志详情,及当前最优的训练集和验证集训练指标。模型在训练过程中通过点击"终止训练"随时终止训练过程。 - -![](./images/05_train.png) - -![](./images/06_VisualDL.png) - -模型训练结束后,点击”下一步“,进入模型评估页面。 - - - -④ **模型评估** - -在模型评估页面,您可将训练后的模型应用在切分时留出的「验证数据集」以测试模型在验证集上的效果。评估方法包括混淆矩阵、精度、召回率等。在这个页面,您也可以直接查看模型在测试数据集上的预测效果。 - -根据评估结果,您可决定进入模型发布页面,或返回先前步骤调整参数配置重新进行训练。 - -![](./images/07_evaluate.png) - -⑤**模型发布** - -当模型效果满意后,您可根据实际的生产环境需求,选择将模型发布为需要的版本。 - -![](./images/08_deploy.png) diff --git a/docs/conf.py b/docs/conf.py old mode 100644 new mode 100755 diff --git a/docs/convertor.md b/docs/convertor.md deleted file mode 100644 index 2f1b4eacb0a1d936b1e937b2837c9796c04ffdc6..0000000000000000000000000000000000000000 --- a/docs/convertor.md +++ /dev/null @@ -1,17 +0,0 @@ -# 模型转换 - -## 转ONNX模型 -PaddleX基于[Paddle2ONNX工具](https://github.com/PaddlePaddle/paddle2onnx),提供了便捷的API,支持用户将PaddleX训练保存的模型导出为ONNX模型。 -通过如下示例代码,用户即可将PaddleX训练好的MobileNetV2模型导出 -``` -import paddlex as pdx -pdx.convertor.to_onnx(model_dir='paddle_mobilenet', save_dir='onnx_mobilenet') -``` - -## 转PaddleLite模型 -PaddleX可支持导出为[PaddleLite](https://github.com/PaddlePaddle/Paddle-Lite)支持的模型格式,用于支持用户将模型部署更多硬件设备。 -通过如下示例代码,用户即可将PaddleX训练好的MobileNetV2模型导出 -``` -import paddlex as pdx -pdx.convertor.to_lite(model_dir='paddle_mobilenet', save_dir='lite_mobilnet', terminal='arm') -``` diff --git a/docs/cv_solutions.md b/docs/cv_solutions.md new file mode 100755 index 0000000000000000000000000000000000000000..5bf084870ba3cbf581c89657daeaff0bebb2d66e --- /dev/null +++ b/docs/cv_solutions.md @@ -0,0 +1,63 @@ +# PaddleX视觉方案介绍 + +PaddleX目前提供了4种视觉任务解决方案,分别为图像分类、目标检测、实例分割和语义分割。用户可以根据自己的任务类型按需选取。 + +## 图像分类 +图像分类任务指的是输入一张图片,模型预测图片的类别,如识别为风景、动物、车等。 + +![](./images/image_classification.png) + +对于图像分类任务,针对不同的应用场景,PaddleX提供了百度改进的模型,见下表所示 + +| 模型 | 模型大小 | 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% | 适用于服务端场景 | + +除上述模型外,PaddleX还支持近20种图像分类模型,模型列表可参考[PaddleX模型库](../appendix/model_zoo.md) + + +## 目标检测 +目标检测任务指的是输入图像,模型识别出图像中物体的位置(用矩形框框出来,并给出框的位置),和物体的类别,如在手机等零件质检中,用于检测外观上的瑕疵等。 + +![](./images/object_detection.png) + +对于目标检测,针对不同的应用场景,PaddleX提供了主流的YOLOv3模型和Faster-RCNN模型,见下表所示 + +| 模型 | 模型大小 | 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模型外,PaddleX同时也支持FasterRCNN模型,支持FPN结构和5种backbone网络,详情可参考[PaddleX模型库](../appendix/model_zoo.md) + +## 实例分割 +在目标检测中,模型识别出图像中物体的位置和物体的类别。而实例分割则是在目标检测的基础上,做了像素级的分类,将框内的属于目标物体的像素识别出来。 + +![](./images/instance_segmentation.png) + +PaddleX目前提供了实例分割MaskRCNN模型,支持5种不同的backbone网络,详情可参考[PaddleX模型库](../appendix/model_zoo.md) + +| 模型 | 模型大小 | 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 | | + + +## 语义分割 +语义分割用于对图像做像素级的分类,应用在人像分类、遥感图像识别等场景。 + +![](./images/semantic_segmentation.png) + +对于语义分割,PaddleX也针对不同的应用场景,提供了不同的模型选择,如下表所示 + +| 模型 | 模型大小 | GPU预测速度 | CPU预测速度 | ARM芯片预测速度 | mIOU | 备注 | +| :---- | :------- | :---------- | :---------- | :------------- | :----- | :----- | +| DeepLabv3p-MobileNetV2_x0.25 | | ? | ? | ? | ? | ? | +| DeepLabv3p-MobileNetV2_x1.0 | | ? | ? | ? | ? | ? | +| DeepLabv3p-Xception65 | | ? | ? | ? | ? | ? | +| UNet | | ? | ? | ? | ? | ? | diff --git a/docs/datasets.md b/docs/datasets.md index b197b43b6c1ce2dd8c91bae3c484573365493ba0..841f4331d3207a5a2fe3a68693781baafdaaeb4d 100644 --- a/docs/datasets.md +++ b/docs/datasets.md @@ -41,8 +41,8 @@ labelA labelB ... ``` -[点击这里](https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz),下载蔬菜分类分类数据集。 -在PaddleX中,使用`paddlex.cv.datasets.ImageNet`([API说明](./apis/datasets.html#imagenet))加载分类数据集。 +[点击这里](https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz),下载蔬菜分类分类数据集 +在PaddleX中,使用`paddlex.cv.datasets.ImageNet`([API说明](./apis/datasets.html#imagenet))加载分类数据集 ## 目标检测VOC 目标检测VOC数据集包含图像文件夹、标注信息文件夹、标签文件及图像列表文件。 @@ -81,8 +81,8 @@ labelA labelB ... ``` -[点击这里](https://bj.bcebos.com/paddlex/datasets/insect_det.tar.gz),下载昆虫检测数据集。 -在PaddleX中,使用`paddlex.cv.datasets.VOCDetection`([API说明](./apis/datasets.html#vocdetection))加载目标检测VOC数据集。 +[点击这里](https://bj.bcebos.com/paddlex/datasets/insect_det.tar.gz),下载昆虫检测数据集 +在PaddleX中,使用`paddlex.cv.datasets.VOCDetection`([API说明](./apis/datasets.html#vocdetection))加载目标检测VOC数据集 ## 目标检测和实例分割COCO 目标检测和实例分割COCO数据集包含图像文件夹及图像标注信息文件。 @@ -135,7 +135,7 @@ labelB ] } ``` -其中,每个字段的含义如下所示: +每个字段的含义如下所示: | 域名 | 字段名 | 含义 | 数据类型 | 备注 | |:-----|:--------|:------------|------|:-----| @@ -155,8 +155,8 @@ labelB | categories | supercategory | 类别父类的标签名 | str | | -[点击这里](https://bj.bcebos.com/paddlex/datasets/garbage_ins_det.tar.gz),下载垃圾实例分割数据集。 -在PaddleX中,使用`paddlex.cv.datasets.COCODetection`([API说明](./apis/datasets.html#cocodetection))加载COCO格式数据集。 +[点击这里](https://bj.bcebos.com/paddlex/datasets/garbage_ins_det.tar.gz),下载垃圾实例分割数据集 +在PaddleX中,使用`paddlex.cv.datasets.COCODetection`([API说明](./apis/datasets.html#cocodetection))加载COCO格式数据集 ## 语义分割数据 语义分割数据集包含原图、标注图及相应的文件列表文件。 @@ -191,176 +191,14 @@ images/xxx2.png annotations/xxx2.png `labels.txt`: 每一行为一个单独的类别,相应的行号即为类别对应的id(行号从0开始),如下所示: ``` -background labelA labelB ... ``` -标注图像为单通道图像,像素值即为对应的类别,像素标注类别需要从0开始递增(一般第一个类别为`background`), +标注图像为单通道图像,像素值即为对应的类别,像素标注类别需要从0开始递增, 例如0,1,2,3表示有4种类别,标注类别最多为256类。其中可以指定特定的像素值用于表示该值的像素不参与训练和评估(默认为255)。 -[点击这里](https://bj.bcebos.com/paddlex/datasets/optic_disc_seg.tar.gz),下载视盘语义分割数据集。 -在PaddleX中,使用`paddlex.cv.datasets.SegReader`([API说明](./apis/datasets.html#segreader))加载语义分割数据集。 +[点击这里](https://bj.bcebos.com/paddlex/datasets/optic_disc_seg.tar.gz),下载视盘语义分割数据集 +在PaddleX中,使用`paddlex.cv.datasets.SegReader`([API说明](./apis/datasets.html#segreader))加载语义分割数据集 - -## 图像分类EasyDataCls - -图像分类EasyDataCls数据集包含存放图像和json文件的文件夹、标签文件及图像列表文件。 -参考数据文件结构如下: -``` -./dataset/ # 数据集根目录 -|--easydata # 存放图像和json文件的文件夹 -| |--0001.jpg -| |--0001.json -| |--0002.jpg -| |--0002.json -| └--... -| -|--train_list.txt # 训练文件列表文件 -| -|--val_list.txt # 验证文件列表文件 -| -└--labels.txt # 标签列表文件 - -``` -其中,图像文件名应与json文件名一一对应。 - -每个json文件存储于`labels`相关的信息。如下所示: -``` -{"labels": [{"name": "labelA"}]} -``` -其中,`name`字段代表对应图像的类别。 - -`train_list.txt`和`val_list.txt`文本以空格为分割符分为两列,第一列为图像文件相对于dataset的相对路径,第二列为json文件相对于dataset的相对路径。如下所示: -``` -easydata/0001.jpg easydata/0001.json -easydata/0002.jpg easydata/0002.json -... -``` - -`labels.txt`: 每一行为一个单独的类别,相应的行号即为类别对应的id(行号从0开始),如下所示: -``` -labelA -labelB -... -``` -[点击这里](https://ai.baidu.com/easydata/),可以标注图像分类EasyDataCls数据集。 -在PaddleX中,使用`paddlex.cv.datasets.EasyDataCls`([API说明](./apis/datasets.html#easydatacls))加载分类数据集。 - - -## 目标检测和实例分割EasyDataDet - -目标检测和实例分割EasyDataDet数据集包含存放图像和json文件的文件夹、标签文件及图像列表文件。 -参考数据文件结构如下: -``` -./dataset/ # 数据集根目录ß -|--easydata # 存放图像和json文件的文件夹 -| |--0001.jpg -| |--0001.json -| |--0002.jpg -| |--0002.json -| └--... -| -|--train_list.txt # 训练文件列表文件 -| -|--val_list.txt # 验证文件列表文件 -| -└--labels.txt # 标签列表文件 - -``` -其中,图像文件名应与json文件名一一对应。 - -每个json文件存储于`labels`相关的信息。如下所示: -``` -"labels": [{"y1": 18, "x2": 883, "x1": 371, "y2": 404, "name": "labelA", - "mask": "kVfc0`0Zg0`_ ,助力开发者高效获取AI开发所需高质量数据。 + | - **模型训练**: 基于飞桨核心框架集成 `PaddleClas `_ ,`PaddleDetection `_ ,`PaddleSeg `_ 视觉开发套件 ,`VisualDL `_ 可视化分析组件,高效完成模型训练。 + | _ **多端部署**: 内置 `PaddleSlim `_ 模型压缩工具和AES模型加密SDK,结合Paddle Inference和 `Paddle Lite `_ 便捷完成高性能且可靠的多端部署。 + +融合产业实践 + | - 精选飞桨产业实践的成熟模型结构,开放案例实践教程,加速开发者产业落地。 + | - 通过 `PaddleHub `_ 内置丰富的飞桨高质量预训练模型,助力开发者高效实现飞桨Master模式。 + +易用易集成 + | - PadldeX提供简洁易用的全流程API,几行代码即可实现上百种数据增强、模型可解释性、C++模型部署等功能。 + | - 提供以PaddleX API为核心集成的跨平台GUI界面,降低深度学习全流程应用门槛。 .. toctree:: - :maxdepth: 1 - :caption: 目录: + :maxdepth: 2 + :caption: 文档目录: quick_start.md install.md - model_zoo.md - slim/index - apis/index - datasets.md - gpu_configure.md tutorials/index.rst - metrics.md - deploy.md - client_use.md + cv_solutions.md + apis/index.rst + paddlex_gui/index.rst + update.md FAQ.md + appendix/index.rst * PaddleX版本: v0.1.7 * 项目官网: http://www.paddlepaddle.org.cn/paddle/paddlex diff --git a/docs/install.md b/docs/install.md old mode 100644 new mode 100755 index 45630f0eea962acbafbd015ea2d9e855698c167d..cdbc84cab3dc825e69e325348b3c528d83bcd225 --- a/docs/install.md +++ b/docs/install.md @@ -1,14 +1,21 @@ -# 安装 +# 快速安装 以下安装过程默认用户已安装好**paddlepaddle-gpu或paddlepaddle(版本大于或等于1.7.1)**,paddlepaddle安装方式参照[飞桨官网](https://www.paddlepaddle.org.cn/install/quick) -> 推荐使用Anaconda Python环境,Anaconda下安装PaddleX参考文档[Anaconda安装使用](./anaconda_install.md) +> 推荐使用Anaconda Python环境,Anaconda下安装PaddleX参考文档[Anaconda安装使用](../appendix/anaconda_install.md) -## Github代码安装 -github代码会跟随开发进度不断更新 +## pip安装 > 注意其中pycocotools在Windows安装较为特殊,可参考下面的Windows安装命令 +``` +pip install paddlex -i https://mirror.baidu.com/pypi/simple +``` + + +## Github代码安装 +github代码会跟随开发进度不断更新 + ``` git clone https://github.com/PaddlePaddle/PaddleX.git cd PaddleX @@ -16,19 +23,16 @@ git checkout develop python setup.py install ``` -## pip安装 -``` -pip install paddlex -i https://mirror.baidu.com/pypi/simple -``` ## 安装问题 ### 1. pycocotools安装问题 > PaddleX依赖pycocotools包,如安装pycocotools失败,可参照如下方式安装pycocotools **Windows** +> Windows安装时可能会提示缺少`Microsoft Visual C++ 2015 build tools`,[点击下载](https://go.microsoft.com/fwlink/?LinkId=691126)安装再执行如下pip命令 ``` pip install cython -pip install git+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI +pip install git+https://gitee.com/jiangjiajun/philferriere-cocoapi.git#subdirectory=PythonAPI ``` **Linux/Mac安装** diff --git a/docs/make.bat b/docs/make.bat old mode 100644 new mode 100755 diff --git a/docs/metrics.md b/docs/metrics.md index da812e94fb73c13a5e5c1504363b359856b952db..7834a43a00028935ccda5bdb89db5c15e886240c 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -1,145 +1 @@ -# 指标及日志含义 - -PaddleX在模型训练、评估过程中,都会有相应的日志和指标反馈,本文档用于说明这些日志和指标的含义。 - -## 训练通用统计信息 - -PaddleX所有模型在训练过程中,输出的日志信息都包含了6个通用的统计信息,用于辅助用户进行模型训练,例如**分割模型**的训练日志,如下图所示。 - -![](./images/seg_train.png) - -各字段含义如下: - -| 字段 | 字段值示例 | 含义 | -| -------------- | -------------------- | ------------------------------------------------------------ | -| Epoch | Epoch=4/20 | [迭代轮数]所有训练数据会被训练20轮,当前处于第4轮 | -| Step | Step=62/66 | [迭代步数]所有训练数据被训练一轮所需要的迭代步数为66,当前处于第62步 | -| loss | loss=0.007226 | [损失函数值]参与当前迭代步数的训练样本的平均损失函数值loss,loss值越低,表明模型在训练集上拟合的效果越好(如上日志中第1行表示第4个epoch的第62个Batch的loss值为0.007226) | -| lr | lr=0.008215 | [学习率]当前模型迭代过程中的学习率 | -| time_each_step | time_each_step=0.41s | [每步迭代时间]训练过程计算得到的每步迭代平均用时 | -| eta | eta=0:9:44 | [剩余时间]模型训练完成所需剩余时间预估为0小时9分钟44秒 | -| | | | - -不同模型的日志中除了上述通用字段外,还有其它字段,这些字段含义可见文档后面对各任务模型的描述。 - -## 评估通用统计信息 - -PaddleX所有模型在训练过程中会根据用户设定的`save_interval_epochs`参数,每间隔一定轮数进行评估和保存。例如**分类模型**的评估日志,如下图所示。 - -![](images/cls_eval.png) - -上图中第1行表明验证数据集中样本数为240,需要迭代8步才能评估完所有验证数据;第5行用于表明第2轮的模型已经完成保存操作;第6行则表明当前保存的模型中,第2轮的模型在验证集上指标最优(分类任务看`acc1`,此时`acc1`值为0.258333),最优模型会保存在`best_model`目录中。 - -## 分类特有统计信息 - -### 训练日志字段 - -分类任务的训练日志除了通用统计信息外,还包括`acc1`和`acc5`两个特有字段。 - -> 注: acck准确率是针对一张图片进行计算的:把模型在各个类别上的预测得分按从高往低进行排序,取出前k个预测类别,若这k个预测类别包含了真值类,则认为该图片分类正确。 - -![](images/cls_train.png) - - -上图中第1行中的`acc1`表示参与当前迭代步数的训练样本的平均top1准确率,值越高代表模型越优;`acc5`表示参与当前迭代步数的训练样本的平均top5(若类别数n少于5,则为topn)准确率,值越高代表模型越优。第4行中的`loss`表示整个训练集的平均损失函数值,`acc1`表示整个训练集的平均top1准确率,`acc5`表示整个训练集的平均top5准确率。 - - -### 评估日志字段 - -![](images/cls_eval.png) - -上图中第3行中的`acc1`表示整个验证集的平均top1准确率,`acc5`表示整个验证集的平均top5准确率。 - - -## 检测特有统计信息 - -### 训练日志字段 - -#### YOLOv3 - -YOLOv3的训练日志只包括训练通用统计信息(见上文训练通用统计信息)。 - -![](images/yolo_train.png) - -上图中第5行`loss`表示整个训练集的平均损失函数loss值。 - -#### FasterRCNN - -FasterRCNN的训练日志除了通用统计信息外,还包括`loss_cls`、`loss_bbox`、`loss_rpn_cls`和`loss_rpn_bbox`,这些字段的含义如下: - -| 字段 | 含义 | -| -------------- | --------------------------------------------- | -| loss_cls | RCNN子网络中分类损失函数值 | -| loss_bbox | RCNN子网络中检测框回归损失函数值 | -| loss_rpn_cls | RPN子网络中分类损失函数值 | -| loss_rpn_bbox | RPN子网络中检测框回归损失函数值 | -| loss | 所有子网络损失函数值之和 | - -![](images/faster_train.png) - -上图中第1行`loss`, `loss_cls`、`loss_bbox`、`loss_rpn_clss`、`loss_rpn_bbox`都是参与当前迭代步数的训练样本的损失值,而第7行是针整个训练集的损失函数值。 - -#### MaskRCNN - -MaskRCNN的训练日志除了通用统计信息外,还包括`loss_cls`、`loss_bbox`、`loss_mask`、`loss_rpn_cls`和`loss_rpn_bbox`,这些字段的含义如下: - - -| 字段 | 含义 | -| -------------- | --------------------------------------------- | -| loss_cls | RCNN子网络中分类损失函数值 | -| loss_bbox | RCNN子网络中检测框回归损失函数值 | -| loss_mask | RCNN子网络中Mask回归损失函数值 | -| loss_rpn_cls | RPN子网络中分类损失函数值 | -| loss_rpn_bbox | RPN子网络中检测框回归损失函数值 | -| loss | 所有子网络损失函数值之和 | - -![](images/mask_train.png) - -上图中第1行`loss`, `loss_cls`、`loss_bbox`、`loss_mask`、`loss_rpn_clss`、`loss_rpn_bbox`都是参与当前迭代步数的训练样本的损失值,而第7行是针整个训练集的损失函数值。 - -### 评估日志字段 - -检测可以使用两种评估标准:VOC评估标准和COCO评估标准。 - -#### VOC评估标准 - -![](images/voc_eval.png) - -> 注:`map`为平均准确率的平均值,即IoU(Intersection Over Union)取0.5时各个类别的准确率-召回率曲线下面积的平均值。 - -上图中第3行`bbox_map`表示检测任务中整个验证集的平均准确率平均值。 - -#### COCO评估标准 - -> 注:COCO评估指标可参见[COCO官网解释](http://cocodataset.org/#detection-eval)。PaddleX主要反馈`mmAP`,即AP at IoU=.50:.05:.95这项指标,为在各个IoU阈值下平均准确率平均值(mAP)的平均值。 - -COCO格式的数据集不仅可以用于训练目标检测模型,也可以用于训练实例分割模型。在目标检测中,PaddleX主要反馈针对检测框的`bbox_mmAP`指标;在实例分割中,还包括针对Mask的`seg_mmAP`指标。如下所示,第一张日志截图为目标检测的评估结果,第二张日志截图为实例分割的评估结果。 - -![](images/faster_eval.png) - -上图中红框标注的`bbox_mmap`表示整个验证集的检测框平均准确率平均值。 - -![](images/mask_eval.png) -上图中红框标注的`bbox_mmap`和`seg_mmap`分别表示整个验证集的检测框平均准确率平均值、Mask平均准确率平均值。 - -## 分割特有统计信息 - -### 训练日志字段 - -语义分割的训练日志只包括训练通用统计信息(见上文训练通用统计信息)。 - -![](images/seg_train.png) - -### 评估日志字段 - -语义分割的评估日志包括了`miou`、`category_iou`、`macc`、`category_acc`、`kappa`,这些字段的含义如下: - -| 字段 | 含义 | -| -------------- | --------------------------------------------- | -| miou | 各类IoU(Intersection Over Union)的平均值 | -| category_iou | 各类别的IoU | -| macc | 平均准确率,即预测正确的像素数/总像素数 | -| category_acc | 各类别的准确率,即各类别预测正确的像素数/预测为该类别的总像素数 | -| kappa | kappa系数,用于一致性检验 | - -![](images/seg_eval.png) +本页面已移至 [这里](./appendix/metrics.md) diff --git a/docs/model_zoo.md b/docs/model_zoo.md index d41629cfcc62d314ee41470053c8b3d04dc99321..e0e5c51b5922df35a89a69a1103d7f54edb73afd 100644 --- a/docs/model_zoo.md +++ b/docs/model_zoo.md @@ -1,72 +1 @@ -# 模型库 -本文档梳理了PaddleX v0.1.0支持的模型,同时也提供了在各个数据集上的预训练模型和对应验证集上的指标。用户也可自行下载对应的代码,在安装PaddleX后,即可使用相应代码训练模型。 - -表中相关模型也可下载好作为相应模型的预训练模型,通过`pretrain_weights`指定目录加载使用。 - -## 图像分类模型 -> 表中模型相关指标均为在ImageNet数据集上使用PaddlePaddle Python预测接口测试得到(测试GPU型号为Nvidia Tesla P40),预测速度为每张图片预测用时(不包括预处理和后处理),表中符号`-`表示相关指标暂未测试。 - - -| 模型 | 模型大小 | 预测速度(毫秒) | Top1准确率(%) | Top5准确率(%) | -| :----| :------- | :----------- | :--------- | :--------- | -| ResNet18| 46.9MB | 1.499 | 71.0 | 89.9 | -| ResNet34| 87.5MB | 2.272 | 74.6 | 92.1 | -| ResNet50| 102.7MB | 2.939 | 76.5 | 93.0 | -| ResNet101 |179.1MB | 5.314 | 77.6 | 93.6 | -| ResNet50_vd |102.8MB | 3.165 | 79.1 | 94.4 | -| ResNet101_vd| 179.2MB | 5.252 | 80.2 | 95.0 | -| ResNet50_vd_ssld |102.8MB | 3.165 | 82.4 | 96.1 | -| ResNet101_vd_ssld| 179.2MB | 5.252 | 83.7 | 96.7 | -| DarkNet53|166.9MB | 3.139 | 78.0 | 94.1 | -| MobileNetV1 | 16.0MB | 32.523 | 71.0 | 89.7 | -| MobileNetV2 | 14.0MB | 23.318 | 72.2 | 90.7 | -| MobileNetV3_large| 21.0MB | 19.308 | 75.3 | 93.2 | -| MobileNetV3_small | 12.0MB | 6.546 | 68.2 | 88.1 | -| MobileNetV3_large_ssld| 21.0MB | 19.308 | 79.0 | 94.5 | -| MobileNetV3_small_ssld | 12.0MB | 6.546 | 71.3 | 90.1 | -| Xception41 |92.4MB | 4.408 | 79.6 | 94.4 | -| Xception65 | 144.6MB | 6.464 | 80.3 | 94.5 | -| DenseNet121 | 32.8MB | 4.371 | 75.7 | 92.6 | -| DenseNet161|116.3MB | 8.863 | 78.6 | 94.1 | -| DenseNet201| 84.6MB | 8.173 | 77.6 | 93.7 | -| ShuffleNetV2 | 9.0MB | 10.941 | 68.8 | 88.5 | - -## 目标检测模型 - -> 表中模型相关指标均为在MSCOCO数据集上使用PaddlePaddle Python预测接口测试得到(测试GPU型号为Nvidia Tesla V100测试得到,表中符号`-`表示相关指标暂未测试。 - -| 模型 | 模型大小 | 预测时间(毫秒) | BoxAP(%) | -|:-------|:-----------|:-------------|:----------| -|FasterRCNN-ResNet50|135.6MB| 78.450 | 35.2 | -|FasterRCNN-ResNet50_vd| 135.7MB | 79.523 | 36.4 | -|FasterRCNN-ResNet101| 211.7MB | 107.342 | 38.3 | -|FasterRCNN-ResNet50-FPN| 167.2MB | 44.897 | 37.2 | -|FasterRCNN-ResNet50_vd-FPN|168.7MB | 45.773 | 38.9 | -|FasterRCNN-ResNet101-FPN| 251.7MB | 55.782 | 38.7 | -|FasterRCNN-ResNet101_vd-FPN |252MB | 58.785 | 40.5 | -|YOLOv3-DarkNet53|252.4MB | 21.944 | 38.9 | -|YOLOv3-MobileNetv1 |101.2MB | 12.771 | 29.3 | -|YOLOv3-MobileNetv3|94.6MB | - | 31.6 | -| YOLOv3-ResNet34|169.7MB | 15.784 | 36.2 | - -## 实例分割模型 - -> 表中模型相关指标均为在MSCOCO数据集上测试得到。 - -| 模型 |模型大小 | 预测时间(毫秒) | BoxAP | SegAP(%) | -|:---------|:---------|:----------|:---------|:--------| -|MaskRCNN-ResNet50|51.2MB| 86.096 | 36.5 |32.2| -|MaskRCNN-ResNet50-FPN|184.6MB | 65.859 | 37.9 |34.2| -|MaskRCNN-ResNet50_vd-FPN |185.5MB | 63.191 | 39.8 |35.4| -|MaskRCNN-ResNet101-FPN|268.6MB | 77.024 | 39.5 |35.2| -|MaskRCNN-ResNet101vd-FPN |268.6MB | 76.307 | 41.4 |36.8| - -## 语义分割模型 - -> 表中符号`-`表示相关指标暂未测试。 - -| 模型| 模型大小 | 预测速度 | mIOU | -|:--------|:----------|:----------|:----------| -| UNet|53.7M | - |-| -| DeepLabv3+/Xception65| 165.1M |- | 0.7930 | -| DeepLabv3+/MobileNetV2 | 7.4M | - | 0.6981 | +本页面已移至 [这里](./appendix/model_zoo.md) diff --git a/docs/paddlex_gui/download.md b/docs/paddlex_gui/download.md new file mode 100644 index 0000000000000000000000000000000000000000..102326977c57ba65c614abca52f65d8a63c80259 --- /dev/null +++ b/docs/paddlex_gui/download.md @@ -0,0 +1 @@ +# PaddleX GUI下载安装 diff --git a/docs/paddlex_gui/how_to_use.md b/docs/paddlex_gui/how_to_use.md new file mode 100644 index 0000000000000000000000000000000000000000..1e9a3eeb69d276596636e814f48fad4fe9f3e9d0 --- /dev/null +++ b/docs/paddlex_gui/how_to_use.md @@ -0,0 +1 @@ +# PaddleX GUI如何训练模型 diff --git a/docs/paddlex_gui/index.rst b/docs/paddlex_gui/index.rst new file mode 100755 index 0000000000000000000000000000000000000000..be17573f2540032b954a4b1b7a96fed5729e32a0 --- /dev/null +++ b/docs/paddlex_gui/index.rst @@ -0,0 +1,29 @@ +PaddleX GUI使用文档 +======================================= + +PaddleX GUI是基于PaddleX开发实现的可视化模型训练套件,可以让开发者免去代码开发的步骤,通过点选式地操作就可以快速完成模型的训练开发。PaddleXGUI具有 **数据集可视化分析** 、**模型参数自动推荐** 、**跨平台使用** 三大特点。 + +数据集可视化分析 + | PaddleX支持导入常见的图像分类、目标检测、实例分割和语义分割数据集,并对数据集的样本分布,标注结果进行可视化展示,数据集的情况一目了然! + +模型参数自动推荐 + | 根据用户的电脑配置和数据集情况,自动推荐模型训练参数,免去用户查看文档,被各种参数所烦的忧心事! + +跨平台使用 + | PaddleX GUI完全跨平台,支持Linux、Windows和Mac三大主流系统! + + +.. toctree:: + :maxdepth: 2 + :caption: 文档目录: + + download.md + how_to_use.md + xx.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/paddlex_gui/xx.md b/docs/paddlex_gui/xx.md new file mode 100644 index 0000000000000000000000000000000000000000..97fd16977da33ba4f122f5c556527fdead2109e5 --- /dev/null +++ b/docs/paddlex_gui/xx.md @@ -0,0 +1 @@ +# 其它 diff --git a/docs/quick_start.md b/docs/quick_start.md index 38a67e12750c636d09bdc0c1263ece049214b17d..dafb902fc66a83de4f5aa6066dd6094b1baa4b86 100644 --- a/docs/quick_start.md +++ b/docs/quick_start.md @@ -2,22 +2,31 @@ 本文档在一个小数据集上展示了如何通过PaddleX进行训练,您可以阅读PaddleX的**使用教程**来了解更多模型任务的训练使用方式。本示例同步在AIStudio上,可直接[在线体验模型训练](https://aistudio.baidu.com/aistudio/projectdetail/439860) -## 1. 准备蔬菜分类数据集 + +## 1. 安装PaddleX +> 安装相关过程和问题可以参考PaddleX的[安装文档](./install.md)。 ``` -wget https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz -tar xzvf vegetables_cls.tar.gz +pip install paddlex -i https://mirror.baidu.com/pypi/simple ``` -## 2. 训练代码开发 -通过如下`train.py`代码进行训练 -> 设置使用0号GPU卡 +## 2. 准备蔬菜分类数据集 ``` -import os -os.environ['CUDA_VISIBLE_DEVICES'] = '0' -import paddlex as pdx +wget https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz +tar xzvf vegetables_cls.tar.gz ``` -> 定义训练和验证时的数据处理流程, 在`train_transforms`中加入了`RandomCrop`和`RandomHorizontalFlip`两种数据增强方式 +## 3. 训练代码开发 +PaddleX的所有模型训练和预测均只涉及到5个API接口,分别是 +> - [transforms](apis/transforms/index.html) 图像数据处理 +> - [datasets](apis/datasets/classification.md) 数据集加载 +> - [models](apis/models/classification.md) 模型类型定义 +> - [train](apis/models/classification.html#train) 开始训练 +> - [predict](apis/models/classification.html#predict) 模型预测 + +在本示例,通过如下`train.py`代码进行训练, 训练环境为1张Tesla P40 GPU卡。 + +### 3.1 定义`transforms`数据处理流程 +由于训练时数据增强操作的加入,因此模型在训练和验证过程中,数据处理流程需要分别进行定义。如下所示,代码在`train_transforms`中加入了[RandomCrop](apis/transforms/cls_transforms.html#RandomCrop)和[RandomHorizontalFlip](apis/transforms/cls_transforms.html#RandomHorizontalFlip)两种数据增强方式, 更多方法可以参考[数据增强文档](apis/transforms/augment.md)。 ``` from paddlex.cls import transforms train_transforms = transforms.Compose([ @@ -32,7 +41,8 @@ eval_transforms = transforms.Compose([ ]) ``` -> 定义数据集,`pdx.datasets.ImageNet`表示读取ImageNet格式的分类数据集 +### 3.2 定义`dataset`加载数据集 +定义数据集,`pdx.datasets.ImageNet`表示读取ImageNet格式的分类数据集, 更多数据集细节可以查阅[数据集格式说明](datasets.md)和[ImageNet接口文档](apis/datasets/classification.md) ``` train_dataset = pdx.datasets.ImageNet( data_dir='vegetables_cls', @@ -46,11 +56,17 @@ eval_dataset = pdx.datasets.ImageNet( label_list='vegetables_cls/labels.txt', transforms=eval_transforms) ``` -> 模型训练 +### 3.3 定义分类模型 +本文档中使用百度基于蒸馏方法得到的MobileNetV3预训练模型,模型结构与MobileNetV3一致,但精度更高。PaddleX内置了20多种分类模型,查阅[PaddleX模型库](appendix/model_zoo.md)了解更多分类模型。 ``` num_classes = len(train_dataset.labels) -model = pdx.cls.MobileNetV2(num_classes=num_classes) +model.pdx.cls.MobileNetV3_small_ssld(num_classes=num_classes) +``` + +### 3.4 定义训练参数 +定义好模型后,即可直接调用`train`接口,定义训练时的参数,分类模型内置了`piecewise_decay`学习率衰减策略,相关参数见[分类train接口文档](apis/models/classification.html#train)。 +``` model.train(num_epochs=10, train_dataset=train_dataset, train_batch_size=32, @@ -61,19 +77,21 @@ model.train(num_epochs=10, use_vdl=True) ``` -## 3. 模型训练 -> `train.py`与解压后的数据集目录`vegetables_cls`放在同一目录下,在此目录下运行`train.py`即可开始训练。如果您的电脑上有GPU,这将会在10分钟内训练完成,如果为CPU也大概会在30分钟内训练完毕。 +## 4. 模型开始训练 +`train.py`与解压后的数据集目录`vegetables_cls`放在同一目录下,在此目录下运行`train.py`即可开始训练。如果您的电脑上有GPU,这将会在10分钟内训练完成,如果为CPU也大概会在30分钟内训练完毕。 ``` python train.py ``` -## 4. 训练过程中查看训练指标 -> 模型在训练过程中,所有的迭代信息将以标注输出流的形式,输出到命令执行的终端上,用户也可通过visualdl以可视化的方式查看训练指标的变化,通过如下方式启动visualdl后,在浏览器打开https://0.0.0.0:8001即可。 + +## 5. 训练过程中查看训练指标 +模型在训练过程中,所有的迭代信息将以标注输出流的形式,输出到命令执行的终端上,用户也可通过visualdl以可视化的方式查看训练指标的变化,通过如下方式启动visualdl后,在浏览器打开https://0.0.0.0:8001 (或 https://localhost:8001)即可。 ``` visualdl --logdir output/mobilenetv2/vdl_log --port 8000 ``` ![](./images/vdl1.jpg) -## 5. 训练完成使用模型进行测试 -> 如使用训练过程中第8轮保存的模型进行测试 + +## 6. 训练完成使用模型进行测试 +如下代码使用训练过程中第8轮保存的模型进行测试。 ``` import paddlex as pdx model = pdx.load_model('output/mobilenetv2/epoch_8') diff --git a/docs/requirements.txt b/docs/requirements.txt old mode 100644 new mode 100755 diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md old mode 100644 new mode 100755 diff --git a/docs/tutorials/compress/classification.md b/docs/tutorials/compress/classification.md old mode 100644 new mode 100755 diff --git a/docs/tutorials/compress/detection.md b/docs/tutorials/compress/detection.md old mode 100644 new mode 100755 diff --git a/docs/tutorials/compress/index.rst b/docs/tutorials/compress/index.rst old mode 100644 new mode 100755 diff --git a/docs/tutorials/compress/segmentation.md b/docs/tutorials/compress/segmentation.md old mode 100644 new mode 100755 diff --git a/docs/slim/index.rst b/docs/tutorials/compress/slim/index.rst old mode 100644 new mode 100755 similarity index 100% rename from docs/slim/index.rst rename to docs/tutorials/compress/slim/index.rst diff --git a/docs/slim/prune.md b/docs/tutorials/compress/slim/prune.md old mode 100644 new mode 100755 similarity index 100% rename from docs/slim/prune.md rename to docs/tutorials/compress/slim/prune.md diff --git a/docs/slim/quant.md b/docs/tutorials/compress/slim/quant.md old mode 100644 new mode 100755 similarity index 100% rename from docs/slim/quant.md rename to docs/tutorials/compress/slim/quant.md diff --git a/docs/tutorials/dataset_prepare.md b/docs/tutorials/dataset_prepare.md new file mode 100644 index 0000000000000000000000000000000000000000..87f368bc29d80aff12b9f6597a1d3901b427c4d7 --- /dev/null +++ b/docs/tutorials/dataset_prepare.md @@ -0,0 +1,7 @@ +# 数据准备 + +## 数据标注 + +## 主流标注软件支持 + +## EasyData数据标注支持 diff --git a/docs/tutorials/datasets.md b/docs/tutorials/datasets.md new file mode 100755 index 0000000000000000000000000000000000000000..b197b43b6c1ce2dd8c91bae3c484573365493ba0 --- /dev/null +++ b/docs/tutorials/datasets.md @@ -0,0 +1,366 @@ +# 数据集格式说明 + +--- +## 图像分类ImageNet + +图像分类ImageNet数据集包含对应多个标签的图像文件夹、标签文件及图像列表文件。 +参考数据文件结构如下: +``` +./dataset/ # 数据集根目录 +|--labelA # 标签为labelA的图像目录 +| |--a1.jpg +| |--... +| └--... +| +|--... +| +|--labelZ # 标签为labelZ的图像目录 +| |--z1.jpg +| |--... +| └--... +| +|--train_list.txt # 训练文件列表文件 +| +|--val_list.txt # 验证文件列表文件 +| +└--labels.txt # 标签列表文件 + +``` +其中,相应的文件名可根据需要自行定义。 + +`train_list.txt`和`val_list.txt`文本以空格为分割符分为两列,第一列为图像文件相对于dataset的相对路径,第二列为图像文件对应的标签id(从0开始)。如下所示: +``` +labelA/a1.jpg 0 +labelZ/z1.jpg 25 +... +``` + +`labels.txt`: 每一行为一个单独的类别,相应的行号即为类别对应的id(行号从0开始),如下所示: +``` +labelA +labelB +... +``` +[点击这里](https://bj.bcebos.com/paddlex/datasets/vegetables_cls.tar.gz),下载蔬菜分类分类数据集。 +在PaddleX中,使用`paddlex.cv.datasets.ImageNet`([API说明](./apis/datasets.html#imagenet))加载分类数据集。 + +## 目标检测VOC +目标检测VOC数据集包含图像文件夹、标注信息文件夹、标签文件及图像列表文件。 +参考数据文件结构如下: +``` +./dataset/ # 数据集根目录 +|--JPEGImages # 图像目录 +| |--xxx1.jpg +| |--... +| └--... +| +|--Annotations # 标注信息目录 +| |--xxx1.xml +| |--... +| └--... +| +|--train_list.txt # 训练文件列表文件 +| +|--val_list.txt # 验证文件列表文件 +| +└--labels.txt # 标签列表文件 + +``` +其中,相应的文件名可根据需要自行定义。 + +`train_list.txt`和`val_list.txt`文本以空格为分割符分为两列,第一列为图像文件相对于dataset的相对路径,第二列为标注文件相对于dataset的相对路径。如下所示: +``` +JPEGImages/xxx1.jpg Annotations/xxx1.xml +JPEGImages/xxx2.jpg Annotations/xxx2.xml +... +``` + +`labels.txt`: 每一行为一个单独的类别,相应的行号即为类别对应的id(行号从0开始),如下所示: +``` +labelA +labelB +... +``` +[点击这里](https://bj.bcebos.com/paddlex/datasets/insect_det.tar.gz),下载昆虫检测数据集。 +在PaddleX中,使用`paddlex.cv.datasets.VOCDetection`([API说明](./apis/datasets.html#vocdetection))加载目标检测VOC数据集。 + +## 目标检测和实例分割COCO +目标检测和实例分割COCO数据集包含图像文件夹及图像标注信息文件。 +参考数据文件结构如下: +``` +./dataset/ # 数据集根目录 +|--JPEGImages # 图像目录 +| |--xxx1.jpg +| |--... +| └--... +| +|--train.json # 训练相关信息文件 +| +└--val.json # 验证相关信息文件 + +``` +其中,相应的文件名可根据需要自行定义。 + +`train.json`和`val.json`存储与标注信息、图像文件相关的信息。如下所示: + +``` +{ + "annotations": [ + { + "iscrowd": 0, + "category_id": 1, + "id": 1, + "area": 33672.0, + "image_id": 1, + "bbox": [232, 32, 138, 244], + "segmentation": [[32, 168, 365, 117, ...]] + }, + ... + ], + "images": [ + { + "file_name": "xxx1.jpg", + "height": 512, + "id": 267, + "width": 612 + }, + ... + ] + "categories": [ + { + "name": "labelA", + "id": 1, + "supercategory": "component" + } + ] +} +``` +其中,每个字段的含义如下所示: + +| 域名 | 字段名 | 含义 | 数据类型 | 备注 | +|:-----|:--------|:------------|------|:-----| +| annotations | id | 标注信息id | int | 从1开始 | +| annotations | iscrowd | 标注框是否为一组对象 | int | 只有0、1两种取值 | +| annotations | category_id | 标注框类别id | int | | +| annotations | area | 标注框的面积 | float | | +| annotations | image_id | 当前标注信息所在图像的id | int | | +| annotations | bbox | 标注框坐标 | list | 长度为4,分别代表x,y,w,h | +| annotations | segmentation | 标注区域坐标 | list | list中有至少1个list,每个list由每个小区域坐标点的横纵坐标(x,y)组成 | +| images | id | 图像id | int | 从1开始 | +| images | file_name | 图像文件名 | str | | +| images | height | 图像高度 | int | | +| images | width | 图像宽度 | int | | +| categories | id | 类别id | int | 从1开始 | +| categories | name | 类别标签名 | str | | +| categories | supercategory | 类别父类的标签名 | str | | + + +[点击这里](https://bj.bcebos.com/paddlex/datasets/garbage_ins_det.tar.gz),下载垃圾实例分割数据集。 +在PaddleX中,使用`paddlex.cv.datasets.COCODetection`([API说明](./apis/datasets.html#cocodetection))加载COCO格式数据集。 + +## 语义分割数据 +语义分割数据集包含原图、标注图及相应的文件列表文件。 +参考数据文件结构如下: +``` +./dataset/ # 数据集根目录 +|--images # 原图目录 +| |--xxx1.png +| |--... +| └--... +| +|--annotations # 标注图目录 +| |--xxx1.png +| |--... +| └--... +| +|--train_list.txt # 训练文件列表文件 +| +|--val_list.txt # 验证文件列表文件 +| +└--labels.txt # 标签列表 + +``` +其中,相应的文件名可根据需要自行定义。 + +`train_list.txt`和`val_list.txt`文本以空格为分割符分为两列,第一列为图像文件相对于dataset的相对路径,第二列为标注图像文件相对于dataset的相对路径。如下所示: +``` +images/xxx1.png annotations/xxx1.png +images/xxx2.png annotations/xxx2.png +... +``` + +`labels.txt`: 每一行为一个单独的类别,相应的行号即为类别对应的id(行号从0开始),如下所示: +``` +background +labelA +labelB +... +``` + +标注图像为单通道图像,像素值即为对应的类别,像素标注类别需要从0开始递增(一般第一个类别为`background`), +例如0,1,2,3表示有4种类别,标注类别最多为256类。其中可以指定特定的像素值用于表示该值的像素不参与训练和评估(默认为255)。 + +[点击这里](https://bj.bcebos.com/paddlex/datasets/optic_disc_seg.tar.gz),下载视盘语义分割数据集。 +在PaddleX中,使用`paddlex.cv.datasets.SegReader`([API说明](./apis/datasets.html#segreader))加载语义分割数据集。 + + +## 图像分类EasyDataCls + +图像分类EasyDataCls数据集包含存放图像和json文件的文件夹、标签文件及图像列表文件。 +参考数据文件结构如下: +``` +./dataset/ # 数据集根目录 +|--easydata # 存放图像和json文件的文件夹 +| |--0001.jpg +| |--0001.json +| |--0002.jpg +| |--0002.json +| └--... +| +|--train_list.txt # 训练文件列表文件 +| +|--val_list.txt # 验证文件列表文件 +| +└--labels.txt # 标签列表文件 + +``` +其中,图像文件名应与json文件名一一对应。 + +每个json文件存储于`labels`相关的信息。如下所示: +``` +{"labels": [{"name": "labelA"}]} +``` +其中,`name`字段代表对应图像的类别。 + +`train_list.txt`和`val_list.txt`文本以空格为分割符分为两列,第一列为图像文件相对于dataset的相对路径,第二列为json文件相对于dataset的相对路径。如下所示: +``` +easydata/0001.jpg easydata/0001.json +easydata/0002.jpg easydata/0002.json +... +``` + +`labels.txt`: 每一行为一个单独的类别,相应的行号即为类别对应的id(行号从0开始),如下所示: +``` +labelA +labelB +... +``` +[点击这里](https://ai.baidu.com/easydata/),可以标注图像分类EasyDataCls数据集。 +在PaddleX中,使用`paddlex.cv.datasets.EasyDataCls`([API说明](./apis/datasets.html#easydatacls))加载分类数据集。 + + +## 目标检测和实例分割EasyDataDet + +目标检测和实例分割EasyDataDet数据集包含存放图像和json文件的文件夹、标签文件及图像列表文件。 +参考数据文件结构如下: +``` +./dataset/ # 数据集根目录ß +|--easydata # 存放图像和json文件的文件夹 +| |--0001.jpg +| |--0001.json +| |--0002.jpg +| |--0002.json +| └--... +| +|--train_list.txt # 训练文件列表文件 +| +|--val_list.txt # 验证文件列表文件 +| +└--labels.txt # 标签列表文件 + +``` +其中,图像文件名应与json文件名一一对应。 + +每个json文件存储于`labels`相关的信息。如下所示: +``` +"labels": [{"y1": 18, "x2": 883, "x1": 371, "y2": 404, "name": "labelA", + "mask": "kVfc0`0Zg0 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) + ### 预测性能对比 #### 测试环境 diff --git a/docs/deploy/deploy_cpp_linux.md b/docs/tutorials/deploy/deploy_cpp_linux.md old mode 100644 new mode 100755 similarity index 93% rename from docs/deploy/deploy_cpp_linux.md rename to docs/tutorials/deploy/deploy_cpp_linux.md index 4b3a6e8159b5bcff313cfc2e752201a28a2058d1..a2eb2f536039a77e645abcfc14c1224a84e8c483 --- a/docs/deploy/deploy_cpp_linux.md +++ b/docs/tutorials/deploy/deploy_cpp_linux.md @@ -95,7 +95,7 @@ make ``` ### Step5: 预测及可视化 -编译成功后,预测demo的可执行程序分别为`build/detector`,`build/classifer`,`build/segmenter`,用户可根据自己的模型类型选择,其主要命令参数说明如下: +编译成功后,预测demo的可执行程序分别为`build/demo/detector`,`build/demo/classifer`,`build/demo/segmenter`,用户可根据自己的模型类型选择,其主要命令参数说明如下: | 参数 | 说明 | | ---- | ---- | @@ -116,7 +116,7 @@ make 不使用`GPU`测试图片 `/path/to/xiaoduxiong.jpeg` ```shell -./build/detector --model_dir=/path/to/inference_model --image=/path/to/xiaoduxiong.jpeg --save_dir=output +./build/demo/detector --model_dir=/path/to/inference_model --image=/path/to/xiaoduxiong.jpeg --save_dir=output ``` 图片文件`可视化预测结果`会保存在`save_dir`参数设置的目录下。 @@ -131,6 +131,6 @@ make /path/to/images/xiaoduxiongn.jpeg ``` ```shell -./build/detector --model_dir=/path/to/models/inference_model --image_list=/root/projects/images_list.txt --use_gpu=1 --save_dir=output +./build/demo/detector --model_dir=/path/to/models/inference_model --image_list=/root/projects/images_list.txt --use_gpu=1 --save_dir=output ``` 图片文件`可视化预测结果`会保存在`save_dir`参数设置的目录下。 diff --git a/docs/deploy/deploy_cpp_win_vs2019.md b/docs/tutorials/deploy/deploy_cpp_win_vs2019.md old mode 100644 new mode 100755 similarity index 97% rename from docs/deploy/deploy_cpp_win_vs2019.md rename to docs/tutorials/deploy/deploy_cpp_win_vs2019.md index 836a2abfdcfbe2252a651ccf7bf22cda4922e932..2572236c5113fa7552bf13929391bc6538d61edd --- a/docs/deploy/deploy_cpp_win_vs2019.md +++ b/docs/tutorials/deploy/deploy_cpp_win_vs2019.md @@ -106,7 +106,7 @@ d: cd D:\projects\PaddleX\deploy\cpp\out\build\x64-Release ``` -编译成功后,预测demo的入口程序为`detector`,`classifer`,`segmenter`,用户可根据自己的模型类型选择,其主要命令参数说明如下: +编译成功后,预测demo的入口程序为`demo\detector`,`demo\classifer`,`demo\segmenter`,用户可根据自己的模型类型选择,其主要命令参数说明如下: | 参数 | 说明 | | ---- | ---- | diff --git a/docs/tutorials/deploy/depoly_openvino.md b/docs/tutorials/deploy/depoly_openvino.md new file mode 100644 index 0000000000000000000000000000000000000000..30a0c3fee0a8a1052a601b0dddea3d7886a1e063 --- /dev/null +++ b/docs/tutorials/deploy/depoly_openvino.md @@ -0,0 +1,103 @@ +# OpenVINO 分类demo编译 + +## 说明 +本文档在 `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` + +**说明**:其中`C++`预测代码在`/root/projects/PaddleX/deploy/openvino` 目录,该目录不依赖任何`PaddleX`下其他目录。 + +### Step1: 软件依赖 + +- openvino: +[编译文档](https://github.com/openvinotoolkit/openvino/blob/2020/build-instruction.md#build-steps) + +- gflags: +[编译文档](https://gflags.github.io/gflags/#download) + +- opencv: +[编译文档](https://docs.opencv.org/master/d7/d9f/tutorial_linux_install.html) +说明:/root/projects/PaddleX/deploy/openvino/scripts/bootstrap.sh提供了预编译版本下载,也可自行编译。 + +- ngraph: +说明:openvino编译的过程中会生成ngraph的lib文件,位于{openvino根目录}/bin/intel64/Release/lib/下。 + +### Step2: 编译demo + + +编译`cmake`的命令在`scripts/build.sh`中,请根据Step1中编译软件的实际情况修改主要参数,其主要内容说明如下: +``` +# openvino预编译库的路径 +OPENVINO_DIR=/path/to/inference_engine/ +# gflags预编译库的路径 +GFLAGS_DIR=/path/to/gflags +# ngraph lib的路径,编译openvino时通常会生成 +NGRAPH_LIB=/path/to/ngraph/lib/ +# opencv预编译库的路径, 如果使用自带预编译版本可不修改 +OPENCV_DIR=$(pwd)/deps/opencv3gcc4.8/ +# 下载自带预编译版本 +sh $(pwd)/scripts/bootstrap.sh +rm -rf build +mkdir -p build +cd build +cmake .. \ + -DOPENCV_DIR=${OPENCV_DIR} \ + -DGFLAGS_DIR=${GFLAGS_DIR} \ + -DOPENVINO_DIR=${OPENVINO_DIR} \ + -DNGRAPH_LIB=${NGRAPH_LIB} +make +``` + +修改脚本设置好主要参数后,执行`build`脚本: + ```shell + sh ./scripts/build.sh + ``` + +### Step3: 模型转换 + +将[]()生成的onnx文件转换为OpencVINO支持的格式,请参考:[Model Optimizer文档](https://docs.openvinotoolkit.org/latest/_docs_MO_DG_Deep_Learning_Model_Optimizer_DevGuide.html) + +### Step4: 预测 +编译成功后,预测demo的可执行程序分别为`build/classifer`,其主要命令参数说明如下: + +| 参数 | 说明 | +| ---- | ---- | +| --model_dir | Model Optimizer生成的.xml文件路径,请保证Model Optimizer生成的三个文件在同一路径下| +| --image | 要预测的图片文件路径 | +| --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 +``` + + +`样例二`: + +预测多个图片`/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/classifier --model_dir=/path/to/models/inference_model --image_list=/root/projects/images_list.txt - +``` + diff --git a/docs/tutorials/deploy/encryption.md b/docs/tutorials/deploy/encryption.md new file mode 100644 index 0000000000000000000000000000000000000000..d71bf276a5f5d1bb18b21f1aacd72d294a833172 --- /dev/null +++ b/docs/tutorials/deploy/encryption.md @@ -0,0 +1,49 @@ +# Paddle模型加密方案 + +飞桨团队推出模型加密方案,使用业内主流的AES加密技术对最终模型进行加密。飞桨用户可以通过PaddleX导出模型后,使用该方案对模型进行加密,预测时使用解密SDK进行模型解密并完成推理,大大提升AI应用安全性和开发效率。 + +## 1. 方案介绍 + +### 1.1 工具组成 + +[PaddleX模型加密SDK下载](https://bj.bcebos.com/paddlex/tools/paddlex-encryption.zip) + +下载并解压后,目录包含内容为: +``` +paddle_model_encrypt +├── include # 头文件:paddle_model_decrypt.h(解密)和paddle_model_encrypt.h(加密) +| +├── lib # libpmodel-encrypt.so和libpmodel-decrypt.so动态库 +| +└── tool # paddle_encrypt_tool +``` + +### 1.2 二进制工具 + +#### 1.2.1 生成密钥 + +产生随机密钥信息(用于AES加解密使用)(32字节key + 16字节iv, 注意这里产生的key是经过base64编码后的,这样可以扩充选取key的范围) + +``` +paddle_encrypt_tool -g +``` +#### 1.2.1 文件加密 + +``` + paddle_encrypt_tool -e -key keydata -infile infile -outfile outfile +``` + +#### 1.3 SDK + +``` +// 加密API +int paddle_encrypt_model(const char* keydata, const char* infile, const char* outfile); +// 加载加密模型API: +int paddle_security_load_model( + paddle::AnalysisConfig *config, + const char *key, + const char *model_file, + const char *param_file); +``` + +## 2. PaddleX C++加密部署 diff --git a/docs/deploy/images/vs2019_step1.png b/docs/tutorials/deploy/images/vs2019_step1.png old mode 100644 new mode 100755 similarity index 100% rename from docs/deploy/images/vs2019_step1.png rename to docs/tutorials/deploy/images/vs2019_step1.png diff --git a/docs/deploy/images/vs2019_step2.png b/docs/tutorials/deploy/images/vs2019_step2.png old mode 100644 new mode 100755 similarity index 100% rename from docs/deploy/images/vs2019_step2.png rename to docs/tutorials/deploy/images/vs2019_step2.png diff --git a/docs/deploy/images/vs2019_step3.png b/docs/tutorials/deploy/images/vs2019_step3.png old mode 100644 new mode 100755 similarity index 100% rename from docs/deploy/images/vs2019_step3.png rename to docs/tutorials/deploy/images/vs2019_step3.png diff --git a/docs/deploy/images/vs2019_step4.png b/docs/tutorials/deploy/images/vs2019_step4.png old mode 100644 new mode 100755 similarity index 100% rename from docs/deploy/images/vs2019_step4.png rename to docs/tutorials/deploy/images/vs2019_step4.png diff --git a/docs/deploy/images/vs2019_step5.png b/docs/tutorials/deploy/images/vs2019_step5.png old mode 100644 new mode 100755 similarity index 100% rename from docs/deploy/images/vs2019_step5.png rename to docs/tutorials/deploy/images/vs2019_step5.png diff --git a/docs/deploy/images/vs2019_step6.png b/docs/tutorials/deploy/images/vs2019_step6.png old mode 100644 new mode 100755 similarity index 100% rename from docs/deploy/images/vs2019_step6.png rename to docs/tutorials/deploy/images/vs2019_step6.png diff --git a/docs/tutorials/deploy/index.rst b/docs/tutorials/deploy/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..022d15ab9ea0ee2963cd9b2cd2a8e2cc6c00c06b --- /dev/null +++ b/docs/tutorials/deploy/index.rst @@ -0,0 +1,2 @@ +多端部署 +============== diff --git a/docs/tutorials/index.rst b/docs/tutorials/index.rst old mode 100644 new mode 100755 index 47eaf6abc6df7080a0d2dcba9681bcb247a35d19..b05bfae7f517a9ec64d82a590dc2bb5ff2404dfb --- a/docs/tutorials/index.rst +++ b/docs/tutorials/index.rst @@ -1,8 +1,10 @@ -使用教程 +PaddleX全流程开发教程 ========================= .. toctree:: :maxdepth: 1 + dataset_prepare.md train/index.rst compress/index.rst + deploy/index.rst diff --git a/docs/tutorials/train/classification.md b/docs/tutorials/train/classification.md old mode 100644 new mode 100755 diff --git a/docs/tutorials/train/detection.md b/docs/tutorials/train/detection.md old mode 100644 new mode 100755 diff --git a/docs/tutorials/train/index.rst b/docs/tutorials/train/index.rst old mode 100644 new mode 100755 diff --git a/docs/tutorials/train/instance_segmentation.md b/docs/tutorials/train/instance_segmentation.md old mode 100644 new mode 100755 diff --git a/docs/tutorials/train/segmentation.md b/docs/tutorials/train/segmentation.md old mode 100644 new mode 100755 diff --git a/docs/tutorials/train/visualdl.md b/docs/tutorials/train/visualdl.md old mode 100644 new mode 100755 diff --git a/docs/update.md b/docs/update.md new file mode 100644 index 0000000000000000000000000000000000000000..881cf72e4ad6bcd1e76360a04a7519fce1069d5e --- /dev/null +++ b/docs/update.md @@ -0,0 +1,9 @@ +# 更新日志 + +- 2020.05.17 +> - 发布v0.1.8 pip更新 +> - 修复部分代码Bug +> - 新增EasyData平台数据标注格式支持 +> - 支持imgaug数据增强库的pixel-level算子 + + diff --git a/paddlex/__init__.py b/paddlex/__init__.py index eff1c0a12f41d539d73f55c56bfc2a09e1bcd378..73647538443d172eee2f043c8c1f87c684a91f67 100644 --- a/paddlex/__init__.py +++ b/paddlex/__init__.py @@ -27,6 +27,7 @@ from . import det from . import seg from . import cls from . import slim +from . import convertor from . import tools try: @@ -48,4 +49,4 @@ load_model = cv.models.load_model datasets = cv.datasets log_level = 2 -__version__ = '0.1.7.github' +__version__ = '0.2.0.github' diff --git a/paddlex/command.py b/paddlex/command.py index 58a50f31973723096066552bbe96614a28070552..07b0e68020a2ce37be043603a705ee6180dee066 100644 --- a/paddlex/command.py +++ b/paddlex/command.py @@ -29,6 +29,12 @@ def arg_parser(): action="store_true", default=False, help="export inference model for C++/Python deployment") + parser.add_argument( + "--export_onnx", + "-eo", + action="store_true", + default=False, + help="export onnx model for deployment") parser.add_argument( "--fixed_input_shape", "-fs", @@ -54,25 +60,36 @@ def main(): print("Repo: https://github.com/PaddlePaddle/PaddleX.git") print("Email: paddlex@baidu.com") return + if args.export_inference: assert args.model_dir is not None, "--model_dir should be defined while exporting inference model" assert args.save_dir is not None, "--save_dir should be defined to save inference model" - fixed_input_shape = eval(args.fixed_input_shape) - assert len( - fixed_input_shape) == 2, "len of fixed input shape must == 2" + + fixed_input_shape = None + if args.fixed_input_shape is not None: + fixed_input_shape = eval(args.fixed_input_shape) + assert len( + fixed_input_shape + ) == 2, "len of fixed input shape must == 2, such as [224,224]" + else: + fixed_input_shape = None model = pdx.load_model(args.model_dir, fixed_input_shape) model.export_inference_model(args.save_dir) if args.export_onnx: assert args.model_dir is not None, "--model_dir should be defined while exporting onnx model" - assert args.save_dir is not None, "--save_dir should be defined to save onnx model" - fixed_input_shape = eval(args.fixed_input_shape) - assert len( - fixed_input_shape) == 2, "len of fixed input shape must == 2" + assert args.save_dir is not None, "--save_dir should be defined to create onnx model" + assert args.fixed_input_shape is not None, "--fixed_input_shape should be defined [w,h] to create onnx model, such as [224,224]" + fixed_input_shape = [] + if args.fixed_input_shape is not None: + fixed_input_shape = eval(args.fixed_input_shape) + assert len( + fixed_input_shape + ) == 2, "len of fixed input shape must == 2, such as [224,224]" model = pdx.load_model(args.model_dir, fixed_input_shape) - model.export_onnx_model(args.save_dir) + pdx.convertor.export_onnx_model(model, args.save_dir) if __name__ == "__main__": diff --git a/paddlex/convertor.py b/paddlex/convertor.py new file mode 100644 index 0000000000000000000000000000000000000000..fa74f49cac68fb7cbacadb6e38e7493c28857a92 --- /dev/null +++ b/paddlex/convertor.py @@ -0,0 +1,148 @@ +#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 +import os +import sys +import paddlex as pdx +import paddlex.utils.logging as logging + +__all__ = ['export_onnx'] + + +def export_onnx(model_dir, save_dir, fixed_input_shape): + assert len(fixed_input_shape) == 2, "len of fixed input shape must == 2" + model = pdx.load_model(model_dir, fixed_input_shape) + model_name = os.path.basename(model_dir.strip('/')).split('/')[-1] + export_onnx_model(model, save_dir) + + +def export_onnx_model(model, save_dir): + support_list = [ + 'ResNet18', 'ResNet34', 'ResNet50', 'ResNet101', 'ResNet50_vd', + 'ResNet101_vd', 'ResNet50_vd_ssld', 'ResNet101_vd_ssld', 'DarkNet53', + 'MobileNetV1', 'MobileNetV2', 'DenseNet121', 'DenseNet161', + 'DenseNet201' + ] + if model.__class__.__name__ not in support_list: + raise Exception("Model: {} unsupport export to ONNX".format( + model.__class__.__name__)) + try: + from fluid.utils import op_io_info, init_name_prefix + from onnx import helper, checker + import fluid_onnx.ops as ops + from fluid_onnx.variables import paddle_variable_to_onnx_tensor, paddle_onnx_weight + from debug.model_check import debug_model, Tracker + except Exception as e: + logging.error( + "Import Module Failed! Please install paddle2onnx. Related requirements see https://github.com/PaddlePaddle/paddle2onnx." + ) + raise e + place = fluid.CPUPlace() + exe = fluid.Executor(place) + inference_scope = fluid.global_scope() + with fluid.scope_guard(inference_scope): + test_input_names = [ + var.name for var in list(model.test_inputs.values()) + ] + inputs_outputs_list = ["fetch", "feed"] + weights, weights_value_info = [], [] + global_block = model.test_prog.global_block() + for var_name in global_block.vars: + var = global_block.var(var_name) + if var_name not in test_input_names\ + and var.persistable: + weight, val_info = paddle_onnx_weight( + var=var, scope=inference_scope) + weights.append(weight) + weights_value_info.append(val_info) + + # Create inputs + inputs = [ + paddle_variable_to_onnx_tensor(v, global_block) + for v in test_input_names + ] + logging.INFO("load the model parameter done.") + onnx_nodes = [] + op_check_list = [] + op_trackers = [] + nms_first_index = -1 + nms_outputs = [] + for block in model.test_prog.blocks: + for op in block.ops: + if op.type in ops.node_maker: + # TODO: deal with the corner case that vars in + # different blocks have the same name + node_proto = ops.node_maker[str(op.type)]( + operator=op, block=block) + op_outputs = [] + last_node = None + if isinstance(node_proto, tuple): + onnx_nodes.extend(list(node_proto)) + last_node = list(node_proto) + else: + onnx_nodes.append(node_proto) + last_node = [node_proto] + tracker = Tracker(str(op.type), last_node) + op_trackers.append(tracker) + op_check_list.append(str(op.type)) + if op.type == "multiclass_nms" and nms_first_index < 0: + nms_first_index = 0 + if nms_first_index >= 0: + _, _, output_op = op_io_info(op) + for output in output_op: + nms_outputs.extend(output_op[output]) + else: + if op.type not in ['feed', 'fetch']: + op_check_list.append(op.type) + logging.info('The operator sets to run test case.') + logging.info(set(op_check_list)) + + # Create outputs + # Get the new names for outputs if they've been renamed in nodes' making + renamed_outputs = op_io_info.get_all_renamed_outputs() + test_outputs = list(model.test_outputs.values()) + test_outputs_names = [var.name for var in model.test_outputs.values()] + test_outputs_names = [ + name if name not in renamed_outputs else renamed_outputs[name] + for name in test_outputs_names + ] + outputs = [ + paddle_variable_to_onnx_tensor(v, global_block) + for v in test_outputs_names + ] + + # Make graph + onnx_name = 'paddlex.onnx' + onnx_graph = helper.make_graph( + nodes=onnx_nodes, + name=onnx_name, + initializer=weights, + inputs=inputs + weights_value_info, + outputs=outputs) + + # Make model + onnx_model = helper.make_model( + onnx_graph, producer_name='PaddlePaddle') + + # Model check + checker.check_model(onnx_model) + if onnx_model is not None: + onnx_model_file = os.path.join(save_dir, onnx_name) + if not os.path.exists(save_dir): + os.mkdir(save_dir) + with open(onnx_model_file, 'wb') as f: + f.write(onnx_model.SerializeToString()) + logging.info("Saved converted model to path: %s" % onnx_model_file) diff --git a/paddlex/cv/datasets/voc.py b/paddlex/cv/datasets/voc.py index b5f1749e31a356879265ca66d580283158166afc..8633fe5305929c5238523a067af172720156d3d5 100644 --- a/paddlex/cv/datasets/voc.py +++ b/paddlex/cv/datasets/voc.py @@ -95,8 +95,8 @@ class VOCDetection(Dataset): if not osp.isfile(xml_file): continue if not osp.exists(img_file): - raise IOError( - 'The image file {} is not exist!'.format(img_file)) + raise IOError('The image file {} is not exist!'.format( + img_file)) tree = ET.parse(xml_file) if tree.find('id') is None: im_id = np.array([ct]) @@ -122,25 +122,20 @@ class VOCDetection(Dataset): y2 = float(obj.find('bndbox').find('ymax').text) x1 = max(0, x1) y1 = max(0, y1) - x2 = min(im_w - 1, x2) - y2 = min(im_h - 1, y2) + if im_w > 0.5 and im_h > 0.5: + x2 = min(im_w - 1, x2) + y2 = min(im_h - 1, y2) gt_bbox[i] = [x1, y1, x2, y2] is_crowd[i][0] = 0 difficult[i][0] = _difficult annotations['annotations'].append({ - 'iscrowd': - 0, - 'image_id': - int(im_id[0]), + 'iscrowd': 0, + 'image_id': int(im_id[0]), 'bbox': [x1, y1, x2 - x1 + 1, y2 - y1 + 1], - 'area': - float((x2 - x1 + 1) * (y2 - y1 + 1)), - 'category_id': - cname2cid[cname], - 'id': - ann_ct, - 'difficult': - _difficult + 'area': float((x2 - x1 + 1) * (y2 - y1 + 1)), + 'category_id': cname2cid[cname], + 'id': ann_ct, + 'difficult': _difficult }) ann_ct += 1 @@ -160,14 +155,10 @@ class VOCDetection(Dataset): self.file_list.append([img_file, voc_rec]) ct += 1 annotations['images'].append({ - 'height': - im_h, - 'width': - im_w, - 'id': - int(im_id[0]), - 'file_name': - osp.split(img_file)[1] + 'height': im_h, + 'width': im_w, + 'id': int(im_id[0]), + 'file_name': osp.split(img_file)[1] }) if not len(self.file_list) > 0: @@ -198,8 +189,7 @@ class VOCDetection(Dataset): else: mix_pos = 0 im_info['mixup'] = [ - files[mix_pos][0], - copy.deepcopy(files[mix_pos][1][0]), + files[mix_pos][0], copy.deepcopy(files[mix_pos][1][0]), copy.deepcopy(files[mix_pos][1][1]) ] self._pos += 1 diff --git a/paddlex/cv/models/base.py b/paddlex/cv/models/base.py index f0a52fa2436ad3303f4cfba447cdfb3b53663e64..3264c8d3b0d9830c679bb02cf2124de8e67affa2 100644 --- a/paddlex/cv/models/base.py +++ b/paddlex/cv/models/base.py @@ -15,6 +15,7 @@ from __future__ import absolute_import import paddle.fluid as fluid import os +import sys import numpy as np import time import math @@ -251,6 +252,9 @@ class BaseAPI: del self.init_params['self'] if '__class__' in self.init_params: del self.init_params['__class__'] + if 'model_name' in self.init_params: + del self.init_params['model_name'] + info['_init_params'] = self.init_params info['_Attributes']['num_classes'] = self.num_classes @@ -371,6 +375,8 @@ class BaseAPI: use_vdl=False, early_stop=False, early_stop_patience=5): + if train_dataset.num_samples < train_batch_size: + raise Exception('The amount of training datset must be larger than batch size.') if not osp.isdir(save_dir): if osp.exists(save_dir): os.remove(save_dir) @@ -428,9 +434,7 @@ class BaseAPI: if use_vdl: # VisualDL component - log_writer = LogWriter(vdl_logdir, sync_cycle=20) - train_step_component = OrderedDict() - eval_component = OrderedDict() + log_writer = LogWriter(vdl_logdir) thresh = 0.0001 if early_stop: @@ -468,13 +472,7 @@ class BaseAPI: if use_vdl: for k, v in step_metrics.items(): - if k not in train_step_component.keys(): - with log_writer.mode('Each_Step_while_Training' - ) as step_logger: - train_step_component[ - k] = step_logger.scalar( - 'Training: {}'.format(k)) - train_step_component[k].add_record(num_steps, v) + log_writer.add_scalar('Metrics/Training(Step): {}'.format(k), v, num_steps) # 估算剩余时间 avg_step_time = np.mean(time_stat) @@ -535,12 +533,7 @@ class BaseAPI: if isinstance(v, np.ndarray): if v.size > 1: continue - if k not in eval_component: - with log_writer.mode('Each_Epoch_on_Eval_Data' - ) as eval_logger: - eval_component[k] = eval_logger.scalar( - 'Evaluation: {}'.format(k)) - eval_component[k].add_record(i + 1, v) + log_writer.add_scalar("Metrics/Eval(Epoch): {}".format(k), v, i+1) self.save_model(save_dir=current_save_dir) time_eval_one_epoch = time.time() - eval_epoch_start_time eval_epoch_start_time = time.time() diff --git a/paddlex/cv/models/deeplabv3p.py b/paddlex/cv/models/deeplabv3p.py index 2880d4bcb40dade036ddbbd9b893a0231fa33015..a253aa5d1d8c005c7903b57a9b9b36da45982d78 100644 --- a/paddlex/cv/models/deeplabv3p.py +++ b/paddlex/cv/models/deeplabv3p.py @@ -400,14 +400,19 @@ class DeepLabv3p(BaseAPI): fetch_list=list(self.test_outputs.values())) pred = result[0] pred = np.squeeze(pred).astype('uint8') + logit = result[1] + logit = np.squeeze(logit) + logit = np.transpose(logit, (1, 2, 0)) for info in im_info[::-1]: if info[0] == 'resize': w, h = info[1][1], info[1][0] pred = cv2.resize(pred, (w, h), cv2.INTER_NEAREST) + logit = cv2.resize(logit, (w, h), cv2.INTER_LINEAR) elif info[0] == 'padding': w, h = info[1][1], info[1][0] pred = pred[0:h, 0:w] + logit = logit[0:h, 0:w, :] else: raise Exception("Unexpected info '{}' in im_info".format( info[0])) - return {'label_map': pred, 'score_map': result[1]} + return {'label_map': pred, 'score_map': logit} diff --git a/paddlex/cv/models/load_model.py b/paddlex/cv/models/load_model.py index 622dd0e2d8cdf0d2625dd52322718f198d8bbb1e..738f4ff00452d278b3988d9303bb15b0d8885979 100644 --- a/paddlex/cv/models/load_model.py +++ b/paddlex/cv/models/load_model.py @@ -38,12 +38,9 @@ def load_model(model_dir, fixed_input_shape=None): if not hasattr(paddlex.cv.models, info['Model']): raise Exception("There's no attribute {} in paddlex.cv.models".format( info['Model'])) - - if info['_Attributes']['model_type'] == 'classifier': - model = paddlex.cv.models.BaseClassifier(**info['_init_params']) - else: - model = getattr(paddlex.cv.models, - info['Model'])(**info['_init_params']) + if 'model_name' in info['_init_params']: + del info['_init_params']['model_name'] + model = getattr(paddlex.cv.models, info['Model'])(**info['_init_params']) model.fixed_input_shape = fixed_input_shape if status == "Normal" or \ status == "Prune" or status == "fluid.save": diff --git a/paddlex/cv/models/slim/post_quantization.py b/paddlex/cv/models/slim/post_quantization.py index ead88401af76997c8b470011da41a75167b6a782..bd173330111da51e0c20a7c622cb32dea98514a4 100644 --- a/paddlex/cv/models/slim/post_quantization.py +++ b/paddlex/cv/models/slim/post_quantization.py @@ -19,6 +19,9 @@ from paddle.fluid.contrib.slim.quantization import PostTrainingQuantization import paddlex.utils.logging as logging import paddle.fluid as fluid import os +import re +import numpy as np +import time class PaddleXPostTrainingQuantization(PostTrainingQuantization): @@ -123,28 +126,37 @@ class PaddleXPostTrainingQuantization(PostTrainingQuantization): the program of quantized model. ''' self._preprocess() - + batch_ct = 0 + for data in self._data_loader(): + batch_ct += 1 + if self._batch_nums and batch_ct >= self._batch_nums: + break batch_id = 0 + logging.info("Start to run batch!") for data in self._data_loader(): + start = time.time() self._executor.run( program=self._program, feed=data, fetch_list=self._fetch_list, return_numpy=False) self._sample_data(batch_id) - - if batch_id % 5 == 0: - logging.info("run batch: {}".format(batch_id)) + end = time.time() + logging.debug('[Run batch data] Batch={}/{}, time_each_batch={} s.'.format( + str(batch_id + 1), + str(batch_ct), + str(end-start))) batch_id += 1 if self._batch_nums and batch_id >= self._batch_nums: break - logging.info("all run batch: ".format(batch_id)) - logging.info("calculate scale factor ...") + logging.info("All run batch: ".format(batch_id)) + logging.info("Calculate scale factor ...") self._calculate_scale_factor() - logging.info("update the program ...") + logging.info("Update the program ...") self._update_program() - + logging.info("Save ...") self._save_output_scale() + logging.info("Finish quant!") return self._program def save_quantized_model(self, save_model_path): @@ -221,3 +233,69 @@ class PaddleXPostTrainingQuantization(PostTrainingQuantization): for var in self._program.list_vars(): if var.name in self._quantized_act_var_name: var.persistable = True + + def _calculate_scale_factor(self): + ''' + Calculate the scale factor of quantized variables. + ''' + # apply channel_wise_abs_max quantization for weights + ct = 1 + for var_name in self._quantized_weight_var_name: + start = time.time() + data = self._sampling_data[var_name] + scale_factor_per_channel = [] + for i in range(data.shape[0]): + abs_max_value = np.max(np.abs(data[i])) + scale_factor_per_channel.append(abs_max_value) + self._quantized_var_scale_factor[ + var_name] = scale_factor_per_channel + end = time.time() + logging.debug('[Calculate weight] Weight_id={}/{}, time_each_weight={} s.'.format( + str(ct), + str(len(self._quantized_weight_var_name)), + str(end-start))) + ct += 1 + + ct = 1 + # apply kl quantization for activation + if self._is_use_cache_file: + for var_name in self._quantized_act_var_name: + start = time.time() + sampling_data = [] + filenames = [f for f in os.listdir(self._cache_dir) \ + if re.match(var_name + '_[0-9]+.npy', f)] + for filename in filenames: + file_path = os.path.join(self._cache_dir, filename) + sampling_data.append(np.load(file_path)) + os.remove(file_path) + sampling_data = np.concatenate(sampling_data) + + if self._algo == "KL": + self._quantized_var_scale_factor[var_name] = \ + self._get_kl_scaling_factor(np.abs(sampling_data)) + else: + self._quantized_var_scale_factor[var_name] = \ + np.max(np.abs(sampling_data)) + end = time.time() + logging.debug('[Calculate activation] Activation_id={}/{}, time_each_activation={} s.'.format( + str(ct), + str(len(self._quantized_act_var_name)), + str(end-start))) + ct += 1 + else: + for var_name in self._quantized_act_var_name: + start = time.time() + self._sampling_data[var_name] = np.concatenate( + self._sampling_data[var_name]) + if self._algo == "KL": + self._quantized_var_scale_factor[var_name] = \ + self._get_kl_scaling_factor(np.abs(self._sampling_data[var_name])) + else: + self._quantized_var_scale_factor[var_name] = \ + np.max(np.abs(self._sampling_data[var_name])) + end = time.time() + logging.debug('[Calculate activation] Activation_id={}/{}, time_each_activation={} s.'.format( + str(ct), + str(len(self._quantized_act_var_name)), + str(end-start))) + ct += 1 \ No newline at end of file diff --git a/paddlex/cv/models/slim/visualize.py b/paddlex/cv/models/slim/visualize.py index d9380abb2f1184cfe59d77b84d6841b5c4fd7288..083b177ea8c8878562070df3b617b32248046fea 100644 --- a/paddlex/cv/models/slim/visualize.py +++ b/paddlex/cv/models/slim/visualize.py @@ -30,7 +30,6 @@ def visualize(model, sensitivities_file, save_dir='./'): import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt - program = model.test_prog place = model.places[0] fig = plt.figure() @@ -51,15 +50,21 @@ def visualize(model, sensitivities_file, save_dir='./'): min(np.array(x)) - 0.01, max(np.array(x)) + 0.01, 0.05) my_y_ticks = np.arange(0.05, 1, 0.05) - plt.xticks(my_x_ticks, fontsize=3) - plt.yticks(my_y_ticks, fontsize=3) + plt.xticks(my_x_ticks, rotation=30, fontsize=8) + plt.yticks(my_y_ticks, fontsize=8) for a, b in zip(x, y): plt.text( a, - b, (float('%0.4f' % a), float('%0.3f' % b)), + b, (float('%0.3f' % a), float('%0.3f' % b)), ha='center', va='bottom', - fontsize=3) + fontsize=8) + plt.rcParams['savefig.dpi'] = 120 + plt.rcParams['figure.dpi'] = 150 suffix = osp.splitext(sensitivities_file)[-1] - plt.savefig('sensitivities.png', dpi=800) + plt.savefig(osp.join(save_dir, 'sensitivities.png')) plt.close() + import pickle + coor = dict(zip(x, y)) + output = open(osp.join(save_dir, 'sensitivities_xy.pkl'), 'wb') + pickle.dump(coor, output) diff --git a/paddlex/cv/transforms/cls_transforms.py b/paddlex/cv/transforms/cls_transforms.py index 6773f2ec469adcca673ef55e80d3a36a24d51b83..844516c79741e87159740a3ab980ac326567c4ef 100644 --- a/paddlex/cv/transforms/cls_transforms.py +++ b/paddlex/cv/transforms/cls_transforms.py @@ -86,10 +86,10 @@ class Compose(ClsTransform): else: import imgaug.augmenters as iaa if isinstance(op, iaa.Augmenter): - im, = execute_imgaug(op, im) - output = (im, ) + im = execute_imgaug(op, im) + outputs = (im, ) if label is not None: - output = (im, label) + outputs = (im, label) return outputs diff --git a/paddlex/cv/transforms/det_transforms.py b/paddlex/cv/transforms/det_transforms.py index b9aee9e3bc8e432b575fbc0f9fc11d86a73ecb88..ca892d75bc7913cd1e238bb96e82e76f9a4fd716 100644 --- a/paddlex/cv/transforms/det_transforms.py +++ b/paddlex/cv/transforms/det_transforms.py @@ -111,8 +111,8 @@ class Compose(DetTransform): try: im = cv2.imread(im_file).astype('float32') except: - raise TypeError( - 'Can\'t read The image file {}!'.format(im_file)) + raise TypeError('Can\'t read The image file {}!'.format( + im_file)) im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB) # make default im_info with [h, w, 1] im_info['im_resize_info'] = np.array( @@ -145,19 +145,10 @@ class Compose(DetTransform): outputs = op(im, im_info, label_info) im = outputs[0] else: + im = execute_imgaug(op, im) if label_info is not None: - gt_poly = label_info.get('gt_poly', None) - gt_bbox = label_info['gt_bbox'] - if gt_poly is None: - im, aug_bbox = execute_imgaug(op, im, bboxes=gt_bbox) - else: - im, aug_bbox, aug_poly = execute_imgaug( - op, im, bboxes=gt_bbox, polygons=gt_poly) - label_info['gt_poly'] = aug_poly - label_info['gt_bbox'] = aug_bbox outputs = (im, im_info, label_info) else: - im, = execute_imgaug(op, im) outputs = (im, im_info) return outputs @@ -218,8 +209,8 @@ class ResizeByShort(DetTransform): im_short_size = min(im.shape[0], im.shape[1]) im_long_size = max(im.shape[0], im.shape[1]) scale = float(self.short_size) / im_short_size - if self.max_size > 0 and np.round( - scale * im_long_size) > self.max_size: + if self.max_size > 0 and np.round(scale * + im_long_size) > self.max_size: scale = float(self.max_size) / float(im_long_size) resized_width = int(round(im.shape[1] * scale)) resized_height = int(round(im.shape[0] * scale)) @@ -302,8 +293,8 @@ class Padding(DetTransform): if isinstance(self.target_size, int): padding_im_h = self.target_size padding_im_w = self.target_size - elif isinstance(self.target_size, list) or isinstance( - self.target_size, tuple): + elif isinstance(self.target_size, list) or isinstance(self.target_size, + tuple): padding_im_w = self.target_size[0] padding_im_h = self.target_size[1] elif self.coarsest_stride > 0: @@ -321,8 +312,8 @@ class Padding(DetTransform): raise ValueError( 'the size of image should be less than target_size, but the size of image ({}, {}), is larger than target_size ({}, {})' .format(im_w, im_h, padding_im_w, padding_im_h)) - padding_im = np.zeros((padding_im_h, padding_im_w, im_c), - dtype=np.float32) + padding_im = np.zeros( + (padding_im_h, padding_im_w, im_c), dtype=np.float32) padding_im[:im_h, :im_w, :] = im if label_info is None: return (padding_im, im_info) @@ -932,8 +923,9 @@ class RandomCrop(DetTransform): crop_y = np.random.randint(0, h - crop_h) crop_x = np.random.randint(0, w - crop_w) crop_box = [crop_x, crop_y, crop_x + crop_w, crop_y + crop_h] - iou = iou_matrix(gt_bbox, np.array([crop_box], - dtype=np.float32)) + iou = iou_matrix( + gt_bbox, np.array( + [crop_box], dtype=np.float32)) if iou.max() < thresh: continue @@ -941,16 +933,21 @@ class RandomCrop(DetTransform): continue cropped_box, valid_ids = crop_box_with_center_constraint( - gt_bbox, np.array(crop_box, dtype=np.float32)) + gt_bbox, np.array( + crop_box, dtype=np.float32)) if valid_ids.size > 0: found = True break if found: if 'gt_poly' in label_info and len(label_info['gt_poly']) > 0: - crop_polys = crop_segms(label_info['gt_poly'], valid_ids, - np.array(crop_box, dtype=np.int64), - h, w) + crop_polys = crop_segms( + label_info['gt_poly'], + valid_ids, + np.array( + crop_box, dtype=np.int64), + h, + w) if [] in crop_polys: delete_id = list() valid_polys = list() diff --git a/paddlex/cv/transforms/imgaug_support.py b/paddlex/cv/transforms/imgaug_support.py index ba8d808fd8759c3d07d17509d0bdba41c3e9bd2f..3924acd1821fc9fc4f85b8c486e4f2a20f4e8543 100644 --- a/paddlex/cv/transforms/imgaug_support.py +++ b/paddlex/cv/transforms/imgaug_support.py @@ -13,36 +13,41 @@ # limitations under the License. import numpy as np +import copy def execute_imgaug(augmenter, im, bboxes=None, polygons=None, segment_map=None): # 预处理,将bboxes, polygons转换成imgaug格式 - import imgaug.augmentables.polys as polys + import imgaug.augmentables.kps as kps import imgaug.augmentables.bbs as bbs aug_im = im.astype('uint8') + aug_im = augmenter.augment(image=aug_im) + return aug_im + # TODO imgaug的标注处理逻辑与paddlex已存的transform存在部分差异 + # 目前仅支持对原图进行处理,因此只能使用pixlevel的imgaug增强操作 + # 以下代码暂不会执行 aug_bboxes = None if bboxes is not None: aug_bboxes = list() for i in range(len(bboxes)): - x1 = bboxes[i, 0] - 1 + x1 = bboxes[i, 0] y1 = bboxes[i, 1] x2 = bboxes[i, 2] y2 = bboxes[i, 3] aug_bboxes.append(bbs.BoundingBox(x1, y1, x2, y2)) - aug_polygons = None - lod_info = list() + aug_points = None if polygons is not None: - aug_polygons = list() + aug_points = list() for i in range(len(polygons)): num = len(polygons[i]) - lod_info.append(num) for j in range(num): - points = np.reshape(polygons[i][j], (-1, 2)) - aug_polygons.append(polys.Polygon(points)) + tmp = np.reshape(polygons[i][j], (-1, 2)) + for k in range(len(tmp)): + aug_points.append(kps.Keypoint(tmp[k, 0], tmp[k, 1])) aug_segment_map = None if segment_map is not None: @@ -56,72 +61,47 @@ def execute_imgaug(augmenter, im, bboxes=None, polygons=None, raise Exception( "Only support 2-dimensions for 3-dimensions for segment_map") - aug_im, aug_bboxes, aug_polygons, aug_seg_map = augmenter.augment( + unnormalized_batch = augmenter.augment( image=aug_im, bounding_boxes=aug_bboxes, - polygons=aug_polygons, - segmentation_maps=aug_segment_map) + keypoints=aug_points, + segmentation_maps=aug_segment_map, + return_batch=True) + aug_im = unnormalized_batch.images_aug[0] + aug_bboxes = unnormalized_batch.bounding_boxes_aug + aug_points = unnormalized_batch.keypoints_aug + aug_seg_map = unnormalized_batch.segmentation_maps_aug aug_im = aug_im.astype('float32') - if aug_polygons is not None: - assert len(aug_bboxes) == len( - lod_info - ), "Number of aug_bboxes should be equal to number of aug_polygons" - if aug_bboxes is not None: - # 裁剪掉在图像之外的bbox和polygon - for i in range(len(aug_bboxes)): - aug_bboxes[i] = aug_bboxes[i].clip_out_of_image(aug_im) - if aug_polygons is not None: - for i in range(len(aug_polygons)): - aug_polygons[i] = aug_polygons[i].clip_out_of_image(aug_im) - - # 过滤掉无效的bbox和polygon,并转换为训练数据格式 converted_bboxes = list() - converted_polygons = list() - poly_index = 0 for i in range(len(aug_bboxes)): - # 过滤width或height不足1像素的框 - if aug_bboxes[i].width < 1 or aug_bboxes[i].height < 1: - continue - if aug_polygons is None: - converted_bboxes.append([ - aug_bboxes[i].x1, aug_bboxes[i].y1, aug_bboxes[i].x2, - aug_bboxes[i].y2 - ]) - continue - - # 如若有polygons,将会继续执行下面代码 - polygons_this_box = list() - for ps in aug_polygons[poly_index:poly_index + lod_info[i]]: - if len(ps) == 0: - continue - for p in ps: - # 没有3个point的polygon被过滤 - if len(p.exterior) < 3: - continue - polygons_this_box.append(p.exterior.flatten().tolist()) - poly_index += lod_info[i] - - if len(polygons_this_box) == 0: - continue converted_bboxes.append([ aug_bboxes[i].x1, aug_bboxes[i].y1, aug_bboxes[i].x2, aug_bboxes[i].y2 ]) - converted_polygons.append(polygons_this_box) - if len(converted_bboxes) == 0: - aug_im = im - converted_bboxes = bboxes - converted_polygons = polygons + aug_bboxes = converted_bboxes + + aug_polygons = None + if aug_points is not None: + aug_polygons = copy.deepcopy(polygons) + idx = 0 + for i in range(len(aug_polygons)): + num = len(aug_polygons[i]) + for j in range(num): + num_points = len(aug_polygons[i][j]) // 2 + for k in range(num_points): + aug_polygons[i][j][k * 2] = aug_points[idx].x + aug_polygons[i][j][k * 2 + 1] = aug_points[idx].y + idx += 1 result = [aug_im] - if bboxes is not None: - result.append(np.array(converted_bboxes)) - if polygons is not None: - result.append(converted_polygons) - if segment_map is not None: + if aug_bboxes is not None: + result.append(np.array(aug_bboxes)) + if aug_polygons is not None: + result.append(aug_polygons) + if aug_seg_map is not None: n, h, w, c = aug_seg_map.shape if len(segment_map.shape) == 2: aug_seg_map = np.reshape(aug_seg_map, (h, w)) diff --git a/paddlex/cv/transforms/seg_transforms.py b/paddlex/cv/transforms/seg_transforms.py index 9eb1222d02e74d8144c813c9f1398c5367c413a7..e562ba2601677085fdef23c57a6779ba77143f8d 100644 --- a/paddlex/cv/transforms/seg_transforms.py +++ b/paddlex/cv/transforms/seg_transforms.py @@ -101,11 +101,10 @@ class Compose(SegTransform): if len(outputs) == 3: label = outputs[2] else: + im = execute_imgaug(op, im) if label is not None: - im, label = execute_imgaug(op, im, segment_map=label) outputs = (im, im_info, label) else: - im, = execute_imgaug(op, im) outputs = (im, im_info) return outputs @@ -391,8 +390,8 @@ class ResizeByShort(SegTransform): im_short_size = min(im.shape[0], im.shape[1]) im_long_size = max(im.shape[0], im.shape[1]) scale = float(self.short_size) / im_short_size - if self.max_size > 0 and np.round( - scale * im_long_size) > self.max_size: + if self.max_size > 0 and np.round(scale * + im_long_size) > self.max_size: scale = float(self.max_size) / float(im_long_size) resized_width = int(round(im.shape[1] * scale)) resized_height = int(round(im.shape[0] * scale)) @@ -423,8 +422,8 @@ class ResizeRangeScaling(SegTransform): def __init__(self, min_value=400, max_value=600): if min_value > max_value: raise ValueError('min_value must be less than max_value, ' - 'but they are {} and {}.'.format( - min_value, max_value)) + 'but they are {} and {}.'.format(min_value, + max_value)) self.min_value = min_value self.max_value = max_value @@ -761,8 +760,8 @@ class RandomPaddingCrop(SegTransform): h_off = np.random.randint(img_height - crop_height + 1) w_off = np.random.randint(img_width - crop_width + 1) - im = im[h_off:(crop_height + h_off), w_off:( - w_off + crop_width), :] + im = im[h_off:(crop_height + h_off), w_off:(w_off + crop_width + ), :] if label is not None: label = label[h_off:(crop_height + h_off), w_off:( w_off + crop_width)] diff --git a/setup.py b/setup.py index 01e778b7453daf986f6f28c0e2be2461747f8711..a67c477c0310e549f797e8e273b9ef03159242c5 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.1.7', + version='0.2.0', author="paddlex", author_email="paddlex@baidu.com", description=long_description, @@ -27,10 +27,10 @@ setuptools.setup( long_description_content_type="text/plain", url="https://github.com/PaddlePaddle/PaddleX", packages=setuptools.find_packages(), - setup_requires=['cython', 'numpy', 'sklearn'], + setup_requires=['cython', 'numpy'], install_requires=[ "pycocotools;platform_system!='Windows'", 'pyyaml', 'colorama', 'tqdm', - 'visualdl==1.3.0', 'paddleslim==1.0.1' + 'paddleslim==1.0.1', 'visualdl==2.0.0a2' ], classifiers=[ "Programming Language :: Python :: 3", @@ -38,6 +38,4 @@ setuptools.setup( "Operating System :: OS Independent", ], license='Apache 2.0', - entry_points={'console_scripts': [ - 'paddlex=paddlex.command:main', - ]}) + entry_points={'console_scripts': ['paddlex=paddlex.command:main', ]})