第二步:pytorch模型转onnx模型步骤和可能遇到的问题

一、环境

本地(win10):cuda11.0 + python3.7.4 + pytorch1.7.1 + onnx1.9.0
服务器(Ubuntu18.04):cuda11.0 + python3.7.6 + pytorch1.7.1 + tensorrt8.0.0.3

二、可能出现的问题

1. pytorch与tensorrt版本对应问题

将pytorch1.7.1的模型降至1.5.0以下版本,再转为onnx模型。以efficientnet_b1为例:

import torch
import configs
import sys
sys.path.append('face_classify')
from timm.models.factory import create_model
from collections import OrderedDict

def torch_2_onnx(model, MODEL_ONNX_PATH):
    OPERATOR_EXPORT_TYPE = torch._C._onnx.OperatorExportTypes.ONNX
    """
    这里构建网络的输入,有几个就构建几个
    和网络正常的inference时输入一致就可以
    """
    device = 'cpu'
    org_dummy_input = torch.randn(8, 3, 240, 240, device=device)

    # 这是支持动态输入和输出的第一步
    # 每一个输入和输出中动态的维度都要在此注明,下标从0开始
    # 注意:1通道channels不能动态输入,所以没有1
    dynamic_axes = {
        'inputs': {0: 'batch_size', 2: 'height', 3: 'width'},
        'outputs': {0: 'batch_size', 1: 'class'},
    }
    output = torch.onnx.export(model,
                               org_dummy_input,
                               MODEL_ONNX_PATH,
                               verbose=True,
                               opset_version=12,
                               operator_export_type=OPERATOR_EXPORT_TYPE,
                               input_names=['inputs'],
                               output_names=['outputs'],
                               dynamic_axes=dynamic_axes
                               )
    print("Export of model to {}".format(MODEL_ONNX_PATH))

model = create_model(
            model_name=configs.model_name,
            num_classes=configs.num_classes,
            in_chans=configs.in_chans,
            checkpoint_path=configs.face_classify_model)

# 必须使用cpu,否则最后一步torch.onnx.export会报错
device = 'cpu'

# 读取1.7版pytorch权重。根据自己权重文件格式读取参数
checkpoint = torch.load(r'/path/to/efficientnet_b1.pth.tar',
                        map_location=device)
state_dict_key = 'state_dict'
if state_dict_key and state_dict_key in checkpoint:
    new_state_dict = OrderedDict()
    for k, v in checkpoint[state_dict_key].items():
        name = k[7:] if k.startswith('module') else k
        new_state_dict[name] = v
    state_dict = new_state_dict
else:
    state_dict = checkpoint
model.load_state_dict(state_dict)

# 保存成1.4版本的pytorch模型
torch.save(model.state_dict(), 'onnx_weights/for_onnx_eff_b1.pth', _use_new_zipfile_serialization=False)

# 重新读取,导出pytorch1.4版本对应的onnx
state_dict = torch.load('onnx_weights/for_onnx_eff_b1.pth', map_location=device)
model.load_state_dict(state_dict)
model.train(False)

model_onnx_path = 'efficientnet_b1.onnx'
torch_2_onnx(model, model_onnx_path)

运行后即可生成efficientnet_b1.onnx,在后续导入tensorrt时可直接使用。

2. onnx与pytorch的一些方法不兼容

最后一步转换报错:RuntimeError: Exporting the operator silu to ONNX opset version 9 is not supported. Please open a bug to request ONNX export support for the missing operator. 原因是onnx不支持silu,解决方法是找到源码位置,换一种写法。源码位置:D:\apps\anaconda3\envs\python3.7\Lib\site-packages\torch\nn\modules\activation.py
原代码:

class SiLU(Module):

    __constants__ = ['inplace']
    inplace: bool

    def __init__(self, inplace: bool = False):
        super(SiLU, self).__init__()
        self.inplace = inplace

    def forward(self, input: Tensor) -> Tensor:
        # ------------------------------------- #
        return F.silu(input, inplace=self.inplace)

修改之后:

class SiLU(Module):

    __constants__ = ['inplace']
    inplace: bool

    def __init__(self, inplace: bool = False):
        super(SiLU, self).__init__()
        self.inplace = inplace

    def forward(self, input: Tensor) -> Tensor:
        # 把F.silu替换掉
        return input * torch.sigmoid(input)
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
要使用PyTorch检测ONNX模型的精度,您可以按照以下步骤进行操作: 1. 导入必要的库: ```python import torch import torchvision.transforms as transforms from torch.utils.data import DataLoader ``` 2. 加载测试数据集:根据您的任务和数据集,使用PyTorch的数据加载加载测试数据集。 3. 加载ONNX模型:使用PyTorch的`torch.onnx`模块加载ONNX模型。 ```python model = torch.onnx.load("your_model.onnx") ``` 4. 设置评估模式:将模型设置为评估模式。 ```python model.eval() ``` 5. 定义评估指标:根据您的任务和模型类型,定义适当的评估指标。例如,对于分类任务,您可以使用交叉熵损失和准确度来评估模型的性能。 ```python criterion = torch.nn.CrossEntropyLoss() accuracy = torchmetrics.Accuracy() ``` 6. 遍历测试数据集并评估模型: ```python with torch.no_grad(): for inputs, labels in test_loader: # 将输入数据传递给模型 outputs = model(inputs) # 计算损失 loss = criterion(outputs, labels) # 计算准确度 acc = accuracy(outputs, labels) # 打印损失和准确度 print(f"Loss: {loss.item()}, Accuracy: {acc.item()}") ``` 请注意,上述示例中的代码仅为参考,具体实现可能因您的任务和模型而有所不同。您可能需要根据您的模型架构和评估需求进行相应的调整。 另外,您还可以使用其他评估指标和工具来衡量模型的性能,如精确度、召回率、F1分数等。根据您的具体需求,您可以选择适合您的评估方法和指标。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值