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管理パッケージの使用をお勧めします.
  • Ubuntu 16.04
  • RTX2080TI, Driver Version: 410.79
  • CUDA 10.0
  • cudnn 7.6.3(7.5.0などの低バージョンで影響なし)
  • pycuda 2019.1.2
  • pytorch 1.3.1
  • torchvision 0.4.2
  • tensorrt 6.0.1.5
  • python 3.6.9
  • 測定ONNXは使用できない、python 3.7を使用することを提案する.x
  • onnx 1.6.0
  • protobuf 3.9.2(3.9.xに降格する必要があります.そうしないとonnxはlibprotobuf.so.20のエラーを報告します)

  • 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モードはサポートされていないようで、bilinearlinearしかサポートされていません.

    解決策


    すべてのnearestモードをbilinearモードに置き換えます.

    5.AdaptivePoolingをAvgPoolingで置き換える

    nearestの問題に対して、2. RuntimeError: ONNX export failed: Couldn't export operator aten::adaptive_avg_pool2dAvgPoolingに置き換えた.ONNXはAdaptivePoolingをサポートしているので、PyTorch 2 ONX、ONNX 2 TRTフローはスルーできます.

    の原因となる


    現在のPyTorch 2 NNXプロセスでは、ONNXはAvgPooling操作をサポートしておらず、この操作はPyTorchにのみ存在する.

    解決策


    [開発テクニック]・AdaptivePoolingとMax/AvgPoolingを相互変換する文書、PyTorch公式文書を参照すると、AdaptivePoolingは入力サイズAdaptivePoolingによって出力サイズinput_sizeを適応制御することができ、一般的なoutput_sizeAvgPooling/MaxPoolingkernel_sizestridepaddingoutput_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_sizeoutput_sizeによってkernel_sizestridepaddingpaddingを反転させ、公式ソースコードを参照してkernel_sizeを0に設定すると、stridenn.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

  • 更新PyTorchから最新版まで、一般的に最新版の中でONNXのOPサポートはもっと多いはずです.
  • 以下のコードに従ってログレベルを最高にし、逐一分析します.
  • 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)resizeshapeの動作を多く見てください.ONNXはtensorスライスの動作をサポートしていません.

    3. ONNX2TRT

  • onnx-tensorrtライブラリ、すなわちpermuteを更新します.TRTのインストール手順を以下に示します.
  • TRTを取り付ける.
  • コンパイルonnx-tensorrt.
  • は、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はもう使いたくありません.