C++にTorchScriptモデルをロードする
10848 ワード
このチュートリアルはPyTorch 1.2と一緒に使用できるように更新されました
名前の通り、PyTorchの主なインタフェースはPythonプログラミング言語です.Pythonは、ダイナミックで反復しやすい多くのシーンに適しており、優先言語であるが、Pythonのこれらの属性は、多くの場合不利である.後者が一般的に適用される環境の1つは、生産-低遅延と厳格な導入を要求することです.本番シーンでは、Java、Rust、Goなどの別の言語にC++のみをバインドしても、よく選択される言語です.次のセクションでは、PyTorchが提供する既存のPythonモデルから、Pythonに依存することなく、C++から完全にロードおよび実行可能なシーケンス化表現形式へのパスについて概説します.
手順1:PyTorchモデルをTorchスクリプトに変換する
PyTorchモデルPythonからC++への旅はTorch Scriptによって開始され、Torch ScriptはPyTorchモデルの表現形式であり、Torch Scriptコンパイラによって理解され、コンパイルされ、シーケンス化されることができる.vanilla「eager」APIを使用して作成された既存のPyTorchモデルから開始する場合は、まずモデルをTorchスクリプトに変換する必要があります.最も一般的な場合(以下で説明します)は、わずかな手間がかかります.すでにTorchスクリプトモジュールがある場合は、このチュートリアルの次のセクションにジャンプできます.
PyTorchモデルをTorchスクリプトに変換する方法は2つあります.1つ目は追跡と呼ばれ、モデルの構造をサンプル入力を用いて評価し、モデルに入力された流量を記録するメカニズムであり、モデルの構造をキャプチャする.これは制御フローを有限に使用するモデルに適している.2つ目の方法は、Torch ScriptコンパイラがTorch Script言語によって加えられた制約に基づいてモデルコードを直接解析およびコンパイルできることを示すために、モデルに明示的なコメントを追加することである.
ヒント:この2つの方法に関する完全なドキュメントと、使用方法の詳細については、公式Torchスクリプトリファレンスを参照してください.
方法1:トレースによるTorchスクリプトへの変換
PyTorchモデルをトレースによってTorchスクリプトに変換するには、モデルのインスタンスおよびサンプル入力を
追跡された
方法2:コメントからTorchスクリプトへの変換
場合によっては、たとえば、モデルが特定の形式の制御フローを使用する場合、Torchスクリプトに直接モデルを記述し、それに応じてモデルを注釈する必要がある場合があります.たとえば、次のvanilla Pytorchモデルがあるとします.
このモジュールの順方向メソッドは、入力された制御フローに依存するため、追跡には適していません.逆に、
まだサポートされていないPython機能を使用しているため、
手順2:スクリプトモジュールをファイルにシーケンス化する
ScriptModuleができたら(PyTorchモデルをトレースまたはアノテーションすることによって)ファイルにシーケンス化できます.後で、Pythonに依存することなく、C++を使用してこのファイルからモジュールをロードして実行できます.トレース例に以前に表示されていた
これにより、作業ディレクトリに
手順3:C++にスクリプトモジュールをロードする
C++にシーケンス化されたPyTorchモデルをロードするには、アプリケーションはPyTorch C++APIに依存する必要があります(LibTorchとも呼ばれる).LibTorchリリース版には、共有ライブラリ、ヘッダファイル、CMake構築プロファイルのセットが含まれています.CMakeはLibTorchの要件に依存するものではありませんが、推奨される方法であり、将来的にはよくサポートされます.このチュートリアルでは、CMakeとLibTorchを使用して最小のC++アプリケーションを構築します.このアプリケーションは簡単にロードして実行できますシーケンス化されたPyTorchモデル.
最小のC++アプリケーション
ロードモジュールのコードについて説明しましょう.以下は既に行われています.
LibTorchおよび構築アプリケーションに依存
上記のコードを
サンプルアプリケーションを作成する最後のことは、LibTorchリリースです.PyTorchのWebサイトのダウンロードページから最新の安定したバージョンをいつでも入手できます.最新のアーカイブをダウンロードして解凍する場合は、次のディレクトリ構造を持つフォルダに格納します.lib/フォルダには、リンクする必要がある共有ライブラリが含まれています include/フォルダには、プログラムに含める必要があるヘッダファイルが含まれています share/フォルダには、上記の単純
ヒント;Windowsでは、デバッグとリリースはABIと互換性がありません.デバッグモードでプロジェクトを構築する場合は、LibTorchのデバッグバージョンを使用してみてください.
最後のステップは、アプリケーションの構築です.このため、サンプルディレクトリのレイアウトは次のようになります.
次のコマンドを実行して、
サンプル・アプリケーション・バイナリ・ファイルへの追跡ResNet 18モデル
手順4:C++でスクリプトモジュールを実行する
C++でシーケンス化されたResNet 18のロードに成功した後、コードを数行実行するだけでいいです.これらの行をC++アプリケーションの
最初の2行には、モデルの入力が設定されています.
ヒント:torch::onesやPyTorch C++APIなどの機能の詳細については、ドキュメント、URLを参照してください.https://pytorch.org/cppdocs. PyTorch C++APIはPython APIとほぼ同じ機能パリティを提供し、Pythonのようにテンソルをさらに操作して処理することができます.
最後の行では、出力の最初の5つのエントリを印刷します.このチュートリアルの前のセクションでは、Pythonのモデルに同じ入力を提供しているので、理想的には同じ出力を見る必要があります.アプリケーションを再コンパイルし、同じシーケンス化モデルで実行してみましょう.
参考までにPythonの以前の出力は:
よくマッチしているようですね.
ヒント:モデルをGPUメモリに移動するには、modelを作成します.to(at::kCUDA);.tensor.to(at::kCUDA)を呼び出すことで、モデルの入力もCUDAメモリにあることを確認し、CUDAメモリに新しいテンソルを返します.
手順5:ヘルプの取得とAPIの探索
このチュートリアルでは、PyTorchモデルのPythonからC++へのパスを大まかに理解することができます.このチュートリアルで説明した概念を使用すると、vanilla、eagerのPyTorchモデル、Pythonのコンパイル済み
もちろん、私たちが紹介していない概念はたくさんあります.たとえば、C++またはCUDAで実装するカスタム演算子拡張Torch Scriptリファレンス:https://pytorch.org/docs/master/jit.html PyTorch C++APIドキュメント:https://pytorch.org/cppdocs/ PyTorch Python APIドキュメント:https://pytorch.org/docs/
いつものように、何か問題や疑問があれば、私たちのフォーラムやGitHub issuesを使用して連絡することができます.
磐創AI技術ブログ資源まとめステーション:http://docs.panchuang.net/PyTorch公式中国語教程ステーション:http://pytorch.panchuang.net/OpenCV中国語公式文書:http://woshicver.com/
名前の通り、PyTorchの主なインタフェースはPythonプログラミング言語です.Pythonは、ダイナミックで反復しやすい多くのシーンに適しており、優先言語であるが、Pythonのこれらの属性は、多くの場合不利である.後者が一般的に適用される環境の1つは、生産-低遅延と厳格な導入を要求することです.本番シーンでは、Java、Rust、Goなどの別の言語にC++のみをバインドしても、よく選択される言語です.次のセクションでは、PyTorchが提供する既存のPythonモデルから、Pythonに依存することなく、C++から完全にロードおよび実行可能なシーケンス化表現形式へのパスについて概説します.
手順1:PyTorchモデルをTorchスクリプトに変換する
PyTorchモデルPythonからC++への旅はTorch Scriptによって開始され、Torch ScriptはPyTorchモデルの表現形式であり、Torch Scriptコンパイラによって理解され、コンパイルされ、シーケンス化されることができる.vanilla「eager」APIを使用して作成された既存のPyTorchモデルから開始する場合は、まずモデルをTorchスクリプトに変換する必要があります.最も一般的な場合(以下で説明します)は、わずかな手間がかかります.すでにTorchスクリプトモジュールがある場合は、このチュートリアルの次のセクションにジャンプできます.
PyTorchモデルをTorchスクリプトに変換する方法は2つあります.1つ目は追跡と呼ばれ、モデルの構造をサンプル入力を用いて評価し、モデルに入力された流量を記録するメカニズムであり、モデルの構造をキャプチャする.これは制御フローを有限に使用するモデルに適している.2つ目の方法は、Torch ScriptコンパイラがTorch Script言語によって加えられた制約に基づいてモデルコードを直接解析およびコンパイルできることを示すために、モデルに明示的なコメントを追加することである.
ヒント:この2つの方法に関する完全なドキュメントと、使用方法の詳細については、公式Torchスクリプトリファレンスを参照してください.
方法1:トレースによるTorchスクリプトへの変換
PyTorchモデルをトレースによってTorchスクリプトに変換するには、モデルのインスタンスおよびサンプル入力を
torch.jit.trace
関数に渡す必要があります.これにより、モジュールのtorch.jit.ScriptModule
メソッドにモデル評価痕跡が埋め込まれるforward
オブジェクトが生成されます.import torch
import torchvision
# .
model = torchvision.models.resnet18()
# forward() 。
example = torch.rand(1, 3, 224, 224)
# `torch.jit.trace ` `torch.jit.ScriptModule`
traced_script_module = torch.jit.trace(model, example)
追跡された
ScriptModule
は、従来のPyTorchモジュールと同じように評価できるようになりました.In[1]: output = traced_script_module(torch.ones(1, 3, 224, 224))
In[2]: output[0, :5]
Out[2]: tensor([-0.2698, -0.0381, 0.4023, -0.3010, -0.0448], grad_fn=)
方法2:コメントからTorchスクリプトへの変換
場合によっては、たとえば、モデルが特定の形式の制御フローを使用する場合、Torchスクリプトに直接モデルを記述し、それに応じてモデルを注釈する必要がある場合があります.たとえば、次のvanilla Pytorchモデルがあるとします.
import torch
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
このモジュールの順方向メソッドは、入力された制御フローに依存するため、追跡には適していません.逆に、
ScriptModule
に変換できます.モジュールをScriptModule
に変換するには、次のように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
my_module = MyModule(10,20)
sm = torch.jit.script(my_module)
まだサポートされていないPython機能を使用しているため、
nn.Module
からいくつかの方法を除外する必要がある場合は、TorchScript
を使用してコメントできます.@torch.jit.ignore
はmy_module
の例であり、シーケンス化することができる.手順2:スクリプトモジュールをファイルにシーケンス化する
ScriptModuleができたら(PyTorchモデルをトレースまたはアノテーションすることによって)ファイルにシーケンス化できます.後で、Pythonに依存することなく、C++を使用してこのファイルからモジュールをロードして実行できます.トレース例に以前に表示されていた
ScriptModule
モデルをシーケンス化するとします.このシーケンス化を実行するには、モジュールでsaveを呼び出してファイル名を渡すだけです.traced_script_module.save("traced_resnet_model.pt")
これにより、作業ディレクトリに
ResNet18
ファイルが生成されます.また、traced_resnet_model.pt
をシーケンス化したい場合は、my_module
を呼び出します.Python領域を正式に離れ、C++領域にまたがる準備ができています.手順3:C++にスクリプトモジュールをロードする
C++にシーケンス化されたPyTorchモデルをロードするには、アプリケーションはPyTorch C++APIに依存する必要があります(LibTorchとも呼ばれる).LibTorchリリース版には、共有ライブラリ、ヘッダファイル、CMake構築プロファイルのセットが含まれています.CMakeはLibTorchの要件に依存するものではありませんが、推奨される方法であり、将来的にはよくサポートされます.このチュートリアルでは、CMakeとLibTorchを使用して最小のC++アプリケーションを構築します.このアプリケーションは簡単にロードして実行できますシーケンス化されたPyTorchモデル.
最小のC++アプリケーション
ロードモジュールのコードについて説明しましょう.以下は既に行われています.
include // One-stop header.
#include
#include
int main(int argc, const char* argv[]) {
if (argc != 2) {
std::cerr << "usage: example-app
";
return -1;
}
torch::jit::script::Module module;
try {
// : torch::jit::load().
module = torch::jit::load(argv[1]);
}
catch (const c10::Error& e) {
std::cerr << "error loading the model
";
return -1;
}
std::cout << "ok
";
}
my_module.save("my_module_model.pt")
ヘッダーには、サンプルを実行するために必要なLibTorchライブラリのすべての関連項目が含まれています.私たちのアプリケーションは、シーケンス化されたPyTorch ScriptModuleのファイルパスを唯一のコマンドラインパラメータとして受け入れ、
関数を使用してモジュールを逆シーケンス化し続け、このファイルパスを入力として使用します.戻ると、torch::jit::load()
オブジェクトが受信されます.後で実行方法について説明します.LibTorchおよび構築アプリケーションに依存
上記のコードを
Torch::jit::script::Module
というファイルに格納するとします.最小example-app.cpp
は簡単に見えるかもしれません.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)
サンプルアプリケーションを作成する最後のことは、LibTorchリリースです.PyTorchのWebサイトのダウンロードページから最新の安定したバージョンをいつでも入手できます.最新のアーカイブをダウンロードして解凍する場合は、次のディレクトリ構造を持つフォルダに格納します.
libtorch/
bin/
include/
lib/
share/
CMakeLists.txt
コマンドを有効にするために必要なCMake構成が含まれています.ヒント;Windowsでは、デバッグとリリースはABIと互換性がありません.デバッグモードでプロジェクトを構築する場合は、LibTorchのデバッグバージョンを使用してみてください.
最後のステップは、アプリケーションの構築です.このため、サンプルディレクトリのレイアウトは次のようになります.
example-app/
CMakeLists.txt
example-app.cpp
次のコマンドを実行して、
find_package(Torch)
フォルダからアプリケーションを構築できます.mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch ..
make
example-app/
は、解凍されたLibTorchリリース版の完全なパスであるべきである.すべてがうまくいけば、このように見えます.root@4b5a67132e81:/example-app# mkdir build
root@4b5a67132e81:/example-app# cd build
root@4b5a67132e81:/example-app/build# cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /example-app/build
root@4b5a67132e81:/example-app/build# make
Scanning dependencies of target example-app
[ 50%] Building CXX object CMakeFiles/example-app.dir/example-app.cpp.o
[100%] Linking CXX executable example-app
[100%] Built target example-app
サンプル・アプリケーション・バイナリ・ファイルへの追跡ResNet 18モデル
/path/to/libtorch
へのパスを以前に作成した場合は、奨励として友好的な「ok」を使用する必要があります.traced_resnet_model.pt
を使用してこの例を実行しようとすると、入力したシェイプが互換性がないことを示すエラーメッセージが表示されます.my_module_model.pt
4 Dではなく1 Dが必要です.root@4b5a67132e81:/example-app/build# ./example-app /traced_resnet_model.pt
ok
手順4:C++でスクリプトモジュールを実行する
C++でシーケンス化されたResNet 18のロードに成功した後、コードを数行実行するだけでいいです.これらの行をC++アプリケーションの
my_module_model.pt
関数に追加します.//
std::vector<:jit::ivalue> inputs;
inputs.push_back(torch::ones({1, 3, 224, 224}));
//
at::Tensor output = module.forward(inputs).toTensor();
std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '
';
最初の2行には、モデルの入力が設定されています.
main()
のベクトルを作成します(タイプtype-erasedの値torch::jit::IValue
メソッドを受け入れて返します)を追加し、単一の入力を追加します.入力テンソルを作成するには、C++APIのScript::Module
と同等のtorch::ones()
を使用します.次に、torch.ones
のscript::Module
メソッドを実行し、作成した入力ベクトルを渡します.見返りとして、forward
を呼び出すことによって、新しいIValueが得られます.|テンソルに変換します.ヒント:torch::onesやPyTorch C++APIなどの機能の詳細については、ドキュメント、URLを参照してください.https://pytorch.org/cppdocs. PyTorch C++APIはPython APIとほぼ同じ機能パリティを提供し、Pythonのようにテンソルをさらに操作して処理することができます.
最後の行では、出力の最初の5つのエントリを印刷します.このチュートリアルの前のセクションでは、Pythonのモデルに同じ入力を提供しているので、理想的には同じ出力を見る必要があります.アプリケーションを再コンパイルし、同じシーケンス化モデルで実行してみましょう.
root@4b5a67132e81:/example-app/build# make
Scanning dependencies of target example-app
[ 50%] Building CXX object CMakeFiles/example-app.dir/example-app.cpp.o
[100%] Linking CXX executable example-app
[100%] Built target example-app
root@4b5a67132e81:/example-app/build# ./example-app traced_resnet_model.pt
-0.2698 -0.0381 0.4023 -0.3010 -0.0448
[ Variable[CPUFloatType]{1,5} ]
参考までにPythonの以前の出力は:
tensor([-0.2698, -0.0381, 0.4023, -0.3010, -0.0448], grad_fn=)
よくマッチしているようですね.
ヒント:モデルをGPUメモリに移動するには、modelを作成します.to(at::kCUDA);.tensor.to(at::kCUDA)を呼び出すことで、モデルの入力もCUDAメモリにあることを確認し、CUDAメモリに新しいテンソルを返します.
手順5:ヘルプの取得とAPIの探索
このチュートリアルでは、PyTorchモデルのPythonからC++へのパスを大まかに理解することができます.このチュートリアルで説明した概念を使用すると、vanilla、eagerのPyTorchモデル、Pythonのコンパイル済み
toTensor()
、ディスク上のシーケンス化ファイル、および–ループの終了–実行可能スクリプト:C++のモジュールに進むことができます.もちろん、私たちが紹介していない概念はたくさんあります.たとえば、C++またはCUDAで実装するカスタム演算子拡張
ScriptModule
を使用して、純粋なC++本番環境にロードされたScriptModuleでカスタム演算子を実行したい場合があります.良いニュースは:これは可能で、そしてとても良い支持を得ました!これで、このフォルダの例を参照できます.すぐにチュートリアルを提供します.通常、次のリンクが役立ちます.いつものように、何か問題や疑問があれば、私たちのフォーラムやGitHub issuesを使用して連絡することができます.
磐創AI技術ブログ資源まとめステーション:http://docs.panchuang.net/PyTorch公式中国語教程ステーション:http://pytorch.panchuang.net/OpenCV中国語公式文書:http://woshicver.com/