Обратное распространение основано на цепочечном правиле для вычисления производных. Это означает, что градиенты вычисляются шаг за шагом от хвоста к голове и всегда передаются обратно на предыдущий шаг («предыдущий» 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.
Так что же здесь происходит?
- Процесс инициируется с помощью
d(c)/d(c) = 1
.
- Затем предыдущий градиент вычисляется как
d(c)/d(b) = 5
и умножается на нисходящий градиент (в данном случае 1
), т.е. 5 * 1 = 5
.
- Опять предыдущий градиент вычисляется как
d(b)/d(a) = 2*a = 2
и снова умножается на нисходящий градиент (в данном случае 5
), т.е. 2 * 5 = 10
.
- Следовательно, мы получаем значение градиента
10
для начального тензора a
.
Теперь в действительности это вычисляет d(c)/d(a)
, и это все, что нужно сделать. Это градиент c
относительно a
, и, следовательно, понятие «целевой потери» не используется (даже если потеря была нулевой, это не означает, что градиент должен быть; это зависит от оптимизатора) шаг в правильном (наклонном) направлении и остановка, когда потери стали достаточно малыми.