def _test_backward(self, device, contiguous): x, weight, offset, bias, stride, padding, dilation = self.get_fn_args( device, contiguous) def func(x_, offset_, weight_, bias_): return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride, padding=padding, dilation=dilation) gradcheck(func, (x, offset, weight, bias), nondet_tol=1e-5) @torch.jit.script def script_func(x_, offset_, weight_, bias_, stride_, pad_, dilation_): # type: (Tensor, Tensor, Tensor, Tensor, Tuple[int, int], Tuple[int, int], Tuple[int, int]) -> Tensor return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride_, padding=pad_, dilation=dilation_) gradcheck(lambda z, off, wei, bi: script_func(z, off, wei, bi, stride, padding, dilation), (x, offset, weight, bias), nondet_tol=1e-5) # Test from https://github.com/pytorch/vision/issues/2598 # Run on CUDA only if "cuda" in device.type: # compare grads computed on CUDA with grads computed on CPU true_cpu_grads = None init_weight = torch.randn(9, 9, 3, 3, requires_grad=True) img = torch.randn(8, 9, 1000, 110) offset = torch.rand(8, 2 * 3 * 3, 1000, 110) if not contiguous: img = img.permute(0, 1, 3, 2).contiguous().permute(0, 1, 3, 2) offset = offset.permute(1, 3, 0, 2).contiguous().permute(2, 0, 3, 1) weight = init_weight.permute(3, 2, 0, 1).contiguous().permute( 2, 3, 1, 0) else: weight = init_weight for d in ["cpu", "cuda"]: out = ops.deform_conv2d(img.to(d), offset.to(d), weight.to(d), padding=1) out.mean().backward() if true_cpu_grads is None: true_cpu_grads = init_weight.grad self.assertTrue(true_cpu_grads is not None) else: self.assertTrue(init_weight.grad is not None) res_grads = init_weight.grad.to("cpu") self.assertTrue(true_cpu_grads.allclose(res_grads))
def script_func_no_mask(x_, offset_, weight_, bias_, stride_, pad_, dilation_): # type:(Tensor, Tensor, Tensor, Tensor, Tuple[int, int], Tuple[int, int], Tuple[int, int])->Tensor return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride_, padding=pad_, dilation=dilation_, mask=None)
def forward( ctx, input, offset, weight, stride=1, padding=0, dilation=1, groups=1, deformable_groups=1, im2col_step=64, ): if input is not None and input.dim() != 4: raise ValueError( "Expected 4D tensor as input, got {}D tensor instead.".format( input.dim())) ctx.stride = _pair(stride) ctx.padding = _pair(padding) ctx.dilation = _pair(dilation) ctx.groups = groups ctx.deformable_groups = deformable_groups ctx.im2col_step = im2col_step ctx.save_for_backward(input, offset, weight) output = input.new_empty( _DeformConv._output_size(input, weight, ctx.padding, ctx.dilation, ctx.stride)) ctx.bufs_ = [input.new_empty(0), input.new_empty(0)] # columns, ones if not input.is_cuda: if deformable_groups != 1: raise NotImplementedError( "Deformable Conv with deformable_groups != 1 is not supported on CPUs!" ) return deform_conv2d(input, offset, weight, stride=stride, padding=padding, dilation=dilation) else: cur_im2col_step = _DeformConv._cal_im2col_step( input.shape[0], ctx.im2col_step) assert (input.shape[0] % cur_im2col_step) == 0, "im2col step must divide batchsize" _C.deform_conv_forward( input, weight, offset, output, ctx.bufs_[0], ctx.bufs_[1], weight.size(3), weight.size(2), ctx.stride[1], ctx.stride[0], ctx.padding[1], ctx.padding[0], ctx.dilation[1], ctx.dilation[0], ctx.groups, ctx.deformable_groups, cur_im2col_step, ) return output
def func_no_mask(x_, offset_, weight_, bias_): return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride, padding=padding, dilation=dilation, mask=None)
def func(x_, offset_, weight_, bias_): return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride, padding=padding, dilation=dilation)