Понимание градиента в Pytorch - PullRequest
1 голос
/ 06 апреля 2019

У меня есть некоторый код Pytorch, который демонстрирует вычисление градиента внутри Pytorch, но я полностью запутался в том, что рассчитано и как оно используется. Этот пост здесь демонстрирует его использование, но он не имеет смысла для меня с точки зрения алгоритма обратного распространения. Глядя на градиент in1 и in2 в приведенном ниже примере, я понял, что градиент in1 и in2 является производной от функции потерь, но, насколько я понимаю, обновление также должно учитывать фактическое значение потерь? Где используется значение потерь? Я что-то здесь упускаю?

in1 = torch.randn(2,2,requires_grad=True)
in2 = torch.randn(2,2,requires_grad=True)
target = torch.randn(2,2)
l1 = torch.nn.L1Loss()
l2 = torch.nn.MSELoss()
out1 = l1(in1,target)
out2 = l2(in2,target)
out1.backward()
out2.backward()
in1.grad
in2.grad

1 Ответ

1 голос
/ 06 апреля 2019

Обратное распространение основано на цепочечном правиле для вычисления производных. Это означает, что градиенты вычисляются шаг за шагом от хвоста к голове и всегда передаются обратно на предыдущий шаг («предыдущий» w.r.t. к предыдущему проходу вперед).

Для скалярного вывода процесс инициируется, принимая градиент d (out1) / d (out1) = 1, чтобы запустить процесс. Если вы звоните backward на (не скалярном) тензоре, вам нужно указать начальный градиент, поскольку он не является однозначным.

Давайте рассмотрим пример, который включает больше шагов для вычисления выходных данных:

a = torch.tensor(1., requires_grad=True)
b = a**2
c = 5*b
c.backward()
print(a.grad)  # Prints: 10.

Так что же здесь происходит?

  1. Процесс инициируется с помощью d(c)/d(c) = 1.
  2. Затем предыдущий градиент вычисляется как d(c)/d(b) = 5 и умножается на нисходящий градиент (в данном случае 1), т.е. 5 * 1 = 5.
  3. Опять предыдущий градиент вычисляется как d(b)/d(a) = 2*a = 2 и снова умножается на нисходящий градиент (в данном случае 5), т.е. 2 * 5 = 10.
  4. Следовательно, мы получаем значение градиента 10 для начального тензора a.

Теперь в действительности это вычисляет d(c)/d(a), и это все, что нужно сделать. Это градиент c относительно a, и, следовательно, понятие «целевой потери» не используется (даже если потеря была нулевой, это не означает, что градиент должен быть; это зависит от оптимизатора) шаг в правильном (наклонном) направлении и остановка, когда потери стали достаточно малыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...