Processus de déploiement du modèle PyTorch (ONNX Runtime)

Le déploiement de modèle fait référence au processus d'exécution d'un modèle d'apprentissage en profondeur formé dans un environnement spécifique. Difficultés rencontrées par le déploiement du modèle :

  • L'environnement requis pour exécuter le modèle est difficile à configurer. Les modèles d'apprentissage en profondeur sont généralement écrits par certains frameworks, tels que PyTorch et TensorFlow. En raison des limites de la taille du framework et de l'environnement dépendant, le framework n'est pas adapté à une installation dans des environnements de production tels que les téléphones mobiles et les cartes de développement.
  • La structure du modèle d'apprentissage en profondeur est généralement relativement grande, nécessitant une grande quantité de puissance de calcul pour répondre aux exigences de fonctionnement en temps réel, et l'efficacité du fonctionnement doit être optimisée.

En raison de ces difficultés, le déploiement du modèle ne peut pas être réalisé par une simple configuration et installation de l'environnement. Il existe actuellement un pipeline populaire pour le déploiement de modèles :

        Pour que le modèle soit finalement déployé dans un certain environnement, n'importe quel cadre d'apprentissage en profondeur peut être utilisé pour définir la structure du réseau, et les paramètres du réseau peuvent être déterminés par la formation. Après cela, la structure et les paramètres du modèle seront convertis en une représentation intermédiaire qui ne décrit que la structure du réseau, et certaines optimisations de la structure du réseau seront effectuées sur la représentation intermédiaire. Enfin, écrit dans un cadre de programmation haute performance orienté matériel (tel que CUDA, OpenCL), le moteur d'inférence qui peut exécuter efficacement les opérateurs dans le réseau d'apprentissage en profondeur convertira la représentation intermédiaire dans un format de fichier spécifique et exécutera le modèle. efficacement sur la plate-forme matérielle correspondante.

Créer un modèle PyTorch

a. Environnement de configuration

#Créez un environnement virtuel appelé deploy avec Python 3.7 préinstallé
conda create -n deploy python=3.7 -y
# Entrez dans l'environnement virtuel
conda activate deploy
# Installez la version Gpu de PyTorch
# Sélectionnez la configuration appropriée sur le site officiel et copiez le chemin de téléchargement --- https://pytorch.org/get-started/locally/
cconda install pytorch torchvision cudatoolkit=11.3 -c pytorch
# Install ONNX Runtime, ONNX, OpenCV
pip install onnxruntime onnx opencv-python

b. Créer un modèle PyTorch

import os

import cv2
import numpy as np
import requests
import torch
import torch.onnx
from torch import nn

class SuperResolutionNet(nn.Module):
    def __init__(self, upscale_factor):
        super().__init__()
        self.upscale_factor = upscale_factor
        self. img_upsampler = nn.Upsample(
            scale_factor=self.upscale_factor,
            mode='bicubic',
            align_corners=False)

        self.conv1 = nn.Conv2d(3,64,kernel_size=9,padding=4)
        self.conv2 = nn.Conv2d( 64,32,kernel_size=1,padding=0)
        self.conv3 = nn.Conv2d(32,3,kernel_size=5,padding=2)

        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.img_upsampler(x)
        out = self.relu(self.conv1(x))
        out = self.relu(self.conv2(out) )
        out = self.conv3(out)
        return out

# Téléchargez
les URL des points de contrôle et des images de test = ['https://download.openmmlab.com/mmediting/restorers/srcnn/srcnn_x4k915_1x16_1000k_div2k_20200608-4186f232.pth',
        'https://raw .githubusercontent.com/open-mmlab/mmediting/master/tests/data/face/000001.png']
names = ['srcnn.pth', 'face.png']
pour url, nom dans zip (urls, noms) :
    sinon os.path.exists(name):
        open(name, 'wb').write(requests.get(url).contenu)

def init_torch_model() :
    torch_model = SuperResolutionNet(upscale_factor=3)

    state_dict = torch.load('srcnn.pth')['state_dict']

    # Adaptez le point de contrôle
    pour old_key dans list(state_dict.keys()):
        new_key = '.'.join(old_key .split('.')[1:])
        state_dict[new_key] = state_dict.pop(old_key)

    torch_model.load_state_dict(state_dict)
    torch_model.eval()
    return torch_model

model = init_torch_model()
input_img = cv2.imread('face. png').astype(np.float32)

# HWC à NCHW
input_img = np.transpose(input_img, [2, 0, 1])
input_img = np.expand_dims(input_img, 0)

# Inférence
torch_output = model(torch.from_numpy( input_img)).detach().numpy()

# NCHW à HWC
torch_output = np.squeeze(torch_output, 0)
torch_output = np.clip(torch_output, 0, 255)
torch_output = np.transpose(torch_output, [1, 2, 0]).astype(np.uint8)

# Afficher l'image
cv2.imwrite("face_torch.png", torch_output)

