pytorch gpu推理、onnxruntime gpu推理、tensorrt gpu推理比较,及安装教程,有详细代码解释

需要下载的测试用的文件
测试图片:
https://upload.wikimedia.org/wikipedia/commons/2/26/YellowLabradorLooking_new.jpg -O dog.jpg
类别文件:
https://raw.githubusercontent.com/Lasagne/Recipes/master/examples/resnet50/imagenet_classes.txt
打包好的也可在这下载:
https://download.csdn.net/download/m0_59156726/88478676

1. pytorch 推理

模型直接使用torchvison里面自带的resnet50,
torchvison 参考 使用PyTorch中的预训练模型进行图像分类

直接看代码就可以了,简单明了。

import time
from torchvision import models, transforms
import torch
from PIL import Image

# 使用resnet50, torchvision 0.13及以后的新版本写法
resnet = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1)

# 加载类别
with open('imagenet_class/imagenet_class.txt') as f:
    classes = [line.strip() for line in f.readlines()]

device = torch.device("cuda:0")

# 加载到gpu
resnet.to(device)

# 推理模式
resnet.eval()

# 图像预处理
transform = transforms.Compose([
 transforms.Resize(256),
 transforms.CenterCrop(224),
 transforms.ToTensor(),
 transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
])

# 加载图片
img = Image.open("./imagenet_class/YellowLabradorLooking_new.jpg")

# 处理图片
img_t = transform(img)

# 加载到gpu
img_t = img_t.unsqueeze(0).to(device)

# 循环推理看耗时
for i in range(10):
    # infer, size(1,1000)
    t1 = time.time()
    out = resnet(img_t)
    t2 = time.time()
    print("time:", t2 - t1)
# size(1,1000)
out_sorted, indices = torch.sort(out, descending=True)
percentage = torch.nn.functional.softmax(out, dim=1)[0] * 100

# 前top5
top5_list = [(classes[idx], percentage[idx].item()) for idx in indices[0][:5]]

# 打印结果及gpu推理时间
print(top5_list)

结果:首次推理时间比较长,后面时间平均10ms,top1概率52.3%,能正确识别类别
在这里插入图片描述

2. onnxruntime gpu推理

2.1 环境准备

所有的nv gpu推理都需要使用到cuda cudnn
默认python已安装pytorch gpu版本,因为安装pytorch gpu环境的时候肯定选择cuda和cudnn的安装,如果你没安装,自己找一下安装的攻略,也就一行代码的事情,下面是官方提供的pytorch cuda11.8安装指令,参考:https://pytorch.org/
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

一般安装了pytorch,都会安装cuda和cudnn,查看一下版本即可
print(torch.version)
print(torch.version.cuda)
print(torch.backends.cudnn.version())

然后根据cuda版本下载安装适配的onnxruntime版本
pip install onnxruntime-gpu==xx.xx.xx
不出意外直接 pip install onnxruntime-gpu即可

2.2 模型转换

仍然拿resnet50举例

import time
from torchvision import models, transforms
import torch
from PIL import Image

# 使用resnet50, torchvision 0.13及以后的新版本写法
resnet_ = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1)

# 模型转换, 详细参数请自行查阅
input_shape = (1,3,224,224)
dummy_input = torch.randn(input_shape)
torch.onnx.export(resnet, dummy_input, "resnet50.onnx", verbose=True, opset_version=11, input_names=["input0"], output_names=["output0"])

2.3 onnxruntime 推理

with open('imagenet_class/imagenet_class.txt') as f:
    classes = [line.strip() for line in f.readlines()]

import onnxruntime as ort
# 构建providers
providers = [
    ('CUDAExecutionProvider', {
     'device_id': 0,
     'arena_extend_strategy': 'kNextPowerOfTwo',
     'gpu_mem_limit': 2 * 1024 * 1024 * 1024,
     'cudnn_conv_algo_search': 'EXHAUSTIVE',
     'do_copy_in_default_stream': True,
     }),
    'CPUExecutionProvider',
]

# 加载模型
ort_session = ort.InferenceSession("resnet50.onnx", providers=providers)

