From 2eea7f88a69bc0cc881d0f0b6d00a7cc4063a93c Mon Sep 17 00:00:00 2001 From: Youngsik Yang Date: Thu, 15 May 2025 09:43:35 +0900 Subject: [PATCH] [FRONTEND][ONNX] Make bias input optional in LayerNormalization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change updates the LayerNormalization converter to support ONNX models where the optional bias input is not provided. When bias is missing, an empty bias tensor is generated. This behavior aligns with the ONNX’s spec for LayerNormalization (opset 17+) where the bias input is officially optional. --- .../tvm/relax/frontend/onnx/onnx_frontend.py | 4 ++++ tests/python/relax/test_frontend_onnx.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/python/tvm/relax/frontend/onnx/onnx_frontend.py b/python/tvm/relax/frontend/onnx/onnx_frontend.py index 24217184b57c..32b2c508f009 100644 --- a/python/tvm/relax/frontend/onnx/onnx_frontend.py +++ b/python/tvm/relax/frontend/onnx/onnx_frontend.py @@ -2489,6 +2489,10 @@ def _impl_v17(cls, bb, inputs, attr, params): axis = attr.get("axis", -1) epsilon = attr.get("epsilon", 1e-05) + if bias is None: + seq_len = data.struct_info.shape[1].value + bias = relax.const([0.0] * seq_len, dtype="float32") + output = relax.op.nn.layer_norm(data, scale, bias, axis, epsilon) # Onnx layernorm has 3 outputs but only the first is used. # We construct two empty constants for this. diff --git a/tests/python/relax/test_frontend_onnx.py b/tests/python/relax/test_frontend_onnx.py index f533c7945548..b7305d4810ed 100644 --- a/tests/python/relax/test_frontend_onnx.py +++ b/tests/python/relax/test_frontend_onnx.py @@ -1303,6 +1303,24 @@ def test_layer_norm(): model = helper.make_model(graph, producer_name="layer_norm_test") check_correctness(model) + # Test case with no bias that is an optional input + layer_norm_node = helper.make_node("LayerNormalization", ["a", "b"], ["d"], epsilon=1e-12) + + graph = helper.make_graph( + [layer_norm_node], + "layer_norm_test", + inputs=[ + helper.make_tensor_value_info("a", TensorProto.FLOAT, [32, 32]), + helper.make_tensor_value_info("b", TensorProto.FLOAT, [32]), + ], + outputs=[ + helper.make_tensor_value_info("d", TensorProto.FLOAT, [32, 32]), + ], + ) + + model = helper.make_model(graph, producer_name="layer_norm_test") + check_correctness(model) + # TODO Enable dynamism @pytest.mark.parametrize("dynamic", [False])