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!