3725 lines
154 KiB
Python
3725 lines
154 KiB
Python
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
from __future__ import unicode_literals
|
|
|
|
import math
|
|
import unittest
|
|
import numpy as np
|
|
import tensorflow as tf
|
|
from onnx_tf.backend import onnx_graph_to_tensorflow_rep
|
|
from onnx_tf.backend import run_node
|
|
from onnx_tf.common import supports_device
|
|
from onnx_tf.common.legacy import legacy_onnx_pre_ver, legacy_opset_pre_ver
|
|
from onnx_tf.common.pooling_helper import py_pool
|
|
from onnx import helper
|
|
from onnx import TensorProto
|
|
from onnx import defs
|
|
|
|
|
|
class TestNode(unittest.TestCase):
|
|
""" Tests for nodes
|
|
"""
|
|
|
|
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 _elu(self, x):
|
|
# f(x) = alpha * (exp(x) - 1.) for x < 0,
|
|
# f(x) = x for x >= 0
|
|
if x < 0.:
|
|
return np.expm1(x)
|
|
return x
|
|
|
|
def _leaky_relu(self, x, alpha):
|
|
# f(x) = alpha * x for x < 0,
|
|
# f(x) = x for x >= 0
|
|
if x < 0.:
|
|
return alpha * x
|
|
return x
|
|
|
|
def test_abs(self):
|
|
node_def = helper.make_node("Abs", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[1000])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.abs(x))
|
|
|
|
def test_acosh(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Acosh.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("Acosh", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(low=1.0, high=np.finfo(np.float32).max, shape=[3, 4, 5])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.arccosh(x))
|
|
|
|
def test_add(self):
|
|
node_def = helper.make_node("Add", ["X", "Y"], ["Z"])
|
|
x = self._get_rnd_float32(shape=[5, 10, 5, 5])
|
|
y = self._get_rnd_float32(shape=[10, 1, 1])
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"],
|
|
np.add(x, y.reshape([1, 10, 1, 1])))
|
|
|
|
# node_def = helper.make_node("Add", ["A", "B"], ["C"], broadcast=1)
|
|
# a = self._get_rnd([10, 10])
|
|
# b = self._get_rnd([10, 10])
|
|
# output = run_node(node_def, [a, b])
|
|
# np.testing.assert_almost_equal(output["C"], np.add(a, b))
|
|
|
|
# node_def = helper.make_node("Add", ["A", "B"], ["C"], broadcast=1)
|
|
# a = self._get_rnd([10, 10])
|
|
# b = self._get_rnd([10,])
|
|
# output = run_node(node_def, [a, b])
|
|
# np.testing.assert_almost_equal(output["C"], np.add(a, b))
|
|
|
|
def test_arg_max(self):
|
|
for axis in [0, 1]:
|
|
node_def = helper.make_node("ArgMax", ["data"], ["reduced"],
|
|
axis=axis,
|
|
keepdims=0)
|
|
data = self._get_rnd_float32(shape=[10, 10])
|
|
output = run_node(node_def, [data])
|
|
np.testing.assert_almost_equal(output["reduced"],
|
|
np.argmax(data, axis=axis))
|
|
# test select_last_index
|
|
if not legacy_opset_pre_ver(12):
|
|
# select_last_index = 0
|
|
node_def = helper.make_node("ArgMax", ["data"], ["reduced"],
|
|
axis=axis,
|
|
keepdims=0,
|
|
select_last_index=0)
|
|
data = self._get_rnd_float32(shape=[10, 10])
|
|
output = run_node(node_def, [data])
|
|
np.testing.assert_almost_equal(output["reduced"],
|
|
np.argmax(data, axis=axis))
|
|
# select_last_index = 1
|
|
node_def = helper.make_node("ArgMax", ["data"], ["reduced"],
|
|
axis=axis,
|
|
keepdims=0,
|
|
select_last_index=1)
|
|
data = np.array([[1, 2, 3, 5, 3, 4, 5, 1], [2, 9, 3, 5, 9, 4, 5, 1]])
|
|
output = run_node(node_def, [data])
|
|
data = np.flip(data, axis)
|
|
result = np.argmax(data, axis=axis)
|
|
result = data.shape[axis] - result - 1
|
|
np.testing.assert_almost_equal(output["reduced"], result)
|
|
|
|
def test_arg_min(self):
|
|
for axis in [0, 1]:
|
|
node_def = helper.make_node("ArgMin", ["data"], ["reduced"],
|
|
axis=axis,
|
|
keepdims=0)
|
|
data = self._get_rnd_float32(shape=[10, 10])
|
|
output = run_node(node_def, [data])
|
|
np.testing.assert_almost_equal(output["reduced"],
|
|
np.argmin(data, axis=axis))
|
|
# test select_last_index
|
|
if not legacy_opset_pre_ver(12):
|
|
# select_last_index = 0
|
|
node_def = helper.make_node("ArgMin", ["data"], ["reduced"],
|
|
axis=axis,
|
|
keepdims=0,
|
|
select_last_index=0)
|
|
data = self._get_rnd_float32(shape=[10, 10])
|
|
output = run_node(node_def, [data])
|
|
np.testing.assert_almost_equal(output["reduced"],
|
|
np.argmin(data, axis=axis))
|
|
# select_last_index = 1
|
|
node_def = helper.make_node("ArgMin", ["data"], ["reduced"],
|
|
axis=axis,
|
|
keepdims=0,
|
|
select_last_index=1)
|
|
data = np.array([[1, 2, 3, 5, 3, 4, 5, 1], [2, 7, 3, 5, 2, 4, 5, 6]])
|
|
output = run_node(node_def, [data])
|
|
data = np.flip(data, axis)
|
|
result = np.argmin(data, axis=axis)
|
|
result = data.shape[axis] - result - 1
|
|
np.testing.assert_almost_equal(output["reduced"], result)
|
|
|
|
def test_asinh(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Asinh.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("Asinh", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[3, 4, 5])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.arcsinh(x))
|
|
|
|
def test_atanh(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Atanh.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("Atanh", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[3, 4, 5])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.arctanh(x))
|
|
|
|
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)
|
|
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)
|
|
output = run_node(node_def, [x, scale, bias, m, v])
|
|
np.testing.assert_almost_equal(output["Y"], golden, decimal=5)
|
|
|
|
def test_cast(self):
|
|
if legacy_onnx_pre_ver(1, 2) or legacy_opset_pre_ver(6):
|
|
test_cases = [("FLOAT", tf.float32), ("UINT8", tf.uint8),
|
|
("INT8", tf.int8),
|
|
("UINT16", tf.uint16), ("INT16", tf.int16),
|
|
("INT32", tf.int32), ("INT64", tf.int64), ("BOOL", tf.bool),
|
|
("FLOAT16", tf.float16), ("DOUBLE", tf.float64),
|
|
("COMPLEX64", tf.complex64), ("COMPLEX128", tf.complex128)]
|
|
else:
|
|
test_cases = [(TensorProto.FLOAT, tf.float32),
|
|
(TensorProto.UINT8, tf.uint8), (TensorProto.INT8, tf.int8),
|
|
(TensorProto.UINT16, tf.uint16),
|
|
(TensorProto.INT16, tf.int16),
|
|
(TensorProto.INT32, tf.int32),
|
|
(TensorProto.INT64, tf.int64), (TensorProto.BOOL, tf.bool),
|
|
(TensorProto.FLOAT16, tf.float16),
|
|
(TensorProto.DOUBLE, tf.float64),
|
|
(TensorProto.COMPLEX64, tf.complex64),
|
|
(TensorProto.COMPLEX128, tf.complex128)]
|
|
if not legacy_opset_pre_ver(9):
|
|
test_cases.append((TensorProto.STRING, tf.string))
|
|
for ty, tf_type in test_cases:
|
|
node_def = helper.make_node("Cast", ["input"], ["output"], to=ty)
|
|
vector = [2, 3]
|
|
output = run_node(node_def, [vector])
|
|
np.testing.assert_equal(output["output"].dtype, tf_type)
|
|
|
|
if not legacy_opset_pre_ver(9):
|
|
test_cases2 = [(TensorProto.FLOAT, tf.float32),
|
|
(TensorProto.INT32, tf.int32),
|
|
(TensorProto.INT64, tf.int64),
|
|
(TensorProto.DOUBLE, tf.float64)]
|
|
for ty, tf_type in test_cases2:
|
|
node_def = helper.make_node("Cast", ["input"], ["output"], to=ty)
|
|
vector = ['2', '3']
|
|
output = run_node(node_def, [vector])
|
|
np.testing.assert_equal(output["output"].dtype, tf_type)
|
|
|
|
def test_ceil(self):
|
|
node_def = helper.make_node("Ceil", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[1000])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.ceil(x))
|
|
|
|
def test_compress(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support Compress.".format(
|
|
defs.onnx_opset_version()))
|
|
axis = 1
|
|
node_def = helper.make_node("Compress",
|
|
inputs=['X', 'condition'],
|
|
outputs=['Y'],
|
|
axis=axis)
|
|
x = self._get_rnd_float32(shape=[5, 5, 5])
|
|
cond = np.array([1, 0, 1])
|
|
output = run_node(node_def, inputs=[x, cond])
|
|
np.testing.assert_almost_equal(output['Y'], np.compress(cond, x, axis=axis))
|
|
|
|
def test_concat(self):
|
|
shape = [10, 20, 5]
|
|
for axis in range(len(shape)):
|
|
node_def = helper.make_node("Concat", ["X1", "X2"], ["Y"], axis=axis)
|
|
x1 = self._get_rnd_float32(shape=shape)
|
|
x2 = self._get_rnd_float32(shape=shape)
|
|
output = run_node(node_def, [x1, x2])
|
|
np.testing.assert_almost_equal(output["Y"], np.concatenate((x1, x2),
|
|
axis))
|
|
|
|
def test_constant(self):
|
|
shape = [16, 16]
|
|
values = np.random.randn(*shape).flatten().astype(float)
|
|
const2_onnx = helper.make_tensor("const2", TensorProto.DOUBLE, shape,
|
|
values)
|
|
node_def = helper.make_node("Constant", [], ["Y"], value=const2_onnx)
|
|
output = run_node(node_def, [])
|
|
np.testing.assert_equal(output["Y"].shape, shape)
|
|
np.testing.assert_almost_equal(output["Y"].flatten(), values)
|
|
|
|
# test sparse tensor
|
|
if not legacy_opset_pre_ver(11):
|
|
expected = np.array([[1, 0, 0, 0], [0, 0, 2, 0], [0, 0, 0, 0]])
|
|
x = np.array([[0, 0], [1, 2]]).flatten().astype(np.int64)
|
|
values = helper.make_tensor("values", TensorProto.INT32, [2], [1, 2])
|
|
indices = helper.make_tensor("indices", TensorProto.INT64, [2, 2], x)
|
|
a = helper.make_sparse_tensor(values, indices, [3, 4])
|
|
node_def = helper.make_node("Constant", [], ["Y"], sparse_value=a)
|
|
output = run_node(node_def, [])
|
|
b = tf.sparse_to_dense(output["Y"].indices, output["Y"].dense_shape,
|
|
output["Y"].values)
|
|
result = b.eval(session=tf.Session())
|
|
np.testing.assert_equal(result, expected)
|
|
|
|
if not legacy_opset_pre_ver(12):
|
|
float_attr = 1.0
|
|
floats_attr = [1.0, 2.0, 3.0]
|
|
int_attr = np.int64(123)
|
|
ints_attr = [np.int64(4), np.int64(5), np.int64(6)]
|
|
string_attr = 'The Cat in the Hat'
|
|
strings_attr = [
|
|
'Green Eggs and Ham', 'How the Grinch Stole Christmas!',
|
|
'The Cat in the Hat Comes Back'
|
|
]
|
|
testcases = [(helper.make_node("Constant", [], ["Y"],
|
|
value_float=float_attr), float_attr),
|
|
(helper.make_node("Constant", [], ["Y"],
|
|
value_floats=floats_attr), floats_attr),
|
|
(helper.make_node("Constant", [], ["Y"],
|
|
value_int=int_attr), int_attr),
|
|
(helper.make_node("Constant", [], ["Y"],
|
|
value_ints=ints_attr), ints_attr),
|
|
(helper.make_node("Constant", [], ["Y"],
|
|
value_string=string_attr), string_attr),
|
|
(helper.make_node("Constant", [], ["Y"],
|
|
value_strings=strings_attr), strings_attr)]
|
|
for node_def, expected in testcases:
|
|
output = run_node(node_def, [])
|
|
if isinstance(expected, str):
|
|
np.testing.assert_string_equal(output["Y"].decode('UTF-8'), expected)
|
|
elif isinstance(expected, list) and isinstance(expected[0], str):
|
|
for i in range(len(expected)):
|
|
np.testing.assert_string_equal(output['Y'][i].decode('UTF-8'),
|
|
expected[i])
|
|
else:
|
|
np.testing.assert_equal(output["Y"], expected)
|
|
|
|
def test_constant_fill(self):
|
|
if not legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support ConstantFill.".format(
|
|
defs.onnx_opset_version()))
|
|
shape = [1, 2, 3, 4]
|
|
extra_shape = [5, 6]
|
|
value = 3.
|
|
node_def = helper.make_node(
|
|
"ConstantFill",
|
|
["X"],
|
|
["Y"],
|
|
value=value,
|
|
extra_shape=extra_shape,
|
|
dtype=1,
|
|
)
|
|
x = self._get_rnd_float32(shape=shape)
|
|
y = np.zeros(shape + extra_shape)
|
|
y.fill(value)
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_equal(output["Y"].dtype, tf.float32)
|
|
np.testing.assert_equal(output["Y"], y)
|
|
|
|
def test_constant_of_shape(self):
|
|
if defs.onnx_opset_version() < 9:
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support ConstantOfShape.".format(
|
|
defs.onnx_opset_version()))
|
|
v = helper.make_tensor("value", TensorProto.FLOAT, [1], [1])
|
|
node_def = helper.make_node("ConstantOfShape", ["X"], ["Y"], value=v)
|
|
x = np.array([4, 3, 2])
|
|
output = run_node(node_def, inputs=[x])
|
|
np.testing.assert_almost_equal(output["Y"], np.ones(x, dtype=np.float32))
|
|
v = helper.make_tensor("value", TensorProto.INT32, [1], [0])
|
|
node_def = helper.make_node("ConstantOfShape", ["X"], ["Y"], value=v)
|
|
x = np.array([10, 6])
|
|
output = run_node(node_def, inputs=[x])
|
|
np.testing.assert_almost_equal(output["Y"], np.zeros(x, dtype=np.int32))
|
|
|
|
def test_conv(self):
|
|
device = "CUDA" if supports_device("CUDA") else "CPU"
|
|
|
|
N, C, H, W = 4, 3, 5, 5
|
|
x_shape = [N, C, H, W]
|
|
K, kH, kW = 6, 3, 3
|
|
weight_shape = [K, C, kH, kW]
|
|
node_def = helper.make_node("Conv", ["X", "weights"], ["Y"],
|
|
pads=[1, 1, 1, 1],
|
|
kernel_shape=[kH, kW])
|
|
|
|
x = self._get_rnd_float32(shape=x_shape)
|
|
weights = self._get_rnd_float32(shape=weight_shape)
|
|
output = run_node(node_def, [x, weights], device=device)
|
|
|
|
out_shape = [N, K, H, W]
|
|
test_output = np.zeros(out_shape)
|
|
for n in range(N):
|
|
for c in range(C):
|
|
for h in range(H):
|
|
for w in range(W):
|
|
for k in range(K):
|
|
for kh in range(kH):
|
|
for kw in range(kW):
|
|
h_in_range = (h - kH // 2 + kh) < H and (h - kH // 2 +
|
|
kh) >= 0
|
|
w_in_range = (w - kW // 2 + kw) < W and (w - kW // 2 +
|
|
kw) >= 0
|
|
if h_in_range and w_in_range:
|
|
test_output[n][k][h][w] += (
|
|
x[n][c][h - kH // 2 + kh][w - kW // 2 + kw] *
|
|
weights[k][c][kh][kw])
|
|
|
|
np.testing.assert_almost_equal(output["Y"], test_output, decimal=5)
|
|
|
|
def test_conv_integer(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support ConvInteger.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
# Test w_zero_point
|
|
x = np.array([2, 3, 4, 5, 6, 7, 8, 9, 10]).astype(np.int8).reshape(
|
|
(1, 1, 3, 3))
|
|
w = np.array([2, 2, 2, 2]).astype(np.int8).reshape((1, 1, 2, 2))
|
|
w_zero_point = np.int8(1)
|
|
y = np.array([16, 20, 28, 32]).astype(np.int32).reshape((1, 1, 2, 2))
|
|
|
|
node = helper.make_node("ConvInteger",
|
|
["X", "W", "x_zero_point", "w_zero_point"], ["Y"],
|
|
kernel_shape=[2, 2],
|
|
pads=[0, 0, 0, 0],
|
|
dilations=[1, 1])
|
|
output = run_node(node, [x, w, np.int8(0), w_zero_point])
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
|
|
# Test x_zero_point and w_zero_point
|
|
x = np.array([2, 3, 4, 5, 6, 7, 8, 9, 10]).astype(np.int8).reshape(
|
|
(1, 1, 3, 3))
|
|
x_zero_point = np.int8(1)
|
|
w = np.array([2, 2, 2, 2]).astype(np.int8).reshape((1, 1, 2, 2))
|
|
w_zero_point = np.int8(1)
|
|
y = np.array([12, 16, 24, 28]).astype(np.int32).reshape((1, 1, 2, 2))
|
|
|
|
node = helper.make_node("ConvInteger",
|
|
["X", "W", "x_zero_point", "w_zero_point"], ["Y"],
|
|
kernel_shape=[2, 2],
|
|
pads=[0, 0, 0, 0],
|
|
dilations=[1, 1])
|
|
output = run_node(node, [x, w, x_zero_point, w_zero_point])
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
|
|
# Test w_zero_point as 1d tensor
|
|
x = np.array([2, 3, 4, 5, 6, 7, 8, 9, 10]).astype(np.int8).reshape(
|
|
(1, 1, 3, 3))
|
|
w = np.array([2, 2, 2, 2]).astype(np.int8).reshape((1, 1, 2, 2))
|
|
w_zero_point = np.array([1]).astype(np.int8)
|
|
y = np.array([16, 20, 28, 32]).astype(np.int32).reshape((1, 1, 2, 2))
|
|
|
|
node = helper.make_node("ConvInteger",
|
|
["X", "W", "x_zero_point", "w_zero_point"], ["Y"],
|
|
kernel_shape=[2, 2],
|
|
pads=[0, 0, 0, 0],
|
|
dilations=[1, 1])
|
|
output = run_node(node, [x, w, np.int8(0), w_zero_point])
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
|
|
# Test w_zero_point as 1d tensor shape 2
|
|
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]).astype(np.int8).reshape(
|
|
(1, 1, 3, 3))
|
|
w = np.array([2, 2, 2, 2, 2, 2, 2, 2]).astype(np.int8).reshape((2, 1, 2, 2))
|
|
w_zero_point = np.array([1, 2]).astype(np.int8)
|
|
y = np.array([12, 16, 24, 28, 0, 0, 0, 0]).astype(np.int32).reshape(
|
|
(1, 2, 2, 2))
|
|
|
|
node = helper.make_node("ConvInteger",
|
|
["X", "W", "x_zero_point", "w_zero_point"], ["Y"],
|
|
kernel_shape=[2, 2],
|
|
pads=[0, 0, 0, 0],
|
|
dilations=[1, 1])
|
|
output = run_node(node, [x, w, np.int8(0), w_zero_point])
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
|
|
def test_conv_transpose(self):
|
|
device = "CUDA" if supports_device("CUDA") else "CPU"
|
|
|
|
pads = [1, 1]
|
|
node_def = helper.make_node("ConvTranspose", ["X", "weights"], ["Y"],
|
|
pads=pads)
|
|
x_shape = [1, 3, 4]
|
|
x = self._get_rnd_float32(shape=x_shape)
|
|
weight_shape = [3, 5, 2]
|
|
weights = self._get_rnd_float32(shape=weight_shape)
|
|
output = run_node(node_def, [x, weights], device=device)
|
|
|
|
padh_left = weight_shape[2]-1-pads[0]
|
|
padh_right = weight_shape[2]-1-pads[1]
|
|
kh = weight_shape[2]
|
|
outh = x_shape[2] + padh_right + padh_right - (kh - 1)
|
|
|
|
out_shape = [x_shape[0], weight_shape[1], outh]
|
|
|
|
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 k in range(h , h + kh):
|
|
if (k - padh_left >= 0):
|
|
test_output[b][m][h] += x[b][c][k-padh_left] * weights[c][m][kh+h-1-k]
|
|
|
|
np.testing.assert_almost_equal(output["Y"], test_output, decimal=5)
|
|
|
|
# test for spatial dimension of colnolution is 2
|
|
pads = [1, 1, 1, 1]
|
|
node_def = helper.make_node("ConvTranspose", ["X", "weights"], ["Y"],
|
|
pads=pads)
|
|
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)
|
|
output = run_node(node_def, [x, weights],device=device)
|
|
|
|
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_cosh(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Cosh.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("Cosh", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[3, 4, 5])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.cosh(x))
|
|
|
|
def test_cumsum(self):
|
|
if legacy_opset_pre_ver(11):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support CumSum.".format(
|
|
defs.onnx_opset_version()))
|
|
x = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.int32)
|
|
axis = 0
|
|
node_def = helper.make_node("CumSum", ["x", "axis"], ["y"])
|
|
# note: if axis is not provided, np.cumsum() will compute over flattened array,
|
|
# which is different than the TensorFlow behavior
|
|
y = np.cumsum(x, axis).astype(np.int32)
|
|
output = run_node(node_def, [x, axis])
|
|
np.testing.assert_almost_equal(output["y"], y)
|
|
|
|
def test_depth_to_space(self):
|
|
node_def = helper.make_node("DepthToSpace", ["X"], ["Y"], blocksize=2)
|
|
x_shape = [1, 12, 1, 1]
|
|
x = self._get_rnd_float32(shape=x_shape)
|
|
output = run_node(node_def, [x])
|
|
x = np.transpose(x, (0, 2, 3, 1))
|
|
y = np.reshape(np.swapaxes(x.reshape(1, 1, 1, 2, 2, 3), 2, 3), (1, 2, 2, 3))
|
|
y = np.transpose(y, (0, 3, 1, 2))
|
|
np.testing.assert_almost_equal(output["Y"], y, decimal=5)
|
|
|
|
def test_dequantize_linear(self):
|
|
node_def = helper.make_node("DequantizeLinear",
|
|
["x", "x_scale", "x_zero_point"], ["y"])
|
|
for x, x_zero_point in [[
|
|
self._get_rnd_int(-128, 127, [2, 6], np.int8),
|
|
self._get_rnd_int(-128, 127, dtype=np.int8)
|
|
],
|
|
[
|
|
self._get_rnd_int(0, 255, [2, 6], np.uint8),
|
|
self._get_rnd_int(0, 255, dtype=np.uint8)
|
|
],
|
|
[self._get_rnd_int(-512, 512, [2, 6]),
|
|
np.int32(0)]]:
|
|
x_scale = self._get_rnd_float32(-10., 10)
|
|
y = np.subtract(np.float32(x), np.float32(x_zero_point))
|
|
y = np.multiply(y, x_scale)
|
|
output = run_node(node_def, [x, x_scale, x_zero_point])
|
|
np.testing.assert_almost_equal(output["y"], y)
|
|
|
|
def test_div(self):
|
|
node_def = helper.make_node("Div", ["X", "Y"], ["Z"])
|
|
x = self._get_rnd_float32(shape=[10, 10])
|
|
y = self._get_rnd_float32(shape=[10, 10])
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"], np.divide(x, y))
|
|
|
|
def test_dropout(self):
|
|
# Since current ONNX only support inference and
|
|
# dropout at inference mode is a no-op,
|
|
# therefore dropout is always a no-op operator
|
|
# in ONNX.
|
|
node_def = helper.make_node("Dropout", ["X"], ["Y"])
|
|
if legacy_opset_pre_ver(7):
|
|
# at inference mode, is_test is always set to 1
|
|
node_def = helper.make_node("Dropout", ["X"], ["Y"], is_test=1)
|
|
x = self._get_rnd_float32(shape=[3, 4, 5])
|
|
y = x
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_equal(output["Y"], y)
|
|
|
|
def test_dot(self):
|
|
# this op is removed
|
|
# remove this test in the future
|
|
return
|
|
node_def = helper.make_node("Dot", ["X", "Y"], ["Z"])
|
|
x = np.floor(self._get_rnd_float32(shape=[10, 10]))
|
|
y = np.floor(self._get_rnd_float32(shape=[10, 10]))
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"], np.dot(x, y))
|
|
|
|
def test_dynamic_quantize_linear(self):
|
|
if legacy_opset_pre_ver(11):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support DynamicQuantizeLinear.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("DynamicQuantizeLinear", ["X"],
|
|
["Y", "Y_Scale", "Y_Zero_Point"])
|
|
x = self._get_rnd_float32(shape=[3, 4])
|
|
min_x = np.minimum(0, np.min(x))
|
|
max_x = np.maximum(0, np.max(x))
|
|
y_scale = np.float32((max_x - min_x) / (255 - 0)) # uint8 -> [0, 255]
|
|
y_zero_point = np.clip(round((0 - min_x) / y_scale), 0,
|
|
255).astype(np.uint8)
|
|
y = np.clip(np.round(x / y_scale) + y_zero_point, 0, 255).astype(np.uint8)
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
np.testing.assert_almost_equal(output["Y_Scale"], y_scale)
|
|
np.testing.assert_almost_equal(output["Y_Zero_Point"], y_zero_point)
|
|
|
|
def test_elu(self):
|
|
node_def = helper.make_node("Elu", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[100])
|
|
output = run_node(node_def, [x])
|
|
test_output = [self._elu(a) for a in x]
|
|
np.testing.assert_almost_equal(output["Y"], test_output)
|
|
|
|
def test_equal(self):
|
|
node_def = helper.make_node("Equal", ["X", "Y"], ["Z"])
|
|
x = self._get_rnd_float32(shape=[5, 3, 3, 2])
|
|
y = self._get_rnd_float32(shape=[3, 3, 1])
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_equal(output["Z"], np.equal(x,
|
|
np.reshape(y, [1, 3, 3, 1])))
|
|
|
|
def test_erf(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Erf.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("Erf", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[3, 4, 5])
|
|
output = run_node(node_def, [x])
|
|
exp_output = np.vectorize(math.erf)(x).astype(np.float32)
|
|
np.testing.assert_allclose(output['Y'], exp_output, rtol=1e-6, atol=1e-6)
|
|
|
|
def test_exp(self):
|
|
node_def = helper.make_node("Exp", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[100])
|
|
x = x - 3.6
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.exp(x))
|
|
|
|
def test_expand(self):
|
|
node_def = helper.make_node("Expand", ["X", "shape"], ["Y"])
|
|
x = [[True], [False], [True]]
|
|
shape = [2, 1, 6]
|
|
y = x * np.ones(shape, dtype=np.bool)
|
|
output = run_node(node_def, [x, shape])
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
|
|
def test_eye_like(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support EyeLike.".format(
|
|
defs.onnx_opset_version()))
|
|
for shape in [[6, 10], [10, 6]]:
|
|
for off_diagonal_offset in [-10, -6, -3, 0, 3, 6, 7, 10]:
|
|
node_def = helper.make_node("EyeLike", ['x'], ['y'],
|
|
dtype=1,
|
|
k=off_diagonal_offset)
|
|
x = self._get_rnd_int(0, 100, shape=shape)
|
|
y = np.eye(shape[0], shape[1], k=off_diagonal_offset, dtype=np.float32)
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_equal(output['y'], y)
|
|
|
|
def test_flatten(self):
|
|
shape = [10, 2, 3, 4, 5]
|
|
x = self._get_rnd_float32(shape=shape)
|
|
for axis in range(-len(shape), len(shape)):
|
|
node_def = helper.make_node("Flatten", ["X"], ["Y"], axis=axis)
|
|
output = run_node(node_def, [x])
|
|
if axis == 0:
|
|
new_shape = (1, -1)
|
|
else:
|
|
new_shape = (np.prod(shape[0:axis]).astype(int), -1)
|
|
np.testing.assert_almost_equal(output["Y"], np.reshape(x, new_shape))
|
|
|
|
def test_gather(self):
|
|
node_def = helper.make_node("Gather", ["X", "Y"], ["Z"])
|
|
x = self._get_rnd_float32(shape=[10, 10])
|
|
y = [[0, 1], [1, 2]]
|
|
output = run_node(node_def, [x, y])
|
|
test_output = np.zeros((2, 2, 10))
|
|
for i in range(0, 2):
|
|
for j in range(0, 10):
|
|
test_output[0][i][j] = x[i][j]
|
|
for i in range(0, 2):
|
|
for j in range(0, 10):
|
|
test_output[1][i][j] = x[i + 1][j]
|
|
np.testing.assert_almost_equal(output["Z"], test_output)
|
|
if defs.onnx_opset_version() >= 11:
|
|
# test negative indices
|
|
y = [[-10, -9], [1, -8]]
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"], test_output)
|
|
# test out of bound indices
|
|
for y in ([[-10, 11], [1, -8]], [[-10, -11], [1, -8]]):
|
|
try:
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"], test_output)
|
|
raise AssertionError("Expected ValueError not raised for indices %d" %
|
|
str(y))
|
|
except tf.errors.InvalidArgumentError as e:
|
|
assert 'Gather indices are out of bound' in str(e), str(y)
|
|
# test non-0 and negative axis
|
|
axis = -3
|
|
node_def = helper.make_node("Gather", ["X", "Y"], ["Z"], axis=axis)
|
|
x = np.reshape(np.arange(5 * 4 * 3 * 2), (5, 4, 3, 2))
|
|
y = np.array([0, 1, 3])
|
|
test_output = np.take(x, y, axis=axis)
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"], test_output)
|
|
# test axis attribute validation
|
|
for axis in [-5, 4, 10]:
|
|
try:
|
|
node_def = helper.make_node("Gather", ["X", "Y"], ["Z"], axis=axis)
|
|
run_node(node_def, [x, y])
|
|
raise AssertionError(
|
|
"Expected ValueError not raised for axis value %d" % axis)
|
|
except ValueError as e:
|
|
assert 'out of bounds' in str(e), str(e) + ' for axis ' + str(axis)
|
|
|
|
def test_gather_elements(self):
|
|
if legacy_opset_pre_ver(11):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support GatherElements.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
data_dtype = np.int32
|
|
data = np.array([
|
|
[[10, 11], [12, 13], [14, 15], [16, 17], [18, 19]],
|
|
[[20, 21], [22, 23], [24, 25], [26, 27], [28, 29]],
|
|
[[30, 31], [32, 33], [34, 35], [36, 37], [38, 39]],
|
|
[[40, 41], [42, 43], [44, 45], [46, 47], [48, 49]],
|
|
],
|
|
dtype=data_dtype)
|
|
|
|
# test default axis
|
|
indices = np.array([[[3, 0], [2, 0], [1, 0], [0, 0], [3, 1]]],
|
|
dtype=np.int64)
|
|
ref_output = np.array([[[40, 11], [32, 13], [24, 15], [16, 17], [48, 29]]],
|
|
dtype=data_dtype)
|
|
node_def = helper.make_node("GatherElements", ["data", "indices"],
|
|
["outputs"])
|
|
output = run_node(node_def, [data, indices])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
|
|
# test non-default axis
|
|
indices = np.array([[[3, 0], [2, 1], [1, 2], [0, 3]]], dtype=data_dtype)
|
|
ref_output = np.array([
|
|
[[16, 11], [14, 13], [12, 15], [10, 17]],
|
|
],
|
|
dtype=data_dtype)
|
|
node_def = helper.make_node("GatherElements", ["data", "indices"],
|
|
["outputs"],
|
|
axis=1)
|
|
output = run_node(node_def, [data, indices])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
|
|
# test negative axis
|
|
indices = np.array([
|
|
[[1, 1, -2], [1, -2, 1], [-1, 1, -1], [-2, 1, -2], [-2, 1, 1]],
|
|
],
|
|
dtype=data_dtype)
|
|
ref_output = np.array([
|
|
[[11, 11, 10], [13, 12, 13], [15, 15, 15], [16, 17, 16], [18, 19, 19]],
|
|
],
|
|
dtype=data_dtype)
|
|
node_def = helper.make_node("GatherElements", ["data", "indices"],
|
|
["outputs"],
|
|
axis=2)
|
|
output = run_node(node_def, [data, indices])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
|
|
def test_gather_nd(self):
|
|
if legacy_opset_pre_ver(11):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support GatherND.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
# valid positive and negative indices for elements
|
|
data = np.array([[0, 1], [2, 3]], dtype=np.int64)
|
|
indices = np.array([[0, 0], [1, 1], [-1, -2]], dtype=np.int64)
|
|
ref_output = np.array([0, 3, 2], dtype=np.int64)
|
|
node_def = helper.make_node("GatherND", ["data", "indices"], ["outputs"])
|
|
output = run_node(node_def, [data, indices])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
|
|
# valid positive and negative indices for slices
|
|
data = np.arange(16, dtype=np.int32).reshape([2, 2, 4])
|
|
indices = np.array([[0, 0], [-1, -2]], dtype=np.int64)
|
|
ref_output = np.array([[0, 1, 2, 3], [8, 9, 10, 11]], dtype=np.int32)
|
|
output = run_node(node_def, [data, indices])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
indices = np.array([[[0, 0]], [[-1, 0]]], dtype=np.int64)
|
|
ref_output = np.array([[[0, 1, 2, 3]], [[8, 9, 10, 11]]], dtype=np.int32)
|
|
output = run_node(node_def, [data, indices])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
|
|
# indices out of bounds
|
|
indices = np.array([[5, 0], [-1, -3]], dtype=np.int64)
|
|
with np.testing.assert_raises(tf.errors.InvalidArgumentError):
|
|
output = run_node(node_def, [data, indices])
|
|
indices = np.array([[1, 1, 6], [-2, -1, -9]], dtype=np.int32)
|
|
with np.testing.assert_raises(tf.errors.InvalidArgumentError):
|
|
output = run_node(node_def, [data, indices])
|
|
|
|
def test_gemm(self):
|
|
# Compute Y = alpha * A * B + beta * C
|
|
node_def = helper.make_node("Gemm", ["A", "B", "C"], ["Y"],
|
|
transA=0,
|
|
transB=0,
|
|
alpha=1.0,
|
|
beta=1.0)
|
|
x = np.floor(self._get_rnd_float32(shape=[10, 10]))
|
|
y = np.floor(self._get_rnd_float32(shape=[10, 10]))
|
|
z = np.floor(self._get_rnd_float32(shape=[10, 10]))
|
|
output = run_node(node_def, [x, y, z])
|
|
test_output = np.matmul(x, y) + z
|
|
np.testing.assert_almost_equal(output["Y"], test_output)
|
|
|
|
def test_global_average_pool(self):
|
|
# Image case: (N x C x H x W), where N is the batch size,
|
|
# C is the number of channels, and H and W are the height
|
|
# and the width of the data
|
|
#
|
|
# Non-image case: (N x C x D1 x D2 ... Dn)
|
|
#
|
|
# Output data tensor from pooling across the input tensor.
|
|
# Dimensions will be N x C x 1 x 1
|
|
node_def = helper.make_node("GlobalAveragePool", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[10, 10, 2, 3])
|
|
output = run_node(node_def, [x])
|
|
test_output = np.zeros([10, 10, 1, 1])
|
|
for i1 in range(0, 10):
|
|
for i2 in range(0, 10):
|
|
sum = 0
|
|
for j1 in range(0, 2):
|
|
for j2 in range(0, 3):
|
|
sum += x[i1][i2][j1][j2]
|
|
test_output[i1][i2][0][0] = sum / 6.
|
|
np.testing.assert_almost_equal(output["Y"], test_output)
|
|
|
|
def test_hardmax(self):
|
|
shape = [2, 3, 4, 5]
|
|
x = self._get_rnd_float32(shape=shape)
|
|
for axis in range(-len(shape), len(shape)):
|
|
node_def = helper.make_node("Hardmax", ["X"], ["Y"], axis=axis)
|
|
output = run_node(node_def, [x])
|
|
shape_in_2d = (np.prod(shape[0:axis]).astype(int),
|
|
np.prod(shape[axis:len(shape)]))
|
|
x_in_2d = np.reshape(x, shape_in_2d)
|
|
y = np.eye(x_in_2d.shape[1], dtype=x.dtype)[np.argmax(x_in_2d, axis=1)]
|
|
np.testing.assert_almost_equal(output["Y"], np.reshape(y, shape))
|
|
|
|
def test_if(self):
|
|
true_val = helper.make_tensor(name='true_tensor',
|
|
data_type=TensorProto.INT64,
|
|
dims=(),
|
|
vals=[np.int64(1)])
|
|
false_val = helper.make_tensor(name='false_tensor',
|
|
data_type=TensorProto.INT64,
|
|
dims=(),
|
|
vals=[np.int64(0)])
|
|
true_node = helper.make_node('Constant',
|
|
inputs=[],
|
|
outputs=['true'],
|
|
value=true_val)
|
|
false_node = helper.make_node('Constant',
|
|
inputs=[],
|
|
outputs=['false'],
|
|
value=false_val)
|
|
|
|
true_out = helper.make_tensor_value_info('true', TensorProto.INT64, [])
|
|
false_out = helper.make_tensor_value_info('false', TensorProto.INT64, [])
|
|
|
|
true_graph = helper.make_graph(nodes=[true_node],
|
|
name="true_graph",
|
|
inputs=[],
|
|
outputs=[true_out])
|
|
false_graph = helper.make_graph(nodes=[false_node],
|
|
name="false_graph",
|
|
inputs=[],
|
|
outputs=[false_out])
|
|
|
|
node_def = helper.make_node('If', ['cond'], ['outputs'],
|
|
then_branch=true_graph,
|
|
else_branch=false_graph)
|
|
|
|
for cond, exp in [[True, true_val], [False, false_val]]:
|
|
output = run_node(node_def, [cond])
|
|
np.testing.assert_equal(output['outputs'], exp.int64_data)
|
|
|
|
x = self._get_rnd_int(low=-50, high=50, dtype=np.int64)
|
|
y = self._get_rnd_int(low=-50, high=50, dtype=np.int64)
|
|
z = self._get_rnd_int(low=-50, high=50, dtype=np.int64)
|
|
x_val = helper.make_tensor(name='x_tensor',
|
|
data_type=TensorProto.INT64,
|
|
dims=(),
|
|
vals=[x])
|
|
y_val = helper.make_tensor(name='y_tensor',
|
|
data_type=TensorProto.INT64,
|
|
dims=(),
|
|
vals=[y])
|
|
z_val = helper.make_tensor(name='z_tensor',
|
|
data_type=TensorProto.INT64,
|
|
dims=(),
|
|
vals=[z])
|
|
x_node = helper.make_node('Constant', inputs=[], outputs=['x'], value=x_val)
|
|
y_node = helper.make_node('Constant', inputs=[], outputs=['y'], value=y_val)
|
|
z_node = helper.make_node('Constant', inputs=[], outputs=['z'], value=z_val)
|
|
add_node = helper.make_node('Add', inputs=['x', 'y'], outputs=['sum'])
|
|
sub_node = helper.make_node('Sub', inputs=['x', 'y'], outputs=['diff'])
|
|
mul1_node = helper.make_node('Mul', inputs=['sum', 'z'], outputs=['prod1'])
|
|
mul2_node = helper.make_node('Mul', inputs=['diff', 'z'], outputs=['prod2'])
|
|
|
|
x_out = helper.make_tensor_value_info('x', TensorProto.INT64, [])
|
|
y_out = helper.make_tensor_value_info('y', TensorProto.INT64, [])
|
|
z_out = helper.make_tensor_value_info('z', TensorProto.INT64, [])
|
|
sum_out = helper.make_tensor_value_info('sum', TensorProto.INT64, [])
|
|
diff_out = helper.make_tensor_value_info('diff', TensorProto.INT64, [])
|
|
prod1_out = helper.make_tensor_value_info('prod1', TensorProto.INT64, [])
|
|
prod2_out = helper.make_tensor_value_info('prod2', TensorProto.INT64, [])
|
|
|
|
true_graph = helper.make_graph(nodes=[add_node, mul1_node],
|
|
name="true_graph",
|
|
inputs=[x_out, y_out, z_out],
|
|
outputs=[sum_out, prod1_out])
|
|
false_graph = helper.make_graph(nodes=[sub_node, mul2_node],
|
|
name="false_graph",
|
|
inputs=[x_out, y_out, z_out],
|
|
outputs=[diff_out, prod2_out])
|
|
|
|
less_node = helper.make_node('Less', inputs=['x', 'y'], outputs=['cond'])
|
|
if_node = helper.make_node('If',
|
|
inputs=['cond'],
|
|
outputs=['result'],
|
|
then_branch=true_graph,
|
|
else_branch=false_graph)
|
|
|
|
result_out = helper.make_tensor_value_info('result', TensorProto.INT64, [])
|
|
|
|
graph = helper.make_graph(
|
|
nodes=[x_node, y_node, z_node, less_node, if_node],
|
|
name="test_if",
|
|
inputs=[],
|
|
outputs=[result_out])
|
|
|
|
tf_rep = onnx_graph_to_tensorflow_rep(graph)
|
|
output = tf_rep.run({})
|
|
expected = [x + y, (x + y) * z] if x < y else [x - y, (x - y) * z]
|
|
np.testing.assert_equal(output['result'], expected)
|
|
|
|
def test_image_sacler(self):
|
|
# Input: (N x C x H x W), where N is the batch size,
|
|
# C is the number of channels, and H and W are the height
|
|
# and the width of the data
|
|
# Scale: (flout, default 1.0) the scale to apply
|
|
# Bias: applied to each channel, same size as C
|
|
# Output has same shape and type as input
|
|
x = self._get_rnd_float32(shape=[1, 3, 224, 224])
|
|
#random distribution over [0,1), so add 0.1
|
|
scale = np.random.rand(1)[0] + 0.1
|
|
bias = np.random.rand(3)
|
|
node_def = helper.make_node("ImageScaler", ["X"], ["Y"],
|
|
scale=scale,
|
|
bias=bias)
|
|
output = run_node(node_def, [x])
|
|
test_out = np.multiply(x, scale)
|
|
test_out = np.transpose(test_out, [0, 2, 3, 1])
|
|
test_out = np.add(test_out, bias)
|
|
test_out = np.transpose(test_out, [0, 3, 1, 2])
|
|
np.testing.assert_almost_equal(output["Y"], test_out)
|
|
|
|
def test_is_inf(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support IsInf.".format(
|
|
defs.onnx_opset_version()))
|
|
input = np.array([-1.2, np.nan, np.inf, 2.8, np.NINF, np.inf],
|
|
dtype=np.float32)
|
|
expected_output = {
|
|
"node_def": np.isinf(input),
|
|
"node_def_neg_false": np.isposinf(input),
|
|
"node_def_pos_false": np.isneginf(input)
|
|
}
|
|
node_defs = {
|
|
"node_def":
|
|
helper.make_node("IsInf", ["X"], ["Y"]),
|
|
"node_def_neg_false":
|
|
helper.make_node("IsInf", ["X"], ["Y"], detect_negative=0),
|
|
"node_def_pos_false":
|
|
helper.make_node("IsInf", ["X"], ["Y"], detect_positive=0)
|
|
}
|
|
for key in node_defs:
|
|
output = run_node(node_defs[key], [input])
|
|
np.testing.assert_equal(output["Y"], expected_output[key])
|
|
|
|
def test_isnan(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support IsNaN.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("IsNaN", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[3, 3])
|
|
x[0][1] = x[1][0] = x[2][2] = np.nan
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.isnan(x))
|
|
|
|
def test_global_lp_pool(self):
|
|
# Image case: (N x C x H x W), where N is the batch size,
|
|
# C is the number of channels, and H and W are the height
|
|
# and the width of the data
|
|
#
|
|
# Non-image case: (N x C x D1 x D2 ... Dn)
|
|
#
|
|
# Output data tensor from pooling across the input tensor.
|
|
# Dimensions will be N x C x 1 x 1
|
|
node_def = helper.make_node("GlobalLpPool", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[10, 10, 2, 3])
|
|
output = run_node(node_def, [x])
|
|
test_output = np.zeros([10, 10, 1, 1])
|
|
for i1 in range(0, 10):
|
|
for i2 in range(0, 10):
|
|
tmp = np.zeros([2, 3])
|
|
for j1 in range(0, 2):
|
|
for j2 in range(0, 3):
|
|
tmp[j1][j2] = x[i1][i2][j1][j2]
|
|
test_output[i1][i2][0][0] = np.linalg.norm(tmp)
|
|
np.testing.assert_almost_equal(output["Y"], test_output, decimal=5)
|
|
|
|
def test_global_max_pool(self):
|
|
# Image case: (N x C x H x W), where N is the batch size,
|
|
# C is the number of channels, and H and W are the height
|
|
# and the width of the data
|
|
#
|
|
# Non-image case: (N x C x D1 x D2 ... Dn)
|
|
#
|
|
# Output data tensor from pooling across the input tensor.
|
|
# Dimensions will be N x C x 1 x 1
|
|
node_def = helper.make_node("GlobalMaxPool", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[10, 10, 2, 3])
|
|
output = run_node(node_def, [x])
|
|
test_output = np.zeros([10, 10, 1, 1])
|
|
for i1 in range(0, 10):
|
|
for i2 in range(0, 10):
|
|
max = x[i1][i2][0][0]
|
|
for j1 in range(0, 2):
|
|
for j2 in range(0, 3):
|
|
if max < x[i1][i2][j1][j2]:
|
|
max = x[i1][i2][j1][j2]
|
|
test_output[i1][i2][0][0] = max
|
|
np.testing.assert_almost_equal(output["Y"], test_output)
|
|
|
|
def test_less(self):
|
|
node_def = helper.make_node("Less", ["X", "Y"], ["Z"])
|
|
x = self._get_rnd_float32(shape=[5, 3, 3, 2])
|
|
y = self._get_rnd_float32(shape=[3, 3, 1])
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_equal(output["Z"], np.less(x, np.reshape(y,
|
|
[1, 3, 3, 1])))
|
|
|
|
def test_lp_normalization(self):
|
|
for ordr in range(1, 3):
|
|
node_def = helper.make_node("LpNormalization", ["X"], ["Y"], p=ordr)
|
|
x = self._get_rnd_float32(shape=[2, 2, 3, 2])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(
|
|
output["Y"],
|
|
x / np.expand_dims(np.linalg.norm(x, axis=-1, ord=ordr), -1),
|
|
rtol=1e-3)
|
|
|
|
def test_l_r_n(self):
|
|
# Each input value is divided by:
|
|
#
|
|
# (bias+(alpha/size)*sum(xi^2 for every xi in the local region))^beta
|
|
alpha = 2.0
|
|
beta = 1.0
|
|
bias = 5.0
|
|
size = 3
|
|
node_def = helper.make_node("LRN", ["X"], ["Y"],
|
|
alpha=alpha,
|
|
beta=beta,
|
|
bias=bias,
|
|
size=size)
|
|
x = self._get_rnd_float32(shape=[10, 2, 10, 10])
|
|
output = run_node(node_def, [x])
|
|
test_output = np.zeros([10, 10, 10, 2])
|
|
x = np.transpose(x, axes=[0, 2, 3, 1])
|
|
for i1 in range(0, 10):
|
|
for i2 in range(0, 10):
|
|
for j1 in range(0, 10):
|
|
for j2 in range(0, 2):
|
|
sqr_sum = 0.
|
|
# size of 3 means radius 1 in TF speak
|
|
# i.e. the immediate neighbouring values
|
|
# if "previous" neighbour exists
|
|
if j2 > 0:
|
|
sqr_sum += x[i1][i2][j1][j2 - 1] * x[i1][i2][j1][j2 - 1]
|
|
# current value
|
|
sqr_sum += x[i1][i2][j1][j2] * x[i1][i2][j1][j2]
|
|
# if "next" neighbour exists
|
|
if j2 < 2 - 1:
|
|
sqr_sum += x[i1][i2][j1][j2 + 1] * x[i1][i2][j1][j2 + 1]
|
|
test_output[i1][i2][j1][j2] = \
|
|
x[i1][i2][j1][j2] / ((bias + (alpha * 1. / size) * sqr_sum) ** beta)
|
|
test_output = np.transpose(test_output, axes=[0, 3, 1, 2])
|
|
np.testing.assert_almost_equal(output["Y"], test_output)
|
|
|
|
def test_floor(self):
|
|
node_def = helper.make_node("Floor", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[100])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.floor(x))
|
|
|
|
def test_leakyrelu(self):
|
|
node_def = helper.make_node("LeakyRelu", ["X"], ["Y"], alpha=0.8)
|
|
x = np.floor(self._get_rnd_float32(shape=[100]))
|
|
output = run_node(node_def, [x])
|
|
test_output = [self._leaky_relu(a, 0.8) for a in x]
|
|
np.testing.assert_almost_equal(output["Y"], test_output)
|
|
|
|
def test_log(self):
|
|
node_def = helper.make_node("Log", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[100])
|
|
x = x + 3.6
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.log(x))
|
|
|
|
def test_loop(self):
|
|
add1_node = helper.make_node('Add', inputs=['x', 'x'], outputs=['sum1'])
|
|
neg_node = helper.make_node('Neg', inputs=['sum1'], outputs=['neg_sum1'])
|
|
add2_node = helper.make_node('Add',
|
|
inputs=['y', 'neg_sum1'],
|
|
outputs=['sum2'])
|
|
add3_node = helper.make_node('Add',
|
|
inputs=['sum1', 'sum2'],
|
|
outputs=['sum3'])
|
|
less_node = helper.make_node('Less',
|
|
inputs=['sum1', 'sum2'],
|
|
outputs=['new_cond'])
|
|
greater_node = helper.make_node('Greater',
|
|
inputs=['sum1', 'sum2'],
|
|
outputs=['new_cond'])
|
|
|
|
m_in = helper.make_tensor_value_info('M', TensorProto.INT64, [])
|
|
cond_in = helper.make_tensor_value_info('cond', TensorProto.BOOL, [])
|
|
cond_int_in = helper.make_tensor_value_info('cond', TensorProto.INT32, [])
|
|
x_in = helper.make_tensor_value_info('x', TensorProto.INT32, [None])
|
|
y_in = helper.make_tensor_value_info('y', TensorProto.INT32, [None])
|
|
|
|
cond_out = helper.make_tensor_value_info('cond', TensorProto.BOOL, [])
|
|
new_cond_out = helper.make_tensor_value_info('new_cond', TensorProto.BOOL,
|
|
[])
|
|
sum1_out = helper.make_tensor_value_info('sum1', TensorProto.INT32, [None])
|
|
sum2_out = helper.make_tensor_value_info('sum2', TensorProto.INT32, [None])
|
|
sum3_out = helper.make_tensor_value_info('sum3', TensorProto.INT32, [None])
|
|
|
|
v1_initial = np.array([1, 1], dtype=np.int32)
|
|
v2_initial = np.array([100, 100], dtype=np.int32)
|
|
|
|
# test for loop
|
|
M = np.int64(10)
|
|
cond = True # value will be ignore because optional "cond" input will be skip
|
|
graph = helper.make_graph(nodes=[add1_node, neg_node, add2_node, add3_node],
|
|
name="for_loop_graph",
|
|
inputs=[m_in, cond_in, x_in, y_in],
|
|
outputs=[cond_out, sum1_out, sum2_out, sum3_out])
|
|
node_def = helper.make_node('Loop', ['M', '', 'v1_initial', 'v2_initial'],
|
|
['v_final', 'scan_outputs'],
|
|
body=graph)
|
|
output = run_node(node_def, [M, cond, v1_initial, v2_initial])
|
|
v_final = [
|
|
np.array([1024, 1024], dtype=np.int32),
|
|
np.array([-1946, -1946], dtype=np.int32)
|
|
]
|
|
scan_outputs = [
|
|
np.array([[100, 100], [98, 98], [94, 94], [86, 86], [70, 70], [38, 38],
|
|
[-26, -26], [-154, -154], [-410, -410], [-922, -922]],
|
|
dtype=np.int32)
|
|
]
|
|
np.testing.assert_almost_equal(output['v_final'], v_final)
|
|
np.testing.assert_almost_equal(output['scan_outputs'], scan_outputs)
|
|
|
|
# test while loop
|
|
M = 0 # value will be ignore because optional "M" input will be skip
|
|
cond = v1_initial < v2_initial
|
|
graph = helper.make_graph(
|
|
nodes=[add1_node, neg_node, add2_node, add3_node, less_node],
|
|
name="while_loop_graph",
|
|
inputs=[m_in, cond_in, x_in, y_in],
|
|
outputs=[new_cond_out, sum1_out, sum2_out, sum3_out])
|
|
node_def = helper.make_node('Loop',
|
|
['', 'cond', 'v1_initial', 'v2_initial'],
|
|
['v_final', 'scan_outputs'],
|
|
body=graph)
|
|
output = run_node(node_def, [M, cond, v1_initial, v2_initial])
|
|
v_final = [
|
|
np.array([64, 64], dtype=np.int32),
|
|
np.array([-26, -26], dtype=np.int32)
|
|
]
|
|
scan_outputs = [
|
|
np.array([[100, 100], [98, 98], [94, 94], [86, 86], [70, 70], [38, 38]],
|
|
dtype=np.int32)
|
|
]
|
|
np.testing.assert_almost_equal(output['v_final'], v_final)
|
|
np.testing.assert_almost_equal(output['scan_outputs'], scan_outputs)
|
|
|
|
# test do-while loop
|
|
M = 0 # value will be ignore because optional "M" input will be skip
|
|
cond = 1
|
|
graph = helper.make_graph(
|
|
nodes=[add1_node, neg_node, add2_node, add3_node, greater_node],
|
|
name="do_while_loop_graph",
|
|
inputs=[m_in, cond_int_in, x_in, y_in],
|
|
outputs=[new_cond_out, sum1_out, sum2_out, sum3_out])
|
|
node_def = helper.make_node('Loop',
|
|
['', 'cond', 'v1_initial', 'v2_initial'],
|
|
['v_final', 'scan_outputs'],
|
|
body=graph)
|
|
output = run_node(node_def, [M, cond, v1_initial, v2_initial])
|
|
v_final = [
|
|
np.array([2, 2], dtype=np.int32),
|
|
np.array([98, 98], dtype=np.int32)
|
|
]
|
|
scan_outputs = [np.array([[100, 100]], dtype=np.int32)]
|
|
np.testing.assert_almost_equal(output['v_final'], v_final)
|
|
np.testing.assert_almost_equal(output['scan_outputs'], scan_outputs)
|
|
|
|
# test for loop and while loop conbine
|
|
M = np.int64(4)
|
|
cond = v1_initial < v2_initial
|
|
graph = helper.make_graph(
|
|
nodes=[add1_node, neg_node, add2_node, add3_node, less_node],
|
|
name="for_and_while_loop_graph",
|
|
inputs=[m_in, cond_in, x_in, y_in],
|
|
outputs=[new_cond_out, sum1_out, sum2_out, sum3_out])
|
|
node_def = helper.make_node('Loop',
|
|
['M', 'cond', 'v1_initial', 'v2_initial'],
|
|
['v_final', 'scan_outputs'],
|
|
body=graph)
|
|
output = run_node(node_def, [M, cond, v1_initial, v2_initial])
|
|
v_final = [
|
|
np.array([16, 16], dtype=np.int32),
|
|
np.array([70, 70], dtype=np.int32)
|
|
]
|
|
scan_outputs = [
|
|
np.array([[100, 100], [98, 98], [94, 94], [86, 86]], dtype=np.int32)
|
|
]
|
|
np.testing.assert_almost_equal(output['v_final'], v_final)
|
|
np.testing.assert_almost_equal(output['scan_outputs'], scan_outputs)
|
|
|
|
# test for loop that doesn't run at all (M = 0)
|
|
M = np.int64(0)
|
|
cond = True # value will be ignore because optional "cond" input will be skip
|
|
graph = helper.make_graph(nodes=[add1_node, neg_node, add2_node, add3_node],
|
|
name="for_loop_graph",
|
|
inputs=[m_in, cond_in, x_in, y_in],
|
|
outputs=[cond_out, sum1_out, sum2_out, sum3_out])
|
|
node_def = helper.make_node('Loop', ['M', '', 'v1_initial', 'v2_initial'],
|
|
['v_final', 'scan_outputs'],
|
|
body=graph)
|
|
output = run_node(node_def, [M, cond, v1_initial, v2_initial])
|
|
v_final = [
|
|
np.array([1, 1], dtype=np.int32),
|
|
np.array([100, 100], dtype=np.int32)
|
|
]
|
|
scan_outputs = np.array([], dtype=np.int32).reshape(1, 0, 2)
|
|
np.testing.assert_almost_equal(output['v_final'], v_final)
|
|
np.testing.assert_almost_equal(output['scan_outputs'], scan_outputs)
|
|
|
|
# test while loop that doesn't run at all (cond = False)
|
|
M = 0 # value will be ignore because optional "M" input will be skip
|
|
cond = False
|
|
graph = helper.make_graph(
|
|
nodes=[add1_node, neg_node, add2_node, add3_node, less_node],
|
|
name="while_loop_graph",
|
|
inputs=[m_in, cond_in, x_in, y_in],
|
|
outputs=[new_cond_out, sum1_out, sum2_out, sum3_out])
|
|
node_def = helper.make_node('Loop',
|
|
['', 'cond', 'v1_initial', 'v2_initial'],
|
|
['v_final', 'scan_outputs'],
|
|
body=graph)
|
|
output = run_node(node_def, [M, cond, v1_initial, v2_initial])
|
|
v_final = [
|
|
np.array([1, 1], dtype=np.int32),
|
|
np.array([100, 100], dtype=np.int32)
|
|
]
|
|
scan_outputs = np.array([], dtype=np.int32).reshape(1, 0, 2)
|
|
np.testing.assert_almost_equal(output['v_final'], v_final)
|
|
np.testing.assert_almost_equal(output['scan_outputs'], scan_outputs)
|
|
|
|
# test while loop that doesn't have any scan_outputs
|
|
M = np.int64(4)
|
|
cond = v1_initial < v2_initial
|
|
graph = helper.make_graph(nodes=[add1_node, neg_node, add2_node, less_node],
|
|
name="while_loop_graph",
|
|
inputs=[m_in, cond_in, x_in, y_in],
|
|
outputs=[new_cond_out, sum1_out, sum2_out])
|
|
node_def = helper.make_node('Loop',
|
|
['M', 'cond', 'v1_initial', 'v2_initial'],
|
|
['v_final'],
|
|
body=graph)
|
|
output = run_node(node_def, [M, cond, v1_initial, v2_initial])
|
|
v_final = [
|
|
np.array([16, 16], dtype=np.int32),
|
|
np.array([70, 70], dtype=np.int32)
|
|
]
|
|
np.testing.assert_almost_equal(output['v_final'], v_final)
|
|
|
|
# test for loop that doesn't run at all (M = 0)
|
|
# and the scan_outputs shape is not the same as the inputs
|
|
v1_initial = np.array([[1, 1, 1], [2, 2, 2]], dtype=np.int32)
|
|
v3_initial = np.array([[1, 1], [2, 2], [3, 3]], dtype=np.int32)
|
|
matmul_node = helper.make_node('MatMul',
|
|
inputs=['x', 'z'],
|
|
outputs=['product'])
|
|
x_in = helper.make_tensor_value_info('x', TensorProto.INT32, [None, None])
|
|
z_in = helper.make_tensor_value_info('z', TensorProto.INT32, [None, None])
|
|
sum1_out = helper.make_tensor_value_info('sum1', TensorProto.INT32,
|
|
[None, None])
|
|
z_out = helper.make_tensor_value_info('z', TensorProto.INT32, [None, None])
|
|
product_out = helper.make_tensor_value_info('product', TensorProto.INT32,
|
|
[None, None])
|
|
|
|
M = np.int64(0)
|
|
cond = True # value will be ignore because optional "cond" input will be skip
|
|
graph = helper.make_graph(nodes=[add1_node, matmul_node],
|
|
name="for_loop_graph",
|
|
inputs=[m_in, cond_in, x_in, z_in],
|
|
outputs=[cond_out, sum1_out, z_out, product_out])
|
|
node_def = helper.make_node('Loop', ['M', '', 'v1_initial', 'v3_initial'],
|
|
['v_final', 'scan_outputs'],
|
|
body=graph)
|
|
output = run_node(node_def, [M, cond, v1_initial, v3_initial])
|
|
v_final = [v1_initial, v3_initial]
|
|
scan_outputs = np.array([], dtype=np.int32).reshape(1, 0, 2, 2)
|
|
for i in range(len(output['v_final'])):
|
|
np.testing.assert_almost_equal(output['v_final'][i], v_final[i])
|
|
np.testing.assert_almost_equal(output['scan_outputs'], scan_outputs)
|
|
|
|
# verify infinite loop will get exception
|
|
M = 0 # value will be ignore because optional "M" input will be skip
|
|
cond = True # value will be ignore because optional "cond" input will be skip
|
|
graph = helper.make_graph(
|
|
nodes=[add1_node, neg_node, add2_node, add3_node, less_node],
|
|
name="while_loop_graph",
|
|
inputs=[m_in, cond_in, x_in, y_in],
|
|
outputs=[cond_out, sum1_out, sum2_out, sum3_out])
|
|
node_def = helper.make_node('Loop', ['', '', 'v1_initial', 'v2_initial'],
|
|
['v_final', 'scan_outputs'],
|
|
body=graph)
|
|
try:
|
|
output = run_node(node_def, [M, cond, v1_initial, v2_initial])
|
|
raise AssertionError("Expected RuntimeError not raise when Loop inputs " +
|
|
"M and cond are both not set at the same time")
|
|
except RuntimeError as e:
|
|
assert "M and cond in Loop are not set" in str(e)
|
|
|
|
def test_matmul_integer(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support MatMulInteger.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
node_def = helper.make_node("MatMulInteger",
|
|
["A", "B", "a_zero_point", "b_zero_point"],
|
|
["Z"])
|
|
lower_bound = {np.uint8: 0, np.int8: -20}
|
|
for dtype in [np.uint8, np.int8]:
|
|
# A & B are 3-D tensor and a_zero_point & b_zero_point are scalar
|
|
A = self._get_rnd_int(lower_bound[dtype],
|
|
20,
|
|
shape=(2, 3, 4),
|
|
dtype=dtype)
|
|
B = self._get_rnd_int(lower_bound[dtype],
|
|
20,
|
|
shape=(2, 4, 6),
|
|
dtype=dtype)
|
|
a_zero_point = self._get_rnd_int(lower_bound[dtype], 20, dtype=dtype)
|
|
b_zero_point = self._get_rnd_int(lower_bound[dtype], 20, dtype=dtype)
|
|
A_minus_zero_point = np.subtract(A.astype(np.int32),
|
|
a_zero_point.astype(np.int32))
|
|
B_minus_zero_point = np.subtract(B.astype(np.int32),
|
|
b_zero_point.astype(np.int32))
|
|
z = np.matmul(A_minus_zero_point, B_minus_zero_point)
|
|
output = run_node(node_def, [A, B, a_zero_point, b_zero_point])
|
|
np.testing.assert_almost_equal(output["Z"], z)
|
|
# A & B are 4-D tensor and a_zero_point & b_zero_point are 1-D tensor
|
|
A = self._get_rnd_int(lower_bound[dtype],
|
|
20,
|
|
shape=(2, 5, 3, 4),
|
|
dtype=dtype)
|
|
B = self._get_rnd_int(lower_bound[dtype],
|
|
20,
|
|
shape=(2, 1, 4, 6),
|
|
dtype=dtype)
|
|
a_zero_point = self._get_rnd_int(lower_bound[dtype],
|
|
20,
|
|
shape=(A.shape[-2]),
|
|
dtype=dtype)
|
|
b_zero_point = self._get_rnd_int(lower_bound[dtype],
|
|
20,
|
|
shape=(B.shape[-1]),
|
|
dtype=dtype)
|
|
a_zero_point_with_reshape = np.reshape(a_zero_point, [A.shape[-2], 1])
|
|
A_minus_zero_point = np.subtract(
|
|
A.astype(np.int32), a_zero_point_with_reshape.astype(np.int32))
|
|
B_minus_zero_point = np.subtract(B.astype(np.int32),
|
|
b_zero_point.astype(np.int32))
|
|
z = np.matmul(A_minus_zero_point, B_minus_zero_point)
|
|
output = run_node(node_def, [A, B, a_zero_point, b_zero_point])
|
|
np.testing.assert_almost_equal(output["Z"], z)
|
|
|
|
node_def = helper.make_node("MatMulInteger", ["A", "B"], ["Z"])
|
|
for dtype in [np.uint8, np.int8]:
|
|
# A & B are 3-D tensor
|
|
A = self._get_rnd_int(lower_bound[dtype],
|
|
20,
|
|
shape=(2, 3, 4),
|
|
dtype=dtype)
|
|
B = self._get_rnd_int(lower_bound[dtype],
|
|
20,
|
|
shape=(2, 4, 6),
|
|
dtype=dtype)
|
|
z = np.matmul(A.astype(np.int32), B.astype(np.int32))
|
|
output = run_node(node_def, [A, B])
|
|
np.testing.assert_almost_equal(output["Z"], z)
|
|
# A & B are 4-D tensor
|
|
A = self._get_rnd_int(lower_bound[dtype],
|
|
20,
|
|
shape=(2, 5, 3, 4),
|
|
dtype=dtype)
|
|
B = self._get_rnd_int(lower_bound[dtype],
|
|
20,
|
|
shape=(2, 1, 4, 6),
|
|
dtype=dtype)
|
|
z = np.matmul(A.astype(np.int32), B.astype(np.int32))
|
|
output = run_node(node_def, [A, B])
|
|
np.testing.assert_almost_equal(output["Z"], z)
|
|
|
|
def test_max(self):
|
|
node_def = helper.make_node("Max", ["X1", "X2", "X3", "X4"], ["Z"])
|
|
x1 = self._get_rnd_float32(shape=[10, 10])
|
|
x2 = self._get_rnd_float32(shape=[10, 10])
|
|
x3 = self._get_rnd_float32(shape=[10, 10])
|
|
x4 = self._get_rnd_float32(shape=[10, 10])
|
|
output = run_node(node_def, [x1, x2, x3, x4])
|
|
test_output = np.maximum(np.maximum(np.maximum(x1, x2), x3), x4)
|
|
np.testing.assert_almost_equal(output["Z"], test_output)
|
|
|
|
def _test_pooling(self,
|
|
input_shape,
|
|
kernel_shape,
|
|
strides=None,
|
|
dilations=None,
|
|
pads=None,
|
|
auto_pad=None,
|
|
ceil_mode=None,
|
|
count_include_pad=None,
|
|
pooling_type="MAX",
|
|
input_dtype=np.float32,
|
|
p=None):
|
|
|
|
op = "MaxPool" if pooling_type.upper().startswith("MAX") else \
|
|
"AveragePool" if pooling_type.upper() == "AVG" else "LpPool"
|
|
node_def_kwargs = {
|
|
"op_type": op,
|
|
"inputs": ["X"],
|
|
"outputs": ["Y"],
|
|
"kernel_shape": kernel_shape
|
|
}
|
|
|
|
if strides is not None:
|
|
node_def_kwargs["strides"] = strides
|
|
if dilations is not None:
|
|
node_def_kwargs["dilations"] = dilations
|
|
if pads is not None:
|
|
node_def_kwargs["pads"] = pads
|
|
if auto_pad is not None:
|
|
node_def_kwargs["auto_pad"] = auto_pad
|
|
pads = auto_pad
|
|
if ceil_mode is not None:
|
|
node_def_kwargs["ceil_mode"] = ceil_mode
|
|
else:
|
|
ceil_mode = 0
|
|
if count_include_pad is not None:
|
|
node_def_kwargs["count_include_pad"] = count_include_pad
|
|
if p is not None:
|
|
node_def_kwargs["p"] = p
|
|
|
|
node_def = helper.make_node(**node_def_kwargs)
|
|
|
|
if input_dtype == np.float32:
|
|
x = self._get_rnd_float32(shape=input_shape)
|
|
else:
|
|
x = self._get_rnd_int(low = np.iinfo(input_dtype).min,
|
|
high = np.iinfo(input_dtype).max,
|
|
shape=input_shape, dtype=input_dtype)
|
|
|
|
x = self._get_rnd_float32(shape=input_shape)
|
|
output = run_node(node_def, [x])
|
|
|
|
test_output = py_pool(x,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
padding=pads,
|
|
ceil_mode=ceil_mode,
|
|
pooling_type=pooling_type,
|
|
include_indices=False,
|
|
p=p)
|
|
|
|
np.testing.assert_almost_equal(output["Y"], test_output,
|
|
decimal=5 if pooling_type=="LP" else 7)
|
|
|
|
def test_max_pool_2d(self):
|
|
kernel_shape = [1, 2]
|
|
strides = [1, 2]
|
|
|
|
input_shape = [10, 10, 4, 4]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides)
|
|
|
|
def test_max_pool_2d_same_lower(self):
|
|
kernel_shape = [1, 2]
|
|
strides = [1, 2]
|
|
auto_pad = "SAME_LOWER"
|
|
|
|
input_shape = [10, 10, 7, 7]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
auto_pad=auto_pad)
|
|
|
|
def test_max_pool_2d_ceil_same_lower(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support ceil mode.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [2, 1]
|
|
strides = [1, 2]
|
|
auto_pad = "SAME_LOWER"
|
|
ceil_mode = 1
|
|
|
|
input_shape = [10, 10, 7, 7]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
auto_pad=auto_pad,
|
|
ceil_mode=ceil_mode)
|
|
|
|
def test_max_pool_2d_same_upper(self):
|
|
kernel_shape = [1, 2]
|
|
strides = [1, 2]
|
|
auto_pad = "SAME_UPPER"
|
|
|
|
input_shape = [10, 10, 7, 7]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
auto_pad=auto_pad)
|
|
|
|
def test_max_pool_2d_ceil(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support ceil mode.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3, 3]
|
|
strides = [2, 2]
|
|
ceil_mode = 1
|
|
|
|
input_shape = [10, 3, 24, 24]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
ceil_mode=ceil_mode)
|
|
|
|
def test_max_pool_2d_dilations(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support dilations.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3, 3]
|
|
strides = [2, 2]
|
|
dilations = [3, 3]
|
|
node_def = helper.make_node("MaxPool", ["X"], ["Y"],
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations)
|
|
|
|
input_shape = [10, 3, 24, 24]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations)
|
|
|
|
def test_max_pool_2d_dilations_ceil(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support dilations nor ceil mode.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3, 3]
|
|
strides = [2, 2]
|
|
dilations = [3, 3]
|
|
ceil_mode = 1
|
|
|
|
input_shape = [10, 3, 23, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
ceil_mode=ceil_mode)
|
|
|
|
def test_max_pool_2d_dilations_pads(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support dilations.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3, 3]
|
|
strides = [2, 2]
|
|
dilations = [3, 3]
|
|
pads = [1, 1, 2, 2]
|
|
|
|
input_shape = [10, 3, 24, 24]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
pads=pads)
|
|
|
|
def test_max_pool_2d_dilations_ceil_pads(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support dilations nor ceil mode.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3, 3]
|
|
strides = [2, 2]
|
|
dilations = [3, 3]
|
|
pads = [1, 1, 2, 2]
|
|
ceil_mode = 1
|
|
|
|
input_shape = [10, 3, 23, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
pads=pads,
|
|
ceil_mode=ceil_mode)
|
|
|
|
def test_max_pool_2d_dilations_same_lower(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support dilations.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3, 3]
|
|
strides = [2, 2]
|
|
dilations = [3, 3]
|
|
auto_pad = "SAME_LOWER"
|
|
|
|
input_shape = [10, 3, 24, 24]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
auto_pad=auto_pad)
|
|
|
|
def test_max_pool_2d_dilations_same_upper(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support dilations.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [2, 3]
|
|
strides = [4, 2]
|
|
dilations = [3, 5]
|
|
auto_pad = "SAME_UPPER"
|
|
|
|
input_shape = [10, 3, 24, 24]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
auto_pad=auto_pad)
|
|
|
|
def test_max_pool_2d_dilations_ceil_pads_int8(self):
|
|
if legacy_opset_pre_ver(12):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} does not support int8 input type.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3, 3]
|
|
strides = [2, 2]
|
|
dilations = [3, 3]
|
|
pads = [1, 1, 2, 2]
|
|
ceil_mode = 1
|
|
|
|
input_shape = [10, 3, 23, 23]
|
|
self._test_pooling(input_shape=input_shape, kernel_shape=kernel_shape,
|
|
strides=strides, dilations=dilations, pads=pads,
|
|
ceil_mode=ceil_mode, input_dtype=np.int8)
|
|
|
|
def test_max_pool_3d(self):
|
|
kernel_shape = [3, 3, 3]
|
|
strides = [2, 2, 2]
|
|
|
|
input_shape = [10, 3, 23, 23, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides)
|
|
|
|
def test_max_pool_3d_dilations_ceil_pads(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support dilations nor ceil mode.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3, 3, 3]
|
|
strides = [2, 2, 2]
|
|
dilations = [3, 3, 3]
|
|
pads = [1, 1, 2, 2, 1, 1]
|
|
ceil_mode = 1
|
|
|
|
input_shape = [10, 3, 23, 23, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
pads=pads,
|
|
ceil_mode=ceil_mode)
|
|
|
|
def test_max_pool_3d_dilations_same_lower(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support dilations.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3, 1, 2]
|
|
strides = [2, 2, 1]
|
|
dilations = [3, 2, 5]
|
|
auto_pad = "SAME_LOWER"
|
|
|
|
input_shape = [10, 3, 23, 23, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
auto_pad=auto_pad)
|
|
|
|
def test_max_pool_1d_dilations_ceil_pads(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support dilations nor ceil mode.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3]
|
|
strides = [2]
|
|
dilations = [3]
|
|
pads = [1, 2]
|
|
ceil_mode = 1
|
|
|
|
input_shape = [10, 3, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
pads=pads,
|
|
ceil_mode=ceil_mode)
|
|
|
|
def test_max_pool_1d(self):
|
|
kernel_shape = [3]
|
|
strides = [2]
|
|
|
|
input_shape = [10, 3, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides)
|
|
|
|
def test_max_pool_with_argmax_2d_dilations_ceil_pads(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support dilations nor ceil mode.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
kernel_shape = [3, 3]
|
|
strides = [2, 2]
|
|
dilations = [3, 3]
|
|
pads = [1, 1, 2, 2]
|
|
ceil_mode = True
|
|
node_def = helper.make_node("MaxPool", ["X"], ["Y", "Ind"],
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
pads=pads,
|
|
ceil_mode=ceil_mode)
|
|
|
|
input_shape = [10, 1, 23, 23]
|
|
x = self._get_rnd_float32(shape=input_shape) - 2
|
|
output = run_node(node_def, [x])
|
|
|
|
test_output, test_ind = py_pool(x,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
dilations=dilations,
|
|
padding=pads,
|
|
ceil_mode=ceil_mode,
|
|
pooling_type="MAX")
|
|
|
|
np.testing.assert_almost_equal(output["Y"], test_output)
|
|
np.testing.assert_almost_equal(output["Ind"], test_ind)
|
|
|
|
def test_max_pool_with_argmax_3d(self):
|
|
kernel_shape = [3, 3, 3]
|
|
strides = [2, 2, 2]
|
|
node_def = helper.make_node("MaxPool", ["X"], ["Y", "Ind"],
|
|
kernel_shape=kernel_shape,
|
|
strides=strides)
|
|
|
|
input_shape = [10, 1, 23, 23, 23]
|
|
x = self._get_rnd_float32(shape=input_shape)
|
|
self.assertRaises(RuntimeError, run_node, node_def, [x])
|
|
|
|
def test_max_pool_4d(self):
|
|
kernel_shape = [3, 3, 3, 3]
|
|
strides = [2, 2, 2, 2]
|
|
node_def = helper.make_node("MaxPool", ["X"], ["Y", "Ind"],
|
|
kernel_shape=kernel_shape,
|
|
strides=strides)
|
|
|
|
input_shape = [1, 1, 4, 4, 4, 4]
|
|
x = self._get_rnd_float32(shape=input_shape)
|
|
self.assertRaises(RuntimeError, run_node, node_def, [x])
|
|
|
|
def test_max_unpool(self):
|
|
input_shape = [10, 10, 4, 4]
|
|
x = self._get_rnd_float32(shape=input_shape)
|
|
|
|
X = helper.make_tensor_value_info('X', TensorProto.FLOAT, input_shape)
|
|
Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, input_shape)
|
|
|
|
node_def = helper.make_node("MaxPool", ["X"], ["Pool", "Indices"],
|
|
kernel_shape=[2, 2],
|
|
strides=[2, 2])
|
|
output_pool = run_node(node_def, [x])
|
|
|
|
node_def = helper.make_node("MaxUnpool", ["Pool", "Indices"], ["Y"],
|
|
kernel_shape=[2, 2],
|
|
strides=[2, 2])
|
|
output_unpool = run_node(node_def,
|
|
[output_pool["Pool"], output_pool["Indices"]])
|
|
|
|
test_output = np.zeros(input_shape)
|
|
for i1 in range(0, input_shape[0]):
|
|
for i2 in range(0, input_shape[1]):
|
|
for i3 in range(0, input_shape[2], 2):
|
|
for i4 in range(0, input_shape[3], 2):
|
|
max_val = float('-inf')
|
|
for j1 in range(i3, i3 + 2):
|
|
for j2 in range(i4, i4 + 2):
|
|
if x[i1][i2][j1][j2] > max_val:
|
|
max_val = x[i1][i2][j1][j2]
|
|
max_ind = (j1, j2)
|
|
j1, j2 = max_ind
|
|
test_output[i1][i2][j1][j2] = max_val
|
|
np.testing.assert_almost_equal(output_unpool["Y"], test_output)
|
|
|
|
def test_average_pool_1d(self):
|
|
kernel_shape = [3]
|
|
strides = [2]
|
|
|
|
input_shape = [10, 3, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
pooling_type="AVG")
|
|
|
|
def test_average_pool_2d(self):
|
|
kernel_shape = [1, 2]
|
|
strides = [1, 2]
|
|
|
|
input_shape = [10, 10, 4, 4]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
pooling_type="AVG")
|
|
|
|
def test_average_pool_2d_same_upper(self):
|
|
kernel_shape=[1, 2]
|
|
strides=[1, 2]
|
|
auto_pad="SAME_UPPER"
|
|
|
|
input_shape = [10, 10, 7, 7]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
auto_pad=auto_pad,
|
|
pooling_type="AVG")
|
|
|
|
def test_average_pool_3d(self):
|
|
kernel_shape = [3, 3, 3]
|
|
strides = [2, 2, 2]
|
|
|
|
input_shape = [10, 3, 23, 23, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
pooling_type="AVG")
|
|
|
|
def test_lp2_pool_2d(self):
|
|
kernel_shape = [1, 2]
|
|
strides = [1, 2]
|
|
p = 2
|
|
|
|
input_shape = [10, 10, 4, 4]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
pooling_type="LP",
|
|
p=p)
|
|
|
|
def test_lp2_pool_2d_same_lower(self):
|
|
kernel_shape = [1, 2]
|
|
strides = [1, 2]
|
|
p = 2
|
|
auto_pad = "SAME_LOWER"
|
|
|
|
input_shape = [10, 10, 7, 7]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
auto_pad=auto_pad,
|
|
pooling_type="LP",
|
|
p=p)
|
|
|
|
def test_lp2_pool_2d_same_upper(self):
|
|
kernel_shape = [1, 2]
|
|
strides = [1, 2]
|
|
p = 2
|
|
auto_pad = "SAME_UPPER"
|
|
|
|
input_shape = [10, 10, 7, 7]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
auto_pad=auto_pad,
|
|
pooling_type="LP",
|
|
p=p)
|
|
|
|
def test_lp2_pool_2d_pads(self):
|
|
kernel_shape = [3, 3]
|
|
strides = [2, 2]
|
|
p = 2
|
|
pads = [1, 1, 2, 2]
|
|
|
|
input_shape = [10, 3, 24, 24]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
pads=pads,
|
|
pooling_type="LP",
|
|
p=p)
|
|
|
|
def test_lp2_pool_3d(self):
|
|
kernel_shape = [3, 3, 3]
|
|
strides = [2, 2, 2]
|
|
p = 2
|
|
|
|
input_shape = [10, 3, 23, 23, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
pooling_type="LP",
|
|
p=p)
|
|
|
|
def test_lp2_pool_1d(self):
|
|
kernel_shape = [3]
|
|
strides = [2]
|
|
p = 2
|
|
|
|
input_shape = [10, 3, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
pooling_type="LP",
|
|
p=p)
|
|
|
|
def test_lp3_pool_2d_pads(self):
|
|
kernel_shape = [3, 3]
|
|
strides = [2, 2]
|
|
p = 3
|
|
pads = [1, 1, 2, 2]
|
|
|
|
input_shape = [10, 3, 24, 24]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
pads=pads,
|
|
pooling_type="LP",
|
|
p=p)
|
|
|
|
def test_lp3_pool_3d(self):
|
|
kernel_shape = [3, 3, 3]
|
|
strides = [2, 2, 2]
|
|
p = 3
|
|
|
|
input_shape = [10, 3, 23, 23, 23]
|
|
self._test_pooling(input_shape=input_shape,
|
|
kernel_shape=kernel_shape,
|
|
strides=strides,
|
|
pooling_type="LP",
|
|
p=p)
|
|
|
|
def test_mean_variance_normalization(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't have test for MeanVarianceNormalization".
|
|
format(defs.onnx_opset_version()))
|
|
|
|
input_data = self._get_rnd_float32(shape=[2, 2, 2, 2])
|
|
# Calculate expected output data using formula:
|
|
# (Input - Mean)/SD
|
|
mean = np.mean(input_data, keepdims=1, axis=(0, 2, 3))
|
|
std = np.std(input_data, keepdims=1, axis=(0, 2, 3))
|
|
expected_output = (input_data - mean) / std
|
|
# Testing without "axes" argument should default to axes=[0,2,3]
|
|
node_def = helper.make_node("MeanVarianceNormalization", ["X"], ["Y"])
|
|
output = run_node(node_def, [input_data])
|
|
np.testing.assert_almost_equal(output["Y"], expected_output, decimal=5)
|
|
|
|
def test_min(self):
|
|
node_def = helper.make_node("Min", ["X1", "X2", "X3", "X4"], ["Z"])
|
|
x1 = self._get_rnd_float32(shape=[10, 10])
|
|
x2 = self._get_rnd_float32(shape=[10, 10])
|
|
x3 = self._get_rnd_float32(shape=[10, 10])
|
|
x4 = self._get_rnd_float32(shape=[10, 10])
|
|
output = run_node(node_def, [x1, x2, x3, x4])
|
|
test_output = np.minimum(np.minimum(np.minimum(x1, x2), x3), x4)
|
|
np.testing.assert_almost_equal(output["Z"], test_output)
|
|
|
|
def test_mul(self):
|
|
node_def = helper.make_node("Mul", ["X", "Y"], ["Z"])
|
|
x = self._get_rnd_float32(shape=[5, 10, 5, 5])
|
|
y = self._get_rnd_float32(shape=[10, 1, 1])
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"],
|
|
np.multiply(x, y.reshape([1, 10, 1, 1])))
|
|
|
|
def test_mod(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Mod.".format(
|
|
defs.onnx_opset_version()))
|
|
x = self._get_rnd_float32(shape=[5, 5])
|
|
y = self._get_rnd_float32(shape=[5, 5])
|
|
node_def = helper.make_node("Mod", ["X", "Y"], ["Z"], fmod=0)
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"], np.mod(x, y))
|
|
node_def = helper.make_node("Mod", ["X", "Y"], ["Z"], fmod=1)
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"], np.fmod(x, y))
|
|
|
|
def test_neg(self):
|
|
node_def = helper.make_node("Neg", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[1000])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.negative(x))
|
|
|
|
def test_non_zero(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support NonZero.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("NonZero", ["x"], ["y"])
|
|
x = self._get_rnd_float32(shape=[3, 4, 5])
|
|
y = np.array(np.nonzero(x))
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_equal(output["y"], y)
|
|
|
|
def test_onehot(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support OneHot.".format(
|
|
defs.onnx_opset_version()))
|
|
indices = np.array([[0, 2], [1, 2], [0, 1]])
|
|
depth = np.int32(5)
|
|
on_value = 6.0
|
|
off_value = 2.0
|
|
values = np.array([off_value, on_value])
|
|
node_def = helper.make_node('OneHot',
|
|
inputs=['indices', 'depth', 'values'],
|
|
outputs=['y'],
|
|
axis=-1)
|
|
y = (np.arange(depth) == indices[..., None]).astype(int)
|
|
y = y * (on_value - off_value) + off_value
|
|
output = run_node(node_def, inputs=[indices, depth, values])
|
|
np.testing.assert_equal(output['y'], y)
|
|
|
|
def test_range(self):
|
|
if legacy_opset_pre_ver(11):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Range.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("Range", ['start', 'limit', 'delta'], ['y'])
|
|
# test positive_delta
|
|
start = self._get_rnd_int(low=0, high=3)
|
|
limit = self._get_rnd_int(low=10, high=30)
|
|
delta = np.int32(3)
|
|
output = run_node(node_def, [start, limit, delta])
|
|
np.testing.assert_equal(output['y'], range(start, limit, delta))
|
|
# test negative_delta
|
|
start = self._get_rnd_int(low=20, high=30)
|
|
limit = self._get_rnd_int(low=1, high=5)
|
|
delta = np.int32(-2)
|
|
output = run_node(node_def, [start, limit, delta])
|
|
np.testing.assert_equal(output['y'], range(start, limit, delta))
|
|
|
|
def test_resize(self):
|
|
if legacy_opset_pre_ver(11):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support Resize with attributes: " +
|
|
"coordinate_transformation_mode, cubic_coeff_a, exclude_outside, " +
|
|
"extrapolation_value, nearest_mode and inputs: roi and sizes".format(
|
|
defs.onnx_opset_version()))
|
|
data = np.reshape(np.arange(1, 101, dtype=np.float32), [1, 1, 10, 10])
|
|
roi = np.array([], dtype=np.float32)
|
|
|
|
# resize_nearest_round_prefer_ceil_align_corners_scales
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode='align_corners',
|
|
mode='nearest',
|
|
nearest_mode='round_prefer_ceil')
|
|
scales = np.array([1, 1, 0.9, 0.9], dtype=np.float32)
|
|
expected = np.array(
|
|
[[[[1, 2, 3, 4, 6, 7, 8, 9, 10], [11, 12, 13, 14, 16, 17, 18, 19, 20],
|
|
[21, 22, 23, 24, 26, 27, 28, 29, 30],
|
|
[31, 32, 33, 34, 36, 37, 38, 39, 40],
|
|
[51, 52, 53, 54, 56, 57, 58, 59, 60],
|
|
[61, 62, 63, 64, 66, 67, 68, 69, 70],
|
|
[71, 72, 73, 74, 76, 77, 78, 79, 80],
|
|
[81, 82, 83, 84, 86, 87, 88, 89, 90],
|
|
[91, 92, 93, 94, 96, 97, 98, 99, 100]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# resize_nearest_round_prefer_ceil_align_corners_sizes
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode='align_corners',
|
|
mode='nearest',
|
|
nearest_mode='round_prefer_ceil')
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array(
|
|
[[[[1, 3, 4, 6, 7, 9, 10], [21, 23, 24, 26, 27, 29, 30],
|
|
[31, 33, 34, 36, 37, 39, 40], [51, 53, 54, 56, 57, 59, 60],
|
|
[61, 63, 64, 66, 67, 69, 70], [81, 83, 84, 86, 87, 89, 90],
|
|
[91, 93, 94, 96, 97, 99, 100]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# resize_nearest_floor_asymmetric_scales
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode='asymmetric',
|
|
mode='nearest',
|
|
nearest_mode='floor')
|
|
scales = np.array([1.0, 1.0, 0.8, 0.8], dtype=np.float32)
|
|
expected = np.array(
|
|
[[[[1, 2, 3, 4, 6, 7, 8, 9], [11, 12, 13, 14, 16, 17, 18, 19],
|
|
[21, 22, 23, 24, 26, 27, 28, 29], [31, 32, 33, 34, 36, 37, 38, 39],
|
|
[51, 52, 53, 54, 56, 57, 58, 59], [61, 62, 63, 64, 66, 67, 68, 69],
|
|
[71, 72, 73, 74, 76, 77, 78, 79], [81, 82, 83, 84, 86, 87, 88, 89]]]
|
|
],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# resize_nearest_floor_asymmetric_sizes
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode='asymmetric',
|
|
mode='nearest',
|
|
nearest_mode='floor')
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array(
|
|
[[[[1, 2, 3, 5, 6, 8, 9], [11, 12, 13, 15, 16, 18, 19],
|
|
[21, 22, 23, 25, 26, 28, 29], [41, 42, 43, 45, 46, 48, 49],
|
|
[51, 52, 53, 55, 56, 58, 59], [71, 72, 73, 75, 76, 78, 79],
|
|
[81, 82, 83, 85, 86, 88, 89]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# resize_nearest_floor_half_pixel_scales
|
|
node_def = helper.make_node(
|
|
"Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode='tf_half_pixel_for_nn',
|
|
mode='nearest',
|
|
nearest_mode='floor')
|
|
scales = np.array([1, 1, 0.8, 0.8], dtype=np.float32)
|
|
expected = np.array(
|
|
[[[[1, 2, 4, 5, 6, 7, 9, 10], [11, 12, 14, 15, 16, 17, 19, 20],
|
|
[31, 32, 34, 35, 36, 37, 39, 40], [41, 42, 44, 45, 46, 47, 49, 50],
|
|
[51, 52, 54, 55, 56, 57, 59, 60], [61, 62, 64, 65, 66, 67, 69, 70],
|
|
[81, 82, 84, 85, 86, 87, 89, 90], [91, 92, 94, 95, 96, 97, 99, 100]]]
|
|
],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# resize_nearest_floor_half_pixel_sizes
|
|
node_def = helper.make_node(
|
|
"Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode='tf_half_pixel_for_nn',
|
|
mode='nearest',
|
|
nearest_mode='floor')
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array(
|
|
[[[[1, 3, 4, 6, 7, 8, 10], [21, 23, 24, 26, 27, 28, 30],
|
|
[31, 33, 34, 36, 37, 38, 40], [51, 53, 54, 56, 57, 58, 60],
|
|
[61, 63, 64, 66, 67, 68, 70], [71, 73, 74, 76, 77, 78, 80],
|
|
[91, 93, 94, 96, 97, 98, 100]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# resize_linear_align_corners_scales
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode="align_corners",
|
|
mode='linear')
|
|
scales = np.array([1, 1, 0.8, 0.8], dtype=np.float32)
|
|
expected = np.array(
|
|
[[[[
|
|
1., 2.2857141, 3.5714285, 4.857143, 6.142857, 7.428571, 8.714286,
|
|
10.
|
|
],
|
|
[
|
|
13.857142, 15.142857, 16.428572, 17.714287, 19., 20.285715,
|
|
21.571428, 22.857143
|
|
],
|
|
[
|
|
26.714287, 28., 29.285713, 30.571426, 31.857141, 33.142857,
|
|
34.428574, 35.714283
|
|
],
|
|
[
|
|
39.57143, 40.857143, 42.14286, 43.428574, 44.714287, 46.,
|
|
47.285717, 48.57143
|
|
],
|
|
[
|
|
52.428574, 53.714283, 55., 56.285713, 57.571426, 58.857143,
|
|
60.142857, 61.428566
|
|
],
|
|
[
|
|
65.28571, 66.57143, 67.85714, 69.14285, 70.428566, 71.71428, 73.,
|
|
74.28571
|
|
],
|
|
[
|
|
78.14286, 79.42857, 80.71428, 82., 83.28572, 84.57143, 85.85715,
|
|
87.14286
|
|
],
|
|
[
|
|
91., 92.28571, 93.57143, 94.85715, 96.14285, 97.42857, 98.71429,
|
|
100.
|
|
]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_allclose(output['Y'], expected, rtol=1e-6, atol=1e-6)
|
|
|
|
# resize_linear_align_corners_sizes
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode="align_corners",
|
|
mode='linear')
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array(
|
|
[[[[1., 2.5, 4., 5.5, 7., 8.5, 10.],
|
|
[16., 17.5, 19., 20.5, 22., 23.5, 25.],
|
|
[31., 32.5, 34., 35.5, 37., 38.5, 40.],
|
|
[46., 47.5, 49., 50.5, 52., 53.5, 55.],
|
|
[61., 62.5, 64., 65.5, 67., 68.5, 70.],
|
|
[76., 77.5, 79., 80.5, 82., 83.5, 85.],
|
|
[91., 92.5, 94., 95.5, 97., 98.5, 100.]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# resize_linear_asymmetric_scales
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode="asymmetric",
|
|
mode='linear')
|
|
scales = np.array([1, 1, 0.8, 0.8], dtype=np.float32)
|
|
expected = np.array(
|
|
[[[[1., 2.25, 3.5, 4.75, 6., 7.25, 8.5, 9.75],
|
|
[13.5, 14.75, 16., 17.25, 18.5, 19.75, 21., 22.25],
|
|
[26., 27.25, 28.5, 29.75, 31., 32.25, 33.5, 34.75],
|
|
[38.5, 39.75, 41., 42.25, 43.5, 44.75, 46., 47.25],
|
|
[51., 52.25, 53.5, 54.75, 56., 57.25, 58.5, 59.75],
|
|
[63.5, 64.75, 66., 67.25, 68.5, 69.75, 71., 72.25],
|
|
[76., 77.25, 78.5, 79.75, 81., 82.25, 83.5, 84.75],
|
|
[88.5, 89.75, 91., 92.25, 93.5, 94.75, 96., 97.25]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# resize_linear_asymmetric_sizes
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode="asymmetric",
|
|
mode='linear')
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array([[
|
|
[[1., 2.4285715, 3.857143, 5.285714, 6.714286, 8.142857, 9.571428],
|
|
[15.285715, 16.714287, 18.142857, 19.571428, 21., 22.42857, 23.857141],
|
|
[29.571428, 31., 32.428574, 33.857143, 35.285717, 36.714287, 38.14286],
|
|
[43.857143, 45.28571, 46.714283, 48.14286, 49.571434, 51., 52.42857],
|
|
[
|
|
58.14286, 59.57143, 61.000004, 62.428574, 63.857143, 65.28572,
|
|
66.71429
|
|
], [72.42857, 73.85713, 75.28572, 76.71429, 78.14286, 79.57143, 81.],
|
|
[86.71429, 88.14285, 89.57143, 91., 92.42857, 93.85714, 95.28571]]
|
|
]],
|
|
dtype=np.float32
|
|
) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_allclose(output['Y'], expected, rtol=1e-6, atol=1e-6)
|
|
|
|
# resize_linear_half_pixel_scales
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
mode='linear')
|
|
scales = np.array([1, 1, 0.8, 0.8], dtype=np.float32)
|
|
expected = np.array(
|
|
[[[[2.375, 3.625, 4.875, 6.125, 7.375, 8.625, 9.875, 11.125],
|
|
[14.875, 16.125, 17.375, 18.625, 19.875, 21.125, 22.375, 23.625],
|
|
[27.375, 28.625, 29.875, 31.125, 32.375, 33.625, 34.875, 36.125],
|
|
[39.875, 41.125, 42.375, 43.625, 44.875, 46.125, 47.375, 48.625],
|
|
[52.375, 53.625, 54.875, 56.125, 57.375, 58.625, 59.875, 61.125],
|
|
[64.875, 66.125, 67.375, 68.625, 69.875, 71.125, 72.375, 73.625],
|
|
[77.375, 78.625, 79.875, 81.125, 82.375, 83.625, 84.875, 86.125],
|
|
[89.875, 91.125, 92.375, 93.625, 94.875, 96.125, 97.375, 98.625]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# resize_linear_half_pixel_sizes
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
mode='linear')
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array([[[[
|
|
3.357143, 4.785714, 6.214286, 7.642857, 9.071428, 10.5, 11.928572
|
|
], [
|
|
17.642857, 19.071428, 20.5, 21.92857, 23.357141, 24.785713, 26.214285
|
|
], [
|
|
31.928572, 33.357143, 34.785713, 36.214287, 37.642857, 39.071426, 40.5
|
|
], [
|
|
46.214287, 47.642857, 49.071426, 50.5, 51.928574, 53.357143, 54.785713
|
|
], [60.5, 61.928577, 63.357147, 64.78572, 66.21429, 67.64286, 69.07143
|
|
], [
|
|
74.78572, 76.21429, 77.64285, 79.07143, 80.50001, 81.92857, 83.35715
|
|
], [89.07143, 90.5, 91.928566, 93.35715, 94.78571, 96.21428, 97.64285]]]
|
|
],
|
|
dtype=np.float32
|
|
) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_allclose(output['Y'], expected, rtol=1e-6, atol=1e-6)
|
|
|
|
# resize_cubic_align_corners_scales
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode="align_corners",
|
|
mode='cubic',
|
|
cubic_coeff_a=-0.5,
|
|
exclude_outside=1)
|
|
scales = np.array([1, 1, 0.8, 0.8], dtype=np.float32)
|
|
expected = np.array(
|
|
[[[[
|
|
1., 2.285714, 3.5714293, 4.857143, 6.142857, 7.4285717, 8.714287,
|
|
10.
|
|
],
|
|
[
|
|
13.857139, 15.142854, 16.42857, 17.714281, 18.999994, 20.28571,
|
|
21.571426, 22.857138
|
|
],
|
|
[
|
|
26.71429, 28.000004, 29.285723, 30.571436, 31.85715, 33.142864,
|
|
34.428577, 35.71429
|
|
],
|
|
[
|
|
39.57143, 40.857143, 42.142864, 43.428574, 44.714287, 46.000004,
|
|
47.28572, 48.57143
|
|
],
|
|
[
|
|
52.42857, 53.714287, 55., 56.285717, 57.571423, 58.857143,
|
|
60.14286, 61.42857
|
|
],
|
|
[
|
|
65.28571, 66.57144, 67.85715, 69.14285, 70.428566, 71.71429,
|
|
73.00001, 74.28571
|
|
],
|
|
[
|
|
78.14287, 79.42857, 80.7143, 82.00001, 83.28573, 84.571434,
|
|
85.857155, 87.14287
|
|
],
|
|
[
|
|
91., 92.28572, 93.57144, 94.85715, 96.14285, 97.42858, 98.714294,
|
|
100.
|
|
]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_allclose(output['Y'], expected, rtol=1e-1, atol=1e-6)
|
|
|
|
# resize_cubic_align_corners_sizes
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode="align_corners",
|
|
mode='cubic',
|
|
cubic_coeff_a=-0.5,
|
|
exclude_outside=1)
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array(
|
|
[[[[1., 2.5, 4., 5.5, 7., 8.5, 10.],
|
|
[16., 17.5, 19., 20.5, 22., 23.5, 25.],
|
|
[31., 32.5, 34., 35.5, 37., 38.5, 40.],
|
|
[46., 47.5, 49., 50.5, 52., 53.5, 55.],
|
|
[61., 62.5, 64., 65.5, 67., 68.5, 70.],
|
|
[76., 77.5, 79., 80.5, 82., 83.5, 85.],
|
|
[91., 92.5, 94., 95.5, 97., 98.5, 100.]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# resize_cubic_asymmetric_scales
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode="asymmetric",
|
|
mode='cubic',
|
|
cubic_coeff_a=-0.5,
|
|
exclude_outside=1)
|
|
scales = np.array([1, 1, 0.8, 0.8], dtype=np.float32)
|
|
expected = np.array(
|
|
[[[[1., 2.25, 3.5, 4.75, 6., 7.25, 8.5, 9.832117],
|
|
[13.5, 14.75, 16., 17.25, 18.5, 19.75, 21., 22.332117],
|
|
[26., 27.25, 28.5, 29.75, 31., 32.25, 33.5, 34.83212],
|
|
[38.5, 39.75, 41., 42.25, 43.5, 44.75, 46., 47.332115],
|
|
[51., 52.25, 53.5, 54.75, 56., 57.25, 58.5, 59.83212],
|
|
[63.5, 64.75, 66., 67.25, 68.5, 69.75, 71., 72.332115],
|
|
[76., 77.25, 78.5, 79.75, 81., 82.25, 83.5, 84.832115],
|
|
[
|
|
89.32117, 90.57117, 91.82117, 93.07117, 94.32117, 95.57117,
|
|
96.82117, 98.15329
|
|
]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_allclose(output['Y'], expected, rtol=1e-1, atol=1e-6)
|
|
|
|
# resize_cubic_asymmetric_sizes
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode="asymmetric",
|
|
mode='cubic',
|
|
cubic_coeff_a=-0.5,
|
|
exclude_outside=1)
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array(
|
|
[[[[1., 2.4285715, 3.8571432, 5.285714, 6.7142863, 8.142857, 9.66485],
|
|
[
|
|
15.285712, 16.714287, 18.142855, 19.571426, 21., 22.428568,
|
|
23.950563
|
|
],
|
|
[
|
|
29.57143, 31.000004, 32.428574, 33.857147, 35.285713, 36.714283,
|
|
38.236282
|
|
],
|
|
[
|
|
43.857143, 45.285717, 46.714287, 48.142868, 49.571434, 50.999992,
|
|
52.52199
|
|
],
|
|
[
|
|
58.142864, 59.57144, 61.000004, 62.428585, 63.857155, 65.28572,
|
|
66.80771
|
|
],
|
|
[
|
|
72.428566, 73.85715, 75.28572, 76.714294, 78.14285, 79.57143,
|
|
81.09343
|
|
],
|
|
[
|
|
87.6485, 89.07708, 90.505646, 91.93422, 93.36279, 94.79135,
|
|
96.313354
|
|
]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_allclose(output['Y'], expected, rtol=1e-1, atol=1e-6)
|
|
|
|
# resize_cubic_half_pixel_scales
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
mode='cubic',
|
|
cubic_coeff_a=-0.5,
|
|
exclude_outside=1)
|
|
scales = np.array([1, 1, 0.8, 0.8], dtype=np.float32)
|
|
expected = np.array([[
|
|
[[
|
|
1.8098788, 3.1112535, 4.3612537, 5.6112533, 6.8612533, 8.111254,
|
|
9.361254, 10.662629
|
|
],
|
|
[14.823625, 16.125, 17.375, 18.625, 19.875, 21.125, 22.375, 23.676373],
|
|
[27.323626, 28.625, 29.875, 31.125, 32.375, 33.625, 34.875, 36.176376],
|
|
[39.823627, 41.125, 42.375, 43.625, 44.875, 46.125, 47.375, 48.676376],
|
|
[52.323624, 53.625, 54.875, 56.125, 57.375, 58.625, 59.875, 61.176373],
|
|
[64.82362, 66.125, 67.375, 68.625, 69.875, 71.125, 72.375, 73.67638],
|
|
[77.32362, 78.625, 79.875, 81.125, 82.375, 83.625, 84.875, 86.17638],
|
|
[
|
|
90.33737, 91.63874, 92.88875, 94.13875, 95.38875, 96.63875,
|
|
97.88875, 99.190125
|
|
]]
|
|
]],
|
|
dtype=np.float32
|
|
) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_allclose(output['Y'], expected, rtol=1e-6, atol=1e-6)
|
|
|
|
# resize_cubic_half_pixel_sizes
|
|
node_def = helper.make_node("Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
mode='cubic',
|
|
cubic_coeff_a=-0.5,
|
|
exclude_outside=1)
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array([[[
|
|
[2.52846, 4.0323663, 5.460938, 6.889509, 8.318081, 9.746653, 11.250559],
|
|
[
|
|
17.567522, 19.071426, 20.499996, 21.928568, 23.357141, 24.785715,
|
|
26.28962
|
|
],
|
|
[
|
|
31.853237, 33.357143, 34.785713, 36.21429, 37.64286, 39.07143,
|
|
40.575344
|
|
],
|
|
[46.13895, 47.642857, 49.071434, 50.5, 51.928566, 53.357147, 54.861053],
|
|
[
|
|
60.42467, 61.92858, 63.357147, 64.78572, 66.214294, 67.64287,
|
|
69.14677
|
|
],
|
|
[
|
|
74.710396, 76.214294, 77.64286, 79.07144, 80.50001, 81.92858,
|
|
83.432495
|
|
],
|
|
[89.749466, 91.253365, 92.68193, 94.1105, 95.53907, 96.96766, 98.47156]
|
|
]]],
|
|
dtype=np.float32
|
|
) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_allclose(output['Y'], expected, rtol=1e-2, atol=1e-6)
|
|
|
|
# crop_and_resize_nearest with scales
|
|
node_def = helper.make_node(
|
|
"Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode='tf_crop_and_resize',
|
|
mode='nearest',
|
|
nearest_mode='round_prefer_ceil',
|
|
extrapolation_value=-20.0)
|
|
roi = np.array([0, 0, 0.4, 0.6, 1, 1, 1.2, 1.7], dtype=np.float32)
|
|
scales = np.array([1.0, 1.0, 0.8, 0.8], dtype=np.float32)
|
|
expected = np.array(
|
|
[[[[46., 48., 49., -20., -20., -20., -20., -20.],
|
|
[56., 58., 59., -20., -20., -20., -20., -20.],
|
|
[66., 68., 69., -20., -20., -20., -20., -20.],
|
|
[76., 78., 79., -20., -20., -20., -20., -20.],
|
|
[86., 88., 89., -20., -20., -20., -20., -20.],
|
|
[96., 98., 99., -20., -20., -20., -20., -20.],
|
|
[-20., -20., -20., -20., -20., -20., -20., -20.],
|
|
[-20., -20., -20., -20., -20., -20., -20., -20.]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# crop_and_resize_nearest with sizes
|
|
node_def = helper.make_node(
|
|
"Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
coordinate_transformation_mode='tf_crop_and_resize',
|
|
mode='nearest',
|
|
nearest_mode='round_prefer_ceil',
|
|
)
|
|
roi = np.array([0, 0, 0.4, 0.6, 1, 1, 1.2, 1.7], dtype=np.float32)
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array(
|
|
[[[[46., 48., 50., 0., 0., 0., 0.], [56., 58., 60., 0., 0., 0., 0.],
|
|
[66., 68., 70., 0., 0., 0., 0.], [76., 78., 80., 0., 0., 0., 0.],
|
|
[86., 88., 90., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0.],
|
|
[0., 0., 0., 0., 0., 0., 0.]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_almost_equal(output["Y"], expected)
|
|
|
|
# crop_and_resize_linear with scales
|
|
node_def = helper.make_node(
|
|
"Resize",
|
|
inputs=['X', 'roi', 'scales'],
|
|
outputs=['Y'],
|
|
mode='linear',
|
|
coordinate_transformation_mode='tf_crop_and_resize',
|
|
extrapolation_value=20.0)
|
|
roi = np.array([0, 0, 0.4, 0.6, 1, 1, 1.2, 1.7], dtype=np.float32)
|
|
scales = np.array([1.0, 1.0, 0.8, 0.8], dtype=np.float32)
|
|
expected = np.array(
|
|
[[[[42.4, 43.814285, 45.228573, 20., 20., 20., 20., 20.],
|
|
[52.685715, 54.100002, 55.514286, 20., 20., 20., 20., 20.],
|
|
[62.971436, 64.38572, 65.80001, 20., 20., 20., 20., 20.],
|
|
[73.25715, 74.67143, 76.08572, 20., 20., 20., 20., 20.],
|
|
[83.54286, 84.957146, 86.37143, 20., 20., 20., 20., 20.],
|
|
[93.82858, 95.24287, 96.65715, 20., 20., 20., 20., 20.],
|
|
[20., 20., 20., 20., 20., 20., 20., 20.],
|
|
[20., 20., 20., 20., 20., 20., 20., 20.]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales])
|
|
np.testing.assert_allclose(output["Y"], expected, rtol=1e-6, atol=1e-6)
|
|
|
|
# crop_and_resize_linear with sizes
|
|
node_def = helper.make_node(
|
|
"Resize",
|
|
inputs=['X', 'roi', 'scales', 'sizes'],
|
|
outputs=['Y'],
|
|
mode='linear',
|
|
coordinate_transformation_mode='tf_crop_and_resize',
|
|
extrapolation_value=50.0)
|
|
roi = np.array([0, 0, 0.4, 0.6, 1, 1, 1.2, 1.7], dtype=np.float32)
|
|
scales = np.array([], dtype=np.float32)
|
|
sizes = np.array([1, 1, 7, 7], dtype=np.int64)
|
|
expected = np.array(
|
|
[[[[42.4, 44.05, 45.7, 50., 50., 50., 50.],
|
|
[54.4, 56.050003, 57.700005, 50., 50., 50., 50.],
|
|
[66.40001, 68.05, 69.700005, 50., 50., 50., 50.],
|
|
[78.40001, 80.05001, 81.700005, 50., 50., 50., 50.],
|
|
[90.40001, 92.05, 93.70001, 50., 50., 50., 50.],
|
|
[50., 50., 50., 50., 50., 50., 50.],
|
|
[50., 50., 50., 50., 50., 50., 50.]]]],
|
|
dtype=np.float32) # expected value is calculated by onnx-runtime
|
|
output = run_node(node_def, [data, roi, scales, sizes])
|
|
np.testing.assert_allclose(output["Y"], expected, rtol=1e-6, atol=1e-6)
|
|
|
|
def test_round(self):
|
|
if legacy_opset_pre_ver(11):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Round.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("Round", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(-20.0, 20.0, shape=[1000])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.round(x))
|
|
|
|
def test_qLinearMatMul(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support QLinearMatMul.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
def qLinearMatMul(a, a_scale, a_zero_point, b, b_scale, b_zero_point,
|
|
y_scale, y_zero_point):
|
|
y_dtype = y_zero_point.dtype
|
|
# reshape 1-D a_scale, a_zero_point, y_scale and
|
|
# y_zero_point so it can broadcast in arithmetic
|
|
# operations later
|
|
a_scale_shape = a_scale.shape
|
|
if a_scale_shape and a_scale_shape[0] > 1:
|
|
a_scale = np.reshape(a_scale, [a_scale_shape[0], 1])
|
|
a_zero_point = np.reshape(a_zero_point, [a_scale_shape[0], 1])
|
|
y_scale_shape = y_scale.shape
|
|
if y_scale_shape and y_scale_shape[0] > 1:
|
|
y_scale = np.reshape(y_scale, [y_scale_shape[0], 1])
|
|
y_zero_point = np.reshape(y_zero_point, [y_scale_shape[0], 1])
|
|
# cast everything to float32
|
|
a = a.astype(np.float32)
|
|
a_zero_point = a_zero_point.astype(np.float32)
|
|
b = b.astype(np.float32)
|
|
b_zero_point = b_zero_point.astype(np.float32)
|
|
y_zero_point = y_zero_point.astype(np.float32)
|
|
# dequantize a and b
|
|
dequantized_a = np.subtract(a, a_zero_point)
|
|
dequantized_a = np.multiply(dequantized_a, a_scale)
|
|
dequantized_b = np.subtract(b, b_zero_point)
|
|
dequantized_b = np.multiply(dequantized_b, b_scale)
|
|
# matmul a and b
|
|
x = np.matmul(dequantized_a, dequantized_b)
|
|
# quantize x
|
|
y = np.divide(x, y_scale)
|
|
y = np.round(y)
|
|
y = np.add(y, y_zero_point)
|
|
y = np.clip(y, np.iinfo(y_dtype).min, np.iinfo(y_dtype).max)
|
|
y = y.astype(y_dtype)
|
|
return y
|
|
|
|
node_def = helper.make_node('QLinearMatMul', [
|
|
'a', 'a_scale', 'a_zero_point', 'b', 'b_scale', 'b_zero_point',
|
|
'y_scale', 'y_zero_point'
|
|
], ['y'])
|
|
for dtype in [np.int8, np.uint8]:
|
|
low = np.iinfo(dtype).min
|
|
high = np.iinfo(dtype).max
|
|
a = self._get_rnd_int(low, high, [3, 4, 5, 6], dtype)
|
|
a_scale = self._get_rnd_float32(-0.005, 0.005, [5])
|
|
a_zero_point = self._get_rnd_int(low, high, [5], dtype)
|
|
b = self._get_rnd_int(low, high, [3, 4, 6, 2], dtype)
|
|
b_scale = self._get_rnd_float32(-0.005, 0.005, [2])
|
|
b_zero_point = self._get_rnd_int(low, high, [2], dtype)
|
|
y_scale = self._get_rnd_float32(-0.05, 0.05, [5])
|
|
y_zero_point = self._get_rnd_int(low, high, [5], dtype)
|
|
y = qLinearMatMul(a, a_scale, a_zero_point, b, b_scale, b_zero_point,
|
|
y_scale, y_zero_point)
|
|
output = run_node(node_def, [
|
|
a, a_scale, a_zero_point, b, b_scale, b_zero_point, y_scale,
|
|
y_zero_point
|
|
])
|
|
np.testing.assert_almost_equal(output['y'], y)
|
|
|
|
def test_relu(self):
|
|
node_def = helper.make_node("Relu", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[1000])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.maximum(x, 0))
|
|
|
|
def test_pad(self):
|
|
x = self._get_rnd_float32(shape=[100, 100])
|
|
if legacy_opset_pre_ver(11): # for opset = 1 or 2
|
|
# mode = constant
|
|
node_def = helper.make_node("Pad", ["X"], ["Y"],
|
|
mode="constant",
|
|
pads=[1, 1, 1, 1],
|
|
value=2.0)
|
|
output = run_node(node_def, [x])
|
|
y = np.pad(x, ((1, 1), (1, 1)), 'constant', constant_values=(2, 2))
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
# mode = reflect and edge
|
|
for mode in ['edge', 'reflect']:
|
|
node_def = helper.make_node("Pad", ["X"], ["Y"],
|
|
mode=mode,
|
|
pads=[1, 1, 1, 1])
|
|
output = run_node(node_def, [x])
|
|
y = np.pad(x, ((1, 1), (1, 1)), mode)
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
else: # for opset = 11
|
|
# mode = constant
|
|
node_def = helper.make_node("Pad", ["X", "pads", "constant_values"],
|
|
["Y"],
|
|
mode="constant")
|
|
pads = np.array([1, 1, 1, 1], dtype=np.int64)
|
|
constant_values = 2.0
|
|
output = run_node(node_def, [x, pads, constant_values])
|
|
y = np.pad(x, ((1, 1), (1, 1)), 'constant', constant_values=(2, 2))
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
# mode = reflect and edge
|
|
for mode in ['edge', 'reflect']:
|
|
node_def = helper.make_node("Pad", ["X", "pads"], ["Y"], mode=mode)
|
|
output = run_node(node_def, [x, pads])
|
|
y = np.pad(x, ((1, 1), (1, 1)), mode)
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
|
|
def test_qlinearconv(self):
|
|
if legacy_opset_pre_ver(10):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support QLinearConv.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
# Test w_scale and w_zero_point as scalar
|
|
node_def = helper.make_node("QLinearConv",
|
|
inputs=[
|
|
"x", "x_scale", "x_zero_point", "w",
|
|
"w_scale", "w_zero_point", "y_scale",
|
|
"y_zero_point"
|
|
],
|
|
outputs=["Y"])
|
|
x = np.array([
|
|
[255, 174, 162, 25, 203, 168, 58],
|
|
[15, 59, 237, 95, 129, 0, 64],
|
|
[56, 242, 153, 221, 168, 12, 166],
|
|
[232, 178, 186, 195, 237, 162, 237],
|
|
[188, 39, 124, 77, 80, 102, 43],
|
|
[127, 230, 21, 83, 41, 40, 134],
|
|
[255, 154, 92, 141, 42, 148, 247],
|
|
],
|
|
dtype=np.uint8).reshape((1, 1, 7, 7))
|
|
x_scale = np.float32(0.00369204697)
|
|
x_zero_point = np.uint8(132)
|
|
|
|
w = np.array([0], dtype=np.uint8).reshape((1, 1, 1, 1))
|
|
w_scale = np.float32(0.00172794575)
|
|
w_zero_point = np.uint8(255)
|
|
|
|
y = np.array([
|
|
[0, 81, 93, 230, 52, 87, 197],
|
|
[240, 196, 18, 160, 126, 255, 191],
|
|
[199, 13, 102, 34, 87, 243, 89],
|
|
[23, 77, 69, 60, 18, 93, 18],
|
|
[67, 216, 131, 178, 175, 153, 212],
|
|
[128, 25, 234, 172, 214, 215, 121],
|
|
[0, 101, 163, 114, 213, 107, 8],
|
|
],
|
|
dtype=np.uint8).reshape((1, 1, 7, 7))
|
|
y_scale = np.float32(0.00162681262)
|
|
y_zero_point = np.uint8(123)
|
|
|
|
output = run_node(node_def, [
|
|
x, x_scale, x_zero_point, w, w_scale, w_zero_point, y_scale,
|
|
y_zero_point
|
|
])
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
|
|
def test_quantize_linear(self):
|
|
node_def = helper.make_node("QuantizeLinear",
|
|
["x", "y_scale", "y_zero_point"], ["y"])
|
|
for x in [
|
|
self._get_rnd_float32(-512., 512., [2, 6]),
|
|
self._get_rnd_int(-512, 512, [2, 6])
|
|
]:
|
|
y_scale = self._get_rnd_float32(-10., 10.)
|
|
for y_zero_point in [
|
|
self._get_rnd_int(-128, 127, dtype=np.int8),
|
|
self._get_rnd_int(0, 255, dtype=np.uint8)
|
|
]:
|
|
y = np.divide(x, y_scale)
|
|
y = np.round(y)
|
|
y = np.add(y, y_zero_point)
|
|
if y_zero_point.dtype.type is np.int8:
|
|
y = np.clip(y, -128, 127).astype(np.int8)
|
|
else:
|
|
y = np.clip(y, 0, 255).astype(np.uint8)
|
|
output = run_node(node_def, [x, y_scale, y_zero_point])
|
|
np.testing.assert_almost_equal(output["y"], y)
|
|
|
|
def test_reciprocal(self):
|
|
node_def = helper.make_node("Reciprocal", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[1000])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], 1.0 / x)
|
|
|
|
def test_reduce_l1(self):
|
|
node_def = helper.make_node("ReduceL1", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_float32(shape=[5, 10, 10, 3])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"],
|
|
np.linalg.norm(x, 1, (1, 2), True))
|
|
|
|
def test_reduce_log_sum_exp(self):
|
|
node_def = helper.make_node("ReduceLogSumExp", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_float32(shape=[5, 10, 10, 3])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.log(
|
|
np.sum(np.exp(x), axis=(1, 2),
|
|
keepdims=True)),
|
|
rtol=1e-3)
|
|
|
|
def test_reduce_max(self):
|
|
node_def = helper.make_node("ReduceMax", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_float32(shape=[5, 10, 10, 3])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.max(x, (1, 2), keepdims=True),
|
|
rtol=1e-3)
|
|
|
|
# test tensor(uint8), tensor(int8)
|
|
node_def = helper.make_node("ReduceMax", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_int(0, 100, [5, 10, 10, 3], np.uint8)
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.max(x, (1, 2), keepdims=True),
|
|
rtol=1e-3)
|
|
|
|
node_def = helper.make_node("ReduceMax", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_int(-100, 100, [5, 10, 10, 3], np.int8)
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.max(x, (1, 2), keepdims=True),
|
|
rtol=1e-3)
|
|
|
|
def test_reduce_mean(self):
|
|
node_def = helper.make_node("ReduceMean", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_float32(shape=[5, 10, 10, 3])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.mean(x, (1, 2), keepdims=True),
|
|
rtol=1e-3)
|
|
|
|
def test_reduce_min(self):
|
|
node_def = helper.make_node("ReduceMin", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_float32(shape=[5, 10, 10, 3])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.min(x, (1, 2), keepdims=True),
|
|
rtol=1e-3)
|
|
|
|
# test tensor(uint8), tensor(int8)
|
|
node_def = helper.make_node("ReduceMin", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_int(0, 100, [5, 10, 10, 3], np.uint8)
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.min(x, (1, 2), keepdims=True),
|
|
rtol=1e-3)
|
|
|
|
node_def = helper.make_node("ReduceMin", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_int(-100, 100, [5, 10, 10, 3], np.int8)
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.min(x, (1, 2), keepdims=True),
|
|
rtol=1e-3)
|
|
|
|
def test_reduce_prod(self):
|
|
node_def = helper.make_node("ReduceProd", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_float32(shape=[1, 5, 5, 3])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.prod(x, (1, 2), keepdims=True),
|
|
rtol=1e-3)
|
|
|
|
def test_reduce_sum(self):
|
|
node_def = helper.make_node("ReduceSum", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_float32(shape=[5, 10, 10, 3])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.sum(x, (1, 2), keepdims=True),
|
|
rtol=1e-3)
|
|
|
|
def test_reduce_sum_square(self):
|
|
node_def = helper.make_node("ReduceSumSquare", ["X"], ["Y"], axes=[1, 2])
|
|
x = self._get_rnd_float32(shape=[5, 10, 10, 3])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"],
|
|
np.sum(np.square(x), (1, 2), keepdims=True),
|
|
rtol=1e-3)
|
|
|
|
def test_pow(self):
|
|
node_def = helper.make_node("Pow", ["X", "Y"], ["Z"])
|
|
x = self._get_rnd_float32(shape=1000) / 2.0 + 0.5
|
|
y = self._get_rnd_float32(shape=1000) / 2.0 + 0.5
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"], np.power(x, y))
|
|
|
|
def test_reshape(self):
|
|
x = self._get_rnd_float32(shape=100)
|
|
shape = [10, 10]
|
|
if defs.onnx_opset_version() < 5:
|
|
node_def = helper.make_node("Reshape", ["X"], ["Z"], shape=shape)
|
|
output = run_node(node_def, [x])
|
|
else:
|
|
node_def = helper.make_node("Reshape", ["X", "Y"], ["Z"])
|
|
output = run_node(node_def, [x, shape])
|
|
|
|
np.testing.assert_almost_equal(output["Z"], x.reshape([10, 10]))
|
|
|
|
def test_reshape_with_copy(self):
|
|
x = self._get_rnd_float32(shape=[10, 20 * 30])
|
|
shape = [0, 20, 30]
|
|
if defs.onnx_opset_version() < 5:
|
|
node_def = helper.make_node("Reshape", ["X"], ["Z"], shape=shape)
|
|
output = run_node(node_def, [x])
|
|
else:
|
|
node_def = helper.make_node("Reshape", ["X", "Y"], ["Z"])
|
|
output = run_node(node_def, [x, shape])
|
|
|
|
np.testing.assert_almost_equal(output["Z"], x.reshape([10, 20, 30]))
|
|
|
|
def test_selu(self):
|
|
node_def = helper.make_node("Selu", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[1000])
|
|
output = run_node(node_def, [x])
|
|
alpha = 1.6732
|
|
gamma = 1.0507
|
|
x[x <= 0] = gamma * (alpha * np.exp(x[x <= 0]) - alpha)
|
|
x[x > 0] = gamma * x[x > 0]
|
|
np.testing.assert_allclose(output["Y"], x, rtol=1e-3, atol=1e-7)
|
|
|
|
def _run_scan_node(self,
|
|
initial,
|
|
x1,
|
|
x2,
|
|
input_shape,
|
|
output_shape,
|
|
scan_input_axes=None,
|
|
scan_input_directions=None,
|
|
scan_output_axes=None,
|
|
scan_output_directions=None,
|
|
sequence_lens=None,
|
|
directions=None):
|
|
"""
|
|
Subgraph looks like this.
|
|
|
|
[const1] state_in concat1_in concat2_in_
|
|
\ | \ /
|
|
\--------[Add] [Concat]
|
|
| |
|
|
| concat_out
|
|
| |
|
|
| [Add]----------[const1]
|
|
| |
|
|
| add_out_1
|
|
| |
|
|
| [Split]
|
|
| / | | \
|
|
state_out split1_out ... split4_out
|
|
"""
|
|
val_1 = helper.make_tensor(
|
|
name='const_tensor',
|
|
data_type=TensorProto.FLOAT,
|
|
dims=[1],
|
|
vals=[1],
|
|
)
|
|
constant_node = helper.make_node("Constant", [], ["const_1"], value=val_1)
|
|
state_add_node = helper.make_node("Add", ["state_in", "const_1"],
|
|
["state_out"])
|
|
concat_node = helper.make_node("Concat", ["concat1_in", "concat2_in"],
|
|
["concat_out"],
|
|
axis=0)
|
|
add_node = helper.make_node("Add", ["concat_out", "const_1"], ["add_out"])
|
|
split_node = helper.make_node(
|
|
"Split", ["add_out"],
|
|
["split1_out", "split2_out", "split3_out", "split4_out"])
|
|
|
|
state_in = helper.make_tensor_value_info('state_in', TensorProto.FLOAT, [1])
|
|
concat1_in = helper.make_tensor_value_info('concat1_in', TensorProto.FLOAT,
|
|
input_shape)
|
|
concat2_in = helper.make_tensor_value_info('concat2_in', TensorProto.FLOAT,
|
|
input_shape)
|
|
state_out = helper.make_tensor_value_info('state_out', TensorProto.FLOAT,
|
|
[1])
|
|
split1_out = helper.make_tensor_value_info('split1_out', TensorProto.FLOAT,
|
|
output_shape)
|
|
split2_out = helper.make_tensor_value_info('split2_out', TensorProto.FLOAT,
|
|
output_shape)
|
|
split3_out = helper.make_tensor_value_info('split3_out', TensorProto.FLOAT,
|
|
output_shape)
|
|
split4_out = helper.make_tensor_value_info('split4_out', TensorProto.FLOAT,
|
|
output_shape)
|
|
|
|
scan_body = helper.make_graph(
|
|
[constant_node, state_add_node, concat_node, add_node, split_node],
|
|
"scan_body",
|
|
[state_in, concat1_in, concat2_in],
|
|
[state_out, split1_out, split2_out, split3_out, split4_out],
|
|
)
|
|
|
|
node_kwargs = {
|
|
"op_type": "Scan",
|
|
"inputs": ["initial", "x1", "x2"],
|
|
"outputs": ["y", "z1", "z2", "z3", "z4"],
|
|
"num_scan_inputs": 2,
|
|
"body": scan_body
|
|
}
|
|
if sequence_lens is not None:
|
|
node_kwargs["inputs"] = ["" if sequence_lens is str else "seq_lens"
|
|
] + node_kwargs["inputs"]
|
|
|
|
if scan_input_axes is not None:
|
|
node_kwargs["scan_input_axes"] = scan_input_axes
|
|
if scan_input_directions is not None:
|
|
node_kwargs["scan_input_directions"] = scan_input_directions
|
|
if scan_output_axes is not None:
|
|
node_kwargs["scan_output_axes"] = scan_output_axes
|
|
if scan_output_directions is not None:
|
|
node_kwargs["scan_output_directions"] = scan_output_directions
|
|
if directions is not None:
|
|
node_kwargs["directions"] = directions
|
|
|
|
scan_node = helper.make_node(**node_kwargs)
|
|
|
|
if sequence_lens is None:
|
|
inputs = [initial, x1, x2]
|
|
else:
|
|
inputs = [sequence_lens, initial, x1, x2]
|
|
|
|
return run_node(scan_node, inputs)
|
|
|
|
def test_scan_v8(self):
|
|
if legacy_opset_pre_ver(8) or not legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} not supported.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
initial = self._get_rnd_int(0, 100, shape=[5, 1]).astype(np.float32)
|
|
x1 = self._get_rnd_float32(0, 1000, shape=[5, 20, 6, 2])
|
|
x2 = self._get_rnd_float32(0, 1000, shape=[5, 20, 6, 2])
|
|
|
|
directions = [0, 1]
|
|
sequence_lens = np.array([15, 20, 14, 18, 20]).astype(np.int32)
|
|
|
|
Y = initial + (np.shape(x1)[1] if sequence_lens is str else \
|
|
np.reshape(sequence_lens,[-1, 1]))
|
|
x1_out = x1 + 1
|
|
# left-right flip x2 (reverse direction)
|
|
x2_out = x2[:, ::-1] + 1
|
|
|
|
Z = np.concatenate([x1_out, x2_out], 2)
|
|
if sequence_lens is not str:
|
|
for batch in range(len(sequence_lens)):
|
|
# zero pad from the sequence_lens
|
|
shape = list(np.shape(Z[batch]))
|
|
seq_len = sequence_lens[batch]
|
|
|
|
zero_pad = np.zeros([shape[0] - seq_len] + shape[1:])
|
|
Z[batch] = np.concatenate([Z[batch][:seq_len], zero_pad])
|
|
|
|
output = self._run_scan_node(initial,
|
|
x1,
|
|
x2, [6, 4], [3, 2],
|
|
sequence_lens=sequence_lens,
|
|
directions=directions)
|
|
output_z = np.concatenate(
|
|
[output["z1"], output["z2"], output["z3"], output["z4"]], 2)
|
|
|
|
np.testing.assert_almost_equal(output["y"], Y)
|
|
np.testing.assert_almost_equal(output_z, Z)
|
|
|
|
def test_scan(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} not supported.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
initial = self._get_rnd_int(0, 100, shape=[2]).astype(np.float32)
|
|
x1 = self._get_rnd_float32(0, 1000, shape=[20, 6, 2])
|
|
x2 = self._get_rnd_float32(0, 1000, shape=[20, 6, 2])
|
|
|
|
Y = initial + np.shape(x1)[0]
|
|
Z = np.concatenate([x1, x2], 1) + 1
|
|
|
|
output = self._run_scan_node(initial, x1, x2, [6, 2], [3, 2])
|
|
output_z = np.concatenate(
|
|
[output["z1"], output["z2"], output["z3"], output["z4"]], 1)
|
|
|
|
np.testing.assert_almost_equal(output["y"], Y)
|
|
np.testing.assert_almost_equal(output_z, Z)
|
|
|
|
def test_scan_input_directions(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} not supported.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
initial = self._get_rnd_int(0, 100, shape=[1]).astype(np.float32)
|
|
x1 = self._get_rnd_float32(0, 1000, shape=[20, 6, 2])
|
|
x2 = self._get_rnd_float32(0, 1000, shape=[20, 6, 2])
|
|
|
|
Y = initial + np.shape(x1)[0]
|
|
Z = np.concatenate([x1[::-1], x2], 1) + 1
|
|
|
|
output = self._run_scan_node(initial,
|
|
x1,
|
|
x2, [6, 2], [3, 2],
|
|
scan_input_directions=[1, 0])
|
|
output_z = np.concatenate(
|
|
[output["z1"], output["z2"], output["z3"], output["z4"]], 1)
|
|
|
|
np.testing.assert_almost_equal(output["y"], Y)
|
|
np.testing.assert_almost_equal(output_z, Z)
|
|
|
|
def test_scan_input_axes(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} not supported.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
initial = self._get_rnd_int(0, 100, shape=[1]).astype(np.float32)
|
|
x1 = self._get_rnd_float32(0, 1000, shape=[20, 6, 2])
|
|
x2 = self._get_rnd_float32(0, 1000, shape=[20, 6, 2])
|
|
|
|
Y = initial + np.shape(x1)[1]
|
|
x1_transpose = np.transpose(x1, (1, 0, 2))
|
|
x2_transpose = np.transpose(x2, (1, 0, 2))
|
|
Z = np.concatenate([x1_transpose, x2_transpose], 1) + 1
|
|
|
|
output = self._run_scan_node(initial,
|
|
x1,
|
|
x2, [3, 2], [10, 2],
|
|
scan_input_axes=[1, 1])
|
|
output_z = np.concatenate(
|
|
[output["z1"], output["z2"], output["z3"], output["z4"]], 1)
|
|
|
|
np.testing.assert_almost_equal(output["y"], Y)
|
|
np.testing.assert_almost_equal(output_z, Z)
|
|
|
|
def test_scan_output_directions(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} not supported.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
initial = self._get_rnd_int(0, 100, shape=[1]).astype(np.float32)
|
|
x1 = self._get_rnd_float32(0, 1000, shape=[20, 6, 2])
|
|
x2 = self._get_rnd_float32(0, 1000, shape=[20, 6, 2])
|
|
|
|
Y = initial + np.shape(x1)[0]
|
|
Z = np.concatenate([x1, x2], 1) + 1
|
|
|
|
output = self._run_scan_node(initial,
|
|
x1,
|
|
x2, [6, 2], [3, 2],
|
|
scan_output_directions=[1, 0, 0, 1])
|
|
output_z = np.concatenate(
|
|
[output["z1"][::-1], output["z2"], output["z3"], output["z4"][::-1]], 1)
|
|
|
|
np.testing.assert_almost_equal(output["y"], Y)
|
|
np.testing.assert_almost_equal(output_z, Z)
|
|
|
|
def test_scan_output_axes(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} not supported.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
initial = self._get_rnd_int(0, 100, shape=[1]).astype(np.float32)
|
|
x1 = self._get_rnd_float32(0, 1000, shape=[20, 6, 2])
|
|
x2 = self._get_rnd_float32(0, 1000, shape=[20, 6, 2])
|
|
|
|
Y = initial + np.shape(x1)[0]
|
|
Z = np.concatenate([x1, x2], 1) + 1
|
|
Z = np.transpose(Z, (1, 0, 2))
|
|
|
|
output = self._run_scan_node(initial,
|
|
x1,
|
|
x2, [10, 2], [3, 2],
|
|
scan_output_axes=[1, 1, 1, 1])
|
|
output_z = np.concatenate(
|
|
[output["z1"], output["z2"], output["z3"], output["z4"]], 0)
|
|
|
|
np.testing.assert_almost_equal(output["y"], Y)
|
|
np.testing.assert_almost_equal(output_z, Z)
|
|
|
|
def test_scatter_elements1(self):
|
|
data = np.array([[1.0, 2.0, 3.0, 4.0, 5.0]], dtype=np.float32)
|
|
indices = np.array([[1, 3]], dtype=np.int64)
|
|
updates = np.array([[1.1, 2.1]], dtype=np.float32)
|
|
axis = 1
|
|
ref_output = np.array([[1.0, 1.1, 3.0, 2.1, 5.0]], dtype=np.float32)
|
|
|
|
if legacy_opset_pre_ver(11):
|
|
node_def = helper.make_node("Scatter", ["data", "indices", "updates"],
|
|
["outputs"],
|
|
axis=axis)
|
|
output = run_node(node_def, [data, indices, updates])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
else:
|
|
node_def = helper.make_node("ScatterElements",
|
|
["data", "indices", "updates"], ["outputs"],
|
|
axis=axis)
|
|
output = run_node(node_def, [data, indices, updates])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
|
|
def test_scatter_elements2(self):
|
|
data = np.array([
|
|
[0.0, 0.0, 0.0],
|
|
[0.0, 0.0, 0.0],
|
|
[0.0, 0.0, 0.0],
|
|
],
|
|
dtype=np.float32)
|
|
indices = np.array([
|
|
[1, 0, 2],
|
|
[0, 2, 1],
|
|
], dtype=np.int64)
|
|
updates = np.array([
|
|
[1.0, 1.1, 1.2],
|
|
[2.0, 2.1, 2.2],
|
|
], dtype=np.float32)
|
|
ref_output = np.array([
|
|
[2.0, 1.1, 0.0],
|
|
[1.0, 0.0, 2.2],
|
|
[0.0, 2.1, 1.2],
|
|
],
|
|
dtype=np.float32)
|
|
|
|
if legacy_opset_pre_ver(11):
|
|
node_def = helper.make_node("Scatter", ["data", "indices", "updates"],
|
|
["outputs"])
|
|
output = run_node(node_def, [data, indices, updates])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
else:
|
|
node_def = helper.make_node("ScatterElements",
|
|
["data", "indices", "updates"], ["outputs"])
|
|
output = run_node(node_def, [data, indices, updates])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
|
|
def test_scatter_elements3(self):
|
|
# indices out of bounds
|
|
data = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=np.float32)
|
|
indices = np.array([[0, 1, 2]], dtype=np.int64)
|
|
updates = np.array([[1.1, 2.1, 3.1]], dtype=np.float32)
|
|
|
|
if legacy_opset_pre_ver(11):
|
|
node_def = helper.make_node("Scatter", ["data", "indices", "updates"],
|
|
["outputs"])
|
|
else:
|
|
node_def = helper.make_node("ScatterElements",
|
|
["data", "indices", "updates"], ["outputs"])
|
|
with np.testing.assert_raises(tf.errors.InvalidArgumentError):
|
|
output = run_node(node_def, [data, indices, updates])
|
|
|
|
def test_scatter_nd(self):
|
|
if legacy_opset_pre_ver(11):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support ScatterND.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
# valid positve and negative indices for elements
|
|
data = np.array([1, 2, 3, 4, 5, 6, 7, 8], dtype=np.float32)
|
|
indices = np.array([[4], [3], [1], [7]], dtype=np.int64)
|
|
updates = np.array([9, 10, 11, 12], dtype=np.float32)
|
|
ref_output = np.array([1, 11, 3, 10, 9, 6, 7, 12], dtype=np.float32)
|
|
node_def = helper.make_node("ScatterND", ["data", "indices", "updates"],
|
|
["outputs"])
|
|
output = run_node(node_def, [data, indices, updates])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
|
|
# valid positive and negative indices for slices
|
|
data = np.reshape(np.arange(1, 25, dtype=np.float32), [2, 3, 4])
|
|
indices = np.array([[-2, -1], [1, 0]], dtype=np.int64)
|
|
updates = np.array([[39, 40, 41, 42], [43, 44, 45, 46]], dtype=np.float32)
|
|
ref_output = np.array(
|
|
[[[1, 2, 3, 4], [5, 6, 7, 8], [39, 40, 41, 42]],
|
|
[[43, 44, 45, 46], [17, 18, 19, 20], [21, 22, 23, 24]]],
|
|
dtype=np.float32)
|
|
output = run_node(node_def, [data, indices, updates])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
indices = np.array([[-1]], dtype=np.int64)
|
|
updates = np.array([[[43, 44, 45, 46], [47, 48, 49, 50], [51, 52, 53, 54]]],
|
|
dtype=np.float32)
|
|
ref_output = np.array(
|
|
[[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],
|
|
[[43, 44, 45, 46], [47, 48, 49, 50], [51, 52, 53, 54]]],
|
|
dtype=np.float32)
|
|
output = run_node(node_def, [data, indices, updates])
|
|
np.testing.assert_almost_equal(output["outputs"], ref_output)
|
|
|
|
# indices out of bounds
|
|
indices = np.array([[0, 1, 2], [-1, -1, -3], [-2, -3, -4], [0, 2, -5]],
|
|
dtype=np.int64)
|
|
updates = np.array([37, 52, 30, 39], dtype=np.float32)
|
|
with np.testing.assert_raises(tf.errors.InvalidArgumentError):
|
|
output = run_node(node_def, [data, indices, updates])
|
|
indices = np.array([[0, 1], [-1, -1], [-2, -4]], dtype=np.int64)
|
|
updates = np.array([[35, 36, 37, 38], [51, 52, 53, 54], [31, 32, 33, 34]],
|
|
dtype=np.float32)
|
|
with np.testing.assert_raises(tf.errors.InvalidArgumentError):
|
|
output = run_node(node_def, [data, indices, updates])
|
|
|
|
def test_shape(self):
|
|
node_def = helper.make_node("Shape", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[5, 10, 10, 3])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_allclose(output["Y"], np.shape(x))
|
|
|
|
def test_shrink(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Shrink.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
node_def = helper.make_node("Shrink", ["X"], ["Y"], bias=1.5, lambd=1.5)
|
|
|
|
X = np.arange(-2.0, 2.1, dtype=np.float32)
|
|
Y = np.array([-0.5, 0, 0, 0, 0.5], dtype=np.float32)
|
|
output = run_node(node_def, [X])
|
|
np.testing.assert_almost_equal(output["Y"], Y)
|
|
|
|
def test_sigmoid(self):
|
|
node_def = helper.make_node("Sigmoid", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[1000])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], 1 / (1 + np.exp(-x)))
|
|
|
|
def test_sign(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Sign.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("Sign", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(-10, 10, [3, 5])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.sign(x))
|
|
|
|
def test_sinh(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Sinh.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("Sinh", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[3, 4, 5])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.sinh(x))
|
|
|
|
def test_size(self):
|
|
node_def = helper.make_node("Size", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[5, 10, 10, 3])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.size(x))
|
|
|
|
def test_slice(self):
|
|
# test case 1 with normal inputs
|
|
axes = [0, 1, 2]
|
|
starts = [0, 0, 0]
|
|
ends = [2, 2, 2]
|
|
steps = [1, 1, 1]
|
|
|
|
if legacy_opset_pre_ver(10):
|
|
node_def = helper.make_node("Slice", ["X"], ["S"],
|
|
axes=axes,
|
|
starts=starts,
|
|
ends=ends)
|
|
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["S"], x[0:2, 0:2, 0:2])
|
|
else:
|
|
node_def = helper.make_node("Slice",
|
|
["X", "starts", "ends", "axes", "steps"],
|
|
["S"])
|
|
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
|
output = run_node(node_def, [x, starts, ends, axes, steps])
|
|
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]
|
|
|
|
if legacy_opset_pre_ver(10):
|
|
node_def = helper.make_node("Slice", ["X"], ["S"],
|
|
axes=axes,
|
|
starts=starts,
|
|
ends=ends)
|
|
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["S"], x[0:-8, :, -7:20])
|
|
else:
|
|
node_def = helper.make_node("Slice", ["X", "starts", "ends", "axes"],
|
|
["S"])
|
|
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
|
output = run_node(node_def, [x, starts, ends, axes])
|
|
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 legacy_opset_pre_ver(10) == False:
|
|
node_def = helper.make_node("Slice",
|
|
["X", "starts", "ends", "axes", "steps"],
|
|
["S"])
|
|
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
|
output = run_node(node_def, [x, starts, ends, axes, steps])
|
|
np.testing.assert_almost_equal(output["S"], x[0:2:2, 0:2:-2, 0:2:-1])
|
|
|
|
def test_softplus(self):
|
|
node_def = helper.make_node("Softplus", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[3, 4, 5])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.log(np.exp(x) + 1), decimal=5)
|
|
|
|
def test_softsign(self):
|
|
node_def = helper.make_node("Softsign", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[3, 4, 5])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], x / (1 + np.abs(x)))
|
|
|
|
def test_space_to_depth(self):
|
|
node_def = helper.make_node("SpaceToDepth", ["X"], ["Y"], blocksize=2)
|
|
x_shape = [1, 3, 2, 2]
|
|
x = self._get_rnd_float32(shape=x_shape)
|
|
output = run_node(node_def, [x])
|
|
x = np.transpose(x, (0, 2, 3, 1))
|
|
y = np.reshape(np.swapaxes(x.reshape(1, 1, 1, 1, 1, 12), 2, 3),
|
|
(1, 1, 1, 12))
|
|
y = np.transpose(y, (0, 3, 1, 2))
|
|
np.testing.assert_allclose(output["Y"], y, rtol=1e-3)
|
|
|
|
def test_split(self):
|
|
split = [3, 3, 4]
|
|
node_def = helper.make_node("Split", ["X"],
|
|
["Z%i" % i for i in range(len(split))],
|
|
axis=0,
|
|
split=split)
|
|
x = self._get_rnd_float32(shape=[100]).reshape([10, 10])
|
|
|
|
output = run_node(node_def, [x])
|
|
for a, b in zip(list(output), np.split(x, np.cumsum(split))[:-1]):
|
|
np.testing.assert_almost_equal(a, b)
|
|
|
|
# test axis out of bound
|
|
node_def = helper.make_node("Split", ["X"],
|
|
["Z%i" % i for i in range(len(split))],
|
|
axis=3,
|
|
split=split)
|
|
with np.testing.assert_raises(ValueError):
|
|
output = run_node(node_def, [x])
|
|
|
|
def test_sqrt(self):
|
|
node_def = helper.make_node("Sqrt", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[1000]) + 1.0
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.sqrt(x), decimal=5)
|
|
|
|
def test_squeeze(self):
|
|
node_def = helper.make_node("Squeeze", ["X"], ["Y"], axes=[2])
|
|
x = np.array([[[0], [1], [2]]])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.squeeze(x, axis=2))
|
|
|
|
def test_sub(self):
|
|
node_def = helper.make_node("Sub", ["X", "Y"], ["Z"])
|
|
x = self._get_rnd_float32(shape=[10, 10])
|
|
y = self._get_rnd_float32(shape=[10, 10])
|
|
output = run_node(node_def, [x, y])
|
|
np.testing.assert_almost_equal(output["Z"], np.subtract(x, y))
|
|
|
|
def test_sum(self):
|
|
node_def = helper.make_node("Sum", ["X1", "X2", "X3", "X4"], ["Z"])
|
|
x1 = self._get_rnd_float32(shape=[10, 10])
|
|
x2 = self._get_rnd_float32(shape=[10, 10])
|
|
x3 = self._get_rnd_float32(shape=[10, 10])
|
|
x4 = self._get_rnd_float32(shape=[10, 10])
|
|
output = run_node(node_def, [x1, x2, x3, x4])
|
|
test_output = x1 + x2 + x3 + x4
|
|
np.testing.assert_almost_equal(output["Z"], test_output)
|
|
|
|
def test_tanh(self):
|
|
node_def = helper.make_node("Tanh", ["X"], ["Y"])
|
|
x = self._get_rnd_float32(shape=[1000]) + 1.0
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.tanh(x), decimal=5)
|
|
|
|
def test_tfidf_vectorizer(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest(
|
|
"ONNX version {} doesn't support TfIdfVectorizer.".format(
|
|
defs.onnx_opset_version()))
|
|
|
|
def run_test_ints():
|
|
node_def = helper.make_node("TfIdfVectorizer", ["X"], ["Y"],
|
|
mode=mode,
|
|
min_gram_length=min_gram_len,
|
|
max_gram_length=max_gram_len,
|
|
max_skip_count=max_skip,
|
|
ngram_counts=ngram_counts,
|
|
ngram_indexes=ngram_indexes,
|
|
weights=weights,
|
|
pool_int64s=pool_int64s)
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
|
|
def run_test_strings():
|
|
node_def = helper.make_node("TfIdfVectorizer", ["X"], ["Y"],
|
|
mode=mode,
|
|
min_gram_length=min_gram_len,
|
|
max_gram_length=max_gram_len,
|
|
max_skip_count=max_skip,
|
|
ngram_counts=ngram_counts,
|
|
ngram_indexes=ngram_indexes,
|
|
weights=weights,
|
|
pool_strings=pool_strings)
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
|
|
# test 2d inputs with 3 elements, output contains 1-grams and 2-grams
|
|
x = np.array([[1, 1, 3, 3, 3, 7], [8, 6, 7, 5, 6, 8], [8, 6, 7, 5, 6,
|
|
8]]).astype(np.int32)
|
|
y = np.array([[0., 3., 0., 0., 0., 0., 0.], [0., 0., 1., 0., 1., 0., 1.],
|
|
[0., 0., 1., 0., 1., 0., 1.]]).astype(np.float32)
|
|
ngram_counts = np.array([0, 4]).astype(np.int64)
|
|
ngram_indexes = np.array([0, 1, 2, 3, 4, 5, 6]).astype(np.int64)
|
|
pool_int64s = np.array([2, 3, 5, 4, 5, 6, 7, 8, 6, 7]).astype(np.int64)
|
|
min_gram_len = 1
|
|
max_gram_len = 2
|
|
max_skip = 0
|
|
mode = 'TF'
|
|
weights = np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])
|
|
run_test_ints()
|
|
|
|
# test 1d inputs with indexes in non-default order, max_skip=3, output 2-grams
|
|
x = np.array([1, 1, 3, 3, 3, 7, 8, 6, 7, 5, 6, 8]).astype(np.int32)
|
|
y = np.array([0., 1., 0., 1., 0., 0., 2.]).astype(np.float32)
|
|
ngram_counts = np.array([0, 4]).astype(np.int64)
|
|
ngram_indexes = np.array([5, 0, 2, 4, 1, 6, 3]).astype(np.int64)
|
|
pool_int64s = np.array([2, 3, 5, 4, 5, 6, 7, 8, 6, 7]).astype(np.int64)
|
|
min_gram_len = 2
|
|
max_gram_len = 2
|
|
max_skip = 3
|
|
mode = 'TF'
|
|
weights = np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])
|
|
run_test_ints()
|
|
|
|
# test IDF mode with weights, max_skip=5, output contains 1-grams and 2-grams
|
|
x = np.array([[1, 1, 3, 3, 3, 7], [8, 6, 7, 5, 6, 8]]).astype(np.int32)
|
|
y = np.array([[0., 0.1, 0., 0., 0., 0., 0.],
|
|
[0., 0., 0.1, 0., 0.5, 0.5, 0.5]]).astype(np.float32)
|
|
ngram_counts = np.array([0, 4]).astype(np.int64)
|
|
ngram_indexes = np.array([0, 1, 2, 3, 4, 5, 6]).astype(np.int64)
|
|
pool_int64s = np.array([2, 3, 5, 4, 5, 6, 7, 8, 6, 7]).astype(np.int64)
|
|
min_gram_len = 1
|
|
max_gram_len = 2
|
|
max_skip = 5
|
|
mode = 'IDF'
|
|
weights = np.array([0.1, 0.1, 0.1, 0.1, 0.5, 0.5, 0.5])
|
|
run_test_ints()
|
|
|
|
# test strings inputs, max_skip=5, output contains 1-grams and 2-grams
|
|
x = np.array(['a', 'a', 'b', 'b', 'b', 'c', 'd', 'e', 'c', 'f', 'e', 'd'])
|
|
y = np.array([0., 3., 1., 0., 1., 3., 1.]).astype(np.float32)
|
|
ngram_counts = np.array([0, 4]).astype(np.int64)
|
|
ngram_indexes = np.array([0, 1, 2, 3, 4, 5, 6]).astype(np.int64)
|
|
pool_strings = np.array(['x', 'b', 'f', 'y', 'f', 'e', 'c', 'd', 'e', 'c'])
|
|
min_gram_len = 1
|
|
max_gram_len = 2
|
|
max_skip = 5
|
|
mode = 'TF'
|
|
run_test_strings()
|
|
|
|
def test_thresholded_relu(self):
|
|
alpha = 2.0
|
|
node_def = helper.make_node("ThresholdedRelu", ["X"], ["Y"], alpha=alpha)
|
|
x = self._get_rnd_float32(-3.0, 3.0, [10])
|
|
y = np.clip(x, alpha, np.inf)
|
|
y[y == alpha] = 0
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], y)
|
|
|
|
def test_tile(self):
|
|
if legacy_onnx_pre_ver(1, 2):
|
|
raise unittest.SkipTest(
|
|
"The current version of ONNX does not record correctly the opset of Tile."
|
|
)
|
|
node_def = helper.make_node("Tile", ["X1", "X2"], ["Z"])
|
|
x = self._get_rnd_float32(shape=[3, 5, 5, 3])
|
|
repeats = [1, 1, 2, 1]
|
|
output = run_node(node_def, [x, repeats])
|
|
np.testing.assert_allclose(output["Z"], np.tile(x, repeats), rtol=1e-3)
|
|
|
|
def test_transpose(self):
|
|
node_def = helper.make_node("Transpose", ["X"], ["Y"], perm=[0, 2, 1])
|
|
x = self._get_rnd_float32(shape=[1000]).reshape([10, 10, 10])
|
|
output = run_node(node_def, [x])
|
|
np.testing.assert_almost_equal(output["Y"], np.transpose(x, (0, 2, 1)))
|
|
|
|
def test_topk(self):
|
|
x = np.arange(15, dtype=np.float32).reshape(3, 5)
|
|
values = np.array([[4, 3], [9, 8], [14, 13]], dtype=np.float32)
|
|
indices = np.array([[4, 3], [4, 3], [4, 3]], dtype=np.int64)
|
|
if legacy_opset_pre_ver(10): # for opset = 1
|
|
node_def = helper.make_node("TopK", ["x"], ["values", "indices"], k=2)
|
|
output = run_node(node_def, [x])
|
|
elif legacy_opset_pre_ver(11): # for opset = 10
|
|
k = np.array([2], dtype=np.int64)
|
|
node_def = helper.make_node("TopK", ["x", "k"], ["values", "indices"])
|
|
output = run_node(node_def, [x, k])
|
|
else: # for opset = 11
|
|
x = np.array([[3, 2, 5, 10, 7], [12, 15, 10, 7, 20], [21, 16, 5, 3, 6]],
|
|
dtype=np.float32)
|
|
values = np.array([[3, 2], [10, 7], [5, 3]], dtype=np.float32)
|
|
indices = np.array([[0, 1], [2, 3], [2, 3]], dtype=np.int64)
|
|
k = np.array([2], dtype=np.int64)
|
|
node_def = helper.make_node("TopK", ["x", "k"], ["values", "indices"],
|
|
largest=0,
|
|
sorted=0)
|
|
output = run_node(node_def, [x, k])
|
|
np.testing.assert_almost_equal(output["values"], values)
|
|
np.testing.assert_almost_equal(output["indices"], indices)
|
|
|
|
def test_where(self):
|
|
if legacy_opset_pre_ver(9):
|
|
raise unittest.SkipTest("ONNX version {} doesn't support Where.".format(
|
|
defs.onnx_opset_version()))
|
|
node_def = helper.make_node("Where", ["C", "X", "Y"], ["Z"])
|
|
c = np.array([[1, 0], [1, 1]], dtype=np.bool)
|
|
x = np.array([[1, 2], [3, 4]], dtype=np.float32)
|
|
y = np.array([[9, 8], [7, 6]], dtype=np.float32)
|
|
output = run_node(node_def, [c, x, y])
|
|
np.testing.assert_almost_equal(output["Z"], np.where(c, x, y))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|