본문 바로가기

카테고리 없음

PyTorch - Autograd(자동미분) 간단 정리 Colab

728x90
반응형

Autograd(자동미분)
torch.autograd 
패키지는 Tensor의 모든 연산에 대해 자동 미분 제공 이는 코드를 어떻게 작성하여 실행하느냐에 따라 역전파가 정의된다는 뜻 backprop를 위해 미분값을 자동으로 계산

requires_grad 속성을 True로 설정하면, 해당 텐서에서 이루어지는 모든 연산들을 추적하기 시작(기록을 남김)

기록을 추적하는 것을 중단하게 하려면 .detach()를 호출하여 연산기록으로부터 분리 import torch

import numpy as np

a = torch.randn(3, 3)
a=a*3
print(a)
print(a.requires_grad) # 
기본적으로 False 값을 가진다.

     tensor([[-0.0095, -0.1138,  0.5453],
             [-1.5549,  0.8544, -0.9525],
             [-4.5307,  1.8810, -6.9271]])
     False

requires_grad(...)는 기존 텐서의 requires_grad 값을 바꿔치기(in-place)하여 변경 grad_fn : 미분값을 계산한 함수에 대한 정보 저장 (어떤 함수에 대해서 bakprop 했는지)

a.requires_grad_(True) # in-plade연산으로 바뀐값을 바로 저장 print(a.requires_grad)

b=(a*a).sum()#a*a의 결과값을 다 합치기 print(b)
print(b.grad_fn)

     True
     tensor(76.4156, grad_fn=<SumBackward0>)
     <SumBackward0 object at 0x7f1c636098e0>

기울기(Gradient)

x = torch.ones(3, 3, requires_grad=True)
print(x)
     tensor([[1., 1., 1.],
             [1., 1., 1.],
             [1., 1., 1.]], requires_grad=True)

y=x+5 print(y)

     tensor([[6., 6., 6.],
             [6., 6., 6.],
             [6., 6., 6.]], grad_fn=<AddBackward0>)

z=y*y
out = z.mean() print(z, out)

     tensor([[36., 36., 36.],
             [36., 36., 36.],
             [36., 36., 36.]], grad_fn=<MulBackward0>) tensor(36., grad_fn=<Mean

계산이 완료된 후, .backward()를 호출하면 자동으로 역전파 계산이 가능하고, .grad 속성에 누적됨print(out)

out.backward()
     tensor(36., grad_fn=<MeanBackward0>)

grad: data가 거쳐온 layer에 대한 미분값 저장 print(x)

print(x.grad) # 미분값 알려줭

     tensor([[1., 1., 1.],
             [1., 1., 1.],
             [1., 1., 1.]], requires_grad=True)
     tensor([[1.3333, 1.3333, 1.3333],
             [1.3333, 1.3333, 1.3333],
             [1.3333, 1.3333, 1.3333]])
x = torch.randn(3, requires_grad=True)

y=x*2
while y.data.norm() < 1000:

y=y*2 print(y)

     tensor([  287.9263,   -13.4300, -1149.8003], grad_fn=<MulBackward0>)
v = torch.tensor([0.1, 1.0, 0.0001], dtype = torch.float)
y.backward(v)
print(x.grad)
     tensor([5.1200e+01, 5.1200e+02, 5.1200e-02])

with torch.no_grad()를 사용하여 기울기의 업데이트를 하지 않음
기록을 추적하는 것을 방지하기 위해 코드 블럭을 
with torch.no_grad()로 감싸면 기울기 계산은 필요없지

,
requires_grad=True
로 설정되어 학습 가능한 매개변수를 갖는 모델을 평가(evaluate)할 때 유용

print(x.requires_grad)
print((x**2).requires_grad)

with torch.no_grad(): # 기울기 계산을 하지 말아줘 print((x**2).requires_grad)

     True
     True
     False

detach(): 내용물(content)은 같지만 require_grad가 다른 새로운 Tensor를 가져올 때

print(x.requires_grad)
y = x.detach()
print(y.requires_grad)
print(x.eq(y).all()) # eq == equal
     True
     False
     tensor(True)

자동 미분 흐름 예제
계산 흐름 
a -> b -> c -> out
미분값 = ?
backward()
를 통해 a <- b <- c <- out을 계산하면 미분값이 a.grad에 채워짐

a = torch.ones(2,2)
print(a)
     tensor([[1., 1.],
             [1., 1.]])
a = torch.ones(2, 2, requires_grad=True)
print(a)
     tensor([[1., 1.],
             [1., 1.]], requires_grad=True)

print(a.data)
print(a.grad) # 
아직 텐서에 대한 연산이 들어간게 없다. print(a.grad_fn)

     tensor([[1., 1.],
             [1., 1.]])

None None

b=a+2 print(b)

     tensor([[3., 3.],
             [3., 3.]], grad_fn=<AddBackward0>)
c = b ** 2
print(c)
     tensor([[9., 9.],
             [9., 9.]], grad_fn=<PowBackward0>)
out = c.sum()
print(out)
     tensor(36., grad_fn=<SumBackward0>)
print(out)
out.backward()
     tensor(36., grad_fn=<SumBackward0>)

a grad_fn None인 이유는 직접적으로 계산한 부분이 없었기 때문

print(a.data)
print(a.grad)
print(a.grad_fn) # a 
값을 활용했을뿐 직접적으로 계산한 적은 없으므로 None

     tensor([[1., 1.],
             [1., 1.]])
     tensor([[6., 6.],
             [6., 6.]])

None

print(b.data) print(b.grad) print(b.grad_fn)

     tensor([[3., 3.],
             [3., 3.]])
     None
     <AddBackward0 object at 0x7f1c635b9a30>
     <ipython-input-22-7222c1aec66c>:2: UserWarning: The .grad attribute of a Te
       print(b.grad)

print(c.data) print(c.grad) print(c.grad_fn)

     tensor([[9., 9.],
             [9., 9.]])
     None
     <PowBackward0 object at 0x7f1ce5f39760>
     <ipython-input-23-f6ca42a4f63f>:2: UserWarning: The .grad attribute of a Te
       print(c.grad)
print(out.data)
print(out.grad)
print(out.grad_fn)
print(out.grad_fn)
tensor(36.)
None
<SumBackward0 object at 0x7f1c6354bf40>
<ipython-input-24-85e75c577388>:2: UserWarning: The .grad attribute of a Te
print(out.grad)
반응형