Le code crée un réseau de super-résolution classique SRCNN . SRCNN suréchantillonne d'abord l'image à la résolution correspondante, puis traite l'image avec 3 couches convolutionnelles. Si le script s'exécute normalement, une photo super-résolution du visage sera enregistrée dans face_torch.png .

Une fois le modèle PyTorch correctement testé, commençons officiellement à déployer le modèle. Notre tâche suivante consiste à convertir le modèle PyTorch en un modèle décrit par la représentation intermédiaire ONNX.

c. Convertir le modèle PyTorch en un modèle décrit par ONNX

ONNX (Open Neural Network Exchange) est un format publié conjointement par Facebook et Microsoft en 2017 pour les descriptions standard des graphes de calcul. À l'heure actuelle, sous la maintenance conjointe de plusieurs institutions, ONNX s'est amarré à divers cadres d'apprentissage en profondeur et à divers moteurs d'inférence. Par conséquent, ONNX est considéré comme un pont entre le cadre d'apprentissage en profondeur et le moteur d'inférence, tout comme le langage intermédiaire du compilateur. En raison de la compatibilité différente des différents frameworks, ONNX n'est généralement utilisé que pour représenter des graphiques statiques plus faciles à déployer.

#  PyTorch 的模型转换成 ONNX 格式的模型
x = torch.randn(1, 3, 256, 256)

with torch.no_grad():
    torch.onnx.export(
        model,
        x,
        "srcnn.onnx",
        opset_version=11,
        input_names=['input'],
        output_names=['output'])

其中torch.onnx.export 是 PyTorch 自带的把模型转换成 ONNX 格式的函数。前三个参数分别是要转换的模型、模型的任意一组输入、导出的 ONNX 文件的文件名。

从 PyTorch 的模型到 ONNX 的模型,PyTorch提供了一种叫做追踪(trace)的模型转换方法:给定一组输入,再实际执行一遍模型,即把这组输入对应的计算图记录下来,保存为 ONNX 格式。export 函数用的就是追踪导出方法,需要给任意一组输入,让模型跑起来。测试图片是三通道256x256 大小的,这里也构造一个同样形状的随机张量。

opset_version 表示 ONNX 算子集的版本。input_names, output_names 是输入、输出 tensor 的名称。代码运行成功,目录下会新增一个 srcnn.onnx 的 ONNX 模型文件

# 验证模型文件是否正确,直接加在前面的代码后面就行
import onnx

onnx_model = onnx.load("srcnn.onnx")
try:
    onnx.checker.check_model(onnx_model)
except Exception:
    print("Model incorrect")
else:
    print("Model correct")

d.ONNX Runtime上运行模型和推理

推理引擎-ONNX Runtime 是由微软维护的一个跨平台机器学习推理加速器。ONNX Runtime 是直接对接ONNX的,即ONNX Runtime可以直接读取并运行.onnx文件,而不需要再把.onnx格式的文件转换成其他格式的文件。也就是说,对于 PyTorch - ONNX - ONNX Runtime 这条部署流水线,只要在目标设备中得到 .onnx 文件,并在 ONNX Runtime 上运行模型,模型部署就算大功告成了。

ONNX Runtime 提供了 Python 接口。

# ONNX Runtime完成模型推理,还是在之前脚本后添加代码
import onnxruntime

ort_session = onnxruntime.InferenceSession("srcnn.onnx")
ort_inputs = {'input': input_img}
ort_output = ort_session.run(['output'], ort_inputs)[0]

ort_output = np.squeeze(ort_output, 0)
ort_output = np.clip(ort_output, 0, 255)
ort_output = np.transpose(ort_output, [1, 2, 0]).astype(np.uint8)
cv2.imwrite("face_ort.png", ort_output)

onnxruntime.InferenceSession 用于获取一个 ONNX Runtime 推理器,其参数是用于推理的 ONNX 模型文件。推理器的 run 方法用于模型推理,其第一个参数为输出张量名的列表,第二个参数为输入值的字典。其中输入值字典的 key 为张量名,value 为 numpy 类型的张量值。输入输出张量的名称需要和 torch.onnx.export 中设置的输入输出名对应。

如果代码正常运行的话,另一幅超分辨率照片会保存在 face_ort.png 中。这幅图片和刚刚得到的 face_torch.png 是一样的。即ONNX Runtime 成功运行了 SRCNN 模型,完成模型部署。

以后再想实现超分辨率的操作,只需要提供一个srcnn.onnx文件,并帮助用户配置好 ONNX Runtime 的 Python 环境,用几行代码就可以运行模型。或者可以利用 ONNX Runtime 编译出一个可以直接执行模型的应用程序。只需给用户提供 ONNX 模型文件,并让用户在应用程序选择要执行的 ONNX 模型文件名就可以运行模型了。

Je suppose que tu aimes

Origine blog.csdn.net/xs1997/article/details/131747242
conseillé
Classement