如何将PyTorch模型保存为无需PyTorch依赖的形式或编译为库?
有多种方法可以实现PyTorch模型脱离PyTorch依赖进行推理,以下是几种实用方案:
方案1:导出为ONNX格式,基于ONNX Runtime构建推理库
ONNX是跨框架的模型标准格式,ONNX Runtime是轻量独立的推理引擎,完全不依赖PyTorch,适合低依赖场景。
训练阶段导出ONNX模型
修改训练代码,将训练完成的PyTorch模型转换为ONNX格式:
import torch import torch.nn as nn # 假设model是训练好的模型实例 model = ... # 替换为你的模型对象 model.eval() # 构造与模型输入维度匹配的示例张量(用于确定导出时的输入形状) dummy_input = torch.randn(1, 3, 224, 224) # 根据你的模型输入维度调整 # 导出ONNX模型 torch.onnx.export( model, dummy_input, "MLmodel.onnx", opset_version=17, # 根据模型算子选择兼容的opset版本 input_names=["input"], output_names=["output"], dynamic_axes={"input": {0: "batch_size"}, "output": {0: "batch_size"}} # 支持动态batch时添加 )
推理阶段:用ONNX Runtime + PyBind11构建动态库
编写C++代码实现推理逻辑,通过PyBind11暴露predict接口供Python调用:
#include <pybind11/pybind11.h> #include <pybind11/numpy.h> #include <onnxruntime/core/session/onnxruntime_cxx_api.h> namespace py = pybind11; class MLModel { private: Ort::Env env; Ort::Session session; Ort::AllocatorWithDefaultOptions allocator; const char* input_names[1] = {"input"}; const char* output_names[1] = {"output"}; public: MLModel(const std::string& model_path) : env(ORT_LOGGING_LEVEL_WARNING, "MLModel"), session(env, model_path.c_str(), Ort::SessionOptions{nullptr}) {} py::array_t<float> predict(py::array_t<float>& input_array) { // 解析输入numpy数组 auto input_info = input_array.request(); float* input_data = static_cast<float*>(input_info.ptr); std::vector<int64_t> input_shape(input_info.shape, input_info.shape + input_info.ndim); // 创建ONNX Runtime输入张量 auto input_tensor = Ort::Value::CreateTensor<float>( allocator, input_data, input_array.size(), input_shape.data(), input_shape.size() ); // 执行推理 auto output_tensors = session.Run( Ort::RunOptions{nullptr}, input_names, &input_tensor, 1, output_names, 1 ); // 解析输出张量并转换为numpy数组返回 float* output_data = output_tensors[0].GetTensorMutableData<float>(); auto output_shape = output_tensors[0].GetTensorTypeAndShapeInfo().GetShape(); return py::array_t<float>(output_shape, output_data); } }; PYBIND11_MODULE(MLmodel, m) { py::class_<MLModel>(m, "MLModel") .def(py::init<const std::string&>()) .def("predict", &MLModel::predict); }
编译命令(示例,需根据环境调整路径)
g++ -O3 -shared -std=c++17 -fPIC `python3 -m pybind11 --includes` mlmodel.cpp -o MLmodel`python3-config --extension-suffix` -I/你的onnxruntime/include路径 -L/你的onnxruntime/lib路径 -lonnxruntime
方案2:导出TorchScript模型,编译为依赖LibTorch轻量版的动态库
LibTorch是PyTorch的C++运行时,支持静态链接,可将依赖打包进库中,无需用户单独安装PyTorch,适合对模型兼容性要求高的场景。
训练阶段导出TorchScript模型
import torch import torch.nn as nn model = ... # 训练好的模型实例 model.eval() # 方式1:Trace导出(适合无动态控制流的模型) dummy_input = torch.randn(1, 3, 224, 224) traced_model = torch.jit.trace(model, dummy_input) traced_model.save("MLmodel.pt") # 方式2:Script导出(适合含if/for等动态控制流的模型) # scripted_model = torch.jit.script(model) # scripted_model.save("MLmodel.pt")
推理阶段:用LibTorch + PyBind11构建动态库
#include <pybind11/pybind11.h> #include <pybind11/numpy.h> #include <torch/script.h> namespace py = pybind11; class MLModel { private: torch::jit::script::Module module; public: MLModel(const std::string& model_path) { module = torch::jit::load(model_path); module.to(torch::kCPU); // 根据需求选择设备,如torch::kCUDA module.eval(); } py::array_t<float> predict(py::array_t<float>& input_array) { // 将numpy数组转换为torch张量 auto input_info = input_array.request(); torch::Tensor input_tensor = torch::from_blob( input_info.ptr, std::vector<int64_t>(input_info.shape, input_info.shape + input_info.ndim), torch::kFloat32 ).to(torch::kCPU); // 执行推理(禁用梯度计算) torch::NoGradGuard no_grad; auto output_tensor = module.forward({input_tensor}).toTensor(); // 转换为numpy数组返回 return py::array_t<float>( output_tensor.sizes().vec(), output_tensor.strides().vec(), output_tensor.data_ptr<float>() ); } }; PYBIND11_MODULE(MLmodel, m) { py::class_<MLModel>(m, "MLModel") .def(py::init<const std::string&>()) .def("predict", &MLModel::predict); }
编译命令(静态链接LibTorch示例)
下载LibTorch轻量静态版后执行:
g++ -O3 -shared -std=c++17 -fPIC `python3 -m pybind11 --includes` mlmodel.cpp -o MLmodel`python3-config --extension-suffix` -I/你的libtorch/include路径 -I/你的libtorch/include/torch/csrc/api/include -L/你的libtorch/lib路径 -ltorch -ltorch_cpu -lc10 -pthread
方案3:编译为纯C静态库(完全脱离框架依赖)
通过onnx2c工具将ONNX模型转换为纯C代码,再编译为静态库,完全不依赖任何ML框架,适合极端轻量的嵌入式或小型软件场景(部分复杂算子可能不支持)。
- 先按方案1将PyTorch模型导出为ONNX格式
- 用onnx2c转换为C代码:
onnx2c MLmodel.onnx > mlmodel.c
- 编写PyBind11封装代码调用生成的C推理函数,编译为动态库即可。
内容的提问来源于stack exchange,提问作者Chenxin
相关产品推荐
相关产品推荐

