add pt2tf tool
This commit is contained in:
@@ -0,0 +1,305 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
import unittest
|
||||
|
||||
from onnx_tf.backend import onnx_graph_to_tensorflow_rep
|
||||
from onnx_tf.common.legacy import legacy_opset_pre_ver
|
||||
from onnx import defs
|
||||
from onnx import helper
|
||||
from onnx import TensorProto
|
||||
|
||||
# Run the following test in graph mode
|
||||
tf.compat.v1.disable_eager_execution()
|
||||
|
||||
|
||||
class TestDynamicShape(unittest.TestCase):
|
||||
""" Tests for dynamic shape support
|
||||
"""
|
||||
|
||||
def _get_rnd_float32(self, low=-1.0, high=1.0, shape=None):
|
||||
output = np.random.uniform(low, high, shape)
|
||||
if shape is None:
|
||||
return np.float32(output)
|
||||
else:
|
||||
return output.astype(np.float32)
|
||||
|
||||
def _get_rnd_int(self, low, high=None, shape=None, dtype=np.int32):
|
||||
return np.random.randint(low, high, size=shape, dtype=dtype)
|
||||
|
||||
def test_arg_max(self):
|
||||
if legacy_opset_pre_ver(12):
|
||||
raise unittest.SkipTest(
|
||||
"ONNX version {} doesn't support select_last_index attribute for ArgMax that depends on shape.".format(
|
||||
defs.onnx_opset_version()))
|
||||
axis = 1
|
||||
node_def = helper.make_node("ArgMax",
|
||||
inputs=['X'],
|
||||
outputs=['Y'],
|
||||
axis=axis,
|
||||
keepdims=0,
|
||||
select_last_index=1)
|
||||
graph_def = helper.make_graph(
|
||||
[node_def],
|
||||
name="test_unknown_shape",
|
||||
inputs=[
|
||||
helper.make_tensor_value_info("X", TensorProto.FLOAT, [None, None])
|
||||
],
|
||||
outputs=[
|
||||
helper.make_tensor_value_info("Y", TensorProto.FLOAT, [None, None])
|
||||
])
|
||||
x = np.array([[ 1, 2, 3, 5, 3, 4, 5, 1 ], [ 2, 9, 3, 5, 9, 4, 5, 1 ]])
|
||||
tf_rep = onnx_graph_to_tensorflow_rep(graph_def)
|
||||
output = tf_rep.run({"X": x})
|
||||
expected_output = np.argmax(np.flip(x, axis), axis=axis)
|
||||
expected_output = x.shape[axis] - expected_output - 1
|
||||
np.testing.assert_almost_equal(output['Y'], expected_output)
|
||||
|
||||
def test_arg_min(self):
|
||||
if legacy_opset_pre_ver(12):
|
||||
raise unittest.SkipTest(
|
||||
"ONNX version {} doesn't support select_last_index attribute for ArgMin that depends on shape.".format(
|
||||
defs.onnx_opset_version()))
|
||||
axis = 1
|
||||
node_def = helper.make_node("ArgMin",
|
||||
inputs=['X'],
|
||||
outputs=['Y'],
|
||||
axis=axis,
|
||||
keepdims=0,
|
||||
select_last_index=1)
|
||||
graph_def = helper.make_graph(
|
||||
[node_def],
|
||||
name="test_unknown_shape",
|
||||
inputs=[
|
||||
helper.make_tensor_value_info("X", TensorProto.FLOAT, [None, None])
|
||||
],
|
||||
outputs=[
|
||||
helper.make_tensor_value_info("Y", TensorProto.FLOAT, [None, None])
|
||||
])
|
||||
x = np.array([[ 1, 2, 3, 5, 3, 4, 5, 1 ], [ 2, 7, 3, 5, 2, 4, 5, 6 ]])
|
||||
tf_rep = onnx_graph_to_tensorflow_rep(graph_def)
|
||||
output = tf_rep.run({"X": x})
|
||||
expected_output = np.argmin(np.flip(x, axis), axis=axis)
|
||||
expected_output = x.shape[axis] - expected_output - 1
|
||||
np.testing.assert_almost_equal(output['Y'], expected_output)
|
||||
|
||||
def _batch_normalization(self, x, mean, variance, bias, scale,
|
||||
variance_epsilon):
|
||||
inv = np.reciprocal(np.sqrt(variance + variance_epsilon))
|
||||
if scale is not None:
|
||||
inv *= scale
|
||||
return x * inv + (bias - mean * inv if bias is not None else -mean * inv)
|
||||
|
||||
def test_batch_normalization(self):
|
||||
if legacy_opset_pre_ver(6):
|
||||
raise unittest.SkipTest("Backend doesn't support consumed flag")
|
||||
node_def = helper.make_node("BatchNormalization",
|
||||
["X", "scale", "bias", "mean", "var"], ["Y"],
|
||||
epsilon=0.001)
|
||||
graph_def = helper.make_graph(
|
||||
[node_def],
|
||||
name="test_unknown_shape",
|
||||
inputs=[
|
||||
helper.make_tensor_value_info("X", TensorProto.FLOAT, [None, None, None, None]),
|
||||
helper.make_tensor_value_info("scale", TensorProto.FLOAT, [None]),
|
||||
helper.make_tensor_value_info("bias", TensorProto.FLOAT, [None]),
|
||||
helper.make_tensor_value_info("mean", TensorProto.FLOAT, [None]),
|
||||
helper.make_tensor_value_info("var", TensorProto.FLOAT, [None])
|
||||
],
|
||||
outputs=[
|
||||
helper.make_tensor_value_info("Y", TensorProto.FLOAT, [None, None, None, None])
|
||||
])
|
||||
x_shape = [3, 5, 4, 2]
|
||||
param_shape = [5]
|
||||
_param_shape = [1, 5, 1, 1]
|
||||
x = self._get_rnd_float32(0, 1, shape=x_shape)
|
||||
m = self._get_rnd_float32(0, 1, shape=param_shape)
|
||||
_m = m.reshape(_param_shape)
|
||||
v = self._get_rnd_float32(0, 1, shape=param_shape)
|
||||
_v = v.reshape(_param_shape)
|
||||
scale = self._get_rnd_float32(0, 1, shape=param_shape)
|
||||
_scale = scale.reshape(_param_shape)
|
||||
bias = self._get_rnd_float32(0, 1, shape=param_shape)
|
||||
_bias = bias.reshape(_param_shape)
|
||||
golden = self._batch_normalization(x, _m, _v, _bias, _scale, 0.001)
|
||||
tf_rep = onnx_graph_to_tensorflow_rep(graph_def)
|
||||
output = tf_rep.run({"X": x, "scale": scale, "bias": bias, "mean": m, "var": v})
|
||||
np.testing.assert_almost_equal(output["Y"], golden, decimal=5)
|
||||
|
||||
def test_conv_transpose(self):
|
||||
# test dynamic batch size on transpose of 2d convolution
|
||||
pads = [1, 1, 1, 1]
|
||||
x_shape = [1, 3, 4, 6]
|
||||
x = self._get_rnd_float32(shape=x_shape)
|
||||
weight_shape = [3, 5, 2, 2]
|
||||
weights = self._get_rnd_float32(shape=weight_shape)
|
||||
|
||||
node_def = helper.make_node("ConvTranspose", ["X", "weights"], ["Y"],
|
||||
pads=pads)
|
||||
graph_def = helper.make_graph(
|
||||
[node_def],
|
||||
name="test_unknown_shape",
|
||||
inputs=[
|
||||
helper.make_tensor_value_info("X", TensorProto.FLOAT, [None, 3, 4, 6]),
|
||||
helper.make_tensor_value_info("weights", TensorProto.FLOAT, weight_shape)
|
||||
],
|
||||
outputs=[
|
||||
helper.make_tensor_value_info("Y", TensorProto.FLOAT, [None, None, None, None])
|
||||
])
|
||||
|
||||
tf_rep = onnx_graph_to_tensorflow_rep(graph_def)
|
||||
output = tf_rep.run({"X": x, "weights": weights})
|
||||
|
||||
padh_left = weight_shape[2] - 1 - pads[0]
|
||||
padh_right = weight_shape[2] - 1 - pads[1]
|
||||
padw_left = weight_shape[3] - 1 - pads[2]
|
||||
padw_right = weight_shape[3] - 1 - pads[3]
|
||||
|
||||
kh = weight_shape[2]
|
||||
kw = weight_shape[3]
|
||||
outh = x_shape[2] + padh_right + padh_right - (kh - 1)
|
||||
outw = x_shape[3] + padw_right + padw_right - (kw - 1)
|
||||
|
||||
out_shape = [x_shape[0], weight_shape[1], outh, outw]
|
||||
|
||||
test_output = np.zeros(out_shape)
|
||||
for b in range(0, x_shape[0]):
|
||||
for m in range(0, weight_shape[1]):
|
||||
for c in range(0, x_shape[1]):
|
||||
for h in range(0, outh):
|
||||
for w in range(0, outw):
|
||||
for k1 in range(h, h + kh):
|
||||
for k2 in range(w, w + kw):
|
||||
if (k1 - padh_left >= 0 and k2 - padw_left >= 0):
|
||||
test_output[b][m][h][w] += x[b][c][k1 - padh_left][
|
||||
k2 - padw_left] * weights[c][m][kh + h - 1 -
|
||||
k1][kw + w - 1 - k2]
|
||||
|
||||
np.testing.assert_almost_equal(output["Y"], test_output, decimal=5)
|
||||
|
||||
def test_slice(self):
|
||||
# test case 1 with normal inputs
|
||||
axes = [0, 1, 2]
|
||||
starts = [0, 0, 0]
|
||||
ends = [2, 2, 2]
|
||||
|
||||
if legacy_opset_pre_ver(10):
|
||||
node_def = helper.make_node("Slice", ["X"], ["S"],
|
||||
axes=axes,
|
||||
starts=starts,
|
||||
ends=ends)
|
||||
graph_def = helper.make_graph(
|
||||
[node_def],
|
||||
name="test_unknown_shape",
|
||||
inputs=[
|
||||
helper.make_tensor_value_info("X", TensorProto.FLOAT,
|
||||
[None, None, None])
|
||||
],
|
||||
outputs=[
|
||||
helper.make_tensor_value_info("S", TensorProto.FLOAT,
|
||||
[None, None, None])
|
||||
])
|
||||
else:
|
||||
node_def = helper.make_node("Slice",
|
||||
["X", "starts", "ends", "axes"],
|
||||
["S"])
|
||||
graph_def = helper.make_graph(
|
||||
[node_def],
|
||||
name="test_unknown_shape",
|
||||
inputs=[
|
||||
helper.make_tensor_value_info("X", TensorProto.FLOAT,
|
||||
[None, None, None]),
|
||||
helper.make_tensor_value_info("starts", TensorProto.INT32,
|
||||
[None]),
|
||||
helper.make_tensor_value_info("ends", TensorProto.INT32,
|
||||
[None]),
|
||||
helper.make_tensor_value_info("axes", TensorProto.INT32,
|
||||
[None]),
|
||||
],
|
||||
outputs=[
|
||||
helper.make_tensor_value_info("S", TensorProto.FLOAT,
|
||||
[None, None, None])
|
||||
])
|
||||
tf_rep = onnx_graph_to_tensorflow_rep(graph_def)
|
||||
|
||||
if legacy_opset_pre_ver(10):
|
||||
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
||||
output = tf_rep.run({"X": x})
|
||||
np.testing.assert_almost_equal(output["S"], x[0:2, 0:2, 0:2])
|
||||
else:
|
||||
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
||||
output = tf_rep.run({"X": x, "starts": starts, "ends": ends, "axes": axes})
|
||||
np.testing.assert_almost_equal(output["S"], x[0:2, 0:2, 0:2])
|
||||
|
||||
# test case 2 with negative, out-of-bound and default inputs
|
||||
axes = [0, 2]
|
||||
starts = [0, -7]
|
||||
ends = [-8, 20]
|
||||
steps = [1, 1]
|
||||
|
||||
if legacy_opset_pre_ver(10):
|
||||
node_def = helper.make_node("Slice", ["X"], ["S"],
|
||||
axes=axes,
|
||||
starts=starts,
|
||||
ends=ends)
|
||||
graph_def = helper.make_graph(
|
||||
[node_def],
|
||||
name="test_unknown_shape",
|
||||
inputs=[
|
||||
helper.make_tensor_value_info("X", TensorProto.FLOAT,
|
||||
[None, None, None])
|
||||
],
|
||||
outputs=[
|
||||
helper.make_tensor_value_info("S", TensorProto.FLOAT,
|
||||
[None, None, None])
|
||||
])
|
||||
else:
|
||||
node_def = helper.make_node("Slice",
|
||||
["X", "starts", "ends", "axes", "steps"],
|
||||
["S"])
|
||||
graph_def = helper.make_graph(
|
||||
[node_def],
|
||||
name="test_unknown_shape",
|
||||
inputs=[
|
||||
helper.make_tensor_value_info("X", TensorProto.FLOAT,
|
||||
[None, None, None]),
|
||||
helper.make_tensor_value_info("starts", TensorProto.INT32,
|
||||
[None]),
|
||||
helper.make_tensor_value_info("ends", TensorProto.INT32,
|
||||
[None]),
|
||||
helper.make_tensor_value_info("axes", TensorProto.INT32,
|
||||
[None]),
|
||||
helper.make_tensor_value_info("steps", TensorProto.INT32,
|
||||
[None]),
|
||||
],
|
||||
outputs=[
|
||||
helper.make_tensor_value_info("S", TensorProto.FLOAT,
|
||||
[None, None, None])
|
||||
])
|
||||
tf_rep = onnx_graph_to_tensorflow_rep(graph_def)
|
||||
if legacy_opset_pre_ver(10):
|
||||
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
||||
output = tf_rep.run({"X": x})
|
||||
np.testing.assert_almost_equal(output["S"], x[0:-8, :, -7:20])
|
||||
else:
|
||||
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
||||
output = tf_rep.run({"X": x, "starts": starts, "ends": ends, "axes": axes, "steps": steps})
|
||||
np.testing.assert_almost_equal(output["S"], x[0:-8, :, -7:20])
|
||||
|
||||
# test case 3 with non-default steps
|
||||
axes = [0, 1, 2]
|
||||
starts = [0, 0, 0]
|
||||
ends = [2, 2, 2]
|
||||
steps = [2, -2, -1]
|
||||
|
||||
if not legacy_opset_pre_ver(10):
|
||||
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
||||
output = tf_rep.run({"X": x, "starts": starts, "ends": ends, "axes": axes, "steps": steps})
|
||||
np.testing.assert_almost_equal(output["S"], x[0:2:2, 0:2:-2, 0:2:-1])
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,157 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
import onnx
|
||||
from onnx_tf.backend import prepare
|
||||
from onnx import helper
|
||||
from onnx import TensorProto
|
||||
|
||||
from onnx_tf.common.legacy import legacy_onnx_pre_ver
|
||||
|
||||
|
||||
class TestModel(unittest.TestCase):
|
||||
""" Tests for models
|
||||
"""
|
||||
|
||||
def _get_rnd(self, shape, low=-1.0, high=1.0):
|
||||
return np.random.uniform(low, high, np.prod(shape)) \
|
||||
.reshape(shape) \
|
||||
.astype(np.float32)
|
||||
|
||||
def test_sequence_ops(self):
|
||||
# test SequenceConstruct and SequenceAt
|
||||
a = np.random.randn(2, 1, 2).astype(np.float32)
|
||||
b = np.random.randn(1, 1, 2).astype(np.float32)
|
||||
c = np.random.randn(3, 1, 2).astype(np.float32)
|
||||
seq_construct_node = helper.make_node('SequenceConstruct', ['a', 'b', 'c'], ['S'])
|
||||
seq_at_node = helper.make_node('SequenceAt', ['S','at'], ['Y'])
|
||||
out_value_info = helper.make_tensor_value_info('Y',onnx.TensorProto.FLOAT,[None])
|
||||
a_value_info = helper.make_tensor_value_info('a',onnx.TensorProto.FLOAT,[2, 1, 2])
|
||||
b_value_info = helper.make_tensor_value_info('b',onnx.TensorProto.FLOAT,[1, 1, 2])
|
||||
c_value_info = helper.make_tensor_value_info('c',onnx.TensorProto.FLOAT,[3, 1, 2])
|
||||
at_value_info = helper.make_tensor_value_info('at',onnx.TensorProto.INT32,[])
|
||||
|
||||
graph = helper.make_graph([seq_construct_node, seq_at_node],
|
||||
name='seq_construct_at_test',
|
||||
inputs=[a_value_info, b_value_info, c_value_info, at_value_info],
|
||||
outputs=[out_value_info])
|
||||
model = helper.make_model(graph, producer_name='backend-test')
|
||||
tf_rep = prepare(model)
|
||||
output = tf_rep.run({'a':a, 'b':b, 'c':c, 'at':0})
|
||||
np.testing.assert_almost_equal(output["Y"], a)
|
||||
output = tf_rep.run({'a':a, 'b':b, 'c':c, 'at':-2})
|
||||
np.testing.assert_almost_equal(output["Y"], b)
|
||||
output = tf_rep.run({'a':a, 'b':b, 'c':c, 'at':2})
|
||||
np.testing.assert_almost_equal(output["Y"], c)
|
||||
|
||||
# test SequenceEmpty, SequenceInsert, and SequenceAt
|
||||
p = np.int32(0)
|
||||
seq_empty_node = helper.make_node('SequenceEmpty', [], ['S'])
|
||||
seq_insert_node1 = helper.make_node('SequenceInsert', ['S','a'], ['S1'])
|
||||
seq_insert_node2 = helper.make_node('SequenceInsert', ['S1','b'], ['S2'])
|
||||
seq_insert_node3 = helper.make_node('SequenceInsert', ['S2','c','p'], ['S3'])
|
||||
seq_at_node = helper.make_node('SequenceAt', ['S3','at'], ['Y'])
|
||||
|
||||
p_value_info = helper.make_tensor_value_info('p',onnx.TensorProto.INT32,[])
|
||||
|
||||
graph = helper.make_graph([seq_empty_node, seq_insert_node1, seq_insert_node2, seq_insert_node3, seq_at_node],
|
||||
name='seq_empty_insert_at_test',
|
||||
inputs=[a_value_info, b_value_info, c_value_info, p_value_info, at_value_info],
|
||||
outputs=[out_value_info])
|
||||
model = helper.make_model(graph, producer_name='backend-test')
|
||||
tf_rep = prepare(model)
|
||||
output = tf_rep.run({'a':a, 'b':b, 'c':c, 'p':p, 'at':0})
|
||||
np.testing.assert_almost_equal(output["Y"], c)
|
||||
|
||||
# test SequenceConstruct, SequenceErase, and SequenceLength
|
||||
seq_construct_node = helper.make_node('SequenceConstruct', ['a', 'b', 'c'], ['S'])
|
||||
seq_erase_node = helper.make_node('SequenceErase', ['S','p'], ['S1'])
|
||||
seq_length_node = helper.make_node('SequenceLength', ['S1'], ['Y'])
|
||||
|
||||
graph = helper.make_graph([seq_construct_node, seq_erase_node, seq_length_node],
|
||||
name='seq_construct_erase_length_test',
|
||||
inputs=[a_value_info, b_value_info, c_value_info, p_value_info],
|
||||
outputs=[out_value_info])
|
||||
model = helper.make_model(graph, producer_name='backend-test')
|
||||
tf_rep = prepare(model)
|
||||
output = tf_rep.run({'a':a, 'b':b, 'c':c, 'p':p})
|
||||
np.testing.assert_almost_equal(output["Y"], 2)
|
||||
|
||||
# test SequenceConstruct and SequenceErase
|
||||
seq_construct_node = helper.make_node('SequenceConstruct', ['a', 'b', 'c'], ['S'])
|
||||
seq_erase_node = helper.make_node('SequenceErase', ['S','p'], ['S1'])
|
||||
seq_at_node = helper.make_node('SequenceAt', ['S1', 'at'], ['Y'])
|
||||
|
||||
graph = helper.make_graph([seq_construct_node, seq_erase_node, seq_at_node],
|
||||
name='seq_construct_erase_test',
|
||||
inputs=[a_value_info, b_value_info, c_value_info, p_value_info, at_value_info],
|
||||
outputs=[out_value_info])
|
||||
model = helper.make_model(graph, producer_name='backend-test')
|
||||
tf_rep = prepare(model)
|
||||
output = tf_rep.run({'a':a, 'b':b, 'c':c, 'p':p, 'at':0})
|
||||
np.testing.assert_almost_equal(output["Y"], b)
|
||||
output = tf_rep.run({'a':a, 'b':b, 'c':c, 'p':p, 'at':1})
|
||||
np.testing.assert_almost_equal(output["Y"], c)
|
||||
|
||||
def test_relu_node_inplace(self):
|
||||
X = np.random.randn(3, 2).astype(np.float32)
|
||||
Y_ref = np.clip(X, 0, np.inf)
|
||||
|
||||
node_def = helper.make_node("Relu", ["X"], ["X1"])
|
||||
|
||||
graph_def = helper.make_graph(
|
||||
[node_def],
|
||||
name="test",
|
||||
inputs=[helper.make_tensor_value_info("X", TensorProto.FLOAT, [3, 2])],
|
||||
outputs=[
|
||||
helper.make_tensor_value_info("X1", TensorProto.FLOAT, [3, 2])
|
||||
])
|
||||
tf_rep = prepare(helper.make_model(graph_def))
|
||||
output = tf_rep.run({"X": X})
|
||||
np.testing.assert_almost_equal(output.X1, Y_ref)
|
||||
|
||||
def test_initializer(self):
|
||||
if legacy_onnx_pre_ver(1, 2):
|
||||
raise unittest.SkipTest(
|
||||
"The current version of ONNX does not record correctly the opset of Cast."
|
||||
)
|
||||
X = np.array([[1, 2], [3, 4]]).astype(np.float32)
|
||||
Y = np.array([[1, 2], [3, 4]]).astype(np.float32)
|
||||
weight = np.array([[1, 0], [0, 1]])
|
||||
graph_def = helper.make_graph(
|
||||
[
|
||||
helper.make_node("Add", ["X", "Y"], ["Z0"]),
|
||||
helper.make_node("Cast", ["Z0"], ["Z"], to=TensorProto.FLOAT),
|
||||
helper.make_node("Mul", ["Z", "weight"], ["W"]),
|
||||
helper.make_node("Tanh", ["W"], ["W1"]),
|
||||
helper.make_node("Sigmoid", ["W1"], ["W2"])
|
||||
],
|
||||
name="test_initializer",
|
||||
inputs=[
|
||||
helper.make_tensor_value_info("X", TensorProto.FLOAT, (2, 2)),
|
||||
helper.make_tensor_value_info("Y", TensorProto.FLOAT, (2, 2)),
|
||||
helper.make_tensor_value_info("weight", TensorProto.FLOAT, (2, 2)),
|
||||
],
|
||||
outputs=[
|
||||
helper.make_tensor_value_info("W2", TensorProto.FLOAT, (2, 2))
|
||||
],
|
||||
initializer=[
|
||||
helper.make_tensor("weight", TensorProto.FLOAT, [2, 2],
|
||||
weight.flatten().astype(float))
|
||||
])
|
||||
|
||||
def sigmoid(x):
|
||||
return 1 / (1 + np.exp(-x))
|
||||
|
||||
W_ref = sigmoid(np.tanh((X + Y) * weight))
|
||||
tf_rep = prepare(helper.make_model(graph_def))
|
||||
output = tf_rep.run({"X": X, "Y": Y})
|
||||
np.testing.assert_almost_equal(output["W2"], W_ref)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,119 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
import re
|
||||
import unittest
|
||||
|
||||
import onnx.backend.test
|
||||
|
||||
from onnx import defs
|
||||
|
||||
from onnx_tf import opset_version
|
||||
from onnx_tf.backend import TensorflowBackend
|
||||
from onnx_tf.common.legacy import legacy_onnx_pre_ver
|
||||
from onnx_tf.common.legacy import legacy_opset_pre_ver
|
||||
|
||||
def get_onnxtf_supported_ops():
|
||||
return opset_version.backend_opset_version
|
||||
|
||||
def get_onnx_supported_ops():
|
||||
onnx_ops_dict = {}
|
||||
for schema in defs.get_all_schemas():
|
||||
onnx_ops_dict[schema.name] = {
|
||||
'version': schema.since_version,
|
||||
'deprecated': schema.deprecated
|
||||
}
|
||||
return onnx_ops_dict
|
||||
|
||||
# This is a pytest magic variable to load extra plugins
|
||||
pytest_plugins = 'onnx.backend.test.report',
|
||||
|
||||
backend_test = onnx.backend.test.BackendTest(TensorflowBackend, __name__)
|
||||
|
||||
# The test cases excluded below should be considered permanent restrictions
|
||||
# based on the TensorFlow implementation. Unimplemented operators will raise
|
||||
# a BackendIsNotSupposedToImplementIt exception so that their test cases
|
||||
# will pass and show a verbose message stating it was effectively skipped.
|
||||
|
||||
# https://github.com/onnx/onnx/issues/349
|
||||
backend_test.exclude(r'[a-z,_]*GLU[a-z,_]*')
|
||||
|
||||
# TF does not support dialation and strides at the same time:
|
||||
# Will produce strides > 1 not supported in conjunction with dilation_rate > 1
|
||||
backend_test.exclude(r'[a-z,_]*dilated_strided[a-z,_]*')
|
||||
backend_test.exclude(r'[a-z,_]*Conv2d_dilated[a-z,_]*')
|
||||
|
||||
# TF does not have column major max_pool_with_argmax
|
||||
backend_test.exclude(
|
||||
r'[a-z,_]*maxpool_with_argmax_2d_precomputed_strides[a-z,_]*')
|
||||
|
||||
# PRelu OnnxBackendPyTorchConvertedModelTest has wrong dim for broadcasting
|
||||
backend_test.exclude(r'[a-z,_]*PReLU_[0-9]d_multiparam[a-z,_]*')
|
||||
|
||||
# TF does not support int8, int16, uint8, uint16, uint32, uint64 for
|
||||
# tf.floormod and tf.truncatemod
|
||||
backend_test.exclude(r'test_mod_[a-z,_]*uint[0-9]+')
|
||||
backend_test.exclude(r'test_mod_[a-z,_]*int(8|(16))+')
|
||||
|
||||
# TF only support uint8, int32, int64 for indices and int32 for depth in
|
||||
# tf.one_hot
|
||||
backend_test.exclude(r'test_onehot_[a-z,_]*')
|
||||
|
||||
# TF doesn't support most of the attributes in resize op
|
||||
# test_node.py will cover the test
|
||||
backend_test.exclude(r'test_resize_[a-z,_]*')
|
||||
|
||||
# range is using loop in the model test but all the outputs datatype are
|
||||
# missing in the body attribute of the loop
|
||||
backend_test.exclude(
|
||||
r'test_range_float_type_positive_delta_expanded[a-z,_]*')
|
||||
backend_test.exclude(
|
||||
r'test_range_int32_type_negative_delta_expanded[a-z,_]*')
|
||||
|
||||
# skip all the cumsum testcases because all the axis in the testcases
|
||||
# are created as a 1-D 1 element tensor, but the spec clearly state
|
||||
# that axis should be a 0-D tensor(scalar)
|
||||
backend_test.exclude(r'test_cumsum_[a-z,_]*')
|
||||
|
||||
if legacy_opset_pre_ver(7):
|
||||
backend_test.exclude(r'[a-z,_]*Upsample[a-z,_]*')
|
||||
|
||||
if 'TRAVIS' in os.environ:
|
||||
backend_test.exclude('test_vgg19')
|
||||
backend_test.exclude('zfnet512')
|
||||
|
||||
if legacy_onnx_pre_ver(1, 2):
|
||||
# These following tests fails by a tiny margin with onnx<1.2:
|
||||
backend_test.exclude('test_operator_add_broadcast_cpu')
|
||||
backend_test.exclude('test_operator_add_size1_broadcast_cpu')
|
||||
backend_test.exclude('test_operator_add_size1_right_broadcast_cpu')
|
||||
backend_test.exclude('test_operator_add_size1_singleton_broadcast_cpu')
|
||||
backend_test.exclude('test_averagepool_3d_default_cpu')
|
||||
# Do not support consumed flag:
|
||||
backend_test.exclude('test_batch_normalization')
|
||||
# Do not support RNN testing on onnx<1.2 due to incorrect tests:
|
||||
backend_test.exclude(r'test_operator_rnn_cpu')
|
||||
backend_test.exclude(r'test_operator_lstm_cpu')
|
||||
backend_test.exclude(r'test_operator_rnn_single_layer_cpu')
|
||||
|
||||
# The onnx test for cast, float to string, does not work
|
||||
if not legacy_opset_pre_ver(9):
|
||||
backend_test.exclude(r'[a-z,_]*cast[a-z,_]*')
|
||||
|
||||
if not legacy_opset_pre_ver(10):
|
||||
# Do not support dilations != 1 for ConvTranspose, test is added in opset 10
|
||||
backend_test.exclude(r'[a-z,_]*convtranspose_dilations[a-z,_]*')
|
||||
|
||||
# some NLL test cases do not use the `NegativeLogLikelihoodLoss` operator
|
||||
# however they use the `where` operator which has some restrictions in TF 1.x
|
||||
# (x,y tensors must have same shape, broadcastable shapes not supported)
|
||||
backend_test.exclude(r'test_negative_log_likelihood_loss_[a-z,_]*')
|
||||
|
||||
# import all test cases at global scope to make them visible to python.unittest
|
||||
globals().update(backend_test.enable_report().test_cases)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,28 @@
|
||||
mkdir -p ../../onnx_models/
|
||||
|
||||
wget https://s3.amazonaws.com/download.onnx/models/bvlc_alexnet.tar.gz --directory-prefix=../../onnx_models/
|
||||
pushd ../../onnx_models/ && tar -xzf bvlc_alexnet.tar.gz && popd
|
||||
|
||||
wget https://s3.amazonaws.com/download.onnx/models/densenet121.tar.gz --directory-prefix=../../onnx_models/
|
||||
pushd ../../onnx_models/ && tar -xzf densenet121.tar.gz && popd
|
||||
|
||||
wget https://s3.amazonaws.com/download.onnx/models/inception_v1.tar.gz --directory-prefix=../../onnx_models/
|
||||
pushd ../../onnx_models/ && tar -xzf inception_v1.tar.gz && popd
|
||||
|
||||
wget https://s3.amazonaws.com/download.onnx/models/inception_v2.tar.gz --directory-prefix=../../onnx_models/
|
||||
pushd ../../onnx_models/ && tar -xzf inception_v2.tar.gz && popd
|
||||
|
||||
wget https://s3.amazonaws.com/download.onnx/models/resnet50.tar.gz --directory-prefix=../../onnx_models/
|
||||
pushd ../../onnx_models/ && tar -xzf resnet50.tar.gz && popd
|
||||
|
||||
wget https://s3.amazonaws.com/download.onnx/models/shufflenet.tar.gz --directory-prefix=../../onnx_models/
|
||||
pushd ../../onnx_models/ && tar -xzf shufflenet.tar.gz && popd
|
||||
|
||||
wget https://s3.amazonaws.com/download.onnx/models/squeezenet.tar.gz --directory-prefix=../../onnx_models/
|
||||
pushd ../../onnx_models/ && tar -xzf squeezenet.tar.gz && popd
|
||||
|
||||
wget https://s3.amazonaws.com/download.onnx/models/vgg16.tar.gz --directory-prefix=../../onnx_models/
|
||||
pushd ../../onnx_models/ && tar -xzf vgg16.tar.gz && popd
|
||||
|
||||
wget https://s3.amazonaws.com/download.onnx/models/vgg19.tar.gz --directory-prefix=../../onnx_models/
|
||||
pushd ../../onnx_models/ && tar -xzf vgg19.tar.gz && popd
|
||||
@@ -0,0 +1,79 @@
|
||||
import inspect
|
||||
import os
|
||||
import subprocess
|
||||
import unittest
|
||||
|
||||
import onnx
|
||||
from onnx.backend.test.runner import Runner
|
||||
from onnx.backend.test.case.model import TestCase
|
||||
|
||||
from onnx_tf.backend import TensorflowBackend
|
||||
from onnx_tf.common import IS_PYTHON3
|
||||
from onnx_tf.common.legacy import legacy_onnx_pre_ver
|
||||
|
||||
_ONNX_MODELS = [(
|
||||
"mobilenetv2-1.0",
|
||||
"https://s3.amazonaws.com/onnx-model-zoo/mobilenet/mobilenetv2-1.0/mobilenetv2-1.0.tar.gz"
|
||||
)]
|
||||
|
||||
|
||||
class TestCli(unittest.TestCase):
|
||||
|
||||
@staticmethod
|
||||
def prepare_model(model_name, url):
|
||||
if legacy_onnx_pre_ver(1, 5, 0):
|
||||
prepare_model_data = Runner._prepare_model_data
|
||||
else:
|
||||
prepare_model_data = Runner.prepare_model_data
|
||||
if IS_PYTHON3:
|
||||
params = list(
|
||||
inspect.signature(prepare_model_data).parameters.keys())
|
||||
else:
|
||||
params = inspect.getargspec(prepare_model_data).args
|
||||
runner_class = Runner
|
||||
if params[0] == "self":
|
||||
runner_class = Runner(TensorflowBackend)
|
||||
if legacy_onnx_pre_ver(1, 5, 0):
|
||||
prepare_model_data = runner_class._prepare_model_data
|
||||
else:
|
||||
prepare_model_data = runner_class.prepare_model_data
|
||||
if legacy_onnx_pre_ver(1, 4, 0):
|
||||
tc = TestCase(
|
||||
name="test_{}".format(model_name),
|
||||
model_name=model_name,
|
||||
url=url,
|
||||
model_dir=None,
|
||||
model=None,
|
||||
data_sets=None,
|
||||
kind='real')
|
||||
else:
|
||||
tc = TestCase(
|
||||
name="test_{}".format(model_name),
|
||||
model_name=model_name,
|
||||
url=url,
|
||||
model_dir=None,
|
||||
model=None,
|
||||
data_sets=None,
|
||||
kind='real',
|
||||
rtol=1e-3,
|
||||
atol=1e-7)
|
||||
return prepare_model_data(model_test=tc)
|
||||
|
||||
def test_convert_to_tf(self):
|
||||
if legacy_onnx_pre_ver(1, 2, 1):
|
||||
raise unittest.SkipTest(
|
||||
"The current version of ONNX uses dead model link.")
|
||||
for model_name, url in _ONNX_MODELS:
|
||||
model_dir = self.prepare_model(model_name, url)
|
||||
subprocess.check_call([
|
||||
"onnx-tf",
|
||||
"convert",
|
||||
"-i",
|
||||
os.path.join(model_dir, '{}.onnx'.format(model_name)),
|
||||
"-o",
|
||||
os.path.join(model_dir, '{}.pb'.format(model_name)),
|
||||
])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user