Are there any methods for making Down/Upscaling function that has gradient flow? I want to make this because of backpropagation for training Downscaling Factor Generation & Faster RCNN.
I'm designing a computer vision deep learning flow with Pytorch.
Preliminary:
It's consists of Two parts : Preprocessing and Vision Task. As Preprocessing part, I created a downscaling factor generator model and an image Down/Upscaling module. In the Vision Task part, I forward the preprocessed image and to do the object detections.
Train flow looks like this :: img input -> Downscaling Factor Generation(img forward) -> img downscaling with downscaling factor -> img upscaling with 1/downscaling factor -> Vision Task(Faster RCNN, upscaled img) -> step backward.
Question:
As i was designing this flow, i got stuck at the Down/Upscaling module. I tried to use Pytorch's F.interpolate(img, scale_factor,,,) function, but this blocked the flow of gradients. I put original image and downscaling factor(from model w/ gradeint) into F.interpolate function, but grad_fn is disappearing.
I tried to made custom interpolation function like this,
def bilinear_interpolate(self, img, scale_factor):
print('img, scale_factor :',img,scale_factor)
n, c, h, w = img.size()
new_h, new_w = int(h * scale_factor), int(w * scale_factor)
device = img.device
h_scale = torch.linspace(0, h-1, new_h, device=device)
w_scale = torch.linspace(0, w-1, new_w, device=device)
grid_h, grid_w = torch.meshgrid(h_scale, w_scale)
h_floor = grid_h.floor().long()
h_ceil = h_floor + 1
h_ceil = h_ceil.clamp(max=h-1)
w_floor = grid_w.floor().long()
w_ceil = w_floor + 1
w_ceil = w_ceil.clamp(max=w-1)
print('h_floor,h_floor, h_ceil, w_floor, w_ceil :',h_floor, h_ceil, w_floor, w_ceil)
tl = img[:, :, h_floor, w_floor]
tr = img[:, :, h_floor, w_ceil]
bl = img[:, :, h_ceil, w_floor]
br = img[:, :, h_ceil, w_ceil]
h_frac = grid_h - h_floor.to(device)
w_frac = grid_w - w_floor.to(device)
# bilinear interpolation
top = tl + (tr - tl) * w_frac
bottom = bl + (br - bl) * w_frac
interpolated_img = top + (bottom - top) * h_frac
return interpolated_img
but it doesn't work because of int/float transformation and sort of variable assignments.
The
BilinearInterpolationlayer below performs scaling whilst preserving gradient flow. It wrapsF.interpolate, and the gradient function at the output is<UpsampleBilinear2DBackward0>.Output:
Interpolation layer:
Reproducible example: