blob: 4f68256ab5d88a6158411e28dfe38df2a28b4786 [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
""" Support level5 operator test cases.
"""
import math
import platform
import sys
import numpy as np
import pytest
import tvm
import tvm.testing
import tvm.topi.testing
from tvm import relay, te
from tvm.relay.testing import run_infer_type
executor_kind = tvm.testing.parameter("graph", "vm")
def test_resize1d_infer_type():
n, c, w = te.size_var("n"), te.size_var("c"), te.size_var("w")
x = relay.var("x", relay.TensorType((n, c, w), "int8"))
tw = te.var("tw")
z = relay.image.resize1d(x, (tw,))
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType((n, c, tw), "int8")
x = relay.var("x", relay.TensorType((n, c, w), "int8"))
z = relay.image.resize1d(x, (200,), None, "NCW", "linear", "align_corners")
assert "size=" in z.astext()
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType((n, c, 200), "int8")
class TestResize1D:
interpolate_method = tvm.testing.parameter("nearest_neighbor", "linear", "cubic")
coord_trans = tvm.testing.parameter("asymmetric", "align_corners", "half_pixel")
layout = tvm.testing.parameter("NWC", "NCW")
dshape, scale = tvm.testing.parameters(
((1, 4, 4), 2),
((2, 8, 17), 3),
((2, 8, 17), 3),
((3, 4, 5), 5),
)
def test_resize(
self, target, dev, executor_kind, dshape, scale, interpolate_method, layout, coord_trans
):
target_kind = tvm.target.Target(target).kind.name
if (
target_kind == "vulkan"
and dshape == (3, 4, 5)
and scale == 5
and interpolate_method == "nearest_neighbor"
and coord_trans == "align_corners"
):
pytest.xfail("Known failing case for these parameters")
if layout == "NWC":
size = (dshape[1] * scale,)
else:
size = (dshape[2] * scale,)
x_data = np.random.uniform(size=dshape).astype("float32")
ref_res = tvm.topi.testing.resize1d_python(
x_data, (scale,), layout, interpolate_method, coord_trans
)
x = relay.var("x", relay.TensorType(dshape, "float32"))
z = relay.image.resize1d(
x, size, None, layout, interpolate_method, coordinate_transformation_mode=coord_trans
)
assert "size=" in z.astext()
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType(ref_res.shape, "float32")
func = relay.Function([x], z)
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
x_data
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-3, atol=1e-4)
def test_resize2d_infer_type():
n, c, h, w = te.size_var("n"), te.size_var("c"), te.size_var("h"), te.size_var("w")
x = relay.var("x", relay.TensorType((n, c, h, w), "int8"))
th, tw = te.var("th"), te.var("tw")
z = relay.image.resize2d(x, (th, tw))
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType((n, c, th, tw), "int8")
x = relay.var("x", relay.TensorType((n, c, h, w), "int8"))
z = relay.image.resize2d(x, (100, 200), None, "NCHW", "linear", "align_corners")
assert "size=" in z.astext()
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType((n, c, 100, 200), "int8")
class TestResize2D:
interpolate_method = tvm.testing.parameter("nearest_neighbor", "linear", "cubic")
coord_trans = tvm.testing.parameter("asymmetric", "align_corners", "half_pixel")
layout = tvm.testing.parameter("NHWC", "NCHW")
dshape, scale = tvm.testing.parameters(
((1, 4, 4, 4), 2),
((2, 8, 17, 20), 3),
((2, 8, 17, 20), 3),
((3, 4, 5, 6), 5),
)
def test_resize(
self, target, dev, executor_kind, dshape, scale, interpolate_method, layout, coord_trans
):
target_kind = tvm.target.Target(target).kind.name
if (
target_kind == "vulkan"
and dshape == (3, 4, 5, 6)
and scale == 5
and interpolate_method == "nearest_neighbor"
and coord_trans == "align_corners"
):
pytest.xfail("Known failing case for these parameters")
if layout == "NHWC":
size = (dshape[1] * scale, dshape[2] * scale)
else:
size = (dshape[2] * scale, dshape[3] * scale)
x_data = np.random.uniform(size=dshape).astype("float32")
ref_res = tvm.topi.testing.resize2d_python(
x_data, (scale, scale), layout, interpolate_method, coord_trans
)
x = relay.var("x", relay.TensorType(dshape, "float32"))
z = relay.image.resize2d(
x, size, None, layout, interpolate_method, coordinate_transformation_mode=coord_trans
)
assert "size=" in z.astext()
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType(ref_res.shape, "float32")
func = relay.Function([x], z)
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
x_data
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-3, atol=1e-4)
def test_resize3d_infer_type():
n, c, d, h, w = (
te.size_var("n"),
te.size_var("c"),
te.size_var("d"),
te.size_var("h"),
te.size_var("w"),
)
x = relay.var("x", relay.TensorType((n, c, d, h, w), "int8"))
td, th, tw = te.var("td"), te.var("th"), te.var("tw")
z = relay.image.resize3d(x, (td, th, tw))
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType((n, c, td, th, tw), "int8")
x = relay.var("x", relay.TensorType((n, c, d, h, w), "int8"))
z = relay.image.resize3d(x, (10, 10, 20), None, "NCDHW", "linear", "align_corners")
assert "size=" in z.astext()
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType((n, c, 10, 10, 20), "int8")
class TestResize3D:
interpolate_method = tvm.testing.parameter("nearest_neighbor", "linear", "cubic")
coord_trans = tvm.testing.parameter("asymmetric", "align_corners", "half_pixel")
layout = tvm.testing.parameter("NDHWC", "NCDHW")
dshape, scale = tvm.testing.parameters(
((1, 4, 4, 4, 4), 2),
)
def test_resize(
self, target, dev, executor_kind, dshape, scale, interpolate_method, layout, coord_trans
):
if layout == "NDHWC":
size = (dshape[1] * scale, dshape[2] * scale, dshape[3] * scale)
else:
size = (dshape[2] * scale, dshape[3] * scale, dshape[4] * scale)
x_data = np.random.uniform(size=dshape).astype("float32")
ref_res = tvm.topi.testing.resize3d_python(
x_data, (scale, scale, scale), layout, interpolate_method, coord_trans
)
x = relay.var("x", relay.TensorType(dshape, "float32"))
z = relay.image.resize3d(x, size, None, layout, interpolate_method, coord_trans)
assert "size=" in z.astext()
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType(ref_res.shape, "float32")
func = relay.Function([x], z)
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
x_data
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-4, atol=1e-6)
class TestCropAndResize:
interpolate_method = tvm.testing.parameter("bilinear", "nearest_neighbor")
layout = tvm.testing.parameter("NHWC", "NCHW")
@pytest.mark.skipif(
platform.machine() == "aarch64",
reason="Currently failing on AArch64 - see https://github.com/apache/tvm/issues/10673",
)
def test_crop_and_resize(self, target, dev, executor_kind, layout, interpolate_method):
target_kind = tvm.target.Target(target).kind.name
if (
target_kind == "vulkan"
and layout == "NHWC"
and interpolate_method == "nearest_neighbor"
):
pytest.xfail("Known failing case for these parameters")
extrapolation_value = 0.0
np.random.seed(0)
eps = 1e-4
if layout == "NHWC":
img_shape = (10, 224, 224, 3)
boxes = np.random.uniform(size=(2, 4)).astype("float32")
box_indices = np.array([1, 0]).astype("int32")
crop_size = np.array([20, 30]).astype("int32")
elif layout == "NCHW":
img_shape = (5, 3, 255, 255)
boxes = np.random.uniform(size=(2, 4)).astype("float32")
box_indices = np.array([0, 1]).astype("int32")
crop_size = np.array([30, 30]).astype("int32")
else:
raise ValueError(f"Unknown layout: {layout}")
image_data = np.random.uniform(size=img_shape).astype("float32")
ref_res = tvm.topi.testing.crop_and_resize_python(
image_data,
boxes,
box_indices,
crop_size,
layout,
interpolate_method,
extrapolation_value,
)
img = relay.var("img", relay.TensorType(img_shape, "float32"))
bx = relay.var("bx", relay.TensorType(boxes.shape, "float32"))
bx_idx = relay.var("bx_idx", relay.TensorType(box_indices.shape, "int32"))
z = relay.image.crop_and_resize(
img, bx, bx_idx, list(crop_size), layout, interpolate_method, extrapolation_value
)
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType(ref_res.shape, "float32")
func = relay.Function([img, bx, bx_idx], z)
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
image_data, boxes, box_indices
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-3, atol=1e-04)
@tvm.testing.uses_gpu
def test_multibox_prior(executor_kind):
def get_ref_result(
dshape, sizes=(1.0,), ratios=(1.0,), steps=(-1.0, -1.0), offsets=(0.5, 0.5), clip=True
):
in_height = dshape[2]
in_width = dshape[3]
num_sizes = len(sizes)
num_ratios = len(ratios)
size_ratio_concat = sizes + ratios
steps_h = steps[0] if steps[0] > 0 else 1.0 / in_height
steps_w = steps[1] if steps[1] > 0 else 1.0 / in_width
offset_h = offsets[0]
offset_w = offsets[1]
oshape = (1, in_height * in_width * (num_sizes + num_ratios - 1), 4)
dtype = "float32"
np_out = np.zeros(oshape).astype(dtype)
for i in range(in_height):
center_h = (i + offset_h) * steps_h
for j in range(in_width):
center_w = (j + offset_w) * steps_w
for k in range(num_sizes + num_ratios - 1):
w = (
size_ratio_concat[k] * in_height / in_width / 2.0
if k < num_sizes
else size_ratio_concat[0]
* in_height
/ in_width
* math.sqrt(size_ratio_concat[k + 1])
/ 2.0
)
h = (
size_ratio_concat[k] / 2.0
if k < num_sizes
else size_ratio_concat[0] / math.sqrt(size_ratio_concat[k + 1]) / 2.0
)
count = (
i * in_width * (num_sizes + num_ratios - 1)
+ j * (num_sizes + num_ratios - 1)
+ k
)
np_out[0][count][0] = center_w - w
np_out[0][count][1] = center_h - h
np_out[0][count][2] = center_w + w
np_out[0][count][3] = center_h + h
if clip:
np_out = np.clip(np_out, 0, 1)
return np_out
def verify_multibox_prior(
x,
dshape,
ref_res,
sizes=(1.0,),
ratios=(1.0,),
steps=(-1.0, -1.0),
offsets=(0.5, 0.5),
clip=True,
check_size=False,
check_type_only=False,
):
z = relay.vision.multibox_prior(x, sizes, ratios, steps, offsets, clip)
zz = run_infer_type(z)
if check_size:
assert "sizes=" in z.astext()
assert zz.checked_type == relay.TensorType(
(1, dshape[2] * dshape[3] * (len(sizes) + len(ratios) - 1), 4), "float32"
)
if check_type_only:
return
data = np.random.uniform(low=-1, high=1, size=dshape).astype("float32")
func = relay.Function([x], z)
func = run_infer_type(func)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
data
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-5)
sizes = (0.3, 1.5, 0.7)
ratios = (1.3, 2.4)
steps = (2.0, 1.5)
offsets = (0.2, 0.3)
dshape = (1, 3, 56, 56)
ref_res = get_ref_result(dshape, sizes, ratios, steps, offsets)
x = relay.var("x", relay.TensorType(dshape, "float32"))
verify_multibox_prior(x, dshape, ref_res, sizes, ratios, steps, offsets, check_size=True)
y = relay.var("y", relay.TensorType((te.size_var("n"), 3, 56, 56), "float32"))
verify_multibox_prior(
x, dshape, ref_res, sizes, ratios, steps, offsets, check_size=True, check_type_only=True
)
dshape = (1, 24, 32, 32)
ref_res = get_ref_result(dshape, clip=False)
x = relay.var("x", relay.TensorType(dshape, "float32"))
verify_multibox_prior(x, dshape, ref_res, clip=False)
y = relay.var("y", relay.TensorType((te.size_var("n"), 24, 32, 32), "float32"))
verify_multibox_prior(x, dshape, ref_res, clip=False, check_type_only=True)
@tvm.testing.uses_gpu
def test_get_valid_counts():
def verify_get_valid_counts(dshape, score_threshold, id_index, score_index):
dtype = "float32"
batch_size, num_anchor, elem_length = dshape
np_data = np.random.uniform(low=-2, high=2, size=dshape).astype(dtype)
np_out1 = np.zeros(shape=(batch_size,))
np_out2 = np.zeros(shape=dshape).astype(dtype)
np_out3 = np.zeros(shape=(batch_size, num_anchor))
for i in range(batch_size):
np_out1[i] = 0
inter_idx = 0
for j in range(num_anchor):
score = np_data[i, j, score_index]
if score > score_threshold and (id_index < 0 or np_data[i, j, id_index] >= 0):
for k in range(elem_length):
np_out2[i, inter_idx, k] = np_data[i, j, k]
np_out1[i] += 1
np_out3[i, inter_idx] = j
inter_idx += 1
if j >= np_out1[i]:
for k in range(elem_length):
np_out2[i, j, k] = -1.0
np_out3[i, j] = -1
x = relay.var("x", relay.ty.TensorType(dshape, dtype))
z = relay.vision.get_valid_counts(x, score_threshold, id_index, score_index)
assert "score_threshold" in z.astext()
func = relay.Function([x], z.astuple())
func = run_infer_type(func)
for target, dev in tvm.testing.enabled_targets():
out = relay.create_executor("vm", device=dev, target=target).evaluate(func)(np_data)
tvm.testing.assert_allclose(out[0].numpy(), np_out1, rtol=1e-3, atol=1e-04)
tvm.testing.assert_allclose(out[1].numpy(), np_out2, rtol=1e-3, atol=1e-04)
tvm.testing.assert_allclose(out[2].numpy(), np_out3, rtol=1e-3, atol=1e-04)
verify_get_valid_counts((1, 2500, 6), 0, 0, 1)
verify_get_valid_counts((1, 2500, 5), -1, -1, 0)
verify_get_valid_counts((3, 1000, 6), 0.55, 1, 0)
verify_get_valid_counts((16, 500, 5), 0.95, -1, 0)
@tvm.testing.uses_gpu
def test_non_max_suppression(executor_kind):
def verify_nms(
x0_data,
x1_data,
x2_data,
x3_data,
dshape,
ref_res,
ref_indices_res,
iou_threshold=0.5,
force_suppress=False,
top_k=-1,
check_type_only=False,
):
x0 = relay.var("x0", relay.ty.TensorType(dshape, "float32"))
x1 = relay.var("x1", relay.ty.TensorType((dshape[0],), "int32"))
x2 = relay.var("x2", relay.ty.TensorType((dshape[0], dshape[1]), "int32"))
x3 = relay.var("x3", relay.ty.TensorType((), "int32"))
z = relay.vision.non_max_suppression(
x0,
x1,
x2,
x3,
iou_threshold=iou_threshold,
force_suppress=force_suppress,
top_k=top_k,
return_indices=False,
)
z_indices = relay.vision.non_max_suppression(
x0,
x1,
x2,
x3,
iou_threshold=iou_threshold,
force_suppress=force_suppress,
top_k=top_k,
return_indices=True,
)
if isinstance(z_indices, relay.expr.TupleWrapper):
z_indices = z_indices.astuple()
zz = run_infer_type(z)
zz_indices = run_infer_type(z_indices)
assert zz.checked_type == relay.ty.TensorType(dshape, "float32")
assert zz_indices.checked_type == relay.ty.TupleType(
[
relay.ty.TensorType((dshape[0], dshape[1]), "int32"),
relay.ty.TensorType((dshape[0], 1), "int32"),
]
)
if check_type_only:
return
func = relay.Function([x0, x1, x2, x3], z)
func = run_infer_type(func)
func_indices = relay.Function([x0, x1, x2, x3], z_indices)
func_indices = run_infer_type(func_indices)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
x0_data, x1_data, x2_data, x3_data
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-5)
op_indices_res = relay.create_executor(
executor_kind, device=dev, target=target
).evaluate(func_indices)(x0_data, x1_data, x2_data, x3_data)
tvm.testing.assert_allclose(op_indices_res[0].numpy(), ref_indices_res, rtol=1e-5)
np_data = np.array(
[
[
[0, 0.8, 1, 20, 25, 45],
[1, 0.7, 30, 60, 50, 80],
[0, 0.4, 4, 21, 19, 40],
[2, 0.9, 35, 61, 52, 79],
[1, 0.5, 100, 60, 70, 110],
]
]
).astype("float32")
np_valid_count = np.array([4]).astype("int32")
np_indices = np.array([[0, 1, 3, 4, -1]]).astype("int32")
np_max_output_size = -1
np_result = np.array(
[
[
[2, 0.9, 35, 61, 52, 79],
[0, 0.8, 1, 20, 25, 45],
[-1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1],
]
]
)
np_indices_result = np.array([[4, 0, -1, -1, -1]])
num_anchors = 5
dshape = (te.size_var("n"), num_anchors, 6)
verify_nms(
np_data,
np_valid_count,
np_indices,
np_max_output_size,
dshape,
np_result,
np_indices_result,
force_suppress=True,
top_k=2,
check_type_only=True,
)
dshape = (1, num_anchors, 6)
verify_nms(
np_data,
np_valid_count,
np_indices,
np_max_output_size,
dshape,
np_result,
np_indices_result,
force_suppress=True,
top_k=2,
check_type_only=False,
)
np_result = np.array(
[
[
[2, 0.9, 35, 61, 52, 79],
[0, 0.8, 1, 20, 25, 45],
[-1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1],
]
]
)
np_indices_result = np.array([[4, 0, -1, -1, -1]])
np_max_output_size = 2
dshape = (te.size_var("n"), num_anchors, 6)
verify_nms(
np_data,
np_valid_count,
np_indices,
np_max_output_size,
dshape,
np_result,
np_indices_result,
check_type_only=True,
)
dshape = (1, num_anchors, 6)
verify_nms(
np_data,
np_valid_count,
np_indices,
np_max_output_size,
dshape,
np_result,
np_indices_result,
top_k=2,
)
np_data = np.array(
[
[
[0, 0.8, 1, 20, 25, 45, 1, 2, 3, 4],
[1, 0.7, 30, 60, 50, 80, 5, 6, 7, 8],
[0, 0.4, 4, 21, 19, 40, 9, 10, 11, 12],
[2, 0.9, 35, 61, 52, 79, 13, 14, 15, 16],
[1, 0.5, 100, 60, 70, 110, 17, 18, 19, 20],
]
]
).astype("float32")
np_result = np.array(
[
[
[2, 0.9, 35, 61, 52, 79, 13, 14, 15, 16],
[0, 0.8, 1, 20, 25, 45, 1, 2, 3, 4],
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
]
]
)
dshape = (1, 5, 10)
verify_nms(
np_data,
np_valid_count,
np_indices,
np_max_output_size,
dshape,
np_result,
np_indices_result,
force_suppress=True,
top_k=2,
check_type_only=False,
)
@tvm.testing.uses_gpu
def test_multibox_transform_loc(executor_kind):
def test_default_value(keep_background):
num_anchors = 3
num_classes = 3
np_cls_prob = np.array([[[0.2, 0.5, 0.3], [0.25, 0.3, 0.45], [0.7, 0.1, 0.2]]]).astype(
"float32"
)
np_loc_preds = np.array(
[[0.1, -0.2, 0.3, 0.2, 0.2, 0.4, 0.5, -0.3, 0.7, -0.2, -0.4, -0.8]]
).astype("float32")
np_anchors = np.array(
[[[-0.1, -0.1, 0.1, 0.1], [-0.2, -0.2, 0.2, 0.2], [1.2, 1.2, 1.5, 1.5]]]
).astype("float32")
expected_np_out = (
np.array(
[
[
[2, 0.69999999, 0, 0, 0.10818365, 0.10008108],
[0, 0.49999999, 0, 0, 0.22903419, 0.20435292],
[1, 0.44999999, 1, 1, 1, 1],
]
]
)
if keep_background
else np.array(
[
[
[1, 0.69999999, 0, 0, 0.10818365, 0.10008108],
[0, 0.44999999, 1, 1, 1, 1],
[0, 0.30000001, 0, 0, 0.22903419, 0.20435292],
]
]
)
)
cls_prob = relay.var(
"cls_prob", relay.ty.TensorType((1, num_anchors, num_classes), "float32")
)
loc_pred = relay.var("loc_pred", relay.ty.TensorType((1, num_anchors * 4), "float32"))
anchors = relay.var("anchors", relay.ty.TensorType((1, num_anchors, 4), "float32"))
mtl = relay.vision.multibox_transform_loc(
cls_prob=cls_prob, loc_pred=loc_pred, anchor=anchors, keep_background=keep_background
)
ret = run_infer_type(mtl.astuple())
ref_type = relay.ty.TupleType(
tvm.runtime.convert(
[
relay.ty.TensorType((1, num_anchors, 6), "float32"),
relay.ty.TensorType((1,), "int"),
]
)
)
assert ret.checked_type == ref_type
nms = relay.vision.non_max_suppression(mtl[0], mtl[1], mtl[0], return_indices=False)
func = relay.Function([cls_prob, loc_pred, anchors], nms)
func = run_infer_type(func)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
np_cls_prob, np_loc_preds, np_anchors
)
tvm.testing.assert_allclose(op_res.numpy(), expected_np_out, rtol=1e-5)
def test_threshold():
num_anchors = 5
num_classes = 5
n = te.size_var("n")
cls_prob = relay.var(
"cls_prob", relay.ty.TensorType((n, num_anchors, num_classes), "float32")
)
loc_pred = relay.var("loc_pred", relay.ty.TensorType((n, num_anchors * 4), "float32"))
anchors = relay.var("anchors", relay.ty.TensorType((1, num_anchors, 4), "float32"))
threshold = 0.02
variances = (0.2, 0.2, 0.3, 0.3)
ret = relay.vision.multibox_transform_loc(
cls_prob=cls_prob,
loc_pred=loc_pred,
anchor=anchors,
threshold=threshold,
variances=variances,
)
ret = run_infer_type(ret.astuple())
ref_type = relay.ty.TupleType(
tvm.runtime.convert(
[
relay.ty.TensorType((n, num_anchors, 6), "float32"),
relay.ty.TensorType((n,), "int"),
]
)
)
assert ret.checked_type == ref_type
test_default_value(keep_background=False)
test_default_value(keep_background=True)
test_threshold()
@tvm.testing.uses_gpu
def test_roi_align(executor_kind):
def verify_roi_align(
data_shape,
rois_shape,
channel,
in_size,
pooled_size,
spatial_scale,
sample_ratio,
mode,
layout,
ref_func,
):
data = relay.var("data", relay.ty.TensorType(data_shape, "float32"))
rois = relay.var("rois", relay.ty.TensorType(rois_shape, "float32"))
z = relay.vision.roi_align(
data,
rois,
pooled_size=(pooled_size, pooled_size),
spatial_scale=spatial_scale,
sample_ratio=sample_ratio,
mode=mode,
layout=layout,
)
zz = run_infer_type(z)
num_roi = rois_shape[0]
if layout == "NCHW":
assert zz.checked_type == relay.ty.TensorType(
(num_roi, channel, pooled_size, pooled_size), "float32"
)
else:
assert zz.checked_type == relay.ty.TensorType(
(num_roi, pooled_size, pooled_size, channel), "float32"
)
func = relay.Function([data, rois], z)
func = run_infer_type(func)
np_data = np.random.uniform(size=data_shape).astype("float32")
np_rois = np.random.uniform(size=rois_shape).astype("float32") * in_size
np_rois[:, 0] = np.random.randint(low=0, high=data_shape[0], size=num_roi)
ref_res = ref_func(
np_data,
np_rois,
pooled_size=pooled_size,
spatial_scale=spatial_scale,
sample_ratio=sample_ratio,
mode=mode,
)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
np_data, np_rois
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, atol=1e-6, rtol=1e-3)
def verify_roi_align_nchw(
data_shape, rois_shape, pooled_size, spatial_scale, sample_ratio, mode
):
_, channel, in_size, _ = data_shape
return verify_roi_align(
data_shape,
rois_shape,
channel,
in_size,
pooled_size,
spatial_scale,
sample_ratio,
mode,
"NCHW",
tvm.topi.testing.roi_align_nchw_python,
)
def verify_roi_align_nhwc(
data_shape, rois_shape, pooled_size, spatial_scale, sample_ratio, mode
):
_, in_size, _, channel = data_shape
return verify_roi_align(
data_shape,
rois_shape,
channel,
in_size,
pooled_size,
spatial_scale,
sample_ratio,
mode,
"NHWC",
tvm.topi.testing.roi_align_nhwc_python,
)
verify_roi_align_nchw(
(1, 4, 16, 16), (32, 5), pooled_size=7, spatial_scale=1.0, sample_ratio=-1, mode="avg"
)
verify_roi_align_nchw(
(4, 4, 16, 16), (32, 5), pooled_size=7, spatial_scale=0.5, sample_ratio=2, mode="avg"
)
verify_roi_align_nchw(
(1, 4, 16, 16), (32, 5), pooled_size=7, spatial_scale=1.0, sample_ratio=-1, mode="max"
)
verify_roi_align_nchw(
(4, 4, 16, 16), (32, 5), pooled_size=7, spatial_scale=0.5, sample_ratio=2, mode="max"
)
verify_roi_align_nhwc(
(1, 16, 16, 4), (32, 5), pooled_size=7, spatial_scale=1.0, sample_ratio=-1, mode="avg"
)
verify_roi_align_nhwc(
(4, 16, 16, 4), (32, 5), pooled_size=7, spatial_scale=0.5, sample_ratio=2, mode="avg"
)
verify_roi_align_nhwc(
(1, 16, 16, 4), (32, 5), pooled_size=7, spatial_scale=1.0, sample_ratio=-1, mode="max"
)
verify_roi_align_nhwc(
(4, 16, 16, 4), (32, 5), pooled_size=7, spatial_scale=0.5, sample_ratio=2, mode="max"
)
@tvm.testing.uses_gpu
def test_roi_pool(executor_kind):
def verify_roi_pool(data_shape, rois_shape, pooled_size, spatial_scale):
data = relay.var("data", relay.ty.TensorType(data_shape, "float32"))
rois = relay.var("rois", relay.ty.TensorType(rois_shape, "float32"))
z = relay.vision.roi_pool(
data,
rois,
pooled_size=(pooled_size, pooled_size),
spatial_scale=spatial_scale,
layout="NCHW",
)
zz = run_infer_type(z)
batch, channel, in_size, _ = data_shape
num_roi = rois_shape[0]
assert zz.checked_type == relay.ty.TensorType(
(num_roi, channel, pooled_size, pooled_size), "float32"
)
func = relay.Function([data, rois], z)
func = run_infer_type(func)
np_data = np.random.uniform(size=data_shape).astype("float32")
np_rois = np.random.uniform(size=rois_shape).astype("float32") * in_size
np_rois[:, 0] = np.random.randint(low=0, high=batch, size=num_roi).astype("float32")
ref_res = tvm.topi.testing.roi_pool_nchw_python(
np_data, np_rois, pooled_size=pooled_size, spatial_scale=spatial_scale
)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
np_data, np_rois
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-4)
verify_roi_pool((1, 4, 16, 16), (32, 5), pooled_size=7, spatial_scale=1.0)
verify_roi_pool((4, 4, 16, 16), (32, 5), pooled_size=7, spatial_scale=0.5)
@tvm.testing.uses_gpu
def test_proposal(executor_kind):
def verify_proposal(np_cls_prob, np_bbox_pred, np_im_info, np_out, attrs):
cls_prob = relay.var("cls_prob", relay.ty.TensorType(np_cls_prob.shape, "float32"))
bbox_pred = relay.var("bbox_pred", relay.ty.TensorType(np_bbox_pred.shape, "float32"))
im_info = relay.var("im_info", relay.ty.TensorType(np_im_info.shape, "float32"))
z = relay.vision.proposal(cls_prob, bbox_pred, im_info, **attrs)
zz = run_infer_type(z)
assert zz.checked_type == relay.ty.TensorType(np_out.shape, "float32")
func = relay.Function([cls_prob, bbox_pred, im_info], z)
func = run_infer_type(func)
for target in ["llvm", "cuda"]:
if not tvm.testing.device_enabled(target):
print("Skip test because %s is not enabled." % target)
continue
dev = tvm.device(target, 0)
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
np_cls_prob, np_bbox_pred, np_im_info
)
tvm.testing.assert_allclose(op_res.numpy(), np_out, rtol=1e-4)
attrs = {
"scales": (0.5,),
"ratios": (0.5,),
"feature_stride": 16,
"iou_loss": False,
"rpn_min_size": 16,
"threshold": 0.7,
"rpn_pre_nms_top_n": 200,
"rpn_post_nms_top_n": 4,
}
np_cls_prob = np.array(
[
[
[[0.3, 0.6, 0.2], [0.4, 0.7, 0.5], [0.1, 0.4, 0.3]],
[[0.7, 0.5, 0.3], [0.6, 0.4, 0.8], [0.9, 0.2, 0.5]],
]
],
dtype="float32",
)
np_bbox_pred = np.array(
[
[
[[0.5, 1.0, 0.6], [0.8, 1.2, 2.0], [0.9, 1.0, 0.8]],
[[0.5, 1.0, 0.7], [0.8, 1.2, 1.6], [2.1, 1.5, 0.7]],
[[1.0, 0.5, 0.7], [1.5, 0.9, 1.6], [1.4, 1.5, 0.8]],
[[1.0, 0.5, 0.6], [1.5, 0.9, 2.0], [1.8, 1.0, 0.9]],
]
],
dtype="float32",
)
np_im_info = np.array([[48.0, 48.0, 1.0]], dtype="float32")
np_out = np.array(
[
[0.0, 0.0, 2.8451548, 28.38012, 18.154846],
[0.0, 0.0, 15.354933, 41.96971, 41.245064],
[0.0, 18.019852, 1.0538368, 51.98015, 25.946163],
[0.0, 27.320923, -1.266357, 55.0, 24.666357],
],
dtype="float32",
)
verify_proposal(np_cls_prob, np_bbox_pred, np_im_info, np_out, attrs)
np_out = np.array(
[
[0.0, -5.25, -2.5, 21.75, 19.0],
[0.0, 11.25, -2.0, 37.25, 18.5],
[0.0, 26.849998, -2.3000002, 53.45, 18.6],
[0.0, -4.95, 13.799999, 22.25, 35.5],
],
dtype="float32",
)
attrs["iou_loss"] = True
verify_proposal(np_cls_prob, np_bbox_pred, np_im_info, np_out, attrs)
def test_yolo_reorg_infer_shape():
def verify_yolo_reorg(shape, stride, out_shape):
x = relay.var("x", relay.TensorType(shape, "float32"))
z = relay.vision.yolo_reorg(x, stride=stride)
zz = run_infer_type(z)
assert "stride=" in z.astext()
assert zz.checked_type == relay.ty.TensorType(out_shape, "float32")
n, c, h, w = te.size_var("n"), te.size_var("c"), te.size_var("h"), te.size_var("w")
idxd = tvm.tir.indexdiv
verify_yolo_reorg((n, c, 20, 20), 10, (n, c * 10 * 10, 2, 2))
verify_yolo_reorg((n, c, h, w), 2, (n, c * 2 * 2, idxd(h, 2), idxd(w, 2)))
@tvm.testing.uses_gpu
def test_yolo_reorg(executor_kind):
def verify_yolo_reorg(shape, stride):
x_data = np.random.uniform(low=-1, high=1, size=shape).astype("float32")
ref_res = tvm.topi.testing.reorg_python(x_data, stride)
x = relay.var("x", relay.TensorType(shape, "float32"))
z = relay.vision.yolo_reorg(x, stride=stride)
zz = run_infer_type(z)
assert "stride=" in z.astext()
assert zz.checked_type == relay.ty.TensorType(ref_res.shape, "float32")
func = relay.Function([x], z)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
x_data
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-5)
verify_yolo_reorg((1, 100, 20, 20), 10)
verify_yolo_reorg((1, 4, 6, 6), 2)
class TestDeformableConv2D:
batch, in_channel, size, out_channel, deformable_groups = tvm.testing.parameters(
(1, 4, 16, 4, 4),
(2, 4, 16, 4, 1),
)
kernel_size = tvm.testing.parameter((3, 3))
groups = tvm.testing.parameter(1, 2)
layout = tvm.testing.parameter("NCHW", "NHWC")
dtype = tvm.testing.parameter("float32")
@tvm.testing.fixture
def data_shape(self, layout, batch, in_channel, size):
if layout == "NCHW":
return (batch, in_channel, size, size)
elif layout == "NHWC":
return (batch, size, size, in_channel)
@tvm.testing.fixture
def kernel_shape(self, layout, in_channel, out_channel, groups, kernel_size):
if layout == "NCHW":
return (out_channel, in_channel // groups, kernel_size[0], kernel_size[1])
elif layout == "NHWC":
return (kernel_size[0], kernel_size[1], in_channel // groups, out_channel)
@tvm.testing.fixture
def out_shape(self, layout, batch, out_channel, size):
if layout == "NCHW":
return (batch, out_channel, size, size)
elif layout == "NHWC":
return (batch, size, size, out_channel)
@tvm.testing.fixture
def offset_shape(self, layout, batch, kernel_size, deformable_groups, out_shape):
if layout == "NCHW":
return (
batch,
2 * kernel_size[0] * kernel_size[1] * deformable_groups,
out_shape[2],
out_shape[3],
)
elif layout == "NHWC":
return (
batch,
out_shape[1],
out_shape[2],
2 * kernel_size[0] * kernel_size[1] * deformable_groups,
)
@tvm.testing.fixture
def kernel_layout(self, layout):
return {"NCHW": "OIHW", "NHWC": "HWIO"}[layout]
@tvm.testing.fixture
def relay_setup(
self,
dtype,
data_shape,
layout,
kernel_layout,
kernel_size,
deformable_groups,
groups,
out_channel,
):
data = relay.var("data", shape=data_shape, dtype=dtype)
offset = relay.var("offset", dtype=dtype)
kernel = relay.var("kernel", dtype=dtype)
expr = relay.nn.deformable_conv2d(
data,
offset,
kernel,
strides=(1, 1),
padding=(1, 1),
dilation=(1, 1),
data_layout=layout,
kernel_layout=kernel_layout,
kernel_size=kernel_size,
deformable_groups=deformable_groups,
groups=groups,
channels=out_channel,
)
func = relay.Function([data, offset, kernel], expr)
return expr, func
def test_infer_type(self, relay_setup, out_shape, offset_shape, kernel_shape):
expr, func = relay_setup
yy = run_infer_type(expr)
assert yy.checked_type == relay.TensorType(out_shape), yy.checked_type
assert yy.args[1].checked_type == relay.TensorType(offset_shape), yy.args[1].checked_type
assert yy.args[2].checked_type == relay.TensorType(kernel_shape), yy.args[2].checked_type
# The reference python implementation only supports groups==1.
@pytest.mark.parametrize("groups", [1])
def test_run(
self,
target,
dev,
dtype,
executor_kind,
data_shape,
offset_shape,
kernel_shape,
relay_setup,
deformable_groups,
groups,
layout,
):
target = tvm.target.Target(target)
if layout == "NHWC" and target.kind.name != "llvm":
pytest.xfail("Can only run NHWC layout on llvm")
expr, func = relay_setup
data = np.random.uniform(size=data_shape).astype(dtype)
offset = np.random.uniform(size=offset_shape).astype(dtype)
kernel = np.random.uniform(size=kernel_shape).astype(dtype)
if layout == "NCHW":
ref_res = tvm.topi.testing.deformable_conv2d_nchw_python(
data,
offset,
kernel,
stride=(1, 1),
padding=(1, 1),
dilation=(1, 1),
deformable_groups=deformable_groups,
groups=groups,
)
else:
ref_res = tvm.topi.testing.deformable_conv2d_nhwc_python(
data,
offset,
kernel,
stride=(1, 1),
padding=(1, 1),
dilation=(1, 1),
deformable_groups=deformable_groups,
groups=groups,
)
op_res1 = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
data, offset, kernel
)
tvm.testing.assert_allclose(op_res1.numpy(), ref_res, rtol=1e-5, atol=1e-5)
@tvm.testing.uses_gpu
def test_depth_to_space(executor_kind):
def verify_depth_to_space(dshape, block_size, layout, mode):
if layout == "NHWC":
out_shape = [
dshape[0],
dshape[1] * block_size,
dshape[2] * block_size,
dshape[3] / (block_size * block_size),
]
else:
out_shape = [
dshape[0],
dshape[1] / (block_size * block_size),
dshape[2] * block_size,
dshape[3] * block_size,
]
x_data = np.random.uniform(size=dshape).astype("float32")
if layout == "NHWC":
x_data = np.transpose(x_data, axes=[0, 3, 1, 2])
ref_res = tvm.topi.testing.depth_to_space_python(x_data, block_size, mode=mode)
if layout == "NHWC":
x_data = np.transpose(x_data, axes=[0, 2, 3, 1])
ref_res = np.transpose(ref_res, axes=[0, 2, 3, 1])
x = relay.var("x", relay.TensorType(dshape, "float32"))
z = relay.nn.depth_to_space(x, block_size, layout, mode)
assert "block_size=" in z.astext()
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType(ref_res.shape, "float32")
func = relay.Function([x], z)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
x_data
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-4)
for layout in ["NHWC", "NCHW"]:
for mode in ["DCR", "CDR"]:
verify_depth_to_space((1, 4, 4, 4), 2, layout, mode)
@tvm.testing.uses_gpu
def test_space_to_depth(executor_kind):
def verify_space_to_depth(dshape, block_size, layout):
if layout == "NHWC":
out_shape = [
dshape[0],
dshape[1] / block_size,
dshape[2] / block_size,
dshape[3] * (block_size * block_size),
]
else:
out_shape = [
dshape[0],
dshape[1] * (block_size * block_size),
dshape[2] / block_size,
dshape[3] / block_size,
]
x_data = np.random.uniform(size=dshape).astype("float32")
if layout == "NHWC":
x_data = np.transpose(x_data, axes=[0, 3, 1, 2])
ref_res = tvm.topi.testing.space_to_depth_python(x_data, block_size)
if layout == "NHWC":
x_data = np.transpose(x_data, axes=[0, 2, 3, 1])
ref_res = np.transpose(ref_res, axes=[0, 2, 3, 1])
x = relay.var("x", relay.TensorType(dshape, "float32"))
z = relay.nn.space_to_depth(x, block_size, layout)
assert "block_size=" in z.astext()
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType(ref_res.shape, "float32")
func = relay.Function([x], z)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
x_data
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-4)
for layout in ["NHWC", "NCHW"]:
verify_space_to_depth((1, 4, 4, 4), 2, layout)
def test_dilation2d_infer_type():
# symbolic in batch dimension
n, h, w, c = te.var("n"), 224, 224, 10
x = relay.var("x", relay.ty.TensorType((n, c, h, w), "float32"))
kc, kh, kw = 10, 8, 8
w = relay.var("w", relay.ty.TensorType((kc, kw, kh), "float32"))
y = relay.image.dilation2d(
x,
w,
# kernel_size=(3, 3),
strides=[1, 1, 1, 1],
dilations=[1, 1, 1, 1],
padding=[0, 0, 0, 0],
)
yy = run_infer_type(y)
assert yy.checked_type == relay.TensorType((n, 10, 217, 217), "float32")
class TestDilation2DRun:
data_layout, kernel_layout = tvm.testing.parameters(("NCHW", "IHW"), ("NHWC", "HWI"))
dtype = tvm.testing.parameter("float32")
config = tvm.testing.parameter(
dict(
image=[[[[0.1], [0.2]], [[0.3], [0.4]]]],
kernel=[[[0.4], [0.3]], [[0.1], [0.0]]],
out=[[[[0.5]]]],
),
dict(
image=[[[[0.1], [0.2]], [[0.3], [0.4]]]],
kernel=[[[0.4], [0.3]], [[0.1], [0.0]]],
out=[[[[0.5], [0.6]], [[0.7], [0.8]]]],
padding=[0, 0, 1, 1],
),
dict(
image=[[[[0.1, 0.2, 0.0], [0.2, 0.3, 0.1]], [[0.3, 0.4, 0.2], [0.4, 0.5, 0.3]]]],
kernel=[[[0.4, 0.5, 0.3], [0.3, 0.4, 0.2]], [[0.1, 0.2, 0.0], [0.0, 0.1, -0.1]]],
out=[[[[0.5, 0.7, 0.3], [0.6, 0.8, 0.4]], [[0.7, 0.9, 0.5], [0.8, 1.0, 0.6]]]],
padding=[0, 0, 1, 1],
),
dict(
image=[[[[0.1], [0.2]], [[0.3], [0.4]]], [[[0.2], [0.3]], [[0.4], [0.5]]]],
kernel=[[[0.4], [0.3]], [[0.1], [0.0]]],
out=[[[[0.5], [0.6]], [[0.7], [0.8]]], [[[0.6], [0.7]], [[0.8], [0.9]]]],
padding=[0, 0, 1, 1],
),
dict(
image=[[[[0.1], [0.2]], [[0.3], [0.4]]]],
kernel=[[[0.4], [0.3]]],
out=[[[[0.5]], [[0.7]]]],
),
dict(
image=[[[[0.1], [0.2], [0.3]], [[0.4], [0.5], [0.6]], [[0.7], [0.8], [0.9]]]],
kernel=[[[0.4], [0.3]], [[0.1], [0.2]]],
out=[[[[0.7], [0.8], [0.6]], [[1.0], [1.1], [0.9]], [[0.8], [0.9], [0.9]]]],
padding=[1, 1],
dilations=[2, 2],
),
dict(
image=[
[
[[0.1], [0.2], [0.3], [0.4]],
[[0.5], [0.6], [0.7], [0.8]],
[[0.9], [1.0], [1.1], [1.2]],
]
],
kernel=[[[0.4], [0.3]], [[0.1], [0.2]]],
out=[[[[0.8], [1.0]], [[1.2], [1.4]]]],
strides=[1, 2],
),
)
@tvm.testing.fixture
def test_case(self, config, data_layout, dtype):
indata = np.array(config["image"], dtype=dtype)
kernel = np.array(config["kernel"], dtype=dtype)
out = np.array(config["out"], dtype=dtype)
if data_layout == "NHWC":
pass
elif data_layout == "NCHW":
indata = indata.transpose([0, 3, 1, 2])
kernel = kernel.transpose([2, 0, 1])
out = out.transpose([0, 3, 1, 2])
else:
raise ValueError(f"Unsupported layout '{data_layout}'")
return indata, kernel, out
@tvm.testing.parametrize_targets("llvm")
def test_dilation2d(
self,
target,
dev,
test_case,
dtype,
config,
data_layout,
kernel_layout,
):
strides = config.get("strides", [1, 1])
padding = config.get("padding", [0, 0])
dilations = config.get("dilations", [1, 1])
indata, kernel, out = test_case
x = relay.var("x", shape=indata.shape, dtype=dtype)
w = relay.var("w", shape=kernel.shape, dtype=dtype)
y = relay.image.dilation2d(
x,
w,
strides=strides,
dilations=dilations,
padding=padding,
data_layout=data_layout,
kernel_layout=kernel_layout,
)
func = relay.Function([x, w], y)
op_res = relay.create_executor("graph", device=dev, target=target).evaluate(func)(
indata, kernel
)
tvm.testing.assert_allclose(op_res.numpy(), out, rtol=1e-5, atol=1e-5)
@tvm.testing.uses_gpu
def test_affine_grid(executor_kind):
def verify_affine_grid(num_batch, target_shape):
dtype = "float32"
data_shape = (num_batch, 2, 3)
data = relay.var("data", relay.ty.TensorType(data_shape, dtype))
y = relay.image.affine_grid(data, target_shape)
yy = run_infer_type(y)
assert yy.checked_type == relay.ty.TensorType(
(num_batch, len(target_shape), *target_shape), dtype
)
func = relay.Function([data], y)
data_np = np.random.uniform(size=data_shape).astype(dtype)
ref_res = tvm.topi.testing.affine_grid_python(data_np, target_shape)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
data_np
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-5, atol=1e-5)
verify_affine_grid(1, (16, 32))
verify_affine_grid(4, (16, 32))
@tvm.testing.uses_gpu
def test_grid_sample(executor_kind):
def verify_grid_sample(
data_shape, grid_shape, method="bilinear", padding_mode="zeros", align_corners=True
):
dtype = "float32"
data = relay.var("data", relay.ty.TensorType(data_shape, dtype))
grid = relay.var("grid", relay.ty.TensorType(grid_shape, dtype))
if len(data_shape) == 4:
layout = "NCHW"
batch, channel, _, _ = data_shape
_, _, out_height, out_width = grid_shape
tensor_type = relay.TensorType((batch, channel, out_height, out_width), dtype)
else: # len(data_shape) == 5:
layout = "NCDHW"
batch, channel, _, _, _ = data_shape
_, _, out_depth, out_height, out_width = grid_shape
tensor_type = relay.TensorType(
(batch, channel, out_depth, out_height, out_width), dtype
)
y = relay.image.grid_sample(
data,
grid,
method=method,
layout=layout,
padding_mode=padding_mode,
align_corners=align_corners,
)
yy = run_infer_type(y)
assert yy.checked_type == tensor_type
func = relay.Function([data, grid], y)
data_np = np.random.uniform(size=data_shape).astype(dtype)
grid_np = np.random.uniform(size=grid_shape, low=-1.5, high=1.5).astype(dtype)
ref_res = tvm.topi.testing.grid_sample_python(
data_np, grid_np, method, layout, padding_mode, align_corners
)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
data_np, grid_np
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-5, atol=1e-5)
methods = ["nearest", "bilinear", "bicubic"]
padding_modes = ["zeros", "border", "reflection"]
align_corners = [True, False]
data_2D_shape = (4, 4, 8, 8)
grid_2D_shape = (4, 2, 16, 16)
# choosing smaller sizes to be testable on weaker GPUs
data_3D_shape = (4, 4, 4, 4, 4)
grid_3D_shape = (4, 3, 8, 8, 8)
for _method in methods:
for _padding in padding_modes:
for _align in align_corners:
verify_grid_sample(data_2D_shape, grid_2D_shape, _method, _padding, _align)
# 3D "bicubic"(tricubic) is not supported in pytorch
if _method != "bicubic":
verify_grid_sample(data_3D_shape, grid_3D_shape, _method, _padding, _align)
@tvm.testing.uses_gpu
def test_space_to_batch_nd(executor_kind):
def verify_space_to_batch_nd(dshape, block_shape, paddings):
x_data = np.random.uniform(size=dshape).astype("float32")
pad_before, pad_after = map(list, zip(*paddings))
ref_res = tvm.topi.testing.space_to_batch_nd_python(
x_data, block_shape, pad_before, pad_after
)
x = relay.var("x", relay.TensorType(dshape, "float32"))
z = relay.nn.space_to_batch_nd(x, block_shape, paddings)
assert "block_shape=" in z.astext()
assert "paddings=" in z.astext()
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType(ref_res.shape, "float32")
func = relay.Function([x], z)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
x_data
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-4)
verify_space_to_batch_nd([3, 3, 2, 1], [3], [[0, 0]])
verify_space_to_batch_nd([2, 2, 4, 1], [2, 2], [[0, 0], [2, 0]])
@tvm.testing.uses_gpu
def test_batch_to_space_nd(executor_kind):
def verify_batch_to_space_nd(dshape, block_shape, crops):
x_data = np.random.uniform(size=dshape).astype("float32")
crop_begin_list, crop_end_list = map(list, zip(*crops))
ref_res = tvm.topi.testing.batch_to_space_nd_python(
x_data, block_shape, crop_begin_list, crop_end_list
)
x = relay.var("x", relay.TensorType(dshape, "float32"))
z = relay.nn.batch_to_space_nd(x, block_shape, crops)
assert "block_shape=" in z.astext()
assert "crops=" in z.astext()
zz = run_infer_type(z)
assert zz.checked_type == relay.TensorType(ref_res.shape, "float32")
func = relay.Function([x], z)
for target, dev in tvm.testing.enabled_targets():
op_res = relay.create_executor(executor_kind, device=dev, target=target).evaluate(func)(
x_data
)
tvm.testing.assert_allclose(op_res.numpy(), ref_res, rtol=1e-4)
verify_batch_to_space_nd([4, 1, 1, 3], [2, 2], [[0, 0], [0, 0]])
verify_batch_to_space_nd([8, 1, 3, 1], [2, 2], [[0, 0], [2, 0]])
@tvm.testing.uses_gpu
def test_all_class_non_max_suppression(executor_kind):
def verify_all_class_non_max_suppression(
boxes_np,
scores_np,
max_output_boxes_per_class,
iou_threshold,
score_threshold,
expected_indices,
):
boxes = relay.var("boxes", relay.ty.TensorType(boxes_np.shape, "float32"))
scores = relay.var("scores", relay.ty.TensorType(scores_np.shape, "float32"))
out = relay.vision.all_class_non_max_suppression(
boxes,
scores,
max_output_boxes_per_class,
iou_threshold,
score_threshold,
)
func = relay.Function([boxes, scores], out.astuple())
func = run_infer_type(func)
for target, dev in tvm.testing.enabled_targets():
selected_indices, num_detections = relay.create_executor(
executor_kind, device=dev, target=target
).evaluate(func)(boxes_np, scores_np)
tvm_res = selected_indices.numpy()[: num_detections.numpy()[0]]
np.testing.assert_equal(tvm_res, expected_indices)
boxes = np.array(
[
[
[0.0, 0.0, 0.3, 0.3],
[0.0, 0.0, 0.4, 0.4],
[0.0, 0.0, 0.5, 0.5],
[0.5, 0.5, 0.9, 0.9],
[0.5, 0.5, 1.0, 1.0],
],
[
[0.0, 0.0, 0.3, 0.3],
[0.0, 0.0, 0.4, 0.4],
[0.5, 0.5, 0.95, 0.95],
[0.5, 0.5, 0.96, 0.96],
[0.5, 0.5, 1.0, 1.0],
],
]
).astype("float32")
scores = np.array(
[
[[0.1, 0.2, 0.6, 0.3, 0.9], [0.1, 0.2, 0.6, 0.3, 0.9]],
[[0.1, 0.2, 0.6, 0.3, 0.9], [0.1, 0.2, 0.6, 0.3, 0.9]],
]
).astype("float32")
max_output_boxes_per_class = 2
iou_threshold = 0.8
score_threshold = 0.0
expected = np.array(
[[0, 0, 4], [0, 0, 2], [0, 1, 4], [0, 1, 2], [1, 0, 4], [1, 0, 1], [1, 1, 4], [1, 1, 1]]
)
verify_all_class_non_max_suppression(
boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, expected
)
boxes = np.array(
[
[
[0.0, 0.0, 1.0, 1.0],
[0.0, 0.1, 1.0, 1.1],
[0.0, -0.1, 1.0, 0.9],
[0.0, 10.0, 1.0, 11.0],
[0.0, 10.1, 1.0, 11.1],
[0.0, 100.0, 1.0, 101.0],
]
]
).astype(np.float32)
scores = np.array([[[0.9, 0.75, 0.6, 0.95, 0.5, 0.3]]]).astype(np.float32)
max_output_boxes_per_class = 3
iou_threshold = 0.5
score_threshold = 0.4
expected = np.array([[0, 0, 3], [0, 0, 0]])
verify_all_class_non_max_suppression(
boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold, expected
)
if __name__ == "__main__":
tvm.testing.main()