pytorch模型从训练到LibTorch部署(标贝科技)
1、pytorch和libtorch安装(标贝科技)
PyTorch 是Torch7 团队开发的,从它的名字就可以看出,其与Torch 的不同之处在于PyTorch 使用了Python 作为开发语言。所谓“Python first”,同样说明它是一个以Python 优先的深度学习框架,不仅能够实现强大的GPU 加速,同时还支持动态神经网络,这是现在很多主流框架比如Tensorflow 等都不支持的。
PyTorch 既可以看做加入了GPU 支持的numpy,同时也可以看成一个拥有自动求导功能的强大的深度神经网络,除了Facebook 之外,它还已经被Twitter、CMU 和Salesforce 等机构采用。
pytorch是一个强大的机器学习库,其中集成了很多方法,但从python本身角度讲,它的速度还不够快,虽然对于许多需要动态性和易迭代性的场景来说,Python是一种合适且首选的语言,但在同样的情况下,Python的这些特性恰恰是不利的。它常常应用于生产环境,这是一个低延迟和有严格部署要求的领域,一般选择C++。
1)安装pytorch
两种方式安装pytorch:根据实际cuda版本和需求安装对应版本pytorch,这里安装的是1.5.0版本。
a.查看cuda版本
cat /usr/local/cuda/version.txt
得到cuda版本,安装合适版本的pytorch。
b.使用pip安装
pip install torch==1.5.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
c.使用conda安装
下载anaconda
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-5.2.0-Linux-x86_64.sh
安装anconda
bash Anaconda3-5.2.0-Linux-x86_64.sh
创建test_torch虚拟环境,python版本=3.6
conda create -n test_torch python=3.6
激活test_torch虚拟环境
conda activate test_torch
安装pytorch
conda install torch=1.5.0
d.torch测试
import torch
torch.version
2)安装libtorch
a.确定libtorch版本
使用libtorch调用c++接口,要保证下载的libtorch的版本和pytorch的版本对应,使用低版本的pytorch和高版本的libtorch是没法成功的。根据pytorch和cuda版本确认libtorch版本
查看libtorch版本
https://blog.csdn.net/lxx4610/article/details/105806017/
https://pytorch.org/get-started/locally/
b.从官网下载编译好的文件
获取libtorch有两种方式:
• 从官网下载编译好的文件
https://pytorch.org/ 下载对应版本
c.自己进行源码编译
码云下载
git clone https://gitee.com/mirrors/pytorch.git
查看libtorch版本
git tag
查看当前分支
git branch
根据cuda和pytorch版本切换到适配的版本
git checkout v1.2.0
更新第三方库
git submodule update --init --recursive
编译
mkdir build
cd build
python ../tools/build_libtorch.py
2、使用pytorch训练模型
这里就不展开介绍
3、将Pytorch模型转化为Torch Script
Torch Script可以完好的表达pytorch模型,而且也能被C++头文件所理解。有两种方法可以将pytorch模型转换成TorchScript,Tracing和Annotation。
1)Tracing
这种方法需要你给模型传入一个sample input,它会跟踪在模型的forward方法中的过程。
例如,加载一个torchvision.models.resnet18()模型
model = torchvision.models.resnet18()
使用 torch.rand(),生成一个随机样例输入
example = torch.rand(1, 3, 224, 224)
torch.jit.trace()方法对根据样例输入跟踪模型的forward方法中的过程
traced_script_module = torch.jit.trace(model, example)
最后导出TorchScript模型。
traced_script_module.save("traced_resnet_model.pt")
完整过程:
import torch
import torchvision
# An instance of your model.
model = torchvision.models.resnet18()
# An example input you would normally provide to your model's forward() method.
example = torch.rand(1, 3, 224, 224)
# Use torch.jit.trace to generate a torch.jit.ScriptModule via tracing.
traced_script_module = torch.jit.trace(model, example) traced_script_module.save("traced_resnet_model.pt")
2)Annotation
如果forward方法中具有判断语句,Tracing方法就行不通了,Annotation方法则可以处理模型里有判断语句的情形,使用torch.jit.script。
模型定义:
class MyModule(torch.nn.Module):
def __init__(self, N, M):
super(MyModule, self).__init__()
self.weight = torch.nn.Parameter(torch.rand(N, M))
def forward(self, input):
if input.sum() > 0:
output = self.weight.mv(input)
else:
output = self.weight + input return output
定义了一个模型结构,在forward方法中使用了判断语句,这种模型在转化为Torch Script时,不能Tracing方法,这时可以使用 torch.jit.script()方法:
my_module = MyModule(10,20)
traced_script_module = torch.jit.script(my_module)
traced_script_module.save("traced_resnet_model.pt")
4、在C++中加载Model
将pytorch训练好的模型导出成torch script形式并保存,C++能够理解,编译并序列化torch script格式的模型。
使用libtorch中torch::jit::load()加载导出的模型。
#include <torch/script.h> // One-stop header.
#include <iostream>
#include <memory>
int main(int argc, const char* argv[]) {
if (argc != 2) {
std::cerr << "usage: example-app <path-to-exported-script-module>\n";
return -1;
}
torch::jit::script::Module module;
try {
// Deserialize the ScriptModule from a file using torch::jit::load().
module = torch::jit::load(argv[1]);
}
catch (const c10::Error& e) {
std::cerr << "error loading the model\n"; return -1;
}
std::cout << "ok\n";
}
torch::jit::load()函数用来加载模形,参数为模型文件名,返回torch::jit::script::Module类,<torch/script.h>头文件包含了需要的类和方法,这个文件通过安装libtorch得到。
5、运行模型
模型已经导入成功,使用libtorch中的一些方法,你就可以像在python中一样去跑你的模型了,并根据c++模型的输出与python模型的输出,对比结果。
// Create a vector of inputs.
std::vector<torch::jit::IValue> inputs;
inputs.push_back(torch::ones({1, 3, 224, 224}));
// Execute the model and turn its output into a tensor.
at::Tensor output = module.forward(inputs).toTensor();
std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';
欢迎体验标贝语音开放平台
地址:https://ai.data-baker.com/#/?source=qaz123
(注:填写邀请码hi25d7,每日免费调用量还可以翻倍)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步