뉴비에욤
PyTorch 튜토리얼 7 - Autograd 본문
2017/07/13 - [Machine Learning/PyTorch] - 윈도우 10 PyTorch 환경 구성 - 설치
2018/04/30 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 1 - PyTorch란?
2018/04/30 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 2 - Autograd : 자동 미분
2018/05/01 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 3 - 뉴럴 네트워크(신경망)
2018/05/01 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 4 - Classifier 학습
2018/05/01 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 5 - 데이터 병렬 처리
2018/05/01 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 6 - 텐서
원문 : http://pytorch.org/tutorials/beginner/former_torchies/autograd_tutorial.html
* 17년도 07월에 초번 번역 후, 파이토치 최신 버전인 0.4.0에 맞추어 갱신 된 번역본
* 최근 갱신일 : 2018-05-01
목 차 ( 초보자 튜토리얼 )
B. Torch 사용자를 위한 PyTorch
7. Autograd
- 과정을 추적하는 텐서
- 그라디언트(기울기)
Autograd
Autograd는 자동 미분을 수행하는 토치의 핵심 패키지로, 자동 미분을 위해 tape-based 시스템을 사용한다.
- tape-based 시스템
- reverse-mode 자동 식별화를 사용하는 시스템
- https://justindomke.wordpress.com/2009/03/24/a-simple-explanation-of-reverse-mode-automatic-differentiation/
정방향 단계(forward phase)으로 autograd tape는 수행하는 모든 연산을 기억하며, 역방향 단계(backward phase)으로 연산들을 재생(reply) 한다.
과정을 추적하는 텐서 ( Tensors that track history )
autograd에서, 연산의 입력 Tensor가 requires_grad=True 속성을 가지고 있다면 계산은 추적된다. 역방향 패스(backward pass)를 계산한 후, 변수에 대한 그라디언트는 .grad 속성에 누적된다.
autograd 구현에 있어 아주 중요한 클래스가 하나 더 있는데 바로 Function 이다. Tensor와 Function은 상호 연결되어 있으며, 비순환(비주기) 그래프를 생성하는데, 이 그래프는 모든 계산 과정을 인코딩 한다. 각 변수는 Tensor를 생성한 Function을 참조하는 .grad_fn 속성을 가지고 있다. (단, 사용자에 의해 생성 된 텐서는 제외한다-해당 텐서들은 grad_fn 자체가 None 상태이다)
만약 도함수(derivatives)들을 계산하고 싶다면, Tensor의 .backward()를 호출하면 된다. 만약 Tensor가 스칼라(i.e. 한 개의 요소(element)를 가지고 있는) 형태라면, backward() 사용에 있어 그 어떠한 파라미터도 필요하지 않는다. 그러나 한 개 이상의 요소를 가지고 있다면 텐서의 올바른 모양(matching shape)을 gradient의 인자로 지정할 필요가 있다.
파이토치 패키지 임포트
- 소스
import torch
텐서를 생성하고 requires_grad=True로 세팅하여 과정을 추적한다.
- 소스
x = torch.ones(2, 2, requires_grad=True)
print(x)
- 결과
tensor([[ 1., 1.],
[ 1., 1.]])
- 소스
print(x.data)
- 결과
tensor([[ 1., 1.],
[ 1., 1.]])
- 소스
print(x.grad)
- 결과
None
- 소스
print(x.grad_fn) # we've created x ourselves
- 결과
None
텐서에 대하여 임의의 연산을 수행한다.
- 소스
y = x + 2
print(y)
- 결과
tensor([[ 3., 3.],
[ 3., 3.]])
y는 연산의 결과로써 생성된 것이기 때문에 grad_fn을 가지고 있다.
- 소스
print(y.grad_fn)
- 결과
<AddBackward0 object at 0x7fb9f73ea518>
y에 대하여 임의의 연산을 수행한다.
- 소스
z = y * y * 3
out = z.mean()
print(z, out)
- 결과
tensor([[ 27., 27.],
[ 27., 27.]]) tensor(27.)
.requires_grad_( ... )은 이미 존재하는 텐서의 requires_grad 플래그를 in-place(내부)에서 변경한다. 입력 플래그를 명시하지 않은 경우 기본적으로 True가 된다.
- 소스
a = torch.randn(2, 2)
a = ((a * 3) / (a - 1))
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b = (a * a).sum()
print(b.grad_fn)
- 결과
False
True
<SumBackward0 object at 0x7fb9f74f1a58>
그라디언트 ( Gradients )
자, 다시 돌아와서 이제 out은 하나의 스칼라(single scalar) 값을 가지고 있기 때문에 out.backward()는 out.backward(torch.tensor(1))와 동등한 결과를 리턴한다.
- 소스
out.backward()
- 소스
print(x.grad)
- 결과 (4.5 행렬이 출력되어야 함)
tensor([[ 4.5000, 4.5000],
[ 4.5000, 4.5000]])
기본적으로, 그라디언트 계산은 그래프에 포함 된 모든 내부 버퍼를 플러시 하기 때문에, 그래프의 어떤 부분에서 backward를 2번 하려면 1 번째 단계에서 retain_variables=True를 전달해 줄 필요가 있다.
- 소스
x = torch.ones(2, 2, requires_grad=True)
y = x + 2
y.backward(torch.ones(2, 2), retain_graph=True)
# the retain_variables flag will prevent the internal buffers from being freed
print(x.grad)
결과
tensor([[ 1., 1.],
[ 1., 1.]])
- 소스
z = y * y
print(z)
결과
tensor([[ 9., 9.],
[ 9., 9.]])
랜덤 그라디언트를 역전파 한다.
- 소스
gradient = torch.randn(2, 2)
# this would fail if we didn't specify
# that we want to retain variables
y.backward(gradient)
print(x.grad)
결과
tensor([[ 0.6683, 2.2307],
[ 1.3618, 0.7551]])
또한 코드 블럭을 with torch.no_grad(): 로 래핑하여 requires_grad=True 속성이 명시된 autograd가 텐서의 추적 기록에 남지 않게 할 수 있다.
- 소스
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
print((x ** 2).requires_grad)
- 결과
True
True
False
- d(out)을 x에 관하여 미분 [본문으로]
'Machine Learning > PyTorch' 카테고리의 다른 글
PyTorch 튜토리얼 9 - 멀티 GPU 예제 (2) | 2018.05.07 |
---|---|
PyTorch 튜토리얼 8 - nn 패키지 (0) | 2018.05.02 |
PyTorch 튜토리얼 6 - 텐서 (0) | 2018.05.01 |
PyTorch 튜토리얼 5 - 데이터 병렬 처리 (1) | 2018.05.01 |
PyTorch 튜토리얼 4 - 분류기(classifier) 학습 (1) | 2018.05.01 |