History

2020.01.25 초안 작성
2020.01.25 초안 작성

들어가며

근래에 NAS(Neural Architecture Search)로 주제를 바꾸며 pytorch를 더 자유자재로 구현할 필요성이 생겼다.

그런데 공부를 하다가 autograd 관련 예제의 결과를 예측하는데 실패한 것들이 있어서 정리할겸 이 글을 쓴다.

우선 Autograd의 동작을 이해하고 싶다면 아래의 동영상을 추천한다.

https://youtu.be/MswxJw-8PvE?si=2gLgc9zm_PW9ypS4

이를 이해하고 나면 몇 개의 예제를 살펴보자.

예제1  - scalar value와 backward

x = torch.ones(1, requires_grad=True)
print(x)
y = x + 2
print(y)
print("===== Run backward =====")
y.backward()
print(y)
# Output
"""
tensor([1.], requires_grad=True)
tensor([3.], grad_fn=<AddBackward0>)
===== Run backward =====
tensor([3.], grad_fn=<AddBackward0>)
"""

위의 예제는 심플하다.

예제2 - chain rule + scalar backward

import torch

x = torch.ones(2, 2, requires_grad=True)
print(x)
"""
tensor([[1., 1.],
        [1., 1.]], requires_grad=True)
"""
y = x + 2
print(y)
"""
tensor([[3., 3.],
        [3., 3.]], grad_fn=<AddBackward0>)
"""
z = y * y * 3
out = z.mean()
print(z, out)
"""
tensor([[27., 27.],
        [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
"""
out.backward()
print(x.grad)
"""
tensor([[4.5000, 4.5000],
        [4.5000, 4.5000]])
"""

2.png

예제3 - vector backward

개인적으로 잘 이해가 되지 않았던 부분은 이 부분이다.

x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
    y = y * 2
print(y)  # tensor([-195.7258,  698.0129, -715.0337], grad_fn=<MulBackward0>)

gradients = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(gradients)
print(x.grad)  # tensor([1.0240e+02, 1.0240e+03, 1.0240e-01])

backward에 넣어주는 gradients가 무엇을 의미하는지, 그리고 x.grad의 결과값은 왜 저렇게 나오는지 이해하기가 어려웠다.

그래서 torch.autograd.backward - pytorch docs