Skip to content

[relax][frontend][tflite] Add tests for l2_normalization/slice/reverse_v2#19371

Open
0xjah wants to merge 3 commits intoapache:mainfrom
0xjah:pr/tflite-relax-l2norm-slice-reversev2-tests
Open

[relax][frontend][tflite] Add tests for l2_normalization/slice/reverse_v2#19371
0xjah wants to merge 3 commits intoapache:mainfrom
0xjah:pr/tflite-relax-l2norm-slice-reversev2-tests

Conversation

@0xjah
Copy link
Copy Markdown

@0xjah 0xjah commented Apr 8, 2026

This PR adds Relax TFLite frontend test coverage for:

  • L2_NORMALIZATION
  • SLICE
  • REVERSE_V2

Part of fixing #18971.

Copy link
Copy Markdown
Contributor

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

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 unit tests for the TFLite frontend in Relax, specifically for L2 normalization, slice, and reverse_v2 operations. The review feedback suggests improving test coverage by parameterizing these tests to handle various input shapes, axes, and edge cases, such as negative size values in the slice operation.

…everse_v2

- Fix test_l2_normalization: Remove expected module using non-existent R.nn.l2_normalize
  - l2_normalize is not yet implemented in relax.op.nn
  - Keep test for TensorFlow conversion without structural equality check

- Fix test_slice: Add missing 'axes' parameter to strided_slice
  - strided_slice() requires axes parameter alongside begin and end
  - Changed from R.strided_slice(x, begin=..., end=...)
           to R.strided_slice(x, axes=[0, 1], begin=..., end=...)

- Fix test_reverse_v2: Replace non-existent R.reverse with R.flip
  - R.reverse doesn't exist in relax.op
  - Changed from R.reverse(x, axis=1) to R.flip(x, axis=1)
@tlopex
Copy link
Copy Markdown
Member

tlopex commented Apr 9, 2026

Hi @0xjah Can you have a look at the CI error and fix it? Thanks!

…se_v2

- Fix convert_l2_normalization: Implement manually since relax.op.nn.l2_normalize doesn't exist
  - L2 norm formula: output = input / sqrt(sum(input^2) + eps)
  - Uses existing ops: square, sum, sqrt, divide
  - Applied along last axis with epsilon=1e-12

- Fix convert_slice: Add missing axes parameter to strided_slice call
  - strided_slice requires axes alongside begin and end parameters
  - Changed from strided_slice(data, begin, end) to strided_slice(data, axes=list(range(rank)), begin, end)

- Fix convert_reverse_v2: Replace non-existent relax.op.reverse with relax.op.flip
  - Both operations reverse along specified axis but flip is the available function in relax
@OmarAzizi
Copy link
Copy Markdown
Contributor

It looks like the Gemini bot suggestions on test_slice and test_reverse_v2 were marked resolved, but weren't actually addressed in the code.

The parameterization suggestions are worth doing since single-shape tests don't catch edge cases like size=-1 in slice or multi-axis reversal.

# L2 normalization is applied along the last axis
squared = relax.op.square(in_expr)
sum_squared = relax.op.sum(squared, axis=input_tensor_rank - 1, keepdims=True)
denom = relax.op.sqrt(sum_squared + 1e-12)
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.

sum_squared is a Relax Expr, so you can't use the + operator with a raw Python float directly. This is what's causing the TypeError: Please convert 1e-12 failure in the CI. You need to wrap the epsilon:

Suggested change
denom = relax.op.sqrt(sum_squared + 1e-12)
eps = relax.const(1e-12, dtype="float32")
denom = relax.op.sqrt(relax.op.add(sum_squared, eps))

Comment on lines +2260 to +2261
axes = list(range(input_tensor_rank))
out = relax.op.strided_slice(in_expr, axes=axes, begin=begin, end=end)
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.

The begin and end values read from the TFLite flatbuffer come back as numpy.int32, and strided_slice doesn't accept those. That's why you get the TypeError: Cannot convert 1 with type <class 'numpy.int32'> CI failure. Cast them to plain Python ints before passing:

Suggested change
axes = list(range(input_tensor_rank))
out = relax.op.strided_slice(in_expr, axes=axes, begin=begin, end=end)
axes = list(range(len(begin)))
begin = [int(b) for b in begin]
end = [int(e) for e in end]
axes = list(range(input_tensor_rank))
out = relax.op.strided_slice(in_expr, axes=axes, begin=begin, end=end)

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.

3 participants