diff --git a/.github/workflows/keras_application_test_ci.yml b/.github/workflows/keras_application_test_ci.yml index 1529cbc75..75d88fb07 100644 --- a/.github/workflows/keras_application_test_ci.yml +++ b/.github/workflows/keras_application_test_ci.yml @@ -34,7 +34,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py38-TF2.9-ubuntu) path: ./**/test-results-*.xml @@ -58,7 +58,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py310-TF2.15-ubuntu) path: ./**/test-results-*.xml @@ -82,7 +82,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py37-TF1.15-ubuntu) path: ./**/test-results-*.xml @@ -119,7 +119,7 @@ jobs: onnx_version: ${{ matrix.onnx_version }} - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (${{ matrix.python_version }}-${{ matrix.tf_version }}-${{ matrix.os }}) path: ./**/test-results*.xml @@ -134,7 +134,7 @@ jobs: if: always() steps: - name: Download Artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: path: artifacts diff --git a/.github/workflows/keras_unit_test_ci.yml b/.github/workflows/keras_unit_test_ci.yml index b6702698c..a8b35f67b 100644 --- a/.github/workflows/keras_unit_test_ci.yml +++ b/.github/workflows/keras_unit_test_ci.yml @@ -33,7 +33,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py38-TF2.9-ubuntu) path: ./**/test-results-*.xml @@ -57,7 +57,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py310-TF2.15-ubuntu) path: ./**/test-results-*.xml @@ -81,7 +81,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py37-TF1.15-ubuntu) path: ./**/test-results-*.xml @@ -118,7 +118,7 @@ jobs: onnx_version: ${{ matrix.onnx_version }} - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (${{ matrix.python_version }}-${{ matrix.tf_version }}-${{ matrix.os }}) path: ./**/test-results*.xml @@ -133,7 +133,7 @@ jobs: if: always() steps: - name: Download Artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: path: artifacts diff --git a/.github/workflows/pretrained_model_test_ci.yml b/.github/workflows/pretrained_model_test_ci.yml index 96077d68a..57e4409be 100644 --- a/.github/workflows/pretrained_model_test_ci.yml +++ b/.github/workflows/pretrained_model_test_ci.yml @@ -37,7 +37,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py38-TF2.9-18-ubuntu) path: ./**/test-results-*.xml @@ -64,7 +64,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py310-TF2.15-18-ubuntu) path: ./**/test-results-*.xml @@ -90,7 +90,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py37-TF1.15-15-ubuntu) path: ./**/test-results-*.xml @@ -132,7 +132,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py${{ matrix.python_version }}_TF${{ matrix.tf_version }}_${{ matrix.os }}_${{ matrix.opset_version }}_${{ matrix.ort_version }}_${{ matrix.skip_tflite }}) path: ./**/test-results-*.xml @@ -147,7 +147,7 @@ jobs: if: always() steps: - name: Download Artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: path: artifacts diff --git a/.github/workflows/unit_test_ci.yml b/.github/workflows/unit_test_ci.yml index bdfae9277..1143963dc 100644 --- a/.github/workflows/unit_test_ci.yml +++ b/.github/workflows/unit_test_ci.yml @@ -37,7 +37,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py38-TF2.9-18-ubuntu) path: ./**/test-results-*.xml @@ -64,7 +64,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py310-TF2.15-18-ubuntu) path: ./**/test-results-*.xml @@ -115,7 +115,7 @@ jobs: - name: Upload Test Results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Test Results (Py${{ matrix.python_version }}_TF${{ matrix.tf_version }}_${{ matrix.os }}_${{ matrix.opset_version }}_${{ matrix.ort_version }}_${{ matrix.skip_tflite }}) path: ./**/test-results-*.xml @@ -130,7 +130,7 @@ jobs: if: always() steps: - name: Download Artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: path: artifacts diff --git a/.gitignore b/.gitignore index 29d7d4ed0..af4dcac1f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ __pycache__ .cache .eggs *.egg-info +*.onnx run.sh node_modules/* tests/tfhub/*/*.onnx diff --git a/tests/keras2onnx_unit_tests/conftest.py b/tests/keras2onnx_unit_tests/conftest.py index 758c31f7f..f3b518d44 100644 --- a/tests/keras2onnx_unit_tests/conftest.py +++ b/tests/keras2onnx_unit_tests/conftest.py @@ -26,7 +26,9 @@ def runner_func(*args, **kwargs): return run_onnx_runtime(*args, model_files, **kwargs) # Ensure Keras layer naming is reset for each function - K.reset_uids() + if hasattr(K, "reset_uids"): + # see https://github.com/onnx/tensorflow-onnx/issues/2370 + K.reset_uids() # Reset the TensorFlow session to avoid resource leaking between tests K.clear_session() diff --git a/tests/keras2onnx_unit_tests/test_utils.py b/tests/keras2onnx_unit_tests/test_utils.py index ae46a4fa5..af10896a1 100644 --- a/tests/keras2onnx_unit_tests/test_utils.py +++ b/tests/keras2onnx_unit_tests/test_utils.py @@ -18,7 +18,8 @@ # Mapping opset to ONNXRuntime version. ORT_OPSET_VERSION = { "1.6.0": 13, "1.7.0": 13, "1.8.0": 14, "1.9.0": 15, "1.10.0": 15, "1.11.0": 16, - "1.12.0": 17, "1.13.0": 17, "1.14.0": 18, "1.15.0": 18, "1.16.0": 18 + "1.12.0": 17, "1.13.0": 17, "1.14.0": 18, "1.15.0": 18, "1.16.0": 18, "1.17.0": 18, + "1.18.0": 18, "1.19.0": 18, "1.20.0": 18, } working_path = os.path.abspath(os.path.dirname(__file__)) @@ -319,13 +320,14 @@ def get_max_opset_supported_by_ort(): if ort_ver in ORT_OPSET_VERSION.keys(): return ORT_OPSET_VERSION[ort_ver] else: - print("Given onnxruntime version doesn't exist in ORT_OPSET_VERSION: {}".format(ort_ver)) return None except ImportError: return None def get_max_opset_supported_for_test(): + if get_max_opset_supported_by_ort() is None: + return get_maximum_opset_supported() return min(get_max_opset_supported_by_ort(), get_maximum_opset_supported()) diff --git a/tests/test_issue_2025.py b/tests/test_issue_2025.py new file mode 100644 index 000000000..57ddae632 --- /dev/null +++ b/tests/test_issue_2025.py @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: Apache-2.0 +# pylint: disable=missing-docstring,unused-import,import-outside-toplevel,unused-variable +import unittest +from backend_test_base import Tf2OnnxBackendTestBase + + +class TestIssue2025(Tf2OnnxBackendTestBase): + def test_tanhgrad(self): + + import tensorflow as tf + import tf2onnx + from tf2onnx.handler import tf_op + import numpy as np + + @tf_op("TanhGrad") + class TanhGrad: + @classmethod + def version_1(cls, ctx, node, **_kwargs): + tanh_output = node.input[0] + grad = node.input[1] + square = ctx.make_node("Mul", [tanh_output, tanh_output]) + one = ctx.make_const( + name=node.name + "_one", np_val=np.array(1, dtype=np.float32) + ) + derivative = ctx.make_node("Sub", [one.output[0], square.output[0]]) + result = ctx.make_node("Mul", [derivative.output[0], grad]) + ctx.replace_all_inputs(node.output[0], result.output[0]) + return result.output + + class QFGrad(tf.keras.Model): + def __init__(self): + super().__init__() + self.output_names = ["grad"] + + def calc_q_grad(self, x): + with tf.GradientTape() as tape: + tape.watch(x) + y = tf.keras.activations.tanh(tf.abs(x)) + # tf.raw_ops.TanhGrad + x_grad = tape.gradient(y, x) + return x_grad + + def call(self, x): + q_grad = self.calc_q_grad(x) + return q_grad + + model = QFGrad() + x = tf.random.uniform((1, 1, 6)) + model(x) + + save_path = "test_tanhgrad.onnx" + model_proto, _ = tf2onnx.convert.from_keras( + model=model, + input_signature=(tf.TensorSpec((1, 1, 6), dtype=tf.float32, name="x"),), + opset=13, + output_path=save_path, + ) + node_types = [n.op_type for n in model_proto.graph.node] + self.assertNotIn("TanhGrad", node_types) + + + +if __name__ == "__main__": + unittest.main()