1.1 模型部署
- 训练好的模型在特定软硬件平台下推理
- 针对硬件优化和加速的推理代码
1.2 推理流程
训练框架:PyTorch、Keras、TensorFlow、MXNet训练 --> 中间表示:ONNX模型文件 --> 推理框架:TensorRT、ONNX RUNTIME、OpenVINO --> 硬件芯片:NVIDIA、Inter、Qualcomm、Apple、Huawei
1.3 ONNX 与 ONNX RUNTIME
- onnx runtime 是一个开源的高性能推理引擎,用于运行onnx 模型。
- onnx是一个开放的机器学习模型。
- onnx runtime 提供了统一的API,可以在不同的硬件和操作系统上高效运行基于onnx格式的模型。
########例子########
# 对 onnx 模型使用 onnxruntime 框架推理
ort_session=onnxruntime.InferenceSession('best.onnx',providers=['CUDAExecutionProvider','CPUExecutionProvider'])
x=torch.randn(1,3,640,640).numpy()
ort_inputs={'images':x}
ort_output=ort_session.run(['output0'],ort_inputs)[0]
print(ort_output.shape)
########例子########
1.4 YOLOv8 使用 ONNX RUNTIME 推理步骤
- Pytorch 训练了 YOLOv8.pt
- 将 pt 文件转为 onnx 文件
# 将 pt 模型文件转换为 onnx 模型文件
model=YOLO('best.pt')
model.export(format='onnx')
- 载入onnx模型,获取onnx runtime 推理器
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'
import cv2
import numpy as np
from PIL import Image
import onnxruntime
from ultralytics.utils import ops
import torch
import matplotlib.pyplot as plt
device=torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
ort_session=onnxruntime.InferenceSession(r'.\weights\best.onnx',providers=['CUDAExecutionProvider','CPUExecutionProvider'])
###########获取onnx模型输入层和数据维度############
model_input=ort_session.get_inputs()
input_name=model_input[0].name
# print(input_name) # images
model_output=ort_session.get_outputs()
output_name=model_output[0].name
# print(output_name) #output0
input_shape=model_input[0].shape
# print(input_shape) # 1, 3, 640, 640
input_height, input_width=input_shape[2:] # 640, 640
output_shape=model_output[0].shape
# print(output_shape) # 1, 37, 8400
###########获取onnx模型输入层和数据维度############
########预测图像########
image_path=r'68.jpg'
img_bgr=cv2.imread(image_path)
img_bgr=cv2.resize(img_bgr,[input_height,input_width]) # 640, 640, 3
img_rgb = img_bgr[:, :, ::-1]
# 预处理-构造输入张量
input_tensor=img_rgb/255 # 640, 640, 3
input_tensor=np.expand_dims(input_tensor,axis=0) # 1, 640, 640, 3
input_tensor=input_tensor.transpose((0, 3, 1, 2)) # 1 3 640 640
input_tensor=np.ascontiguousarray(input_tensor) # 将内存不连续存储的数组转为连续存储,提高访问速度
input_tensor=torch.from_numpy(input_tensor).to(device).float() # 转为tensor向量 <class 'torch.Tensor'>
# 推理
ort_output=ort_session.run([output_name],{input_name:input_tensor.cpu().numpy()})[0]
preds=torch.Tensor(ort_output) # torch.Size([1, 37, 8400]) 37=1个类别+32个mask+4个box信息
# 后处理
preds=ops.non_max_suppression(preds, conf_thres=0.25, iou_thres=0.7, nc=1) # 1, 38
# ...没写完 后面不知道怎么操作了