当前位置: 首页>数据库>正文

深度学习模型怎么部署?

深度学习模型怎么部署?,第1张

我们在构建完成深度学习的模型之后,往往需要将模型部署到我们需要的设备上,例如:电脑、手机、边缘设备等

一、通常部署的设备

  • PC/服务端:pytorch/C++
  • 手机端(Android/IOS):NCNN框架(CPU推理)、tflite
  • IOT设备:NVIDIA JETSON 系列(Linux,tensorRT)、瑞芯微(Android)、海思(鸿蒙)
  • HTTP部署:Flask + pytorch/C++

模型推理框架之间的转换(pytorch / tensorflow):onnx

二、模型部署方案

一个模型格式转换的网站:一键转换 Caffe, ONNX, TensorFlow 到 NCNN, MNN, Tengine (convertmodel.com)

(1) torchscript ——让其他语言调用pytorch模型。

那么python语言编写的代码怎么被其它语言调用呢?我们需要将模型转换成torchScript的格式。这里以C++为例,官方教程:Loading a TorchScript Model in C++ — PyTorch Tutorials 2.0.1+cu117 documentation

深度学习模型怎么部署?,第2张

网站中有详细的教程(这里仅将代码搬运过来):

  • step1: 打包模型
import torch
import torchvision

# An instance of your model.
model = torchvision.models.resnet18()

# An example input you would normally provide to your model's forward() method.
example = torch.rand(1, 3, 224, 224)

# Use torch.jit.trace to generate a torch.jit.ScriptModule via tracing.
traced_script_module = torch.jit.trace(model, example)

打包自定义模型

class MyModule(torch.nn.Module):
    def __init__(self, N, M):
        super(MyModule, self).__init__()
        self.weight = torch.nn.Parameter(torch.rand(N, M))

    def forward(self, input):
        if input.sum() > 0:
          output = self.weight.mv(input)
        else:
          output = self.weight + input
        return output

my_module = MyModule(10,20)
sm = torch.jit.script(my_module)
  • step2:保存模型文件
traced_script_module.save("traced_resnet_model.pt")
  • step3:在C++程序中使用模型
#include <torch/script.h> // One-stop header.

#include <iostream>
#include <memory>

int main(int argc, const char* argv[]) {
  if (argc != 2) {
    std::cerr << "usage: example-app <path-to-exported-script-module>\n";
    return -1;
  }


  torch::jit::script::Module module;
  try {
    // Deserialize the ScriptModule from a file using torch::jit::load().
    module = torch::jit::load(argv[1]);
  }
  catch (const c10::Error& e) {
    std::cerr << "error loading the model\n";
    return -1;
  }

  std::cout << "ok\n";
}
(2) 将模型部署到安卓或IOS设备上

官网给出的解决方案:Android | PyTorch
、iOS | PyTorch

  • step1: 模型准备
import torch
import torchvision
from torch.utils.mobile_optimizer import optimize_for_mobile

model = torchvision.models.mobilenet_v2(pretrained=True)
model.eval()
example = torch.rand(1, 3, 224, 224)
traced_script_module = torch.jit.trace(model, example)
traced_script_module_optimized = optimize_for_mobile(traced_script_module)
traced_script_module_optimized._save_for_lite_interpreter("app/src/main/assets/model.ptl")
  • step2: 从Git上下载安卓示例APP
git clone https://github.com/pytorch/android-demo-app.git
cd HelloWorldApp

详细教程见官网

(3)ncnn 框架

ncnn是腾讯开发的一个为手机端极致优化的高性能神经网络前向计算框架,无第三方依赖,跨平台。ncnn目前已在腾讯多款应用中使用,如 QQ,Qzone,微信,天天P图等。ncnn主要基于C++和caffe,ncnn项目地址见:https://github.com/Tencent/ncnn。ncnn是使用CPU进行推理,其支持超多操作平台、并支持大部分的CNN网络,非常值得试试。

深度学习模型怎么部署?,第3张
深度学习模型怎么部署?,第4张
(4)onnx

