1 분 소요

본문에서는 Pytorch의 가장 중요한 기능 중 하나인 자동미분, 즉 Autograd에 대해 다룬다. Deep Neural Network(이하 DNN)에서 미분은 Back propagation을 위한 필수적인 개념이다. 이를 Pytorch에서 제공함으로써 DNN을 쉽게 구현할 수 있다.

2.1 - 자동미분

pytorch에서 autograd는 tensor 단위로 실행된다. 이때, 역전파를 통해 계산된 gradient는 leaf tensor에만 저장된다.

  • leaf tensor : tensor로 이루어진 연산 graph의 마지막에 위치한 tensor를 의미하며, 다른 tensor의 연산으로 생성되지 않은 tensor이다. 즉, 사용자가 명시적으로 정의한 tensor를 말한다. requires_grad=True 로 설정하여 gradient 계산을 허용한다.
  • 즉, x라는 tensor를 정의하고 yx**2 라면 y 에 대한 x 의 gradient가 x 에 저장된다. 미분을 시행할 시에는 y.backward() 명령어를 통해 실행한다. 아래 code를 보면 이해가 수월할 것이다.


    (code)

      x = torch.tensor([1.], requires_grad=True)
      y = x**2
      print(x.grad)
      y.backward() # 미분 실행
      print(x.grad)
    

    (결과)

      None
      tensor([2.])
    

    위 code에서 y.backward() 실행 전에는 미분이 되지 않았기 때문에 x.grad 의 값이 None 인 것을 확인할 수 있다. 그러나 실행 후에는 y 를 미분한 2xx 의 값인 1을 대입한 2가 나온다.

2.2 - 미분 불가능

그렇다면 자동 미분은 모든 형태의 함수에 사용할 수 있을까? 답은 아니다. 수학에서의 미분이 그러하듯 자동 미분 또한 미분 가능한 함수에서만 적용 가능하다.

예시로, argmax 함수는 미분 불가능하다. 따라서 이를 실행한다면 error가 발생한다.


(code)

x = torch.tensor([1.], requires_grad=True)
y = x.argmax()

y.backward()
print(x.grad)

(결과)

RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn

위 code의 결과는 RuntimeError로, 미분 불가능한 함수라는 이유를 볼 수 있다. 즉, 미분 불가능한 함수는 자동미분이 적용되지 않는다.

2.3 - non leaf tensor의 gradient 확인

위에서 gradient는 leaf tensor에만 저장된다고 설명하였다. 그렇다면 non-leaf tensor의 gradient를 저장하고 싶을 때에는 어떻게 해야 할까. .retain_grad() 를 사용하면 된다.


(code)

x = torch.tensor([1.], requires_grad=True)
y = x**2
y.retain_grad()
z = 3*y
z.backward()

print(x.grad)
print(y.grad)
print(z.grad)

(결과)

tensor([6.])
tensor([3.])
None

위 결과에서 y 는 gradient가 존재하고, z 에는 gradient가 존재하지 않는다. 이는 y 에만 .retain_grad() 를 적용했기 때문이다.

2.4 - training 시 autograd

model을 training 시 또는 transfer learning에 이용할 때는 parameter를 update하면 안 된다. 이 때, 크게 세 가지 방법을 통해 gradient update를 막을 수 있다.

  1. tensor.requires_grad=False 를 통해 gradient update를 중지한다.

     x = torch.tensor([1.],requires_grad=True)
     y = x**2
        
     x.requires_grad=False
    
  2. tensor.detach() 를 통해 gradient를 중지한다.

     x = torch.tensor([1.],requires_grad=True)
     y = x**2
        
     x = x.detach()
    
  3. tensor.no_grad() 를 통해 gradient를 일시중지한다.

     x = torch.tensor([1.], requires_grad=True)
     with torch.no_grad():
     	y=x**2
     y = x**2
    

카테고리:

업데이트:

댓글남기기