代码拉取完成,页面将自动刷新
同步操作将从 PaddlePaddle/FastDeploy 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
在FastDeploy里面新增一个模型,包括增加C++/Python的部署支持。 本文以torchvision v0.12.0中的ResNet50模型为例,介绍使用FastDeploy做外部模型集成,具体包括如下3步。
步骤 | 说明 | 创建或修改的文件 |
---|---|---|
1 | 在fastdeploy/vision相应任务模块增加模型实现 | resnet.h、resnet.cc、vision.h |
2 | 通过pybind完成Python接口绑定 | resnet_pybind.cc、classification_pybind.cc |
3 | 实现Python相应调用接口 | resnet.py、__init__.py |
在完成上述3步之后,一个外部模型就集成好了。
如果您想为FastDeploy贡献代码,还需要为新增模型添加测试代码、说明文档和代码注释,可在测试中查看。
在集成外部模型之前,先要将训练好的模型(.pt,.pdparams 等)转换成FastDeploy支持部署的模型格式(.onnx,.pdmodel)。多数开源仓库会提供模型转换脚本,可以直接利用脚本做模型的转换。由于torchvision没有提供转换脚本,因此手动编写转换脚本,本文中将 torchvison.models.resnet50
转换为 resnet50.onnx
, 参考代码如下:
import torch
import torchvision.models as models
model = models.resnet50(pretrained=True)
batch_size = 1 #批处理大小
input_shape = (3, 224, 224) #输入数据,改成自己的输入shape
model.eval()
x = torch.randn(batch_size, *input_shape) # 生成张量
export_onnx_file = "resnet50.onnx" # 目的ONNX文件名
torch.onnx.export(model,
x,
export_onnx_file,
opset_version=12,
input_names=["input"], # 输入名
output_names=["output"], # 输出名
dynamic_axes={"input":{0:"batch_size"}, # 批处理变量
"output":{0:"batch_size"}})
执行上述脚本将会得到 resnet50.onnx
文件。
resnet.h
文件
Predict
、Initialize
、Preprocess
、Postprocess
和构造函数
,以及必要的变量,具体的代码细节请参考resnet.h。class FASTDEPLOY_DECL ResNet : public FastDeployModel {
public:
ResNet(...);
virtual bool Predict(...);
private:
bool Initialize();
bool Preprocess(...);
bool Postprocess(...);
};
resnet.cc
文件
resnet.cc
中实现resnet.h
中声明函数的具体逻辑,其中PreProcess
和 PostProcess
需要参考源官方库的前后处理逻辑复现,ResNet每个函数具体逻辑如下,具体的代码请参考resnet.cc。ResNet::ResNet(...) {
// 构造函数逻辑
// 1. 指定 Backend 2. 设置RuntimeOption 3. 调用Initialize()函数
}
bool ResNet::Initialize() {
// 初始化逻辑
// 1. 全局变量赋值 2. 调用InitRuntime()函数
return true;
}
bool ResNet::Preprocess(Mat* mat, FDTensor* output) {
// 前处理逻辑
// 1. Resize 2. BGR2RGB 3. Normalize 4. HWC2CHW 5. 处理结果存入 FDTensor类中
return true;
}
bool ResNet::Postprocess(FDTensor& infer_result, ClassifyResult* result, int topk) {
//后处理逻辑
// 1. Softmax 2. Choose topk labels 3. 结果存入 ClassifyResult类
return true;
}
bool ResNet::Predict(cv::Mat* im, ClassifyResult* result, int topk) {
Preprocess(...)
Infer(...)
Postprocess(...)
return true;
}
vision.h
文件中加入新增模型文件
#ifdef ENABLE_VISION
#include "fastdeploy/vision/classification/contrib/resnet.h"
#endif
void BindResNet(pybind11::module& m) {
pybind11::class_<vision::classification::ResNet, FastDeployModel>(
m, "ResNet")
.def(pybind11::init<std::string, std::string, RuntimeOption, ModelFormat>())
.def("predict", ...)
.def_readwrite("size", &vision::classification::ResNet::size)
.def_readwrite("mean_vals", &vision::classification::ResNet::mean_vals)
.def_readwrite("std_vals", &vision::classification::ResNet::std_vals);
}
void BindResNet(pybind11::module& m);
void BindClassification(pybind11::module& m) {
auto classification_module =
m.def_submodule("classification", "Image classification models.");
BindResNet(classification_module);
}
resnet.py
文件
\_\_init\_\_
、Pybind绑定的函数(如predict()
)、以及对Pybind绑定的全局变量进行赋值和获取的函数
,具体代码请参考resnet.py。class ResNet(FastDeployModel):
def __init__(self, ...):
self._model = C.vision.classification.ResNet(...)
def predict(self, input_image, topk=1):
return self._model.predict(input_image, topk)
@property
def size(self):
return self._model.size
@size.setter
def size(self, wh):
...
from .contrib.resnet import ResNet
mkdir build & cd build
cmake .. -DENABLE_ORT_BACKEND=ON -DENABLE_VISION=ON -DCMAKE_INSTALL_PREFIX=${PWD/fastdeploy-0.0.3
-DENABLE_PADDLE_BACKEND=ON -DENABLE_TRT_BACKEND=ON -DWITH_GPU=ON -DTRT_DIRECTORY=/PATH/TO/TensorRT/
make -j8
make install
编译会得到 build/fastdeploy-0.0.3/。
export TRT_DIRECTORY=/PATH/TO/TensorRT/ # 如果用TensorRT 需要填写TensorRT所在位置,并开启 ENABLE_TRT_BACKEND
export ENABLE_TRT_BACKEND=ON
export WITH_GPU=ON
export ENABLE_PADDLE_BACKEND=ON
export ENABLE_OPENVINO_BACKEND=ON
export ENABLE_VISION=ON
export ENABLE_ORT_BACKEND=ON
python setup.py build
python setup.py bdist_wheel
cd dist
pip install fastdeploy_gpu_python-版本号-cpxx-cpxxm-系统架构.whl
.
├── cpp
│ ├── CMakeLists.txt
│ ├── infer.cc // C++ 版本测试代码
│ └── README.md // C++版本使用文档
├── python
│ ├── infer.py // Python 版本测试代码
│ └── README.md // Python版本使用文档
└── README.md // ResNet 模型集成说明文档
mkdir build & cd build
cmake .. -DFASTDEPLOY_INSTALL_DIR=/PATH/TO/FastDeploy/build/fastdeploy-0.0.3/
make
为了方便用户理解代码,我们需要为新增代码添加注释,添加注释方法可参考如下示例。
/** \brief Predict for the input "im", the result will be saved in "result".
*
* \param[in] im Input image for inference.
* \param[in] result Saving the inference result.
* \param[in] topk The length of return values, e.g., if topk==2, the result will include the 2 most possible class label for input image.
*/
virtual bool Predict(cv::Mat* im, ClassifyResult* result, int topk = 1);
/// Tuple of (width, height)
std::vector<int> size;
/*! @brief Initialize for ResNet model, assign values to the global variables and call InitRuntime()
*/
bool Initialize();
def predict(self, input_image, topk=1):
"""Classify an input image
:param input_image: (numpy.ndarray)The input image data, 3-D array with layout HWC, BGR format
:param topk: (int)The topk result by the classify confidence score, default 1
:return: ClassifyResult
"""
return self._model.predict(input_image, topk)
对于集成模型过程中的其他文件,您也可以对实现的细节添加适当的注释说明。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。