관리 메뉴

TEAM EDA

[파이토치로 시작하는 딥러닝 기초] 2.3 ReLU 본문

EDA Study/PyTorch

[파이토치로 시작하는 딥러닝 기초] 2.3 ReLU

김현우 2020. 3. 20. 17:46

이번 글에서는 PyTorch로 ReLU를 적용하는 것에 대해서 배워보도록 하겠습니다. 이번 글은 EDWITH에서 진행하는 파이토치로 시작하는 딥러닝 기초를 토대로 하였고 같이 스터디하는 팀원분들의 자료를 바탕으로 작성하였습니다. 

목차

  • Problem of Sigmoid
  • ReLU
  • Optimizer in PyTorch 
  • Review : MNIST
  • Code : mnist_softmax
  • Code : mnist_nn 

1. Problem of Sigmoid 

시그모이드의 가장 큰 문제점은 Vanishing Gradient입니다. Vanishing Gradient는 역전파를 하는 과정에서 미분값이 점점 0이나 1로 가는 현상을 의미합니다. 미분 값이 0이나 1로 가게되면 아무리 학습을 진행해도 파라미터의 값은 변하지 않고 학습이 의미가 없게 됩니다. 아래의 사진을 보면 더 잘 이해가 가는데, 신경망이 깊어지게 되면 체인 룰에 의해서 0~1의 값을 게속 곱하게 되고 이는 결국 0으로 수렴한다는 의미입니다. 즉, 초기의 레이어보다는 후자의 레이어에 의해 모델이 생성될 수도 있습니다. 

2. ReLU 

이러한 문제를 해결하기위해 나온 함수가 ReLU입니다. ReLU는 max(0, x)를 의미하는 함수인데, 0보다 작아지게 되면 0이 되는 특징을 가지고 있습니다. 이러한 특징에 의해서 미분 값은 0과 1만을 가지고 계속해서 작아지는 문제를 줄여주게 됩니다. 

하지만, 이러한 ReLU도 하나의 문제점이 있는데 입력값이 음수이면 미분 값이 0이다보니 weight를 완전히 죽여버리게 됩니다. 이렇게 죽은 weight는 어떤 식으로든 복구를 할 수 없게되고 학습이 진행됨에 따라서 많은 weight가 죽어버릴 수 있습니다. 그렇기에 이를 해결해주기 위해서 조그만한 기울기를 가지는 선을 가지는 leaky ReLU를 사용하게 됩니다. 

출처 : https://ratsgo.github.io/deep%20learning/2017/04/22/NNtricks/

3. Optimizer in PyTorch 

PyTorch에는 다양한 Optimizer가 구현되어 있고 대부분의 사람들이 성능적인 측면에서 Adam을 사용하는 것 같습니다.

4. Code : mnist_softmax

5. Code : mnist_nn

풀코드 

# Lab 10 MNIST and softmax
import torch
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import random

device = 'cuda' if torch.cuda.is_available() else 'cpu'

# for reproducibility
random.seed(111)
torch.manual_seed(777)
if device == 'cuda':
    torch.cuda.manual_seed_all(777)
    
# parameters
learning_rate = 0.001
training_epochs = 15
batch_size = 100

# MNIST dataset
mnist_train = dsets.MNIST(root='MNIST_data/',
                          train=True,
                          transform=transforms.ToTensor(),
                          download=True)

mnist_test = dsets.MNIST(root='MNIST_data/',
                         train=False,
                         transform=transforms.ToTensor(),
                         download=True)
                         
                         
# dataset loader
data_loader = torch.utils.data.DataLoader(dataset=mnist_train,
                                          batch_size=batch_size,
                                          shuffle=True,
                                          drop_last=True)
                                          
                                          
# nn layers
linear1 = torch.nn.Linear(784, 256, bias=True)
linear2 = torch.nn.Linear(256, 256, bias=True)
linear3 = torch.nn.Linear(256, 10, bias=True)
relu = torch.nn.ReLU()

# Initialization
torch.nn.init.normal_(linear1.weight)
torch.nn.init.normal_(linear2.weight)
torch.nn.init.normal_(linear3.weight)

# model
model = torch.nn.Sequential(linear1, relu, linear2, relu, linear3).to(device)

# define cost/loss & optimizer
criterion = torch.nn.CrossEntropyLoss().to(device)    # Softmax is internally computed.
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

total_batch = len(data_loader)
for epoch in range(training_epochs):
    avg_cost = 0

    for X, Y in data_loader:
        # reshape input image into [batch_size by 784]
        # label is not one-hot encoded
        X = X.view(-1, 28 * 28).to(device)
        Y = Y.to(device)

        optimizer.zero_grad()
        hypothesis = model(X)
        cost = criterion(hypothesis, Y)
        cost.backward()
        optimizer.step()

        avg_cost += cost / total_batch

    print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.9f}'.format(avg_cost))

print('Learning finished')

# Test the model using test sets
with torch.no_grad():
    X_test = mnist_test.test_data.view(-1, 28 * 28).float().to(device)
    Y_test = mnist_test.test_labels.to(device)

    prediction = model(X_test)
    correct_prediction = torch.argmax(prediction, 1) == Y_test
    accuracy = correct_prediction.float().mean()
    print('Accuracy:', accuracy.item())

    # Get one and predict
    r = random.randint(0, len(mnist_test) - 1)
    X_single_data = mnist_test.test_data[r:r + 1].view(-1, 28 * 28).float().to(device)
    Y_single_data = mnist_test.test_labels[r:r + 1].to(device)

    print('Label: ', Y_single_data.item())
    single_prediction = model(X_single_data)
    print('Prediction: ', torch.argmax(single_prediction, 1).item())