Nanmur opened a new issue, #19965:
URL: https://github.com/apache/tvm/issues/19965

   
   ## Summary
   
   During compatibility testing, two industrial-style ONNX graphs consistently 
fail at the TVM Relax ONNX importer stage, before tuning can start:
   
   1. `PP-OCRv6_tiny.onnx`, exported from a PaddleOCR-style model, fails around 
`Squeeze -> Transpose`.
   2. `FasterRCNN-12.onnx`, a detection graph with dynamic post-processing, 
fails around shape `Gather` and then dynamic `TopK`.
   
   I would like to ask whether these are expected importer limitations in the 
current Relax ONNX frontend, and whether the preprocessing workarounds 
described below are recommended, or if there is a better official way to handle 
these graphs.
   
   ## Environment
   
   ```text
   TVM version: 0.24.0
   Python: 3.11.15
   ONNX: 1.21.0
   OS: Linux
   Frontend used: tvm.relax.frontend.onnx.from_onnx
   ```
   
   ## Case 1: PP-OCRv6_tiny Squeeze axes are lost before Transpose
   
   The model is `PP-OCRv6_tiny.onnx`, opset 11. The failing pattern in the ONNX 
graph is:
   
   ```text
   Squeeze.0
     inputs  = ['p2o.pd_op.pool2d.0.0']
     outputs = ['p2o.pd_op.squeeze.0.0']
     attrs   = {'axes': [2]}
   
   Transpose.0
     inputs  = ['p2o.pd_op.squeeze.0.0']
     outputs = ['p2o.pd_op.transpose.0.0']
     attrs   = {'perm': [0, 2, 1]}
   ```
   
   Using either OCR runtime shape below gives the same failure:
   
   ```python
   from tvm.relax.frontend.onnx import from_onnx
   import onnx
   
   model = onnx.load("PP-OCRv6_tiny.onnx")
   from_onnx(
       model,
       shape_dict={"x": [1, 3, 48, 128]},
       dtype_dict={"x": "float32"},
       opset=11,
       keep_params_in_input=False,
   )
   ```
   
   Observed error:
   
   ```text
   Error converting operator Transpose, with inputs: [R.squeeze(lv151, 
axis=None)]
   ValueError: Transpose: number of axes in perm attribute (3) must equal the 
number of input tensor dimensions (2)
   ```
   
   The ONNX node has `Squeeze axes=[2]`, so the expected output rank should be 
3 and `Transpose perm=[0,2,1]` should be valid. The TVM error shows 
`R.squeeze(..., axis=None)`, which suggests that the importer may be ignoring 
the ONNX `axes` attribute for this opset/node form.
   
   ### Related PaddleOCR Conv pattern
   
   The same model also contains Paddle-style grouped/depthwise `1xK` conv 
patterns:
   
   ```text
   node    = Conv.35
   inputs  = ['p2o.pd_op.unsqueeze.1.0', 'p2o.pd_op.unsqueeze.0.0']
   outputs = ['p2o.pd_op.depthwise_conv2d.9.0']
   attrs   = {
     'dilations': [1, 1],
     'kernel_shape': [1, 5],
     'strides': [1, 1],
     'group': 160,
     'pads': [0, 2, 0, 2]
   }
   ```
   
   I experimented with two graph rewrites:
   
   1. Normalize symmetric ONNX Conv pads from `[top,left,bottom,right]` to 
`[h,w]` for TVM.
   2. Rewrite `Unsqueeze(axis=2) -> Conv(1xK) -> Squeeze(axis=2)` into an 
equivalent Conv1D form.
   
   However, the first rewrite is not ONNX-spec-safe as a persisted ONNX model, 
because ONNX Runtime validation reports:
   
   ```text
   Node (Conv.0) Op (Conv) [ShapeInferenceError] Attribute pads has incorrect 
size
   ```
   
   So I currently treat this as a TVM-only workaround and avoid saving it as a 
general runtime ONNX graph.
   
   ## Case 2: FasterRCNN-12 dynamic detection post-processing
   
   The model is `FasterRCNN-12.onnx`, opset 12. It contains a full detection 
post-processing graph:
   
   ```text
   TopK: 7
   NonMaxSuppression: 85
   RoiAlign: 4
   Resize: 3
   Shape: 117
   Gather: 798
   ```
   
   Raw import fails first at shape `Gather`:
   
   ```text
   Error converting operator Gather, with inputs: [R.shape([1, 3, 1, 1]), 2034]
   AssertionError: Only constant indices supported for shape gather.
   ```
   
   After freezing/stabilizing static shape subgraphs and importing the prepared 
runtime ONNX with:
   
   ```python
   from_onnx(
       model,
       shape_dict={"image": [3, 224, 224]},
       dtype_dict={"image": "float32"},
       opset=12,
       keep_params_in_input=False,
   )
   ```
   
   the next importer failure is dynamic `TopK`:
   
   ```text
   Error converting operator TopK, with inputs: [R.sigmoid(lv242), v_5635]
   ValueError: TopK k must be a constant
   ```
   
   
   ## Current workarounds in my pipeline
   
   The pipeline currently does the following:
   
   - Fold static shape subgraphs into initializers when this preserves ONNX 
Runtime validation.
   - Fix missing or empty `Resize` ROI inputs.
   - Rewrite static `Split` tensor inputs to `Slice` where TVM treats the 
second input as dynamic.
   - Remove or bypass inference-time `Dropout`.
   - Skip full detection post-processing graphs containing `NonMaxSuppression + 
dynamic TopK`.
   - Skip Paddle-style degenerate grouped `1xK` conv graphs when the rewrite 
would make the persisted ONNX invalid.
   
   ## Questions
   
   1. For opset 11 `Squeeze` with an `axes` attribute, should the Relax ONNX 
importer preserve the axes and emit `R.squeeze(..., axis=[2])` instead of 
`axis=None`?
   2. Is the shape `Gather` failure expected when the input is `R.shape(...)` 
and the index is a scalar constant-like value?
   3. Is dynamic `TopK k` unsupported by design in Relax ONNX import, or is 
there a recommended way to keep it symbolic?
   4. For full detection graphs with `NonMaxSuppression + TopK`, does the TVM 
team recommend splitting the graph before import, or should users expect 
full-graph import to work eventually?
   5. Are graph-level rewrites such as static shape folding, static 
Split-to-Slice, and `Unsqueeze-Conv-Squeeze -> Conv1D` considered reasonable 
preprocessing for TVM, or is there a more official path?
   
   ## Expected behavior
   
   Ideally, TVM should import the valid ONNX graph or report a precise 
