Repository: onnx/onnx-tensorflow

Issue:
Upsample TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'
Hi,  
I have a problem with the upsample op when trying to prepare an onnx model converted from keras. Any idea of the solution ? Thx

> 
>   File "C:\Users\vthibault\anaconda3\envs\tensorflow\lib\site-packages\onnx_tf\backend.py", line 56, in prepare
>     return cls.onnx_model_to_tensorflow_rep(model, strict)
>   File "C:\Users\vthibault\anaconda3\envs\tensorflow\lib\site-packages\onnx_tf\backend.py", line 76, in onnx_model_to_tensorflow_rep
>     return cls._onnx_graph_to_tensorflow_rep(model.graph, opset_import, strict)
>   File "C:\Users\vthibault\anaconda3\envs\tensorflow\lib\site-packages\onnx_tf\backend.py", line 133, in _onnx_graph_to_tensorflow_rep
>     onnx_node, tensor_dict, handlers, opset=opset, strict=strict)
>   File "C:\Users\vthibault\anaconda3\envs\tensorflow\lib\site-packages\onnx_tf\backend.py", line 228, in _onnx_node_to_tensorflow_op
>     return handler.handle(node, tensor_dict=tensor_dict, strict=strict)
>   File "C:\Users\vthibault\anaconda3\envs\tensorflow\lib\site-packages\onnx_tf\handlers\handler.py", line 59, in handle
>     return ver_handle(node, **kwargs)
>   File "C:\Users\vthibault\anaconda3\envs\tensorflow\lib\site-packages\onnx_tf\handlers\backend\upsample.py", line 33, in version_7
>     new_height = np.floor(x_shape[2] * scales[2])
> TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'


Discussion:
My model uses dynamic shapes
A similar issue is opened, https://github.com/onnx/onnx-tensorflow/issues/464, for not supporting dynamic shapes. We are working on a solution now. Will provide updates later.

Resolving patch:
diff --git a/onnx_tf/handlers/backend/upsample.py b/onnx_tf/handlers/backend/upsample.py
--- a/onnx_tf/handlers/backend/upsample.py
+++ b/onnx_tf/handlers/backend/upsample.py
@@ -1,6 +1,5 @@
 import copy
 
-import numpy as np
 import tensorflow as tf
 
 from onnx_tf.common import exception
@@ -33,20 +32,28 @@ def args_check(cls, node, **kwargs):
   @classmethod
   def version_7(cls, node, **kwargs):
     x = kwargs["tensor_dict"][node.inputs[0]]
-    x_shape = x.get_shape().as_list()
+    x_shape = tf_shape(x)
     attrs = copy.deepcopy(node.attrs)
     scales = attrs["scales"]
-    new_height = np.floor(x_shape[2] * scales[2])
-    new_weight = np.floor(x_shape[3] * scales[3])
 
-    mode = attrs.get("mode", "nearest")
-    if mode.lower() == "bilinear" or mode.lower() == "linear":
-      mode = tf.image.ResizeMethod.BILINEAR
-    else:
-      mode = tf.image.ResizeMethod.NEAREST_NEIGHBOR
+    assert_n_c_scale_is_one = tf.Assert(
+        tf.logical_and(tf.equal(scales[0], 1), tf.equal(scales[1], 1)),
+        [scales])
+
+    with tf.control_dependencies([assert_n_c_scale_is_one]):
+      h_w_scale = scales[2:]
+      h_w_shape = x_shape[2:]
+      new_h_w_shape = tf.cast(h_w_scale * tf.cast(h_w_shape, type(h_w_scale[0])),
+                              tf.int32)
+
+      mode = attrs.get("mode", "nearest")
+      if mode.lower() == "bilinear" or mode.lower() == "linear":
+        mode = tf.image.ResizeMethod.BILINEAR
+      else:
+        mode = tf.image.ResizeMethod.NEAREST_NEIGHBOR
 
-    attrs["size"] = np.array((new_height, new_weight), dtype=np.int32)
-    attrs["method"] = mode
+      attrs["size"] = new_h_w_shape
+      attrs["method"] = mode
 
     return [
         cls.make_tensor_from_onnx_node(


Test patch: