ํ์ดํ ์น์ ์๋ ๋ฏธ๋ถ(Auto differentiation)์ ์ด์ฉํ ๋ณํ๋(Gradient) ๊ณ์ฐ ๋ฐฉ๋ฒ์ ์์๋ณผ ๊ฒ์ด๋ค. ๋ค๋ฃฐ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ๋ค.
1. ์๋ ๋ฏธ๋ถ ์ค๋น
2. ๋ณํ๋ ๊ณ์ฐ
1. ์๋ ๋ฏธ๋ถ ์ค๋น
In:
import torch
x = torch.ones(2, 2, requires_grad = True)
print(x)
Out:
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
โท torch.ones()์ ํ ์ ํฌ๊ธฐ์ ๋ํ ์ธ์์ requires_grad ์ธ์๋ฅผ ์ฃผ์ด ํ ์๋ฅผ ์์ฑํ์๋ค. ๊ฒฐ๊ณผ ์ฐฝ์ requires_grad=True๊ฐ ๋ํ๋ ๊ฒ์ ๋ณผ ์ ์๋๋ฐ, ์ด๋ ์ดํ ์ญ์ ํ ๊ณผ์ ์ ์ํ ํ, ํด๋น ํ ์์ ๋ณํ๋๋ฅผ ๊ตฌํ ์ ์๋๋ก ํ๋ค.
In:
y = x + 2
print(y)
Out:
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
โท x์ ๋ง์ ์ฐ์ฐ์ ์ํํ์ฌ y๋ฅผ ๋ง๋ค์๋ค. ์ฝ๋ ๊ฒฐ๊ณผ์ ์ฐ์ฐ ์ํ ๊ฒฐ๊ณผ์ grad_fn์ด <AddBackward0>์ธ ๊ฒ์ ํ์ธํ ์ ์๋ค. grad_fn์๋ ํ ์๊ฐ ์ฐ์ฐ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๊ณ , ์ด ์ ๋ณด๋ ์ญ์ ํ ๊ณผ์ ์ ์ฌ์ฉ๋ ๊ฒ์ด๋ค.
In:
y = x * 2
print(y)
Out:
tensor([[2., 2.],
[2., 2.]], grad_fn=<MulBackward0>)
โท y๊ฐ x์ 2๋ฅผ ๊ณฑํ์ฌ ๋ง๋ค์ด์ก๋ค. ์ฝ๋ ๊ฒฐ๊ณผ์ grad_fn์ด <MulBackward0>๋ก ๋ํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ์ฆ, y๋ ๊ณฑ์ ์ ๋ํ ์ฐ์ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ค.
In:
x = torch.randn(2, 2)
y = ((x * 3) / (x - 1))
print(y)
print(y.requires_grad)
y.requires_grad_(True)
print(y)
print(y.requires_grad)
Out:
tensor([[-3.7594, 7.5623],
[ 1.2762, 1.2044]])
False
tensor([[-3.7594, 7.5623],
[ 1.2762, 1.2044]], requires_grad=True)
True
โท ํ ์๋ฅผ ์์ฑํ ๋, requires_grad ์ธ์์ ๊ธฐ๋ณธ๊ฐ์ False์ด๊ธฐ ๋๋ฌธ์, ์ฒซ ๋ฒ์งธ ํ ์์ ์ถ๋ ฅ ๊ฒฐ๊ณผ์์๋ requires_grad์ ๋ํ ์ ๋ณด๊ฐ ๋ํ๋ ์์ง ์๋ค. torch.requires_grad_()๋ฅผ ์ด์ฉํ์ฌ requires_grad ์ธ์์ ์ ๋ ฅ๊ฐ์ ์ค ์ ์๋ค. ์ด๋ฅผ ์ ์ฉํ y์ ๊ฒฐ๊ด๊ฐ์๋ requires_grad๊ฐ True๋ก ๋ํ๋ ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
2. ๋ณํ๋ ๊ณ์ฐ
In:
x = torch.randn(2, 2, requires_grad=True)
y = x + 2
z = (y * y).sum()
z.backward()
print(x)
print(y)
print(z)
print(x.grad)
print(y.grad)
print(z.grad)
Out:
tensor([[-0.0246, -0.5667],
[-0.0226, 0.1128]], requires_grad=True)
tensor([[1.9754, 1.4333],
[1.9774, 2.1128]], grad_fn=<AddBackward0>)
tensor(14.3310, grad_fn=<SumBackward0>)
tensor([[3.9509, 2.8667],
[3.9548, 4.2257]])
None
None
โท z์ torch.backward()๋ฅผ ์ด์ฉํ์ฌ ์ญ์ ํ ๊ณผ์ ์ ์ํํ์๋ค. x.grad๋ x์ ๋ณํ๋์ธ dz/dx์ ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ธ๋ค.
โท ํ ์ y์ z์ ๊ฒฝ์ฌ๋์ ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ None์ด ๋์๋ค. ์ด๋ y, z์ requires_grad๋ False์ด๊ธฐ ๋๋ฌธ์ด๋ค.
โถ ๋ง์ฝ z๊ฐ ์ค์นผ๋ผ๊ฐ ์๋ ๋ฒกํฐ๋ผ๋ฉด z.backward()๋ฅผ ์คํํ ๊ฒฝ์ฐ, "RuntimeError: grad can be implicitly created only for scalar outputs"๋ผ๋ ๋ฌธ๊ตฌ๊ฐ ๋จ๋ฉฐ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
In:
x = torch.randn(2, 2, requires_grad=True)
y = x + 2
z = y * y
y.backward(z)
print(x.grad)
Out:
tensor([[ 2.1441, 8.8653],
[10.3739, 2.6593]])
โท z๊ฐ ์ค์นผ๋ผ๊ฐ ์๋ ๊ฒฝ์ฐ, ์ญ์ ํ ๊ณผ์ ์ ์ํํ๊ธฐ ์ํด torch.backward()์ z๋ฅผ ์ธ์๋ก ๋ฃ์ด ์ฃผ์ด์ผ ํ๋ค.
์ด์ธ์ ์๋ ๋ฏธ๋ถ์ ๊ดํ ์ ๋ณด๋ ์ฌ๊ธฐ(https://pytorch.org/docs/stable/autograd.html#function)์์ ํ์ธํ ์ ์๋ค.
Reference:
"AUTOGRAD: AUTOMATIC DIFFERENTIATION," PyTorch, https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#sphx-glr-beginner-blitz-autograd-tutorial-py.
'Deep Learning > PyTorch' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
ํ ์(Tensor) ์ฌ์ฉ๋ฒ (0) | 2020.07.24 |
---|