开发环境:
以ResNet18为基础结构,进行分类网络实际部署测试验证。libtorch c++部署分为两个部分:
1)python端实现将pytorch模型转为traces script模型文件.pt;
2)c++端加载.pt模型文件,通过libtorch进行前项推理。
这里使用torchvision中预置的ResNet18模型,加载预训练权重文件后,转为traces script模型文件。
import torch
import torchvision
def test_ts_model():
model = torchvision.models.resnet18(True)
model.eval()
ts_model = torch.jit.trace(model, torch.rand(1, 3, 224, 224))
ts_model.save("traces_script_module.pt")
实际使用中,可加载数据,测试一下,对比输出结果,以保证模型转换的正确性。测试代码:
input = torch.ones(1, 3, 224, 224) # 测试图像
output = model(input)
print("torch model out[0:5]: ", output[0, :5])
output = ts_model(torch.ones(1, 3, 224, 224))
print("traces script model out[0:5]: ", output[0, :5])
输出结果:
torch model out[0:5]: tensor([-0.0391, 0.1145, -1.7968, -1.2343, -0.8190], grad_fn=)
traces script model out[0:5]: tensor([-0.0391, 0.1145, -1.7968, -1.2343, -0.8190], grad_fn=)
此处,torch model与traces script model对同一输入,预测结果一致。
环境配置参照:https://blog.csdn.net/weixin_34910922/article/details/109344356
测试代码:
此处引入两个lib文件:c10.lib、torch_cpu.lib。
#include
#include
#include
int main()
{
torch::jit::script::Module model;
try
{
// 使用以下命令从文件中反序列化脚本模块: torch::jit::load().
model = torch::jit::load("traces_script_module.pt");
}
catch (const c10::Error& e) {
std::cerr << "error loading the model\n";
return -1;
}
std::vector inputs;
inputs.push_back(torch::ones({1, 3, 224, 224}));
at::Tensor output = model.forward(inputs).toTensor();
std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';
system("pause");
}
执行结果:
预测结果,打印出前5数值与python端一致。实现了libtorch前项推理逻辑。但是,存在问题,推理过程在cpu中进行,未使用GPU加速。
测试代码:
#include
#include
#include
#include
int main()
{
torch::jit::script::Module model;
try
{
// 使用以下命令从文件中反序列化脚本模块: torch::jit::load().
model = torch::jit::load("traces_script_module.pt");
}
catch (const c10::Error& e) {
std::cerr << "error loading the model\n";
return -1;
}
torch::DeviceType device_type = at::kCPU;
std::cout <<"cuda::is_available():" << torch::cuda::is_available() << std::endl;
if (torch::cuda::is_available())
{
device_type = at::kCUDA;
}
model.to(device_type);
std::vector inputs;
inputs.push_back(torch::ones({1, 3, 224, 224 }).to(device_type));
at::Tensor output = model.forward(inputs).toTensor();
std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';
system("pause");
}
执行结果: