Оригінальний код я більше не знайшов на веб-сайті PyTorch.
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(x.grad)
Проблема з кодом вище не існує функції, заснованої на тому, що обчислювати градієнти. Це означає, що ми не знаємо, скільки параметрів (аргументів приймає функція) та розмірність параметрів.
Щоб повністю зрозуміти це, я створив приклад, близький до оригіналу:
Приклад 1:
a = torch.tensor([1.0, 2.0, 3.0], requires_grad = True)
b = torch.tensor([3.0, 4.0, 5.0], requires_grad = True)
c = torch.tensor([6.0, 7.0, 8.0], requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients,retain_graph=True)
print(a.grad) # tensor([3.0000e-01, 3.0000e+00, 3.0000e-04])
print(b.grad) # tensor([1.2000e+00, 1.6000e+01, 2.0000e-03])
print(c.grad) # tensor([1.6667e-02, 1.4286e-01, 1.2500e-05])
Я припускав, що наша функція є, y=3*a + 2*b*b + torch.log(c)
а параметри - це тензори з трьома елементами всередині.
Ви можете подумати, gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
як ось цей акумулятор.
Як ви можете почути, обчислення системи автоградів PyTorch еквівалентно продукту Jacobian.
Якщо у вас є функція, як у нас:
y=3*a + 2*b*b + torch.log(c)
Якобієць був би [3, 4*b, 1/c]
. Однак, цей якобіан не як PyTorch роблять речі для обчислення градієнтів в певній точці.
PyTorch використовує автоматичну диференціацію в режимі прямого і зворотного режимів (AD) в тандемі.
Немає символічної математики і чисельної диференціації.
Числову диференціацію було б обчислити δy/δb
, для b=1
і b=1+ε
де ε невелика.
Якщо ви не використовуєте градієнти в y.backward()
:
Приклад 2
a = torch.tensor(0.1, requires_grad = True)
b = torch.tensor(1.0, requires_grad = True)
c = torch.tensor(0.1, requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
y.backward()
print(a.grad) # tensor(3.)
print(b.grad) # tensor(4.)
print(c.grad) # tensor(10.)
Ви просто отримати результат в точці, грунтуючись на тому , як ви встановите a
, b
, c
тензори спочатку.
Будьте обережні , як ви ініціалізації a
, b
, c
:
Приклад 3:
a = torch.empty(1, requires_grad = True, pin_memory=True)
b = torch.empty(1, requires_grad = True, pin_memory=True)
c = torch.empty(1, requires_grad = True, pin_memory=True)
y=3*a + 2*b*b + torch.log(c)
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)
print(a.grad) # tensor([3.3003])
print(b.grad) # tensor([0.])
print(c.grad) # tensor([inf])
Якщо ви використовуєте torch.empty()
та не використовуєте, pin_memory=True
то кожен раз можуть бути різні результати.
Крім того, градієнти примітки схожі на акумулятори, тому нулю їх потрібно, коли це потрібно.
Приклад 4:
a = torch.tensor(1.0, requires_grad = True)
b = torch.tensor(1.0, requires_grad = True)
c = torch.tensor(1.0, requires_grad = True)
y=3*a + 2*b*b + torch.log(c)
y.backward(retain_graph=True)
y.backward()
print(a.grad) # tensor(6.)
print(b.grad) # tensor(8.)
print(c.grad) # tensor(2.)
Нарешті, кілька порад щодо умов, які PyTorch використовує:
PyTorch створює динамічний обчислювальний графік при обчисленні градієнтів в прямому проході. Це схоже на дерево.
Тому ви часто чуєте, як листя цього дерева є вхідними тензорами, а корінь - вихідним тензором .
Градієнти обчислюються шляхом відстеження графіка від кореня до листа і множення кожного градієнта способом за допомогою ланцюгового правила . Це множення відбувається в зворотному проході.