본문 바로가기
A.I./PyTorch

PyTorch 문서) PyTorch Recipes - Zeroing out gradients in PyTorch

by 채소장사 2024. 10. 12.

파이토치에서 그래디언트를 0으로 설정하기

  • 원글 : Zeroing out gradients in PyTorch
  • 신경망을 구성할 때, 그래디언트를 0으로 설정하는 것이 좋다.
    • 이것은 .backward()가 호출될 때, 그래디언트는 기존값을 덮어쓰지 않고, 버퍼에 계속해서 쌓이기 때문이다.

Introduction

  • 신경망의 훈련에서, 모델은 경사하강법(gradient descent)을 통해 정확도를 향상시킬 수 있다.
    • 경사하강법은 가중치(weight)와 편향(bias)값들을 변경해가면서 오차(또는 손실)값을 최소화하는 과정이다.
  • torch.Tensor는 파이토치의 핵심 클래스로서, 텐서의 속성을 설정할 때, .requires_grad를 True로 지정하면 텐서에 대한 모든 연산이 추적된다.
    • 이는 역전파 과정(backward process)에서도 마찬가지다.
    • 해당 텐서의 그래디언트는 .grad 속성값에 계속해서 쌓인다.
    • 이처럼 모든 그래디언트의 합은 .backward()가 호출될 때 계산된다.
  • 텐서의 그래디언트를 0으로 설정하는 작업이 필요할 때가 있을 수 있다.
    • 예를 들어, 훈련 반복과정을 시작할 때 그래디언트를 0으로 설정하여서, 앞으로의 그래디언트 추적이 올바르게 이뤄지게 할 수 있다.
  • 이 예제에서는 CIFAR10 데이터셋에서 신경망 학습하는 과정을 통해 이를 설명한다.

Setup

  • 코랩 등의 환경이라면, 런타임을 GPU 또는 TPU 등의 가속장치를 이용하도록 변경하도록 하는 것이 좋다.
pip install torchvision

Steps

  1. 데이터를 로드하기 위해 필요한 라이브러리를 불러온다.
  2. 데이터셋을 불러오고 정규화한다.
  3. 신경망을 구성한다.
  4. 손실함수를 정의한다.
  5. 신경망을 훈련할 때, 그래디언트를 0으로 설정한다.

#과정 1. 데이터를 로드하기 위해 필요한 라이브러리 불러오기

import torch

import torch.nn as nn
import torch.nn.functional as F

import torch.optim as optim

import torchvision
import torchvision.transforms as transforms

#과정 2. 데이터의 로드와 정규화

  • 파이토치에서는 제공되는 내장 데이터셋이 여럿 있다.
transform = transforms.Compose([
                transforms.ToTensor(),
                transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

trainset = torchvision.datasets.CIFAR10(root = './data', train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                          shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                         shuffle=True, num_worker=2)

classes = ('plane', 'car', 'bird', 'cat', 'deer',
           'dog', 'frog', 'horse', 'ship', 'truck')

#과정 3. 신경망 구성

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 6 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

#과정 4. 손실함수와 옵티마이저 정의

  • 이미지 분류를 위해 교차 엔트로피(cross-entropy) 손실함수와 모멘텀이 있는 SGD 옵티마이저를 정의하여 사용한다.
net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

#과정 5. 신경망을 훈련할 때, 그래디언트를 0으로 설정하여 시작하기

  • 신경망의 훈련이란, 데이터 이터레이터를 반복하면서 각 데이터 입력을 신경망에 넣어주고, 신경망을 최적화하는 과정이다.
    • 각 데이터 (배치)입력 마다, 그래디언트를 0으로 설정한다.
    • 이를 통해, 신경망 학습과정에서 불필요한 정보는 추적하지 않게 된다.
for epoch in range(2):

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data

        # 매개변수의 그래디언트를 0으로 설정
        optimizer.zero_grad()

        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if i % 2000 == 1999:
            print('%d, %5d] loss: %3f' % (epoch+1, i+1, running_loss/2000))
            running_loss = 0.0

print('Finished Training')
  • 모델의 매개변수를 옵티마이저에 지정한 뒤에는
    • optimizer.zero_grad() 대신에 model.zero_grad()를 사용할 수도 있다.

댓글