ONNX 是一种基于numpy的用于表示机器学习的开放格式 模型。ONNX 定义了一组通用运算符(机器学习和深度学习模型的构建基块)和通用文件格式,使 AI 开发人员能够使用具有各种框架、工具、运行时和编译器的模型。其支持大部分神经网络框架。

  • 我们使用onnx进行不同模型之间的转换时,模型的精度会有一定的下降。

如何将pytorch打包成onnx格式?
首先需要安装onnx和onnxruntime
onnx安装命令:pip install onnx
onnx-cpu安装命令:pip install onnxruntime
onnx-gpu安装命令:pip install onnxruntime-gpu这里需要注意版本问题,官方参考:NVIDIA - CUDA | onnxruntime

转换仅需一行代码:

torch.onnx.export(model, args, f, export_params=True, verbose=False, input_names=None, 
output_names=None,do_constant_folding=True,dynamic_axes=None,opset_version=9)
  • 常用参数:
    1. model:torch.nn.model 要导出的模型
    2. args:tuple or tensor 模型的输入参数。注意tuple的最后参数为dict要小心,详见pytorch文档。输入参数只需满足shape正确,为什么要输入参数呢?因为后面torch.jit.trace要用到,先按下不表。
    3. f:file object or string 转换输出的模型的位置,如'yolov4.onnx'
    4. export_params:bool,default=True,true表示导出trained model,false则untrained model。默认即可
    5. verbose:bool,default=False,true表示打印调试信息
    6. input_names:list of string,default=None,指定输入节点名称
    7. output_names:list of string,default=None,指定输出节点名称
    8. do_constant_folding:bool,default=True,是否使用常量折叠,默认即可
    9. dynamic_axes:dict<string, dict<int, string>> or dict<string, list(int)>,default=None,有时模型的输入输出是可变的,如RNN,或者输入输出图片的batch是可变的,这时我们通过dynamic_axes来指定输入tensor的哪些参数可变。
    10. opset_version:int,default=9,指定onnx的opset版本,版本过低的话,不支持upsample等操作。

举个例子:

import torch 
from torch import nn 
from torchvision.models import resnet18

model = resnet18()
model.eval()

x = torch.randn((1,3,224,224),  requires_grad=True)

input_name = ["input"]
output_name = ["output"]

torch.onnx.export(model, x, "./resnet18.onnx", input_names=input_name, output_names=output_name, verbose=False)

转换完之后,检查并运行onnx模型。

import onnxruntime as ort 
import torch 
import onnx 
import numpy as np 

# 加载模型
model = onnx.load("./resnet18.onnx")
# 检查模型
onnx.checker.check_model(model)

# 1. 开启会话
session = ort.InferenceSession("./resnet18.onnx")
x = np.random.randn(1,3,224,224).astype(np.float32) # 输入的类型必须是numpy float32 

outputs = session.run(None, input_feed={"input" : x})
print(len(outputs[0][0]))

需要进行精度验证,如果精度不达标,则可能需要进行精度对齐:

import torch 
from torch import nn 
from torchvision.models import resnet18
from torchvision.models import ResNet18_Weights
import onnxruntime as ort 
import onnx 
import numpy as np 

# 构建模型,并载入权重向量
model1 = resnet18(weights = ResNet18_Weights.IMAGENET1K_V1)
model1.eval()

x1 = torch.randn((1,3,224,224),  requires_grad=True)
x2 = x1.detach().numpy().astype(np.float32)

input_name = ["input"]
output_name = ["output"]

# 保存模型
torch.onnx.export(model1, x1, "./resnet18.onnx", input_names=input_name, output_names=output_name, verbose=False)

# 加载模型
model2 = onnx.load("./resnet18.onnx")
# 检查模型
onnx.checker.check_model(model2)

# 开启会话
session = ort.InferenceSession("./resnet18.onnx")

output1 = model1(x1)
output2 = session.run(None, input_feed={"input" : x2})
print("torch: ", output1[0][0].item())
print("onnx: ", output2[0][0][0])

https://www.xamrdz.com/database/6wc1877609.html

相关文章: