Use mx.nd.UpSampling with bilinear sample_type

Hi,
Has anyone of you ever successfully used the mx.nd.Upsampling method with bilinear upsampling?
Everything works fine with ‘nearest’ but when running it with ‘bilinear’ I get the following error:


File “”, line 38, in UpSampling
File “/home/local/ANT/dfferstl/AdnExMXNet/build/private/src/python/mxnet/_ctypes/ndarray.py”, line 92, in _imperative_invoke
ctypes.byref(out_stypes)))
File “/home/local/ANT/dfferstl/AdnExMXNet/build/private/src/python/mxnet/base.py”, line 210, in check_call
raise MXNetError(py_str(_LIB.MXGetLastError()))
mxnet.base.MXNetError: [16:26:52] src/c_api/…/imperative/imperative_utils.h:336: Check failed: num_inputs == infered_num_inputs (1 vs. 2) Operator UpSampling expects 2 inputs, but got 1 instead.

It does not matter if I am setting the number of filters or not.

Thanks for your help,
David

This appears to be a bug. I checked and unfortunately the unittest for bilinear interpolation isn’t properly setup, so it’s not enabled. I submitted this GitHub issue.

The underlying code simply performs a deconvolution operation for bilinear upsampling, so you can implement it using that. Here is my implementation:

def deconv_kernel(scale):
    """
    create deconvolution kernel for upsampling by scale
    """
    epsilon = 1e-8
    kernel = nd.zeros((2 * scale - 1,))
    kernel[0:(scale - 1)] = nd.arange(1. / scale, 1 - epsilon, 1. / scale)
    kernel[scale - 1:] = nd.arange(1, 1. / scale - epsilon, -1. / scale)
    kernel = kernel.expand_dims(0)
    kernel = nd.dot(kernel.T, kernel)
    return kernel.reshape((1, 1) + kernel.shape)


def bilinear_upsampling(x, scale):
    """
    :param x: input with shape NCHW
    :param scale: upsampling scale (>1)
    :return: upsampled result
    """
    kernel = deconv_kernel(scale)
    return _bilinear_upsampling(x, scale, kernel)


def _bilinear_upsampling(x, scale, kernel):
    """ Recursive function to implement upsampling
    """
    if x.shape[1] > 1:
        x_split = nd.split(x, num_outputs=x.shape[1], axis=1)
        o = [_bilinear_upsampling(d, scale, kernel) for d in x_split]
        o = nd.concat(*o, dim=1)
    else:
        o = nd.Deconvolution(x, weight=kernel, kernel=kernel.shape[2:],
                             stride=(scale, scale), num_filter=1)
        left_trim = (scale - 1) // 2
        right_trim = scale - 1 - (scale - 1) // 2
        o = o[:, :, left_trim:-right_trim, left_trim:-right_trim]
    return o


x = nd.ones((5, 3, 10, 10))
x_upsampled = bilinear_upsampling(x, 4)
1 Like

That’s what I thought. Thanks for your implementation. I will try if this works for me!