diff --git a/.azure-pipelines/linux-CI-keras-applications-nightly.yml b/.azure-pipelines/linux-CI-keras-applications-nightly.yml index 13cac069..ed6df241 100644 --- a/.azure-pipelines/linux-CI-keras-applications-nightly.yml +++ b/.azure-pipelines/linux-CI-keras-applications-nightly.yml @@ -64,7 +64,7 @@ jobs: ONNX_PATH: onnx==1.6.0 INSTALL_KERAS: UNINSTALL_KERAS: pip uninstall keras -y - INSTALL_TENSORFLOW: pip install tensorflow==2.1.0 + INSTALL_TENSORFLOW: pip install tensorflow==2.2.0 INSTALL_ORT: pip install -i https://test.pypi.org/simple/ ort-nightly INSTALL_KERAS_RESNET: pip install keras-resnet INSTALL_TRANSFORMERS: pip install transformers diff --git a/.azure-pipelines/win32-CI-keras-applications-nightly.yml b/.azure-pipelines/win32-CI-keras-applications-nightly.yml index 134ffb29..ae7c29af 100644 --- a/.azure-pipelines/win32-CI-keras-applications-nightly.yml +++ b/.azure-pipelines/win32-CI-keras-applications-nightly.yml @@ -64,7 +64,7 @@ jobs: ONNX_PATH: onnx==1.6.0 INSTALL_KERAS: UNINSTALL_KERAS: pip uninstall keras -y - INSTALL_TENSORFLOW: pip install tensorflow==2.1.0 + INSTALL_TENSORFLOW: pip install tensorflow==2.2.0 INSTALL_ORT: pip install onnxruntime==1.1.1 INSTALL_KERAS_RESNET: pip install keras-resnet INSTALL_TRANSFORMERS: pip install transformers diff --git a/applications/nightly_build/test_keras_applications_v2.py b/applications/nightly_build/test_keras_applications_v2.py index 9689721c..c3645772 100644 --- a/applications/nightly_build/test_keras_applications_v2.py +++ b/applications/nightly_build/test_keras_applications_v2.py @@ -54,7 +54,6 @@ def test_InceptionV3(self): keras.backend.set_learning_phase(0) InceptionV3 = keras.applications.inception_v3.InceptionV3 model = InceptionV3(include_top=True) - model.save('inception.h5') res = run_image(model, self.model_files, img_path, target_size=299, tf_v2=True) self.assertTrue(*res) diff --git a/keras2onnx/parser.py b/keras2onnx/parser.py index c088edee..7dfeb021 100644 --- a/keras2onnx/parser.py +++ b/keras2onnx/parser.py @@ -482,15 +482,24 @@ def _get_output_nodes(node_list, node): return [n_ for n_ in node_list if n_ not in nodes_has_children] # need to keep the order. +def _filter_out_input(node_name): + # tf.keras BN layer sometimes create a placeholder node 'scale' in tf 2.x. + # It creates 'cond/input' since tf 2.2. + # Given bn layer will be converted in a whole layer, it's fine to just filter this node out. + filter_patterns = [r"batch_normalization_\d+\/scale$", r"batch_normalization_\d+\/cond/input"] + filter_out = False + for pattern_ in filter_patterns: + filter_out = filter_out or re.match(pattern_, node_name) + return filter_out + + def _advance_by_input(cur_node, layer_nodes, subgraph, inputs, graph_inputs, q_overall): for input_ in cur_node.inputs: predecessor = input_.op - if is_placeholder_node(predecessor): - # tf.keras BN layer sometimes create a placeholder node 'scale' in tf2.x. - # Given bn layer will be converted in a whole layer, it's fine to just filter this node out. - if not re.match(r"batch_normalization_\d+\/scale$", predecessor.name): - inputs.add(predecessor) - graph_inputs.add(predecessor) + if is_placeholder_node(predecessor) and not _filter_out_input(predecessor.name): + inputs.add(predecessor) + graph_inputs.add(predecessor) + continue if predecessor in layer_nodes or len(layer_nodes) == 0: subgraph.append(predecessor) else: @@ -735,7 +744,15 @@ def parse_graph_modeless(topo, graph, target_opset, input_names, output_names, k for ts_i_ in input_tensors: var_type = _adjust_input_batch_size(infer_variable_type(ts_i_, target_opset)) - str_value = ts_i_.name + if ts_i_.name.endswith(':0'): + str_value = ts_i_.name[:-2] + op = top_level.declare_local_operator(TYPES.Identity) + var0 = top_level.get_local_variable_or_declare_one(str_value, var_type) + var1 = top_level.get_local_variable_or_declare_one(ts_i_.name, var_type) + op.add_input(var0) + op.add_output(var1) + else: + str_value = ts_i_.name top_level.get_local_variable_or_declare_one(str_value, var_type) topo.raw_model.add_input_name(str_value) diff --git a/tests/test_utils.py b/tests/test_utils.py index 2dba8be4..43220f45 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -137,7 +137,9 @@ def run_onnx_runtime(case_name, onnx_model, data, expected, model_files, rtol=1. if expected is None: return - if not isinstance(expected, list): + if isinstance(expected, tuple): + expected = list(expected) + elif not isinstance(expected, list): expected = [expected] res = all(np.allclose(expected[n_], actual[n_], rtol=rtol, atol=atol) for n_ in range(len(expected)))