Auto Gradient

Human Being·2023년 1월 13일
0

Pytorch

목록 보기
1/3
post-thumbnail

tensor의 gradient?

y=3a3+2b4y=3a^3 + 2b^4를 각각 a와 b에 대해서 편미분한 결과를 알고 싶다

먼저 각 미지수에 대해 미분한 결과식은 다음과 같다

  • a에 대해서 미분하면, ya=9a2+0\frac{\partial y}{\partial a} = 9a^2 + 0
  • b에 대해서 미분하면, yb=0+8b3\frac{\partial y}{\partial b} = 0 + 8b^3

이 때 a=3a=3, b=2b=2라면 아래와 같은 결과가 산출되어야 한다

  • ya=9(3)2+0=81\frac{\partial y}{\partial a} = 9(3)^2 + 0 = 81
  • yb=0+8(2)3=64\frac{\partial y}{\partial b} = 0 + 8(2)^3 = 64

이 과정을 Pytorch의 Autograd를 이용하여 계산할 수 있다

앞서 gradient 값을 기록하기 위한 pytorch의 grad field를 보자

a, b를 requires_grad=True로 하니 y의 grad_fnAddBackward가 추가되었다.

import torch

a = torch.tensor([3.])
b = torch.tensor([2.])
y = 3*a**3 + 2*b**4

# print(a.data, a.grad, a.grad_fn)  ## tensor([[3.]]) None None
# print(b.data, b.grad, b.grad_fn)  ## tensor([[2.]]) None None
print(y.data, y.grad_fn)  ## tensor([[113.]]) None None


a = torch.tensor([3.], requires_grad=True)
b = torch.tensor([2.], requires_grad=True)
y = 3*a**3 + 2*b**4

print(y.data, y.grad_fn)  ## tensor([113.]) None <AddBackward0 object at 0x113cafd90>

y에 대해서 back-propagation을 진행하면 a,b의 grad에 찾고자하는 결과값이 저장됐음을 확인할 수 있다

이렇게 변화도(gradient)를 저장해가는 것을 Tensor들의 연산 기록을 추적한다고도 표현한다

y.backward()

print(a.data, a.grad, a.grad_fn)  ## tensor([3.]) tensor([81.]) None
print(b.data, b.grad, b.grad_fn)  ## tensor([2.]) tensor([64.]) None

다만, 학습이 아닌 추론처럼 back-propagation 과정이 불필요할 경우 다음과 같이 연산 추적을 멈출 수 있다

y의 grad_fn이 지정되지 않으면 당연히 backward() 계산도 이뤄지지 않아 에러가 발생한다

a = torch.tensor([3.], requires_grad=True)
b = torch.tensor([2.], requires_grad=True)

###
with torch.no_grad():
    y = 3*a**3 + 2*b**4
###
### y = y.detach()와 같은 기능

print(y.requires_grad)   ## False
print(y.data, y.grad, y.grad_fn)  ## tensor([113.]) None None

변화도 추적을 멈추는 다른 상황

  • Transfer Learning 시, pretrained model의 frozen parameter, 즉 고정된 매개변수를 유지하기 위해
  • back-propagation 과정을 생략함으로써 연산 속도 향상

심화

단순 사칙연산 외의 연산 및 벡터 입력값에 대한 미분도 지원한다

import numpy as np

def mean_squared_error(y,y_pred):
    return torch.mean((y-y_pred)**2)

y = torch.tensor([1., 2., 3.], requires_grad=True)
pred = torch.tensor([2., 2., 3.], requires_grad=True)

error = mean_squared_error(y, pred)

error.backward()
print(y.data, y.grad, y.grad_fn)
print(pred.data, pred.grad, pred.grad_fn)
print(error.data, error.grad_fn)
tensor([1., 2., 3.]) tensor([-0.6667,  0.0000,  0.0000]) None
tensor([2., 2., 3.]) tensor([0.6667, -0.0000, -0.0000]) None
tensor(0.3333) <MeanBackward0 object at 0x11d450a30>

0개의 댓글