Skip to content

[Relax][Frontend][ONNX] Add GroupNormalization support#19907

Open
napronald wants to merge 1 commit into
apache:mainfrom
napronald:relax-onnx-group-normalization
Open

[Relax][Frontend][ONNX] Add GroupNormalization support#19907
napronald wants to merge 1 commit into
apache:mainfrom
napronald:relax-onnx-group-normalization

Conversation

@napronald

Copy link
Copy Markdown

Summary

Adds ONNX frontend support for GroupNormalization by mapping it to the existing relax.op.nn.group_norm.

Supports opset 18 per-group scale/bias expansion, opset 21 per-channel scale/bias, and stash_type cast behavior.

Testing

Includes structural checks for opset 18, opset 21, rank-3 inputs, and fp16 stash_type paths.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request adds support for converting ONNX GroupNormalization nodes (opsets 18 and 21) into equivalent Relax expressions, along with comprehensive unit tests to verify correctness. The feedback suggests optimizing the opset 18 implementation by resolving scale and bias to constants at import time using get_constant. If they are constants, they can be expanded directly using NumPy (_np.repeat), which avoids adding redundant reshape and broadcast_to operators to the generated Relax graph.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +3901 to +3903
data = inputs[0]
scale = inputs[1]
bias = inputs[2]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

We can use get_constant to resolve scale and bias to constants if they are initializers. This allows us to perform the per-group to per-channel expansion at import time using NumPy, avoiding redundant reshape and broadcast_to operators in the Relax graph.

Suggested change
data = inputs[0]
scale = inputs[1]
bias = inputs[2]
data = inputs[0]
scale = get_constant(inputs[1], params)
bias = get_constant(inputs[2], params)

Comment on lines +3938 to +3944
scale = relax.op.reshape(scale, [num_groups, 1])
scale = relax.op.broadcast_to(scale, [num_groups, channels_per_group])
scale = relax.op.reshape(scale, [channels])

bias = relax.op.reshape(bias, [num_groups, 1])
bias = relax.op.broadcast_to(bias, [num_groups, channels_per_group])
bias = relax.op.reshape(bias, [channels])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

If scale and bias are resolved to constants, we can expand them directly using _np.repeat at import time. This simplifies the generated Relax graph by eliminating unnecessary reshape and broadcast_to operations.

Suggested change
scale = relax.op.reshape(scale, [num_groups, 1])
scale = relax.op.broadcast_to(scale, [num_groups, channels_per_group])
scale = relax.op.reshape(scale, [channels])
bias = relax.op.reshape(bias, [num_groups, 1])
bias = relax.op.broadcast_to(bias, [num_groups, channels_per_group])
bias = relax.op.reshape(bias, [channels])
if isinstance(scale, relax.Constant):
scale = relax.const(_np.repeat(scale.data.numpy(), channels_per_group), scale.ty.dtype)
else:
scale = relax.op.reshape(scale, [num_groups, 1])
scale = relax.op.broadcast_to(scale, [num_groups, channels_per_group])
scale = relax.op.reshape(scale, [channels])
if isinstance(bias, relax.Constant):
bias = relax.const(_np.repeat(bias.data.numpy(), channels_per_group), bias.ty.dtype)
else:
bias = relax.op.reshape(bias, [num_groups, 1])
bias = relax.op.broadcast_to(bias, [num_groups, channels_per_group])
bias = relax.op.reshape(bias, [channels])

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant