PyTorch에서 0_grad()로 전화해야 하는 이유는?
방법zero_grad()
훈련 중에 소집되어야 한다.하지만 그 문서는 별로 도움이 되지 않는다.
| zero_grad(self)
| Sets gradients of all model parameters to zero.
왜 우리는 이 방법을 불러야 하는가?
에서는 PyTorch가 후속 후진 패스에 대한 그라데이션이 누적되기 때문에 일반적으로 백프로그래밍(즉, 체중 및 편향 업데이트)을 시작하기 전에 그라데이션(gradients)을 0으로 명시적으로 설정하고자 한다.이러한 누적된 행동은 RNN을 훈련하는 동안 또는 여러 개의 미니 배치에 대한 총 손실 구배를 계산하고 싶을 때 편리하다.따라서, 기본 동작은 모든 것에 대한 그라데이션 누적(즉, 합계)으로 설정되었다.loss.backward()
전화를 걸다
이 때문에 훈련 루프를 시작할 때 이상적으로는 파라미터 업데이트를 올바르게 수행해야 한다.그렇지 않으면, 그라데이션은 모델 매개변수를 업데이트하는 데 이미 사용한 이전 그라데이션과 새로 계산된 그라데이션의 조합이 될 것이다.따라서 최소(또는 최대화 목표의 경우 최대화)를 향한 의도된 방향이 아닌 다른 방향을 가리킬 것이다.
여기 간단한 예가 있다.
import torch
from torch.autograd import Variable
import torch.optim as optim
def linear_model(x, W, b):
return torch.matmul(x, W) + b
data, targets = ...
W = Variable(torch.randn(4, 3), requires_grad=True)
b = Variable(torch.randn(3), requires_grad=True)
optimizer = optim.Adam([W, b])
for sample, target in zip(data, targets):
# clear out the gradients of all Variables
# in this optimizer (i.e. W, b)
optimizer.zero_grad()
output = linear_model(sample, W, b)
loss = (output - target) ** 2
loss.backward()
optimizer.step()
또는 바닐라 그라데이션 강하를 수행하는 경우:
W = Variable(torch.randn(4, 3), requires_grad=True)
b = Variable(torch.randn(3), requires_grad=True)
for sample, target in zip(data, targets):
# clear out the gradients of Variables
# (i.e. W, b)
W.grad.data.zero_()
b.grad.data.zero_()
output = linear_model(sample, W, b)
loss = (output - target) ** 2
loss.backward()
W -= learning_rate * W.grad.data
b -= learning_rate * b.grad.data
참고:
- 구배 누적(즉, 합계)은 텐서상에서 호출할 때 발생한다.
- v1.7.0을 기준으로 Pytorch는 그라데이션 값을 다음과 같이 재설정할 수 있는 옵션을 제공한다.
None
optimizer.zero_grad(set_to_none=True)
그들에게 0의 텐서 대신.이 문서들은 이 설정이 메모리 요구 사항을 줄이고 성능을 약간 향상시키지만 주의 깊게 다루지 않으면 오류가 발생하기 쉽다고 주장한다.
비록 그 아이디어는 선택된 답변에서 도출될 수 있지만, 나는 그것을 명시적으로 쓰고 싶은 기분이 든다.
전화할 시기를 결정할 수 있는 능력optimizer.zero_grad()
그리고optimizer.step()
훈련 루프에서 최적기에 의해 그라데이션이 축적되고 적용되는 방법에 대해 더 많은 자유를 제공한다.이것은 모델이나 입력 데이터가 크고 하나의 실제 훈련 배치가 gpu 카드에 맞지 않을 때 중요하다.
여기 구글 리서치의 예에서, 두 가지 주장이 있다.train_batch_size
그리고gradient_accumulation_steps
.
train_batch_size
다다다닥의 다기 에 있다.loss.backward()
이것은 gpu 기억력에 의해 제한된다.gradient_accumulation_steps
다중 전진 패스로 인한 손실이 누적되는 실제 훈련 배치 크기.이것은 gpu 메모리에 의해 제한되지 않는다.
이 예에서 당신은 어떻게 하는지 알 수 있다.optimizer.zero_grad()
다음이 될 수도 있다optimizer.step()
그러나 그렇지 않다 loss.backward()
.loss.backward()
모든 반복(라인 216)에서 호출되지만optimizer.zero_grad()
그리고optimizer.step()
누적된 열차 배치의 수가 다음과 같은 경우에만 호출된다.gradient_accumulation_steps
에 있음)if
219호선 막힘)
https://github.com/google-research/xtreme/blob/master/third_party/run_classify.py
또한 누군가가 텐서플로우의 동등한 방법에 대해 묻고 있다.tf인가봐.GradientTape는 동일한 목적을 제공한다.
(아직 AI 도서관은 처음이라 틀린 말이 있으면 고쳐달라)
zero_grad()
오류(또는 손실)를 줄이기 위해 그라데이션 방법을 사용할 경우 마지막 단계부터 손실 없이 루핑을 다시 시작하십시오.
사용하지 않을 경우zero_grad()
손실은 필요에 따라 증가하지 않을 것이다.
예를 들면 다음과 같다.
사용한다면zero_grad()
다음과 같은 결과를 얻을 수 있다.
model training loss is 1.5
model training loss is 1.4
model training loss is 1.3
model training loss is 1.2
사용하지 않을 경우zero_grad()
다음과 같은 결과를 얻을 수 있다.
model training loss is 1.4
model training loss is 1.9
model training loss is 2
model training loss is 2.8
model training loss is 3.5
grad_zero()를 대안으로 호출할 필요는 없다. 예를 들어, gradients가 붕괴될 수 있다.
optimizer = some_pytorch_optimizer
# decay the grads :
for group in optimizer.param_groups:
for p in group['params']:
if p.grad is not None:
''' original code from git:
if set_to_none:
p.grad = None
else:
if p.grad.grad_fn is not None:
p.grad.detach_()
else:
p.grad.requires_grad_(False)
p.grad.zero_()
'''
p.grad = p.grad / 2
이런 식으로 학습은 훨씬 더 계속된다.
참조URL: https://stackoverflow.com/questions/48001598/why-do-we-need-to-call-zero-grad-in-pytorch
'programing' 카테고리의 다른 글
Vue.js + Vuex: 중첩된 항목 상태를 변경하는 방법 (0) | 2022.04.06 |
---|---|
초기 v-선택 값 설정 (0) | 2022.04.06 |
Vuex - 계산된 속성 "name"이(가) 할당되었지만 세터가 없음 (0) | 2022.04.06 |
매개 변수를 사용하여 라우터 반응 - CSS 스타일링 BREAKS? - 상태 304 수정 안 됨? (0) | 2022.04.06 |
Vuex 작업에서 약속 반환 (0) | 2022.04.06 |