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

   
   ## Expected behavior
   
   In the ONNX `LayerNormalization` spec, the bias input `B` is **optional**. 
When omitted, the operator should behave as if `B` is a tensor of zeros with 
the same shape as the scale `W`.
   
   ONNX Runtime accepts the no-bias form fine.
   
   ## Actual behavior
   
   The TVM frontend synthesizes a zero bias whose shape is `[data.shape[1]]` 
(i.e., the second dim of the input, unrelated to the normalization axes). This 
shape does not match `W`, and `relax.nn.layer_norm` then fails:
   
   ```
   tvm.error.InternalError: Op(relax.nn.layer_norm) requires the input gamma,
   beta, etc., to have size same as the lengths of the data on the given axes.
   However, there exists [T.int64(8)] and [T.int64(3)] that are unequal.
   ```
   
   ## Reproduction
   
   ```python
   import numpy as np
   import onnx
   from onnx import helper, TensorProto, numpy_helper
   import onnxruntime as ort
   from tvm.relax.frontend.onnx import from_onnx
   
   X = helper.make_tensor_value_info("X", TensorProto.FLOAT, [2, 3, 4, 8])
   Y = onnx.ValueInfoProto(); Y.name = "Y"
   W = numpy_helper.from_array(np.ones((8,), dtype=np.float32), "W")
   # axis = -1 (default), no B input
   node = helper.make_node("LayerNormalization", ["X", "W"], ["Y"], axis=-1, 
epsilon=1e-5)
   g = helper.make_graph([node], "g", [X], [Y], initializer=[W])
   m = helper.make_model(g, opset_imports=[helper.make_opsetid("", 17)])
   
   x = np.random.randn(2, 3, 4, 8).astype(np.float32)
   print("ORT shape:", ort.InferenceSession(m.SerializeToString()).run(None, 
{"X": x})[0].shape)
   # ORT shape: (2, 3, 4, 8)
   
   inf = onnx.shape_inference.infer_shapes(m)
   mod = from_onnx(inf)  # InternalError: gamma/beta size mismatch
   ```
   
   ## Root cause
   
   `python/tvm/relax/frontend/onnx/onnx_frontend.py`, 
`LayerNormalization._impl_v17`:
   
   ```python
   gamma_shape = get_const_tuple(scale.struct_info.shape)
   
   if bias is None:
       seq_len = data.struct_info.shape[1].value      # <-- wrong: uses data 
dim 1
       bias = relax.const([0.0] * seq_len, dtype="float32")
   else:
       beta_shape = get_const_tuple(bias.struct_info.shape)
       if gamma_shape != beta_shape:
           raise ValueError("gamma and beta shapes do not match")
   ```
   
   The synthesized `bias` should match `gamma_shape`, not `data.shape[1]`. With 
the example above, `gamma_shape = (8,)` but the bias is created with length 
`data.shape[1] = 3`.
   
   A secondary issue: indexing `data.struct_info.shape[1]` is fragile — it 
crashes if `data` is symbolic or has fewer than 2 dims.
   
   ## Suggested fix
   
   ```python
   if bias is None:
       bias = relax.const(np.zeros(gamma_shape, dtype="float32"))
   else:
       beta_shape = get_const_tuple(bias.struct_info.shape)
       if gamma_shape != beta_shape:
           raise ValueError("gamma and beta shapes do not match")
   ```
   
   ## Impact
   
   Any ONNX model exporting `LayerNormalization` without explicit `B` fails. 
PyTorch's `nn.LayerNorm(elementwise_affine=True, bias=False)` (added in PyTorch 
1.10 to control bias separately) exports exactly this form; many transformer 
variants (LLaMA-style architectures with no LayerNorm bias) hit this path.
   
   ## Environment
   
   - TVM: latest `main` (commit b172d5ea3)
   - Python: 3.11
   - ONNX Runtime: 1.24.4
   


-- 
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