unsupported-pattern diagnostic. In the PP-OCRv6 case, the `Squeeze axes=[2]` 
attribute appears to be valid and should not reduce the tensor with `axis=None`.
   
   ## Attachments
   
   log:
   
   ```text
   [11:04:07] /home/perception/Nanmur/tvm/src/relax/ir/block_builder.cc:66: 
Warning: BlockBuilder destroyed with remaining blocks!
   [11:04:07] /home/perception/Nanmur/tvm/src/relax/ir/block_builder.cc:66: 
Warning: BlockBuilder destroyed with remaining blocks!
   [11:04:07] /home/perception/Nanmur/tvm/src/relax/ir/block_builder.cc:66: 
Warning: BlockBuilder destroyed with remaining blocks!
   [11:04:08] /home/perception/Nanmur/tvm/src/relax/ir/block_builder.cc:66: 
Warning: BlockBuilder destroyed with remaining blocks!
   
   
==========================================================================================
   PP-OCRv6_tiny raw ONNX -> TVM Relax from_onnx
   
==========================================================================================
   shape_dict = {'x': [1, 3, 48, 1]}
   dtype_dict = {'x': 'float32'}
   Error converting operator Transpose, with inputs: [R.squeeze(lv151, 
axis=None)]
   IMPORT_FAILED
   ValueError: Transpose: number of axes in perm attribute (3) must equal the 
number of input tensor dimensions (2)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5173, in from_onnx
       self._construct_nodes(graph)
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5382, in _construct_nodes
       raise err
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5376, in _construct_nodes
       op = self._convert_operator(op_name, inputs, attr, self.opset)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5476, in _convert_operator
       sym = op_function(self.bb, inputs, attrs, [self._nodes, self._params])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 931, in _impl_v13
       raise ValueError(
   ValueError: Transpose: number of axes in perm attribute (3) must equal the 
number of input tensor dimensions (2)
   [Preprocess] Normalized 37 symmetric Conv pads from 4D to 2D for TVM.
   
   
==========================================================================================
   PP-OCRv6_tiny after symmetric Conv pads normalization
   
==========================================================================================
   shape_dict = {'x': [1, 3, 48, 1]}
   dtype_dict = {'x': 'float32'}
   Error converting operator Transpose, with inputs: [R.squeeze(lv151, 
axis=None)]
   IMPORT_FAILED
   ValueError: Transpose: number of axes in perm attribute (3) must equal the 
number of input tensor dimensions (2)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5173, in from_onnx
       self._construct_nodes(graph)
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5382, in _construct_nodes
       raise err
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5376, in _construct_nodes
       op = self._convert_operator(op_name, inputs, attr, self.opset)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5476, in _convert_operator
       sym = op_function(self.bb, inputs, attrs, [self._nodes, self._params])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 931, in _impl_v13
       raise ValueError(
   ValueError: Transpose: number of axes in perm attribute (3) must equal the 
number of input tensor dimensions (2)
   [Preprocess] Normalized 37 symmetric Conv pads from 4D to 2D for TVM.
   
   
==========================================================================================
   PP-OCRv6_tiny after pads normalization + Unsqueeze-Conv-Squeeze to Conv1D 
rewrite
   
==========================================================================================
   shape_dict = {'x': [1, 3, 48, 1]}
   dtype_dict = {'x': 'float32'}
   Error converting operator Transpose, with inputs: [R.squeeze(lv151, 
axis=None)]
   IMPORT_FAILED
   ValueError: Transpose: number of axes in perm attribute (3) must equal the 
number of input tensor dimensions (2)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5173, in from_onnx
       self._construct_nodes(graph)
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5382, in _construct_nodes
       raise err
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5376, in _construct_nodes
       op = self._convert_operator(op_name, inputs, attr, self.opset)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5476, in _convert_operator
       sym = op_function(self.bb, inputs, attrs, [self._nodes, self._params])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 931, in _impl_v13
       raise ValueError(
   ValueError: Transpose: number of axes in perm attribute (3) must equal the 
number of input tensor dimensions (2)
   
   
==========================================================================================
   PP-OCRv6_tiny representative grouped 1xK Conv nodes
   
==========================================================================================
   node= Conv.35 inputs= ['p2o.pd_op.unsqueeze.1.0', 'p2o.pd_op.unsqueeze.0.0'] 
outputs= ['p2o.pd_op.depthwise_conv2d.9.0'] attrs= {'dilations': [1, 1], 
'kernel_shape': [1, 5], 'strides': [1, 1], 'group': 160, 'pads': [0, 2, 0, 2]}
   
   
==========================================================================================
   FasterRCNN-12 raw ONNX -> TVM Relax from_onnx
   
==========================================================================================
   shape_dict = {'image': [3, 1, 1]}
   dtype_dict = {'image': 'float32'}
   Error converting operator Gather, with inputs: [R.shape([1, 3, 1, 1]), 2034]
   IMPORT_FAILED
   AssertionError: Only constant indices supported for shape gather.
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5173, in from_onnx
       self._construct_nodes(graph)
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5382, in _construct_nodes
       raise err
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5376, in _construct_nodes
       op = self._convert_operator(op_name, inputs, attr, self.opset)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5476, in _convert_operator
       sym = op_function(self.bb, inputs, attrs, [self._nodes, self._params])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 1086, in _impl_v13
       assert isinstance(indices, relax.Constant), (
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   AssertionError: Only constant indices supported for shape gather.
   
   
==========================================================================================
   FasterRCNN-12 prepared runtime_fp32.onnx -> TVM Relax from_onnx
   
==========================================================================================
   shape_dict = {'image': [3, 224, 224]}
   dtype_dict = {'image': 'float32'}
   Error converting operator TopK, with inputs: [R.sigmoid(lv242), v_5635]
   IMPORT_FAILED
   ValueError: TopK k must be a constant
              ^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5173, in from_onnx
       self._construct_nodes(graph)
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5382, in _construct_nodes
       raise err
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5376, in _construct_nodes
       op = self._convert_operator(op_name, inputs, attr, self.opset)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 5476, in _convert_operator
       sym = op_function(self.bb, inputs, attrs, [self._nodes, self._params])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File 
"/home/perception/Nanmur/tvm/python/tvm/relax/frontend/onnx/onnx_frontend.py", 
line 4154, in _impl_v11[11:04:08] 
/home/perception/Nanmur/tvm/src/relax/ir/block_builder.cc:66: Warning: 
BlockBuilder destroyed with remaining blocks!
   
       raise ValueError("TopK k must be a constant")
   ValueError: TopK k must be a constant
   
   
==========================================================================================
   
   ```
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to