C++(Libtorch)加载python(pytorch)网络进行预测(版本、cpu、cuda、runtime error问题)

写在前面:

(1)如果C++中不使用GPU,需保证libtorch的版本与pytorch的版本一致,否则可能会出错,例如出现c++中load网络失败的情况。
(2)如果C++中使用cuda,libtorch版本与pytorch版本可能会不一致,未做统计。
(3)VS为2017版本,系统win10

1. C++中不使用CUDA

我的版本是:
Pytorch:torch-1.6.0-cp36-cp36m-win_amd64.whl(cu102) + torchvision-0.7.0-cp36-cp36m-win_amd64.whl(cu102)
libtorch:libtorch-win-shared-with-deps-1.6.0(cu102)
基本步骤如下:

1.1 Python环境下网络训练保存

首先在python环境下训练网络,然后保存,例如:
torch.save(net.state_dict(), ‘best_model.pth’)

1.2 python环境下生成pt文件

使用trace方法。
(1)新建网络
device = torch.device(‘cuda’ if torch.cuda.is_available() else ‘cpu’)
device = torch.device(‘cpu’) #不使用GPU
net = UNet(n_channels=1, n_classes=1)
net.to(device=device)
(2)load训练好的权重
dic_path = ‘best_model_202111111946.pth’
net.load_state_dict(torch.load(dic_path))
net.eval()
(3)导入一张图片用以预测。需要将图片转为tensor格式
img = cv2.imread(‘data/testAl/image/9.tif’,-1)
img = img.reshape(1, 1, img.shape[0], img.shape[1])
img_tensor = torch.from_numpy(img)
img_tensor = img_tensor.to(device=device, dtype=torch.float32)
这里,reshape成什么样的维度,取决于网络训练时使用的参数。不导入图片,使用产生随机数来预测也可以,例如:
img = torch.ones(1, 1, 32,32)
img_tensor = img.to(device=device, dtype=torch.float32)
(4)trace并保存pt文件
traced_script_module_resnet = torch.jit.trace(net, img_tensor)
output = traced_script_module_resnet(img_tensor)
traced_script_module_resnet.save(“model_20211112_jit.pt”)
这里,output是网络的输出,可与C++环境预测的输出做对比。

1.3 C++环境下导入pt文件并预测

(1)导入pt文件
torch::jit::script::Module module = torch::jit::load("\model_2111111021_jit.pt");
module.eval();
//module.to(at::kCUDA);
(2)读取图片并转为tensor
Mat imgSrc = imread("…/0.png", -1);
torch::Tensor tensor_image = torch::from_blob(imgSrc.data,{ 1,1,imgSrc.rows, imgSrc.cols }, torch::kByte);
tensor_image = tensor_image.toType(torch::kFloat);
std::vectortorch::jit::IValue inputs;
inputs.push_back(tensor_image);
//tensor_image = tensor_image.to(at::kCUDA);
注意,mat转tensor,需要转成何种维度,取决于网络训练时的输入维度
(3)使用网络预测
at::Tensor outputs = module.forward(inputs).toTensor();
(4)获得输出并转为图片
outputs = outputs[0];
outputs = outputs[0];
cout << outputs.dim() << endl;
Mat outimg(cv::Size(outputs.size(0),outputs.size(1)), CV_32F, outputs.data_ptr());

2. C++中使用CUDA

C++中使用cuda进行网络预测时(在保证vs2017环境部署好的前提下),如果libtorch仍然使用上述版本,则会出现问题。现象如下:
检测cuda和cudnn,通过:
cout << “cuda是否可用:” << torch::cuda::is_available() << endl;
cout << “cudnn是否可用:” << torch::cuda::cudnn_is_available() << endl;
在这里插入图片描述
导入pt文件通过:
string modPaht = “202111180132.pt”;
torch::jit::script::Module module = torch::jit::load(modPaht);
module.to(at::kCUDA);
module.eval();
产生数据,并置于cuda,通过,
torch::Tensor tensor = torch::ones({ 1,1,32,32 });
tensor = tensor.to(at::kCUDA);
cout << “data is on:” << tensor.device() << endl;
std::vectortorch::jit::IValue inputs;
inputs.push_back(tensor);
在这里插入图片描述
使用网络预测,出现runtime error异常
module.forward(inputs);//出现异常
反复检查后,仍无法解决。后来解决办法是,提高libtorch的版本,将libtorch的版本替换为
libtorch-win-shared-with-deps-1.7.0(cu10.2),问题解决。

3. C++中使用CUDA注意事项

(1)要保证模型和输入数据在同一设备上(CPU或CUDA)
如果使用cuda,在进行module.forward()之前,要将module.to(at::kCUDA);以及输入数据tensor.to(at::kCUDA);
(2)若使用cuda,则复制网络输出Tensor变量至Mat变量前,需先将输出Tensor转移至CPU上
at::Tensor outputs = module.forward({ tensor_image }).toTensor();
//提取预测结果
outputs = outputs[0];
outputs = outputs[0];
outputs = outputs.to(at::kCPU);
Mat outimg(cv::Size(outputs.size(0), outputs.size(1)), CV_32F, outputs.data_ptr());
(3)若python在产生pt文件时,device为‘cpu’,C++中读取pt文件时,在不加限定(torch::jit::load函数中的第二个参数可以限定设备位置)的情况下,会将模型加载到cpu;同样,如果python产生pt文件时,device为‘cuda’设备,在不加限定情况下,会将模型加载到cuda。在做预测时,需保证输入数据的设备位置与模型所在设备位置相同。
(4)如果python产生的是pt文件在cpu上,c++中仍然可以通过module.to(at::kCUDA);将模型加载到cuda上;同理,若pt在cuda上,c++中仍然可以通过module.to(at::kCPU);将模型加载到CPU上。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: YOLOv5是一种常用的物体检测算法,而ONNX是一种用于机器学习模型的开放式格式。将YOLOv5之前的.pt模型转换为ONNX格式模型有很多好处,例如可以将模型部署到不同平台、实现模型量化和优化等。 想要将.pt模型转换为ONNX格式,需要使用pytorchtorch.onnx模块。首先,需要加载模型和相应的参数。 import torch model = torch.load('yolov5.pt', map_location='cpu')['model'].float() # 加载模型 然后,需要输入一个随机的数据张量,保存模型输出。 dummy_input = torch.randn(1, 3, 640, 640).float() # 输入数据张量 torch.onnx.export(model, dummy_input, "yolov5.onnx", verbose=False, opset_version=11) # 保存模型 最后一行代码将模型导出成ONNX格式,参数中的verbose表示是否显示模型信息,opset_version表示使用的模型版本。可以根据需要对这些参数进行修改。 总之,将YOLOv5的.pt模型转换成ONNX格式,可以使得模型更加灵活地应用到不同的平台和资源中。 ### 回答2: YOLOv5是一种用于图像检测和目标识别的深度学习模型,它使用神经网络架构,可以快速准确地检测出图像中的多个物体,是广泛应用于计算机视觉领域的一种先进技术。在训练得到YOLOv5 的权重文件(.pt)后,需要将其转换为ONNX格式,以便在不同的平台和环境中使用。 要将YOLOv5的.pt文件转换为ONNX格式,可以使用ONNX导出器,这是一个开源工具包,具有简单易用的API接口和丰富的功能,需要具备Python语言和PyTorch库支持。首先,需要安装ONNX导出器和PyTorch库,然后导入YOLOv5的权重文件,创建模型和图形,设置输入和输出格式,并运行转换代码。在转换完成后,生成的ONNX文件可以直接用于推理或部署到其他环境中。 需要注意的是,转换过程中可能会出现一些问题,比如不支持的层类型、维度不匹配、精度损失等,需要对转换结果进行测试和优化。同时,如果需要从其他框架或模型转换成ONNX格式,也需要进行类似的操作,不同模型和框架之间的差异性可能会对结果产生影响。因此,在进行转换时,需要仔细阅读文档和API接口,了解实际情况,并根据需求进行调整和优化,以获得更好的性能和效果。 ### 回答3: YOLOv5是一种用于实时目标检测的神经网络模型,而.onnx是一种可移植的机器学习模型格式。将YOLOv5的.pt模型转换为.onnx格式,可以使该模型能够在不同平台上运行,并具有更好的跨平台兼容性和可移植性。下面是将YOLOv5 .pt模型转换为.onnx格式的步骤: 1. 安装ONNX和pytorch 转换模型需要安装ONNX和pytorch。您可以使用下面的命令在conda环境中安装: ```python conda install -c conda-forge onnx conda install pytorch torchvision -c pytorch ``` 2. 执行转换脚本 在安装好ONNX和pytorch之后,您需要下载yolov5的转换脚本,然后执行以下命令: ```python python models/export.py --weights /path/to/pt/file.pt --img 640 --batch 1 --names /path/to/your/classes.txt --dynamic ``` 在该命令中,您需要将”/path/to/pt/file.pt”替换为您下载的yolov5 .pt模型的路径,将“/path/to/your/classes.txt”替换为你自己的类别文件。默认情况下,YOLOv5的输入图像大小为640x640,并且批量大小为1。如果您想定制这些值,请使用“--img”和“--batch”选项,例如: ```python python models/export.py --weights /path/to/pt/file.pt --img 416 --batch 4 --names /path/to/your/classes.txt --dynamic ``` 3. 检查输出文件 脚本将生成一个可转换为.onnx格式的中间格式文件,“/path/to/pt/file.onnx”。检查该文件,确保没有出现错误。如果没有问题,您可以继续将该文件转换为.onnx格式,如下所示: ```python import torch model = torch.onnx.export(model, x, onnx_file, opset_version=11, input_names=['images'], output_names=['output']) ``` 4. 验证转换结果 最后,验证转换结果是否与原始.pt模型相同。您可以使用以下代码来比较两个模型的输出: ```python import onnxruntime as rt ort_sess = rt.InferenceSession(onnx_file) # Load an image image = cv2.imread("my_image.jpg") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = cv2.resize(image, (416, 416)) # Preprocess the image image = image.astype(np.float32) image /= 255.0 # Run inference on the onnx model ort_inputs = {input_name: np.expand_dims(image, axis=0)} ort_outs = ort_sess.run(None, ort_inputs) # Compare outputs to Pytorch with torch.no_grad(): pytorch_inputs = { "image": torch.from_numpy(np.expand_dims(image, axis=0)).to(device), } pytorch_out = torch_model(**pytorch_inputs) assert np.allclose(ort_outs[0], pytorch_out.cpu().numpy(), atol=1e-2) ``` 如果两个输出之间具有相同的值,则意味着您已成功地将YOLOv5 .pt模型转换为ONNX格式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值