뉴비에욤

PyTorch 튜토리얼 7 - Autograd 본문

Machine Learning/PyTorch

PyTorch 튜토리얼 7 - Autograd

초보에욤 2018. 5. 2. 00:20

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()


d(out)/dx[각주:1] 그라디언트 출력

- 소스

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



  1. d(out)을 x에 관하여 미분 [본문으로]
Comments