programing

PyTorch에서 0_grad()로 전화해야 하는 이유는?

prostudy 2022. 4. 6. 21:43
반응형

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에 있음)if219호선 막힘)

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

반응형