# 图像预处理
transform = transforms.Compose([
 transforms.Resize(256),
 transforms.CenterCrop(224),
 transforms.ToTensor(),
 transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
])

# 加载图片
img = Image.open("./imagenet_class/YellowLabradorLooking_new.jpg")

# 处理图片
img_t = transform(img)
img_numpy = img_t.numpy()[None,:]
for i in range(10):
    t1 = time.time()
    input_name = ort_session.get_inputs()[0].name

    # size(1,1000)
    out = ort_session.run(None, {input_name: img_numpy})[0]
    t2 = time.time()
    print("time:", t2 - t1)
# size(1,1000) 降序
out = torch.from_numpy(out)
out_sorted, indices = torch.sort(out, descending=True)
percentage = torch.nn.functional.softmax(out, dim=1)[0] * 100

# 前top5
top5_list = [(classes[idx], percentage[idx].item()) for idx in indices[0][:5]]

# 打印结果及gpu推理时间
print(top5_list)

结果:首次推理时间比较长,后面时间平均4ms左右,top1概率52.3%,能正确识别类别。类别识别精度跟pytorch没差,时间比pytorch快了6ms,还是比较快的
在这里插入图片描述

3. tensorrt 推理

3.1 安装准备

根据cuda对应版本下载tensorrt
https://developer.nvidia.com/nvidia-tensorrt-8x-download
详细安装教程参考,可以不用看,看下面的即可
https://blog.csdn.net/hjxu2016/article/details/122868139

我下载的是这个,因为我用的是cuda11.8版本
在这里插入图片描述
下载解压之后,把lib目录配置到环境变量中,以便程序能找到dll。
在这里插入图片描述
pip 安装
找到安装包解压后python的目录,可以看到里面有很多,具体解释
https://docs.nvidia.com/deeplearning/tensorrt/release-notes/index.html
在这里插入图片描述
在这里插入图片描述

接下来到该目录根据python版本直接安装:
pip install tensorrt-8.6.1-cp38-none-win_amd64.whl

显示成功后,检查安装是否正确

import tensorrt as trt

报错:提示找不到dll,可以博主已经配置了环境变量了啊,原因是因为博主配置环境变量后没有重开IDE,导致IDE没有加载新的环境变量。那就重开一下pycharm,没有报错,安装成功。
在这里插入图片描述

3.2 onnx 转tensorrt 模型

使用安装包里面的工具转换, 其他方法自行百度,为了方便也把这个目录加到环境变量中去。
在这里插入图片描述
执行一下命令转换, 这里给一个使用参考https://blog.csdn.net/qq_43673118/article/details/123547503,包括一下常用参数。特别说明一下默认精度是fp32
trtexec --onnx=resnet50.onnx --saveEngine=resnet_engine.trt

3.3 tensorrt 推理

官方的推理参考,这里面的API有些老的,会有告警
https://github.com/NVIDIA/TensorRT/blob/main/quickstart/SemanticSegmentation/tutorial-runtime.ipynb
要用到cuda driver 安装一下
pip install pycuda
写一下自己的推理
API参考:
https://docs.nvidia.com/deeplearning/tensorrt/api/python_api/infer/Core/Engine.html

import numpy as np
import tensorrt as trt
import pycuda.driver as cuda
import pycuda.autoinit
import time


# 加载tensort 构建runtime
def load_engine(engine_file_path):
    with open(engine_file_path, "rb") as f, trt.Runtime(trt.Logger(trt.Logger.WARNING)) as runtime:
        return runtime.deserialize_cuda_engine(f.read())


# 图片预处理

def preprocess(input_file):
    # 图像预处理
    transform = transforms.Compose([
     transforms.Resize(256),
     transforms.CenterCrop(224),
     transforms.ToTensor(),
     transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
    ])

    # 加载图片
    img = Image.open(input_file)

    # 处理图片
    img_t = transform(img)

    # NCHW (1,3,244,244)
    return img_t.numpy()[None,:]


