CoolFace
Apppublic

breadlicker45/gpuGAN

sourceHugging Facecc-by-nc-4.0updated 8mo agoView on Hugging Face
0likes
grid_sample_gradfix.py84 linesDownload Raw Back to ops
1# Copyright (c) 2021, NVIDIA CORPORATION.  All rights reserved.2#3# NVIDIA CORPORATION and its licensors retain all intellectual property4# and proprietary rights in and to this software, related documentation5# and any modifications thereto.  Any use, reproduction, disclosure or6# distribution of this software and related documentation without an express7# license agreement from NVIDIA CORPORATION is strictly prohibited.8 9"""Custom replacement for `torch.nn.functional.grid_sample` that10supports arbitrarily high order gradients between the input and output.11Only works on 2D images and assumes12`mode='bilinear'`, `padding_mode='zeros'`, `align_corners=False`."""13 14import warnings15import torch16 17# pylint: disable=redefined-builtin18# pylint: disable=arguments-differ19# pylint: disable=protected-access20 21#----------------------------------------------------------------------------22 23enabled = False  # Enable the custom op by setting this to true.24 25#----------------------------------------------------------------------------26 27def grid_sample(input, grid):28    if _should_use_custom_op():29        return _GridSample2dForward.apply(input, grid)30    return torch.nn.functional.grid_sample(input=input, grid=grid, mode='bilinear', padding_mode='zeros', align_corners=False)31 32#----------------------------------------------------------------------------33 34def _should_use_custom_op():35    if not enabled:36        return False37    if any(torch.__version__.startswith(x) for x in ['1.7.', '1.8.', '1.9']):38        return True39    warnings.warn(f'grid_sample_gradfix not supported on PyTorch {torch.__version__}. Falling back to torch.nn.functional.grid_sample().')40    return False41 42#----------------------------------------------------------------------------43 44class _GridSample2dForward(torch.autograd.Function):45    @staticmethod46    def forward(ctx, input, grid):47        assert input.ndim == 448        assert grid.ndim == 449        output = torch.nn.functional.grid_sample(input=input, grid=grid, mode='bilinear', padding_mode='zeros', align_corners=False)50        ctx.save_for_backward(input, grid)51        return output52 53    @staticmethod54    def backward(ctx, grad_output):55        input, grid = ctx.saved_tensors56        grad_input, grad_grid = _GridSample2dBackward.apply(grad_output, input, grid)57        return grad_input, grad_grid58 59#----------------------------------------------------------------------------60 61class _GridSample2dBackward(torch.autograd.Function):62    @staticmethod63    def forward(ctx, grad_output, input, grid):64        op = torch._C._jit_get_operation('aten::grid_sampler_2d_backward')65        grad_input, grad_grid = op(grad_output, input, grid, 0, 0, False)66        ctx.save_for_backward(grid)67        return grad_input, grad_grid68 69    @staticmethod70    def backward(ctx, grad2_grad_input, grad2_grad_grid):71        _ = grad2_grad_grid # unused72        grid, = ctx.saved_tensors73        grad2_grad_output = None74        grad2_input = None75        grad2_grid = None76 77        if ctx.needs_input_grad[0]:78            grad2_grad_output = _GridSample2dForward.apply(grad2_grad_input, grid)79 80        assert not ctx.needs_input_grad[2]81        return grad2_grad_output, grad2_input, grad2_grid82 83#----------------------------------------------------------------------------84