[LibTorch] C++ 调用 PyTorch 导出的模型

本文介绍了如何将PyTorch的神经网络模型PoolNet部署到C++环境中,主要对比了两种方法:TorchScript导出模型和手动复现网络结构。TorchScript工具允许我们将模型转换为可在C++中运行的形式,虽然首次运行可能慢,但后续处理速度快。文章详细展示了使用TorchScript导出PyTorch的resnet50模型的步骤,并提供了C++中加载和使用模型的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考文章

问题

pytorch 的神经网络模型有很多,但 libtorch 就特别少。现在面临的问题是要在 C++ 环境下应用神经网络模型,肯定不能直接使用 pytorch 模型。解决办法有两个:

  • 方法一是用 TorchScript 工具导出模型 poolnet.pt,模型中包含网络结构参数权重,因此可以直接在 C++ 里面生成神经网络。

  • 方法二是用 C++ 复现网络结构,封装为为类对象,再从 poolnet.pt 中导入参数权重

在这里插入图片描述

对于神经网络模型 PoolNet ,将其应用到 C++ 环境下进行视频处理,下面这是前 10 帧画面处理时间。明显看出,方法一前两次运行时间很长,从第三帧开始,两种方法的处理时间几乎相同。但是,方法一相当简单,导出模型即可,方法二需要复现网络结构,工程量巨大。下面重点介绍方法一

在这里插入图片描述

TorchScript 工具介绍

必定要看 官方文档。上面介绍了 trace 和 script 的区别。

PyTorch 导出模型

resnet50

编辑 export.py 文件,以 pytorch 提供的 resnet50 为例,分别使用 trace 和 script 导出模型。trace 需要提供一个输入样例,script 则不需要。但是复杂的模型使用 script 一般会失败,但 trace 可以。trace 和 script 导出的模型几乎没有区别,缺点是前两次处理时间都格外久

import torch
from torchvision.models import resnet50

net = resnet50(pretrained=True)
net = net.cuda()
net.eval()
for key, value in net.named_parameters(): 
	print(key)

# trace
x = torch.ones(1, 3, 224, 224)
x = x.cuda()
traced_module = torch.jit.trace(net, x)
traced_module.save("resnet50_trace.pt")

# script
scripted_module = torch.jit.script(net)
scripted_module.save("resnet50_script.pt")

在 python3+pytorch 的虚拟环境下执行

python export.py

net

上面的例子是 pytorch 提供的 resnet50,如果是自己写的模型,可以按照下面的方式来。其中,net.pth 是训练后保存的参数,net.pt 则是期望导出的模型,使用 trace 方法。

import torch 
import torchvision

# 初始化神经网络
net = Net()
net.load_state_dict(torch.load("net.pth"))
net.cuda()
net.eval()

# 导出模型
x = torch.ones(1, 3, 224, 224)
x = x.cuda()
m = torch.jit.trace(net, x)
m.save("net.pt")

其中

m.save("net.pt")

也可写为

torch.jit.save(m, "net.pt")

C++ 中调用模型

C++ 使用 libtorch 时,一般使用 CMake 进行管理(参考 Pytorch 官网教程)。下面是在 C++ 环境中调用模型的方法。

#include <torch/torch.h>
#include <torch/script.h>

torch::Device device(torch::kCUDA);
// image.rows, image.cols 高在前,宽在后
torch::Tensor img_tensor = torch::from_blob(img.data, {1, image.rows, image.cols, 3}, torch::kByte).to(device);
img_tensor = img_tensor.permute({0, 3, 1, 2});
img_tensor = img_tensor.toType(torch::kFloat);
img_tensor = img_tensor.div(255.0);
torch::jit::script::Module net = torch::jit::load("../models/net.pt");
// 打印模型中的参数
for (const auto& pair : net.named_parameters()) {
    std::cout << pair.name << " " << pair.value.requires_grad() << std::endl;
}
net.to(device)
torch::NoGradGuard no_grad;
torch::Tensor output = net.forward({img_tensor}).toTensor();
在ROS 2 (Robot Operating System) 中,要使用 C++ 调用 PyTorch 训练的模型,你需要做以下几个步骤: 1. **安装依赖**: - 安装 ROS 2:按照官方文档《安装指南》(https://docs.ros.org/en/foxy/Installation/index.html)完成基础设置。 - 安装 PyTorch:如果还没有,使用 `pip` 或者 ROS 内置的包管理工具如 `colcon` 来安装 PyTorch及其相关的Python库。 - 对于 C++ 接口,你可以考虑使用 PyTorchC++ API (`torch::jit::script`) 或者通过 Python C API 间接调用。 2. **将模型转换**: - 为了能在 C++ 中直接使用,需要将 PyTorch 模型导出为 TorchScript(`.pt` 或 `.pb` 文件)。可以使用 `torch.jit.save(model, 'model.pt')` 导出模型到 TorchScript。 3. **编写 C++ 代码**: - 使用 C++ 面向对象编程(如 C++11 或更高版本)或现代 C++(例如 C++17)编写代码。 - 使用 PyTorch C++ API (`torch/script.h`) 加载模型并执行推理。示例代码可能类似这样: ```cpp #include <torch/script.h> // 加载模型 torch::jit::script::Module module; try { std::ifstream model_file("model.pt", std::ios::binary); module = torch::jit::load(model_file); } catch (const c10::Error& e) { std::cerr << "Error loading the model: " << e.what() << std::endl; } // 创建输入数据 auto input_data = ...; // 根据模型需求创建适当的数据 // 运行模型 at::Tensor output = module.forward(input_data); ``` 4. **整合到ROS节点**: - 将上述 C++ 代码封装成一个 ROS Nodelet 或者直接作为服务/动作服务器的一部分。 - 调整数据格式,确保输入输出能够适应ROS的消息传递系统。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值