def infer(engine, input_file):
    input_image = preprocess(input_file)
    t1 = time.time()
    with engine.create_execution_context() as context:

        # 根据输入设置输入的size, 因为只有一个输入,因此只需设置一个即可。这里可以不用设置,
        # 由于我们onnx转换的不是动态shape,而是固定1,3,224,224。所以获得的shape必定是(1,3,224,224)这里只是展示set的用法
        # input0_shape = context.get_tensor_shape("input0")
        # 老API context.set_binding_shape(engine.get_binding_index("input"), img.size())
        context.set_input_shape("input0", input_image.shape)

        # Allocate host and device buffers, 分配内存 cpu gpu 内存
        bindings = []
        # 遍历输入输出
        for binding in engine:
            # binding_idx = engine.get_binding_index(binding)
            size = trt.volume(context.get_tensor_shape(binding))  # 1 * 3 * 224 * 224
            dtype = trt.nptype(engine.get_tensor_dtype(binding))  # 1 * 3 * 224 * 224

            # 老API engine.binding_is_input(binding)
            if engine.get_tensor_mode(binding) == trt.TensorIOMode.INPUT:
                input_buffer = np.ascontiguousarray(input_image)
                input_memory = cuda.mem_alloc(input_image.nbytes)
                bindings.append(int(input_memory))
            else:
                output_buffer = cuda.pagelocked_empty(size, dtype)
                output_memory = cuda.mem_alloc(output_buffer.nbytes)
                bindings.append(int(output_memory))

        # stream
        stream = cuda.Stream()

        # Transfer input data from CPU to the GPU.
        cuda.memcpy_htod_async(input_memory, input_buffer, stream)
        # Run inference
        context.execute_async_v2(bindings=bindings, stream_handle=stream.handle)

        # Transfer prediction output from GPU to CPU.
        cuda.memcpy_dtoh_async(output_buffer, output_memory, stream)
        # Synchronize the stream
        stream.synchronize()

    t2 = time.time()
    # 打印top5推理结果
    with open('imagenet_class/imagenet_class.txt') as f:
        classes = [line.strip() for line in f.readlines()]
        out = torch.from_numpy(output_buffer)
        out_sorted, indices = torch.sort(out, descending=True)
        percentage = torch.nn.functional.softmax(out, dim=0) * 100

        # 前top5
        top5_list = [(classes[idx], percentage[idx].item()) for idx in indices[:5]]

        # 打印结果及gpu推理时间
        print("time: ", t2 - t1)
        print(top5_list)
def run():

    engine_file_path = "resnet_engine.trt"
    input_file = "./imagenet_class/YellowLabradorLooking_new.jpg"
    class_txt = "./imagenet_class/imagenet_class.txt"

    engine = load_engine(engine_file_path)
    for i in range(10):
        infer(engine, input_file)

run()

结果比onnx差不多,看来tensorrt还是有优势的,这只是一个小模型,想必在其他模型上更有优势
在这里插入图片描述

PyTorch 是一个开源的深度学习框架,可以用于构建、训练和推理神经网络模型。推理是指使用已经训练好的模型对新的数据进行预测或分类。而置信度是指模型对预测结果的自信程度。 在 PyTorch 中,要获取推理中的置信度,一种常见的方法是使用softmax 函数。softmax 函数将模型的输出转化为概率分布,它可以将原始输出转化为在 [0, 1] 范围内的概率,且所有概率的和为 1。 对于分类任务,通常将模型的输出经过 softmax 函数,然后选取具有最大概率的类别作为预测结果。此时,可以直接使用 softmax 输出作为置信度。例如,如果模型对某个类别的输出为 0.7,则可以认为模型对该类别有 70% 的置信度。 另一种常见的方法是使用 softmax 输出中的最大概率值作为置信度,并设置一个阈值来进一步判断模型的置信度。如果最大概率超过阈值,则可以认为模型有足够的置信度进行预测;否则,可以认为模型对预测结果不够自信。 除了 softmax 外,还可以使用其他方法来获取置信度,例如,对输出结果进行后处理、使用置信度评估指标等。具体方法需要根据具体的模型和应用场景来选择。 综上所述,PyTorch 推理中的置信度获取可以使用 softmax 函数将模型的输出转化为概率分布,并将最大概率或 softmax 输出作为置信度。同时,可以根据实际需求选择不同的方法和阈值来获取更准确的置信度信息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

idealmu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值