最近因为项目需求,而且面对的是一些用户级的,也就是windows客户端,所以就在思考在windows下如何调用深度学习模型,做了以下尝试:
使用Caffe框架,虽然也可以,但我的大部分项目都使用的Pytorch,真的不想去碰Caffe,而且修改不能按照自己的思想,pass!
使用ONNX,当时由于Pytorch1.0并没有发布windows版,我们想着把Pytorch模型转换为ONNX,然后使用Caffe2的相关库去调用,但发现其使用了docker,实际还是在linux下操作的。
终于等到了Pytorch1.0的windows版的libtorch,开心,但是官方教程不是太详细,就自己摸索,看看论坛什么的,最终成功了!
VS2017(官方说VS2015也支持,没有测试)
Windows10
Cmake3.0以上(我的是3.13.2)
由于C++和Python读取的文件方式不同,所以在使用C++调用之间先把训练生成的模型文件转换成Torch Script,这样子就可以使用C++进行调用了!话不多说,我们开始吧!
以ResNet18为例,官方给了两种生成Torch Script的方式。
方法一:(本篇使用)
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("model.pt")
方法二:
import torch
class MyModule(torch.jit.ScriptModule):
def __init__(self, N, M):
super(MyModule, self).__init__()
self.weight = torch.nn.Parameter(torch.rand(N, M))
@torch.jit.script_method
def forward(self, input):
if input.sum() > 0:
output = self.weight.mv(input)
else:
output = self.weight + input
return output
my_script_module = MyModule()
my_script_module.save("model.pt")
当我们得到一个Torch Script后,也就是model.pt,这就是C++需要调用的模型,这个文件应该包含了网络结构和权重,接下来就需要建立这个工程了!
libtorch/
------------ bin/
-------------include/
-------------lib/
-------------share/
-------------cmake/
我们在任意位置建立一个文件夹,并把下面的C++测试代码存为一个cpp文件,放到这个文件夹中,并命名为example-app.cpp,代码:
#include // One-stop header.
#include
#include
int main() {
// Deserialize the ScriptModule from a file using torch::jit::load().
std::shared_ptr module = torch::jit::load("D:/Desktop/pytorch1_0/model.pt");
assert(module != nullptr);
std::cout << "ok\n";
// Create a vector of inputs.
std::vector 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';
while (1);
}
然后还要建立一个CMakeLists.txt,注意文件名需要根据自己设置的进行修改,我这里是example-app.cpp,并在CMakeLists.txt中写入以下语句:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(custom_ops)
find_package(Torch REQUIRED)
add_executable(example-app example-app.cpp)
target_link_libraries(example-app ${TORCH_LIBRARIES})
set_property(TARGET example-app PROPERTY CXX_STANDARD 11)
官网还有一个版本可以编译opencv,我这里没有使用!!
除此以外,还需要在这个文件夹中,新建一个文件夹叫做build。至此,目录文件为:
example-app/
-----------CMakeLists.txt
-----------example-app.cpp model.pt
-----------build/
完成了之后,我们就开始使用CMake去进行编译,注意把CMake添加到环境变量中,我们打开GUI界面,并设置工程目录和build目录:
注意:build文件夹要是空的,进行Configure,这时会跳出一个选择框,并选择Generator,在这里我们选用Visual Studio 15 2017 Win64(一定要是64位的)
选择后进行Configure,但是这时会报错,这是因为libtorch的地址没有传入,我们使用命令行进行编译!我们进到build文件夹中,然后运行如下命令行:(后面有两个点,Cmake GUI不要关闭!)
cmake -DCMAKE_PREFIX_PATH=libtorch绝对地址 …
没有错误的话,就说明成功了!!
– Found torch: F:/libtorch/lib/torch.lib
– Configuring done
– Generating done
– Build files have been written to: D:/Desktop/pytorch1_0/build
这样就行了~~对,就这么简单,不用使用mingGW。只使用Cmake和VS2017就好了!
然后我们就可以得到这个工程项目,如下:
打开example-app.vcxproj后,所有的包含目录和连接器都不需要去配置了,都自动添加进去了,感觉FB真的很人性化,这也是我使用Pytorch的最大原因~
直接运行example-app.vcxproj,得到最终结果如下:
这样,我们就实现了调用Torch Script模型,然后进行正向传播,就可以得到上图的矩阵。
至此,就完成了!
1、缺失DLL文件
把libtorch/lib中的相关DLL文件,复制到Debug和Release文件夹,就解决了!Happy!