Skip to content

[torchlib] Fix aten_conv3d generating a 2D bias when bias is missing#2935

Open
javierdejesusda wants to merge 1 commit into
microsoft:mainfrom
javierdejesusda:fix/2931-conv3d-missing-bias-shape
Open

[torchlib] Fix aten_conv3d generating a 2D bias when bias is missing#2935
javierdejesusda wants to merge 1 commit into
microsoft:mainfrom
javierdejesusda:fix/2931-conv3d-missing-bias-shape

Conversation

@javierdejesusda

Copy link
Copy Markdown

The bias is None branch of aten_conv3d was copy-pasted from aten_conv3d_complex, so it builds
the bias shape with Concat(weight_dim_0, [2]), producing a rank-2 bias [out_channels, 2]. ONNX
Conv requires a 1D bias [out_channels]. aten_conv1d and aten_conv2d already use the correct
pattern.

-        bias_shape = op.Concat(weight_dim_0, op.Constant(value_ints=[2]), axis=0)
+        bias_shape = op.Expand(weight_dim_0, op.Constant(value_ints=[1]))

aten_conv3d_complex is left unchanged - its rank-2 bias is correct for the real/imag pair.

Adds test_conv3d_without_bias_produces_1d_bias, which asserts the synthesized Conv bias is rank 1.
It fails (2 != 1) before the fix and passes after. (assert_onnx_program alone misses this because
the rank-2 bias broadcasts numerically.)

Fixes #2931

## Problem

The missing-bias branch of aten_conv3d was copy-pasted from
aten_conv3d_complex, so it built the bias shape with
Concat(weight_dim_0, [2]). That produces a rank-2 bias ([out_channels, 2]),
which violates the ONNX Conv spec (B must be 1D, shape [out_channels]) and
can cause downstream issues. aten_conv1d and aten_conv2d already use the
correct pattern.

## Fix

Use the same construction as aten_conv2d / aten_conv1d:

    bias_shape = op.Expand(weight_dim_0, op.Constant(value_ints=[1]))

aten_conv3d_complex is left unchanged: its rank-2 bias is correct for the
real/imag pair of a complex tensor.

## Tests

Added test_conv3d_without_bias_produces_1d_bias in
tests/function_libs/torch_lib/e2e_ops_tests.py. It exports a bias-less
nn.Conv3d and asserts the synthesized Conv bias is 1D. assert_onnx_program
alone does not catch the bug because the rank-2 bias broadcasts numerically,
so the test checks the bias rank explicitly. It fails before this change and
passes after.

Fixes microsoft#2931
@javierdejesusda

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Comment on lines +1022 to +1032
# The bias synthesized for a bias-less conv must be 1D ([out_channels]) to
# match the ONNX Conv spec. See https://github.com/microsoft/onnxscript/issues/2931.
inferred = onnx.shape_inference.infer_shapes(onnx_program.model_proto, data_prop=True)
shape_ranks = {
value_info.name: len(value_info.type.tensor_type.shape.dim)
for value_info in inferred.graph.value_info
if value_info.type.tensor_type.HasField("shape")
}
conv_nodes = [node for node in inferred.graph.node if node.op_type == "Conv"]
self.assertEqual(len(conv_nodes), 1)
self.assertEqual(shape_ranks[conv_nodes[0].input[2]], 1)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok to review this part as assert_onnx_program will already run the model and validate the shapes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before I drop it: the synthesized bias is all zeros, so assert_onnx_program passes even with the rank-2 bias. The conv output is numerically identical, so only the rank check fails (2 != 1) before the fix, which is the part that actually pins this regression. If you'd rather rely on assert_onnx_program for path coverage here, I'll remove the block and the onnx import to match the convention in the suite.

import math
import unittest

import onnx

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import onnx

@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.66%. Comparing base (c72e810) to head (761aea4).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2935   +/-   ##
=======================================
  Coverage   72.66%   72.66%           
=======================================
  Files         259      259           
  Lines       31748    31748           
  Branches     3005     3005           
=======================================
  Hits        23069    23069           
  Misses       7660     7660           
  Partials     1019     1019           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

aten::conv3d onnx export bug when bias is missing

2 participants