| # 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. |
| |
| # pylint: skip-file |
| from __future__ import print_function |
| import numpy as np |
| import mxnet as mx |
| import random |
| import itertools |
| from numpy.testing import assert_allclose, assert_array_equal |
| from mxnet.test_utils import * |
| from common import assert_raises_cudnn_not_satisfied, xfail_when_nonstandard_decimal_separator |
| import unittest |
| |
| def test_box_nms_op(): |
| def test_box_nms_forward(data, expected, thresh=0.5, valid=0, topk=-1, coord=2, score=1, cid=0, bid=-1, |
| force=False, in_format='corner', out_format='corner'): |
| for dtype in ['float16', 'float32', 'float64']: |
| data = mx.nd.array(data, dtype=dtype) |
| out = mx.contrib.nd.box_nms(data, overlap_thresh=thresh, valid_thresh=valid, topk=topk, |
| coord_start=coord, score_index=score, id_index=cid, background_id=bid, |
| force_suppress=force, in_format=in_format, out_format=out_format) |
| assert_almost_equal(out.asnumpy(), expected.astype(dtype), rtol=1e-3, atol=1e-3) |
| |
| def test_box_nms_backward(data, grad, expected, thresh=0.5, valid=0, topk=-1, coord=2, score=1, |
| cid=0, bid=-1, force=False, in_format='corner', out_format='corner'): |
| in_var = mx.sym.Variable('data') |
| arr_data = mx.nd.array(data) |
| arr_grad = mx.nd.empty(arr_data.shape) |
| op = mx.contrib.sym.box_nms(in_var, overlap_thresh=thresh, valid_thresh=valid, topk=topk, |
| coord_start=coord, score_index=score, id_index=cid, background_id=bid, |
| force_suppress=force, in_format=in_format, out_format=out_format) |
| exe = op._bind(ctx=default_device(), args=[arr_data], args_grad=[arr_grad]) |
| exe.forward(is_train=True) |
| exe.backward(mx.nd.array(grad)) |
| assert_almost_equal(arr_grad.asnumpy(), expected) |
| |
| def corner_to_center(data): |
| out = np.reshape(data, (-1, 6)).copy() |
| out[:, 2] = (data[:, 2] + data[:, 4]) / 2.0 |
| out[:, 3] = (data[:, 3] + data[:, 5]) / 2.0 |
| out[:, 4] = data[:, 4] - data[:, 2] |
| out[:, 5] = data[:, 5] - data[:, 3] |
| invalid = np.where(data[:, 0] < 0)[0] |
| out[invalid, :] = -1 |
| return out |
| |
| def center_to_corner(data): |
| data = np.reshape(data, (-1, 6)).copy() |
| out[:, 2] = data[:, 2] - data[:, 4] / 2.0 |
| out[:, 3] = data[:, 3] - data[:, 5] / 2.0 |
| out[:, 4] = data[:, 2] + data[:, 4] / 2.0 |
| out[:, 5] = data[:, 3] + data[:, 5] / 2.0 |
| invalid = np.where(data[:, 0] < 0)[0] |
| out[invalid, :] = -1 |
| return out |
| |
| def swap_position(data, expected, coord=2, score=1, cid=0, new_col=0): |
| data = np.reshape(data, (-1, 6)) |
| expected = np.reshape(expected, (-1, 6)) |
| new_coord = random.randint(0, 6 + new_col - 4) |
| others = list(range(new_coord)) + list(range(new_coord + 4, 6 + new_col)) |
| random.shuffle(others) |
| new_score = others[0] |
| new_cid = others[1] |
| new_data = np.full((data.shape[0], data.shape[1] + new_col), -1.0) |
| new_expected = np.full((expected.shape[0], expected.shape[1] + new_col), -1.0) |
| new_data[:, new_coord:new_coord+4] = data[:, coord:coord+4] |
| new_data[:, new_score] = data[:, score] |
| new_data[:, new_cid] = data[:, cid] |
| new_expected[:, new_coord:new_coord+4] = expected[:, coord:coord+4] |
| new_expected[:, new_score] = expected[:, score] |
| new_expected[:, new_cid] = expected[:, cid] |
| return new_data, new_expected, new_coord, new_score, new_cid |
| |
| # manually set up test cases |
| boxes = [[0, 0.5, 0.1, 0.1, 0.2, 0.2], [1, 0.4, 0.1, 0.1, 0.2, 0.2], |
| [0, 0.3, 0.1, 0.1, 0.14, 0.14], [2, 0.6, 0.5, 0.5, 0.7, 0.8]] |
| |
| # case1 |
| force = True |
| thresh = 0.5 |
| expected = [[2, 0.6, 0.5, 0.5, 0.7, 0.8], [0, 0.5, 0.1, 0.1, 0.2, 0.2], |
| [0, 0.3, 0.1, 0.1, 0.14, 0.14], [-1, -1, -1, -1, -1, -1]] |
| grad = np.random.rand(4, 6) |
| expected_in_grad = grad[(1, 3, 2, 0), :] |
| expected_in_grad[1, :] = 0 |
| test_box_nms_forward(np.array(boxes), np.array(expected), force=force, thresh=thresh) |
| test_box_nms_backward(np.array(boxes), grad, expected_in_grad, force=force, thresh=thresh) |
| |
| # case2: multi batch |
| boxes2 = [boxes] * 3 |
| expected2 = [expected] * 3 |
| grad2 = np.array([grad.tolist()] * 3) |
| expected_in_grad2 = np.array([expected_in_grad.tolist()] * 3) |
| test_box_nms_forward(np.array(boxes2), np.array(expected2), force=force, thresh=thresh) |
| test_box_nms_backward(np.array(boxes2), grad2, expected_in_grad2, force=force, thresh=thresh) |
| # another new dim |
| boxes2 = [boxes2] * 2 |
| expected2 = [expected2] * 2 |
| grad2 = np.array([grad2.tolist()] * 2) |
| expected_in_grad2 = np.array([expected_in_grad2.tolist()] * 2) |
| test_box_nms_forward(np.array(boxes2), np.array(expected2), force=force, thresh=thresh) |
| test_box_nms_backward(np.array(boxes2), grad2, expected_in_grad2, force=force, thresh=thresh) |
| |
| # case3: thresh |
| thresh = 0.1 |
| boxes3 = boxes |
| expected3 = [[2, 0.6, 0.5, 0.5, 0.7, 0.8], [0, 0.5, 0.1, 0.1, 0.2, 0.2], |
| [-1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1]] |
| grad3 = np.random.rand(4, 6) |
| expected_in_grad3 = grad3[(1, 3, 2, 0), :] |
| expected_in_grad3[(1, 2), :] = 0 |
| test_box_nms_forward(np.array(boxes3), np.array(expected3), force=force, thresh=thresh) |
| test_box_nms_backward(np.array(boxes3), grad3, expected_in_grad3, force=force, thresh=thresh) |
| |
| # case4: non-force |
| boxes4 = boxes |
| force = False |
| expected4 = [[2, 0.6, 0.5, 0.5, 0.7, 0.8], [0, 0.5, 0.1, 0.1, 0.2, 0.2], |
| [1, 0.4, 0.1, 0.1, 0.2, 0.2], [-1, -1, -1, -1, -1, -1]] |
| grad4 = np.random.rand(4, 6) |
| expected_in_grad4 = grad4[(1, 2, 3, 0), :] |
| expected_in_grad4[2, :] = 0 |
| test_box_nms_forward(np.array(boxes4), np.array(expected4), force=force, thresh=thresh) |
| test_box_nms_backward(np.array(boxes4), grad4, expected_in_grad4, force=force, thresh=thresh) |
| |
| # case5: different coding |
| boxes5 = corner_to_center(np.array(boxes4)) |
| test_box_nms_forward(np.array(boxes5), np.array(expected4), force=force, thresh=thresh, |
| in_format='center') |
| expected5 = corner_to_center(np.array(expected4)) |
| test_box_nms_forward(np.array(boxes4), np.array(expected5), force=force, thresh=thresh, |
| out_format='center') |
| test_box_nms_forward(np.array(boxes5), np.array(expected5), force=force, thresh=thresh, |
| in_format='center', out_format='center') |
| |
| # case6: different position |
| boxes6, expected6, new_coord, new_score, new_id = swap_position(np.array(boxes4), |
| np.array(expected4), new_col=2) |
| test_box_nms_forward(np.array(boxes6), np.array(expected6), force=force, thresh=thresh, |
| coord=new_coord, score=new_score, cid=new_id) |
| |
| # case7: no id, should be same with force=True |
| force = False |
| thresh = 0.5 |
| test_box_nms_forward(np.array(boxes), np.array(expected), force=force, thresh=thresh, cid=-1) |
| |
| # case8: multi-batch thresh + topk |
| boxes8 = [[[1, 1, 0, 0, 10, 10], [1, 0.4, 0, 0, 10, 10], [1, 0.3, 0, 0, 10, 10]], |
| [[2, 1, 0, 0, 10, 10], [2, 0.4, 0, 0, 10, 10], [2, 0.3, 0, 0, 10, 10]], |
| [[3, 1, 0, 0, 10, 10], [3, 0.4, 0, 0, 10, 10], [3, 0.3, 0, 0, 10, 10]]] |
| expected8 = [[[1, 1, 0, 0, 10, 10], [-1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1]], |
| [[2, 1, 0, 0, 10, 10], [-1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1]], |
| [[3, 1, 0, 0, 10, 10], [-1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1]]] |
| grad8 = np.random.rand(3, 3, 6) |
| expected_in_grad8 = np.zeros((3, 3, 6)) |
| expected_in_grad8[(0, 1, 2), (0, 0, 0), :] = grad8[(0, 1, 2), (0, 0, 0), :] |
| force = False |
| thresh = 0.5 |
| valid = 0.5 |
| topk = 2 |
| test_box_nms_forward(np.array(boxes8), np.array(expected8), force=force, thresh=thresh, valid=valid, topk=topk) |
| test_box_nms_backward(np.array(boxes8), grad8, expected_in_grad8, force=force, thresh=thresh, valid=valid, topk=topk) |
| |
| # case9: background id filter out |
| # default background id -1 |
| boxes9 = [[0, 0.5, 0.1, 0.1, 0.2, 0.2], [0, 0.4, 0.1, 0.1, 0.2, 0.2], |
| [1, 0.3, 0.1, 0.1, 0.14, 0.14], [-1, 0.6, 0.5, 0.5, 0.7, 0.8]] |
| expected9 = [[0, 0.5, 0.1, 0.1, 0.2, 0.2], [1, 0.3, 0.1, 0.1, 0.14, 0.14], |
| [-1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1]] |
| force = True |
| thresh = 0.5 |
| grad9 = np.random.rand(4, 6) |
| expected_in_grad9 = grad9[(0, 2, 1, 3), :] |
| expected_in_grad9[(1, 3), :] = 0 |
| test_box_nms_forward(np.array(boxes9), np.array(expected9), force=force, thresh=thresh) |
| test_box_nms_backward(np.array(boxes9), grad9, expected_in_grad9, force=force, thresh=thresh) |
| # set background id |
| background_id = 0 |
| expected9 = [[-1, 0.6, 0.5, 0.5, 0.7, 0.8], [1, 0.3, 0.1, 0.1, 0.14, 0.14], |
| [-1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1]] |
| grad9 = np.random.rand(4, 6) |
| expected_in_grad9 = grad9[(2, 3, 1, 0), :] |
| expected_in_grad9[(0, 1), :] = 0 |
| test_box_nms_forward(np.array(boxes9), np.array(expected9), force=force, thresh=thresh, bid=background_id) |
| test_box_nms_backward(np.array(boxes9), grad9, expected_in_grad9, force=force, thresh=thresh, bid=background_id) |
| |
| def test_box_iou_op(): |
| def numpy_box_iou(a, b, fmt='corner'): |
| def area(left, top, right, bottom): |
| return np.maximum(0, right - left) * np.maximum(0, bottom - top) |
| |
| assert a.shape[-1] == 4 |
| assert b.shape[-1] == 4 |
| oshape = a.shape[:-1] + b.shape[:-1] |
| a = a.reshape((-1, 4)) |
| ashape = a.shape |
| b = b.reshape((-1, 4)) |
| a = np.tile(a, reps=[1, b.shape[0]]).reshape((-1, 4)) |
| b = np.tile(b, reps=[ashape[0], 1]).reshape((-1, 4)) |
| if fmt == 'corner': |
| al, at, ar, ab = np.split(a, 4, axis=-1) |
| bl, bt, br, bb = np.split(b, 4, axis=-1) |
| elif fmt == 'center': |
| ax, ay, aw, ah = np.split(a, 4, axis=-1) |
| bx, by, bw, bh = np.split(b, 4, axis=-1) |
| al, at, ar, ab = ax - aw / 2, ay - ah / 2, ax + aw / 2, ay + ah / 2 |
| bl, bt, br, bb = bx - bw / 2, by - bh / 2, bx + bw / 2, by + bh / 2 |
| else: |
| raise NotImplementedError("Fmt {} not supported".format(fmt)) |
| width = np.maximum(0, np.minimum(ar, br) - np.maximum(al, bl)) |
| height = np.maximum(0, np.minimum(ab, bb) - np.maximum(at, bt)) |
| intersect = width * height |
| union = area(al, at, ar, ab) + area(bl, bt, br, bb) - intersect |
| union[np.where(intersect <= 0)] = 1e-12 |
| iou = intersect / union |
| return iou.reshape(oshape) |
| |
| def generate_boxes(dims): |
| s1, off1, s2, off2 = np.random.rand(4) * 100 |
| xy = np.random.rand(*(dims + [2])) * s1 + off1 |
| wh = np.random.rand(*(dims + [2])) * s2 + off2 |
| xywh = np.concatenate([xy, wh], axis=-1) |
| ltrb = np.concatenate([xy - wh / 2, xy + wh / 2], axis=-1) |
| return xywh, ltrb |
| |
| |
| for ndima in range(1, 6): |
| for ndimb in range(1, 6): |
| dims_a = np.random.randint(low=1, high=3, size=ndima).tolist() |
| dims_b = np.random.randint(low=1, high=3, size=ndimb).tolist() |
| # generate left, top, right, bottom |
| xywh_a, ltrb_a = generate_boxes(dims_a) |
| xywh_b, ltrb_b = generate_boxes(dims_b) |
| |
| iou_np = numpy_box_iou(ltrb_a, ltrb_b, fmt='corner') |
| iou_np2 = numpy_box_iou(xywh_a, xywh_b, fmt='center') |
| iou_mx = mx.nd.contrib.box_iou(mx.nd.array(ltrb_a), mx.nd.array(ltrb_b), format='corner') |
| iou_mx2 = mx.nd.contrib.box_iou(mx.nd.array(xywh_a), mx.nd.array(xywh_b), format='center') |
| assert_allclose(iou_np, iou_np2, rtol=1e-5, atol=1e-5) |
| assert_allclose(iou_np, iou_mx.asnumpy(), rtol=1e-5, atol=1e-5) |
| assert_allclose(iou_np, iou_mx2.asnumpy(), rtol=1e-5, atol=1e-5) |
| |
| def test_bipartite_matching_op(): |
| def assert_match(inputs, x, y, threshold, is_ascend=False): |
| for dtype in ['float16', 'float32', 'float64']: |
| inputs = mx.nd.array(inputs, dtype=dtype) |
| x = np.array(x, dtype=dtype) |
| y = np.array(y, dtype=dtype) |
| a, b = mx.nd.contrib.bipartite_matching(inputs, threshold=threshold, is_ascend=is_ascend) |
| assert_array_equal(a.asnumpy().astype('int64'), x.astype('int64')) |
| assert_array_equal(b.asnumpy().astype('int64'), y.astype('int64')) |
| assert_match([[0.5, 0.6], [0.1, 0.2], [0.3, 0.4]], [1, -1, 0], [2, 0], 1e-12, False) |
| assert_match([[0.5, 0.6], [0.1, 0.2], [0.3, 0.4]], [-1, 0, 1], [1, 2], 100, True) |
| |
| def test_multibox_target_op(): |
| anchors = mx.nd.array([[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8]], ctx=default_device()).reshape((1, -1, 4)) |
| cls_pred = mx.nd.array(list(range(10)), ctx=default_device()).reshape((1, -1, 2)) |
| label = mx.nd.array([1, 0.1, 0.1, 0.5, 0.6], ctx=default_device()).reshape((1, -1, 5)) |
| |
| loc_target, loc_mask, cls_target = \ |
| mx.nd.contrib.MultiBoxTarget(anchors, label, cls_pred, |
| overlap_threshold=0.5, |
| negative_mining_ratio=3, |
| negative_mining_thresh=0.4) |
| expected_loc_target = np.array([[5.0, 2.5000005, 3.4657357, 4.581454, 0., 0., 0., 0.]]) |
| expected_loc_mask = np.array([[1, 1, 1, 1, 0, 0, 0, 0]]) |
| expected_cls_target = np.array([[2, 0]]) |
| assert_allclose(loc_target.asnumpy(), expected_loc_target, rtol=1e-5, atol=1e-5) |
| assert_array_equal(loc_mask.asnumpy(), expected_loc_mask) |
| assert_array_equal(cls_target.asnumpy(), expected_cls_target) |
| |
| @xfail_when_nonstandard_decimal_separator |
| def test_gradient_multiplier_op(): |
| # We use the quadratic function in combination with gradient multiplier |
| def f(x, a, b, c): |
| return a * x**2 + b * x + c |
| |
| a = np.random.random_sample() |
| b = np.random.random_sample() |
| c = np.random.random_sample() |
| m = np.random.random_sample() - 0.5 |
| |
| data = mx.symbol.Variable('data') |
| quad_sym = mx.sym.contrib.quadratic(data=data, a=a, b=b, c=c) |
| gr_q_sym = mx.sym.contrib.gradientmultiplier(quad_sym, scalar=m) |
| |
| for dtype in [np.float16, np.float32, np.float64]: |
| for ndim in range(1, 6): |
| shape = rand_shape_nd(ndim, 5) |
| data_np = np.random.randn(*shape).astype(dtype) |
| expected = f(data_np, a, b, c) |
| backward_expected = (2 * a * data_np + b) * m |
| |
| # check imperative forward |
| output = mx.nd.contrib.quadratic(mx.nd.array(data_np), a=a, b=b, c=c) |
| output = mx.nd.contrib.gradientmultiplier(output, scalar=m) |
| assert_almost_equal(output.asnumpy(), expected, |
| rtol=1e-2 if dtype is np.float16 else 1e-5, |
| atol=1e-2 if dtype is np.float16 else 1e-5) |
| # check forward |
| check_symbolic_forward(gr_q_sym, [data_np], [expected], |
| rtol=1e-2 if dtype is np.float16 else 1e-5, |
| atol=1e-2 if dtype is np.float16 else 1e-5) |
| # check backward |
| check_symbolic_backward(gr_q_sym, [data_np], [np.ones(expected.shape)], |
| [backward_expected], |
| rtol=1e-2 if dtype is np.float16 else 1e-5, |
| atol=1e-2 if dtype is np.float16 else 1e-5) |
| def test_multibox_prior_op(): |
| h = 561 |
| w = 728 |
| X = mx.nd.random.uniform(shape=(1, 3, h, w)) |
| Y = mx.contrib.nd.MultiBoxPrior(X, sizes=[0.75, 0.5, 0.25], ratios=[1, 2, 0.5]) |
| assert_array_equal(Y.shape, np.array((1, 2042040, 4))) |
| boxes = Y.reshape((h, w, 5, 4)) |
| assert_allclose(boxes.asnumpy()[250, 250, 0, :], np.array([0.055117, 0.071524, 0.63307 , 0.821524]), atol=1e-5, rtol=1e-5) |
| # relax first ratio if user insists |
| Y = mx.contrib.nd.MultiBoxPrior(X, sizes=[0.75, 0.5, 0.25], ratios=[20, 2, 0.5]) |
| boxes = Y.reshape((h, w, 5, 4)) |
| assert_allclose(boxes.asnumpy()[250, 250, 0, :], np.array([-0.948249, 0.362671, 1.636436, 0.530377]), atol=1e-5, rtol=1e-5) |
| |
| def test_box_encode_op(): |
| anchors = mx.nd.array([[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8]]).reshape((1, -1, 4)) |
| refs = mx.nd.array([[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8]]).reshape((1, -1, 4)) |
| samples = mx.nd.array([[0, 1]]) |
| matches = mx.nd.array([[0, 1]]) |
| means = mx.nd.array([0.0, 0.0, 0.0, 0.0]) |
| stds = mx.nd.array([0.1, 0.1, 0.2, 0.2]) |
| Y, mask = mx.nd.contrib.box_encode(samples, matches, anchors, refs, means, stds) |
| assert_allclose(Y.asnumpy(), np.zeros((1, 2, 4)), atol=1e-5, rtol=1e-5) |
| assert_allclose(mask.asnumpy(), np.array([[[0., 0., 0., 0.], [1., 1., 1., 1.]]]), atol=1e-5, rtol=1e-5) |
| |
| def test_box_decode_op(): |
| data = mx.nd.array([[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8]]).reshape((1, -1, 4)) |
| anchors = mx.nd.array([[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8]]).reshape((1, -1, 4)) |
| Y = mx.nd.contrib.box_decode(data, anchors, .1, .1, .2, .2) |
| assert_allclose(Y.asnumpy(), np.array([[[-0.0562755, -0.00865743, 0.26227552, 0.42465743], \ |
| [0.13240421, 0.17859563, 0.93759584, 1.1174043 ]]]), atol=1e-5, rtol=1e-5) |
| |
| def test_op_mrcnn_mask_target(): |
| if default_device().device_type != 'gpu': |
| return |
| |
| num_rois = 2 |
| num_classes = 4 |
| mask_size = (3, 3) |
| ctx = mx.gpu(0) |
| # (B, N, 4) |
| rois = mx.nd.array([[[2.3, 4.3, 2.2, 3.3], |
| [3.5, 5.5, 0.9, 2.4]]], ctx=ctx) |
| gt_masks = mx.nd.arange(0, 4*32*32, ctx=ctx).reshape(1, 4, 32, 32) |
| |
| # (B, N) |
| matches = mx.nd.array([[2, 0]], ctx=ctx) |
| # (B, N) |
| cls_targets = mx.nd.array([[2, 1]], ctx=ctx) |
| |
| mask_targets, mask_cls = mx.nd.contrib.mrcnn_mask_target(rois, gt_masks, matches, cls_targets, |
| num_rois=num_rois, |
| num_classes=num_classes, |
| mask_size=mask_size) |
| |
| # Ground truth outputs were generated with GluonCV's target generator |
| # gluoncv.model_zoo.mask_rcnn.MaskTargetGenerator(1, num_rois, num_classes, mask_size) |
| gt_mask_targets = mx.nd.array([[[[[2193.4 , 2193.7332 , 2194.0667 ], |
| [2204.0667 , 2204.4 , 2204.7334 ], |
| [2214.7334 , 2215.0667 , 2215.4 ]], |
| [[2193.4 , 2193.7332 , 2194.0667 ], |
| [2204.0667 , 2204.4 , 2204.7334 ], |
| [2214.7334 , 2215.0667 , 2215.4 ]], |
| [[2193.4 , 2193.7332 , 2194.0667 ], |
| [2204.0667 , 2204.4 , 2204.7334 ], |
| [2214.7334 , 2215.0667 , 2215.4 ]], |
| [[2193.4 , 2193.7332 , 2194.0667 ], |
| [2204.0667 , 2204.4 , 2204.7334 ], |
| [2214.7334 , 2215.0667 , 2215.4 ]]], |
| [[[ 185. , 185.33334, 185.66667], |
| [ 195.66667, 196.00002, 196.33334], |
| [ 206.33333, 206.66666, 207. ]], |
| [[ 185. , 185.33334, 185.66667], |
| [ 195.66667, 196.00002, 196.33334], |
| [ 206.33333, 206.66666, 207. ]], |
| [[ 185. , 185.33334, 185.66667], |
| [ 195.66667, 196.00002, 196.33334], |
| [ 206.33333, 206.66666, 207. ]], |
| [[ 185. , 185.33334, 185.66667], |
| [ 195.66667, 196.00002, 196.33334], |
| [ 206.33333, 206.66666, 207. ]]]]]) |
| |
| gt_mask_cls = mx.nd.array([[0,0,1,0], [0,1,0,0]]) |
| gt_mask_cls = gt_mask_cls.reshape(1,2,4,1,1).broadcast_axes(axis=(3,4), size=(3,3)) |
| |
| assert_almost_equal(mask_targets.asnumpy(), gt_mask_targets.asnumpy()) |
| assert_almost_equal(mask_cls.asnumpy(), gt_mask_cls.asnumpy()) |
| |
| def test_dynamic_reshape(): |
| def dynamic_reshape_testcases(src_shape, shape_arg, dst_shape): |
| data = mx.sym.Variable('data') |
| shape = mx.sym.Variable('shape') |
| net = mx.sym.contrib.dynamic_reshape(data, shape) |
| js = net.tojson() |
| net = mx.sym.fromjson(js) |
| dat_npy = np.random.rand(*src_shape) |
| grad_npy = np.random.rand(*dst_shape) |
| args = { |
| 'data': mx.nd.array(dat_npy), |
| 'shape': mx.nd.array(shape_arg) |
| } |
| args_grad = { |
| 'data': mx.nd.empty(src_shape) |
| } |
| exe = net._bind(default_device(), args, args_grad) |
| exe.forward(is_train=True) |
| assert np.square(exe.outputs[0].asnumpy() - dat_npy.reshape(dst_shape)).mean() < 1E-7 |
| exe.backward(out_grads=mx.nd.array(grad_npy)) |
| assert np.square(exe.grad_dict['data'].asnumpy() - grad_npy.reshape(src_shape)).mean() < 1E-7 |
| |
| # test ndarray |
| X = mx.nd.random.uniform(shape=src_shape) |
| Y = mx.contrib.nd.dynamic_reshape(X, mx.nd.array(shape_arg)) |
| assert_array_equal(Y.shape, dst_shape) |
| |
| test_cases = [ |
| [(2, 3, 5, 5), (0, -1), (2, 75)], |
| [(2, 3, 5, 5), (0, 0, -1), (2, 3, 25)], |
| [(5, 3, 4, 5), (0, -1, 0), (5, 15, 4)], |
| [(2, 3, 5, 4), (-1, 0, 0), (8, 3, 5)], |
| [(2, 3, 5, 5), (0, 0, 0, 0), (2, 3, 5, 5)], |
| [(2, 4, 5, 3), (-1, 2, 2, 1), (30, 2, 2, 1)], |
| [(2, 3, 5, 6), (-2,), (2, 3, 5, 6)], |
| [(2, 3, 5, 6), (6, 1, -2), (6, 1, 5, 6)], |
| [(2, 3, 5, 6), (-3, -3), (6, 30)], |
| [(2, 3, 5, 6), (-3, -1), (6, 30)], |
| [(64,), (-4, 16, 4), (16, 4)], |
| [(64,), (-4, 16, -1), (16, 4)], |
| [(64, 1, 2, 3), (-4, 16, -1, -2), (16, 4, 1, 2, 3)]] |
| |
| for test_case in test_cases: |
| dynamic_reshape_testcases(*test_case) |
| |
| if __name__ == '__main__': |
| import nose |
| nose.runmodule() |