Windows使用C++調用Pytorch1.0模型

最近因為項目需求,而且面對的是一些用戶級的,也就是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)

生成Torch Script

由於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 models 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++需要調用的模型,這個文件應該包含了網路結構和權重,接下來就需要建立這個工程了!

C++調用Torch Script模型文件

  • 下載Cmake和VS2017,並安裝 :

Download | CMake?

cmake.org

  • 從官網下載libtorch文件(本篇為CPU版):

準備好這些文件後,我們開始進行libtorch的編譯和C++工程的建立,然後解壓libtorch壓縮文件,其目錄為:

libtorch/

----------- bin/

------------include/

------------lib/

------------share/

------------cmake/

我們在任意位置建立一個文件夾,並把下面的C++測試代碼存為一個cpp文件,放到這個文件夾中,並命名為example-app.cpp,代碼:

#include <torch/script.h> // One-stop header.

#include <iostream>
#include <memory>

int main() {
// Deserialize the ScriptModule from a file using torch::jit::load().
std::shared_ptr<torch::jit::script::Module> module = torch::jit::load("D:/Desktop/pytorch1_0/model.pt");

assert(module != nullptr);
std::cout << "ok
";
// 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) <<
;
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!

推薦閱讀:

TAG:PyTorch | 深度學習(DeepLearning) | 卷積神經網路(CNN) |