데알못정을

Pytorch를 이용한 Dropout 효과 시각화(코드구현) 본문

Coding

Pytorch를 이용한 Dropout 효과 시각화(코드구현)

쩡을이 2022. 9. 30. 18:01
728x90

pytorch를 이용하여 신경망을 설계하고, 학습과정에서 dropout을 지정할 때와, 그렇지 않을 때를 비교해서drop out의 효과를 공부해보자. 먼저, dropout이란 무엇인지 살펴보면 신경망 뿐만 아니라 머신러닝에서 자주 발생하는 문제 중에 'overfitting'이 있다. dropout은 이를 신경망에서 해결하기 위한 방법인데, 어떻게 하냐면

 

왼: 드롭아웃 미적용 / 오: 드롭아웃 적용

오른쪽 그림과 같이 일정한 비율로 훈련세트에서 무작위로 노드를 제거하면서 학습을 이어나가는 것이다. 이렇게 되면 활성화된 노드만 학습에 참여하여 과적합을 방지할 수 있다. 테스트 셋에서는 모든 뉴런에 신호를 전달하는 대신 훈련때 삭제한 비율을 각 뉴런에 곱해서 출력을 한다. 실제로 drop out을 할때 train, test loss의 변화는 어떤지 보자.

[Dropout x]

import torch
from torch import nn, optim
from sklearn.model_selection import train_test_split
from torch.utils.data import TensorDataset, DataLoader

X = digits.data
y = digits.target

X_train, X_test, Y_train, Y_test = train_test_split(X,Y,test_size = 0.2)

X_train = torch.tensor(X_train, dytpe = torch.float32)
X_test = torch.tensor(X_test, dytpe = torch.float32)
Y_train = torch.tensor(Y_train, dytpe = torch.float32)
Y_test = torch.tensor(Y_test, dytpe = torch.float32)


"""신경망 모델 구성"""

k=100

net = nn.Sequential(
	nn.Linear(64,k),
    nn.ReLU(),
    nn.Linear(k,k),
    nn.ReLU(),
    nn.Linear(k,k),
    nn.ReLU(),
    nn.Linear(k,k),
    nn.ReLU(),
    nn.Linear(k,10)


"""손실함수"""
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters())

ds = TensorDataset(X_train, Y_train)
loader = DataLoader(ds, batch_size = 32, shuffle = True)

"""훈련루프"""
train_losses = []
test_losses = []

for epoch in range(100):
	running_loss = 0.0
    for i ,(xx,yy) in enumerate(loader):
        y_pred = net(xx)
        loss = loss_fn(y_pred, yy)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        running_loss+=loss.item()
    train_lossed.append(running_loss/i)
    y_pred = net(X_test)
    test_loss = loss_fn(y_pred, Y_test)
    test_lossed.append(test_loss.item())

결과

다음과 같이 학습데이터 loss(파란선)은 epoch를 반복할 수록 loss가 감소한다. 그러나 test loss는 어느 순간까지는 감소하다가 반대로 증가하는 경향을 볼 수 있다. 이는 과적합 현상이 일어난 것이다.

 

[Dropout o]

"""신경망 모델 구성"""

k=100

net = nn.Sequential(
	nn.Linear(64,k),
    nn.ReLU(),
    nn.Dropout(0.5),
    nn.Linear(k,k),
    nn.ReLU(),
    nn.Dropout(0.5),
    nn.Linear(k,k),
    nn.ReLU(),
    nn.Dropout(0.5),
    nn.Linear(k,k),
    nn.ReLU(),
    nn.Dropout(0.5),
    nn.Linear(k,10)


"""손실함수"""
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters())

ds = TensorDataset(X_train, Y_train)
loader = DataLoader(ds, batch_size = 32, shuffle = True)

"""훈련루프"""
train_losses = []
test_losses = []

for epoch in range(100):
	running_loss = 0.0
    net.train()
    for i ,(xx,yy) in enumerate(loader):
        y_pred = net(xx)
        loss = loss_fn(y_pred, yy)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        running_loss+=loss.item()
    train_lossed.append(running_loss/i)
    net.eval()
    y_pred = net(X_test)
    test_loss = loss_fn(y_pred, Y_test)
    test_lossed.append(test_loss.item())

drop out을 모델 설계시 넣어줄 경우에 주의할 점은 훈련루프에서 학습 할때는 '모델이름.train', 추론할때는 '모델이름.eval()'을 꼭 해줘야 한다. 이렇게하면 추론할때 drop out이 작동하지 않는다.

결과

test 데이터에 대해서도 loss가 잘 줄어들었다.

dropout은 과적합을 잘 막을 수 있는 도구다!

728x90
Comments