무효 클릭 IP 추적 중...
카테고리 없음

[파이토치 기초] model.zero_grad() , optimizer.zero_grad() 쓰는 이유?

꼬예 2021. 11. 25.

파이토치 초보자들이 자주 만나게 되는 zero_grad()!

 

검색을 하다보면 그레디언트를 0으로 초기화시키려는 목적이라고 하는데, 구체적으로 이게 무슨일까요?

(참고로 model.zero_grad(), optimizer.zero_grad()는 자주 혼용되며 사용되어지는데, 사실상 같은 기능이라고 보시면 됩니다. )

 

그레디언트를 0으로 초기화시킨다고 하는데, 왜 초기화를 시킬까요?

그 이유는 파이토치에서는 미분한 값들이 누적되는 특징이 있기 때문입니다. 

 

누적되면 무엇이 문제일까요?

코드를 통해 확인해보시죠.

 

import torch
w = torch.tensor(2.0, requires_grad=True)

위와 같은 2라는 값을 가진 w, 파라미터가 있다고 해보시죠.

 

z = 2*w

그 후, 2라는 값을 곱해서 z값을 만들어 냅니다. 

 

dz/dw의 값은 무엇일까요? 2입니다. 

 

 

pytorch를 통해서 미분을 해보고 정말 2가 나오는지 확인해보죠.

z.backward()
print(w.grad)

output :

 

 

여기까지는 특별한 문제가 없습니다. 이때 우리가 모종의 이유로 z값을 재 지정하고, 미분을 구하면 어떤 값이 나올까요?

앞선 예와 달라진게 없으니 당연히 미분값은 2가 나와야하는데,

z = 2*w
z.backward()
print(w.grad)

output :

4가 나옵니다. 이게 무슨 일일까요.

 

다시 한번 위 과정을 반복해보겠습니다.

z = 2*w
z.backward()
print(w.grad)

output :

 

이제 어느 정도 눈치채셨나요? 원래 미분값인 2가 계속해서 누적되어가는걸 볼 수 있죠.

 

우리는 이 미분값을 이용해서 

w -= learning_rate * w.grad

파라미터 값을 수정해줘야 하는데, 누적된 미분값을 사용하면 당연히 잘못된 연산이 이루어지겠죠?

 

 

 

아래 코드를 한번 보시죠.

 

 

첫번째 에포크를 통해 parameter가 수정되고 loss값을 미분 하게 됩니다. 이때 까지는 문제가 없죠.

 

문제는 두번째 에포크부터 발생되는데요.  업데이트된 weight를 가지고 forward 연산을 한 후, backpropagation을 통해 새로운 미분 값을 가지게 되는데요.

 

이 새로운 미분값이 첫번째 에포크에서 계산된 값이 더해진 값입니다.

 

앞선 예제에서 봤듯이 당연히 이 미분값은 문제가 있습니다. 

 

첫번째 에포크를 통해 생성된 gradient값들은 w -= learning_rate * w.grad 에서 사용되고 그 역할을 다한것입니다, 계속 사용되면 문제가 생기는건 당연합니다. 

 

 

  • 트위터 공유하기
  • 페이스북 공유하기
  • 카카오톡 공유하기
이 컨텐츠가 마음에 드셨다면 커피 한잔(후원) ☕

댓글