Зачем нам клонировать grad_output и назначать его grad_input при определении функции автоградации ReLU? - PullRequest
0 голосов
/ 29 марта 2020

Я хожу по части автограда в уроках Pytorch. У меня два вопроса:

  1. Зачем нам нужно клонировать grad_output и назначить его grad_input, кроме простого назначения при обратном распространении?
  2. Какова цель grad_input[input < 0] = 0 ? Означает ли это, что мы не обновляем градиент при вводе меньше нуля?

Вот код:

class MyReLU(torch.autograd.Function):
    @staticmethod
    def forward(ctx, input):
        """
        In the forward pass we receive a Tensor containing the input and return
        a Tensor containing the output. ctx is a context object that can be used
        to stash information for backward computation. You can cache arbitrary
        objects for use in the backward pass using the ctx.save_for_backward method.
        """
        ctx.save_for_backward(input)
        return input.clamp(min=0)

    @staticmethod
    def backward(ctx, grad_output):
        """
        In the backward pass we receive a Tensor containing the gradient of the loss
        with respect to the output, and we need to compute the gradient of the loss
        with respect to the input.
        """
        input, = ctx.saved_tensors
        grad_input = grad_output.clone()
        grad_input[input < 0] = 0
        return grad_input

Ссылка здесь: https://pytorch.org/tutorials/beginner/pytorch_with_examples.html#pytorch -defining- new-autograd-functions

Заранее большое спасибо.

1 Ответ

2 голосов
/ 29 марта 2020

Зачем нам клонировать grad_output и назначать его в grad_input, кроме простого присваивания во время обратного распространения?

tensor.clone() создает копию тензора, которая имитирует исходный тензор requires_grad поле. clone - это способ скопировать тензор, сохраняя при этом копию как часть графа вычислений, из которого он получен.

Итак, grad_input является частью того же графа вычислений, что и grad_output, и если мы вычисляем градиент для grad_output, затем то же самое будет сделано для grad_input.

Поскольку мы вносим изменения в grad_input, мы сначала его клонируем.

Какова цель 'grad_input [input <0] = 0'? Означает ли это, что мы не обновляем градиент при вводе меньше нуля? </p>

Это делается в соответствии с определением функции ReLU. Функция ReLU f(x)=max(0,x). Это означает, что если x<=0, то f(x)=0, иначе f(x)=x. В первом случае, когда x<0, производная f(x) по x равна f'(x)=0. Итак, мы выполняем grad_input[input < 0] = 0. Во втором случае это f'(x)=1, поэтому мы просто передаем grad_output в grad_input (работает как открытые ворота).

...