PyTorch 2 ONNX 2 TensorRT踏み込みログ
PyTorch 2 ONNX 2 TensorRT踏み込みログ
「PyTorchで書かれたネットワークから、ONNXを通じてTensorRTを用いてシーケンス化し、最終的にモデル加速を完了する」という全フローピットログ.
2009/12/07初版2009/12/17更新AdaptivePooling,寻BUG想法2019/12/27添加AdaptivePooling例2020/01/01添加VGG 16例链接
じっけんかんきょう
ONNXはインストールせず、ONNX 2 TRTに影響がないので、anaconda管理パッケージの使用をお勧めします.
1. RuntimeError: ONNX export failed: Couldn’t export operator aten::upsample_bilinear2d
解決できません.ONNX 2 TensorRTエラーを報告し、TensorRTの後続バージョンのサポートを待っています.後述の代替方法4を参照してください.
近似すると、警告情報
UserWarning: ONNX export failed on upsample_bilinear2d because align_corners == True not supported
に関連付けるべきである.の原因となる
変換ONNXの使用バージョンは低く、PyTorch.ONNXはサポートされていません.また、
torch.onnx.export
は、ソースコードを参照して、opset_version=9
がデフォルトで使用される.解決策
警告情報は完全に説明されているため、
ONNX's Upsample/Resize operator did not match Pytorch's Interpolation until opset 11.
のエクスポートコードにそのバージョンが規定されています.具体的には、次のようになります.import torch
torch.onnx.export(model, ..., opset_version=11)
より完全なエラーメッセージ
出力された個人情報は私に隠され、誤りを報告し、警告を簡潔にするために、ここでは「より完全」と呼ばれ、この説明は後述しない.
UserWarning: You are trying to export the model with onnx:Upsample for ONNX opset version 9. This operator might cause results to not match the expected results by PyTorch.
ONNX's Upsample/Resize operator did not match Pytorch's Interpolation until opset 11. Attributes to determine how to transform the input were added in onnx:Resize in opset 11 to support Pytorch's behavior (like coordinate_transformation_mode and nearest_mode).
We recommend using opset 11 and above for models using this operator.
UserWarning: ONNX export failed on upsample_bilinear2d because align_corners == True not supported
RuntimeError: ONNX export failed: Couldn't export operator aten::upsample_bilinear2d
2. RuntimeError: ONNX export failed: Couldn’t export operator aten::adaptive_avg_pool2d
解決できません.ONNX 2 TensorRTエラーを報告し、TensorRTの後続バージョンのサポートを待っています.後述の代替方法5を参照してください.
同様のエラー
ONNX
:onnx#63,pytorch#14395,discuss.pytorch#30204 の原因となる
PyTorchのネットワークには
aten::adaptive_avg_pool*d
が使用されているので、個人的な感覚では、ONNXはtorch.nn.AdaptiveAvgPool2d
操作がない、ONNX Operatorを参照して、PyTorch.ONNXはavg_pool2d
を間違えて変換できません.解決策
参考pytorch#14395追加Optionを以下のように追加します.
import torch
torch.onnx.export(model, ..., operator_export_type=torch.onnx.OperatorExportTypes.ONNX_ATEN_FALLBACK)
この方法は、ONNXがPyTorchのOPを置き換えるのを阻止するだけでなく、ATenのOPを用いて置き換え、PyTorch 2 ONXは通じるが、ONNX 2 TRTは通じない.ONNX phaserがONNX以外のOPを認識しないためである.
より完全なエラーメッセージ
UserWarning: ONNX export failed on adaptive_avg_pool2d because output size that are not factor of input size not supported
RuntimeError: ONNX export failed: Couldn't export operator aten::adaptive_avg_pool2d
3. Error: In node 2 (importGather): UNSUPPORTED_NODE: Assertion failed: !(data->getType() == nvinfer1::DataType::kINT32 && nbDims == 1) && “Cannot perform gather on a shape tensor!”
の原因となる
aten::adaptive_avg_pool2d
、ネットワーク内部では"Cannot perform gather on a shape tensor!"
などの類似の操作が使用されており、TensorRTはtraceのときにshape layerの出力として解析され、shape tensorが得られ、Netronツールで可視化されると、対応するx_size = x.size()[1:]
は実際にはnode 2
であり、予想と一致しないことがわかります.解決策
この操作を使用しないで、もう一つの解法はonnx-tensorrt#192から来ている.
x_size = torch.tensor(x.shape)[1:]
4. Error: In node 1 (importUpsample): UNSUPPORTED_NODE: Assertion failed: (nbDims >= 1) && (nbDims <= 3)
Netronツールを使用してモデルを可視化し、対応する
Constant node
を見つけると、対応するnode 1
操作が発見されます.の原因となる
現在、ONNX 2 TRTの変換過程では、
F.interpolate(x, size=(128, 128), mode='bilinear', align_corners=False)
のF.interpolate
モードはサポートされていないようで、bilinear
とlinear
しかサポートされていません.解決策
すべての
nearest
モードをbilinear
モードに置き換えます.5.AdaptivePoolingをAvgPoolingで置き換える
nearest
の問題に対して、2. RuntimeError: ONNX export failed: Couldn't export operator aten::adaptive_avg_pool2d
をAvgPooling
に置き換えた.ONNXはAdaptivePooling
をサポートしているので、PyTorch 2 ONX、ONNX 2 TRTフローはスルーできます.の原因となる
現在のPyTorch 2 NNXプロセスでは、ONNXは
AvgPooling
操作をサポートしておらず、この操作はPyTorchにのみ存在する.解決策
[開発テクニック]・AdaptivePoolingとMax/AvgPoolingを相互変換する文書、PyTorch公式文書を参照すると、
AdaptivePooling
は入力サイズAdaptivePooling
によって出力サイズinput_size
を適応制御することができ、一般的なoutput_size
はAvgPooling/MaxPooling
、kernel_size
、stride
、padding
でoutput_size
を計算する.o u t p u t _ s i z e = c e i l ( ( i n p u t _ s i z e + 2 ∗ p a d d i n g − k e r n e l _ s i z e )/s t r i d e ) + 1\mathbf{output\_size} = ceil((\mathbf{input\_size} + 2 *\mathbf{padding} -\mathbf{kernel\_size})/\mathbf{stride})+1 output_size=ceil((input_size+2∗padding−kernel_size)/stride)+1
したがって、
input_size
、output_size
によってkernel_size
、stride
、padding
、padding
を反転させ、公式ソースコードを参照してkernel_size
を0に設定すると、stride
、nn.AdaptiveAvgPool2d(output_size=(14,14))
を押し出すことができる.s t r i d e = f l o o r ( i n p u t _ s i z e/o u t p u t _ s i z e )\mathbf{stride} = floor(\mathbf{input\_size}/\mathbf{output\_size}) stride=floor(input_size/output_size) k e r n e l _ s i z e = i n p u t _ s i z e − ( o u t p u t _ s i z e − 1 ) ∗ s t r i d e\mathbf{kernel\_size} =\mathbf{input\_size}- (\mathbf{output\_size}-1) *\mathbf{stride} kernel_size=input_size−(output_size−1)∗stride
例
例えば、PyTorchネットワークのある層は
output_size
を含み、その(14, 14)
は10*128*128
であり、その層の入力特徴図サイズは10*14*14
であり、出力された特徴図サイズはnn.AvgPool2d(kernel_size, stride)
である.import torch
from torch import nn
input = torch.randn(10, 36, 36)
AAVP = nn.AdaptiveAvgPool2d(output_size=(12,12))
AVP = nn.AvgPool2d(kernel_size=(3,3), stride=(3,3))
output_AAVP = AAVP(input)
output_AVP = AVP(input)
6.PyTorch 2 ONX、ONNX 2 TRTはいったいどこが問題なのか?
次は、解決できない問題に遭遇した後、誰に聞くべきかという考え方です.
PyTorch 2 ONNXは呼び出したPyTorch内部の変換スクリプトであるため、PyTorch 2 ONNXに問題が発生し、PyTorchのissueに行って解決方法を探す必要がある.ONNX 2 TRTはONNX自身が書いた変換スクリプトonnx-tensorrtを使用しており、同様にONNX 2 TRTに問題が発生した場合、そこに解決策を探す必要がある.TRTモデルを作成した後、TRTモデルを使って推理して問題が発生したので、TRTに聞いてみます.GitHubと公式フォーラムがあります.
では、どのように新聞の間違いを暴露させるのか、次の方法があります.
解決策
以下の方法で問題点が見つかることが多い.
1. PyTorch2ONNX
import torch
torch.onnx.export(..., verbose=True, ...)
2.ONNXモデルの検出
Netronをダウンロードして自分のONNXモデルを可視化し、PyTorchモデルと一致するか、自分が作りたいモデルと一致するかを分析します.
stride=(int(128/14), int(128/14))
、kernel_size=((128-(14-1)*stride, (128-(14-1)*stride)
、resize
、shape
の動作を多く見てください.ONNXはtensorスライスの動作をサポートしていません.3. ONNX2TRT
permute
を更新します.TRTのインストール手順を以下に示します.libnvonnxparser.so
をTRTのlibフォルダに移動する.import tensorrt as trt
TRT_LOGGER = trt.Logger(trt.Logger.VERBOSE)
最終的な解決策
ONNX 2 TRTを放棄しましょう、PyTorchとONNXとTRTのバージョンは互いに支持し合いにくくて、バージョンの反復の中で任意のノードが支持しないで、全体のリンクは切れて、またTRTは閉源のプロジェクトで、あなたはONNX 2 TRTの過程の中でどんな問題が発生したことを全く知らないで、スタックの情報があっても、情報によってその誤りをtraceすることはできません.したがって,TRTが提供するapiを直接用いてネットワークを直接構築することは,最も複雑で最も簡単で直接的な方法である.
Pytorch 2 TRT python API
TRTが提供するpythonインタフェースを使用して、ネットワークを構築するプロセスは非常に簡単です.TRTが提供する例libnvonnxparser.so
を見てみましょう.これに対して/samples/python/network_api_pytorch_mnist/sample.py
です.def populate_network(network, weights):
# Configure the network layers based on the weights provided.
input_tensor = network.add_input(name=ModelData.INPUT_NAME, dtype=ModelData.DTYPE, shape=ModelData.INPUT_SHAPE)
"""
TRT python API
"""
network.mark_output(tensor=fc2.get_output(0))
この/samples/python/network_api_pytorch_mnist/model.py
を書けばいいのに、populate_network
はネットの重みで、weights
から得られます.超簡単ではないでしょうか.PyTorchのtorch.load()
のF.interpolate
モードを使いたいですか?TRT提供!次のログでは「TRT python APIを使って簡単なVGG 16ネットワークを構築する方法」を記録しますが、ONNX 2 TRTはもう使いたくありません.
def populate_network(network, weights):
# Configure the network layers based on the weights provided.
input_tensor = network.add_input(name=ModelData.INPUT_NAME, dtype=ModelData.DTYPE, shape=ModelData.INPUT_SHAPE)
"""
TRT python API
"""
network.mark_output(tensor=fc2.get_output(0))