머신러닝을 처음 공부할 때 dropout이라는 개념을 봤을 때, 중퇴?라는 뜻으로 외웠던 게 기억났고 그냥 도중 나가는 건가? 이렇게 생각했었습니다.
그때만 해도 제가 공부하기에는 그냥 과적합을 방지하기 위해 몇 개의 node를 kill 하는 거는구나라고 생각했었습니다. 얼마나 얕게 공부했었는지...
Dropout에 대해 다시 자세히 공부하면서 가졌던 궁금증을 정리하고 기억하고자 포스팅을 하게 됐습니다.
편히 읽어보시면서 놓친 개념이 없는지 확인해 보세요~~
Dropout Implementation
Dropout의 정확한 개념은 신경망에서 특정 비율만큼의 뉴런을 무작위로 비활성화하여 과적합을 방지하는 정규화 기법입니다.
def train_step(data, p):
# p = dropout rate
h1 = np.maximum(0, np.dot(w1, data) + b1)
u1 = (np.random.rand(*h1.shape) < p) # Dropout mask 생성
h1 *= u1 # 뉴런 중 일부를 무작위로 0으로 설정
h2 = np.maximum(0, np.dot(w2, h1) + b2)
u2 = (np.random.rand(*h2.shape) < p) # Dropout mask 생성
h2 *= u2 # 뉴런 중 일부를 0으로 설정
return np.dot(w3, h2) + b3
Dropout을 구현하는 코드로 한줄한줄 자세하게 보겠습니다.
h1 = np.maximum(0, np.dot(w1, data) + b1)
첫 번째 hidden layer의 선형 변환을 수행한 후, ReLU 활성화 함수를 적용합니다. np.maximum()을 통해 0보다 작으면 0으로 0보다 크면 그대로 출력하여 ReLU 함수를 구현해 줍니다.
u1 = (np.random.rand(*h1.shape) < p)
먼저 *는 파이썬의 unpacking 연산자로 튜플형태인 h1.shape을 unpack 하여 전달합니다. 예를 들어 (5,10)으로 들어오면 5,10으로 전달됩니다.
h1.shape만큼 0~1 사이의 난수가 형성되고 그중 p보다 작으면 그대로 남기고 p보다 크면 0으로 만들어줍니다.
0~1에서 10개를 생성할 때 p를 0.8로 설정해 놓으면 10개 중 8개가 true로 나오는 겁니다. 정확히 8개가 나오는 것은 아니지만 0과 1 사이에서 균일하게(randomly uniform) 10개의 실수를 생성하기 때문에 대략적으로 나온다고 이해하시면 될 것 같습니다.
h1 *= u1
즉, 마스크 u1을 h1에 곱하여, dropout을 적용합니다. p 확률로 뉴런을 남기고 1-p확률로 뉴런을 제거하는 것으로 이해하시면 됩니다.
이 부분이 전 처음 알았던 내용이어서 집중해서 보시면 좋을 것 같습니다!!
def test_step(data):
h1 = np.maximum(0, np.dot(w1, data) + b1) / p
h2 = np.maximum(0, np.dot(w2, h1) + b2) / p
return np.dot(w3, h2) + b3
테스트를 할 때는 학습한 모든 노드를 사용해야겠죠? 그렇기 때문에 train시 p 확률만큼 활성화시켰던 노드를 보정해 주기 위해 p로 나눠줍니다.
train_step에서 기댓값이 감소하였던 것을 test_step에서 고려해 줘서 보정해줘야 한다는 것입니다.
지금까지 Pytorch 또는 tensor flow를 이용하여 모델을 만들어서 이런 작업이 자동으로 되고 있었던 것입니다.
이런 기저동작을 이해하시고 dropout을 이용하면 좀 더 이해도도 높은 상태에서 작업을 할 수 있지 않을까 합니다ㅎㅎ
Dropout: Inference time vs train time
Dropout은 언제 쓰고 언제 꺼야 할까요??
설명 전에 Inference time, train time, train time에 대해 알아보고 설명하겠습니다.
학습(training): 모델이 데이터를 기반으로 패턴을 학습하는 과정.
추론(inference): 학습된 모델이 새로운 데이터에 대해 예측을 수행하는 과정.
구분 | Inference (추론) | Test (테스트) |
목적 | 새로운 데이터를 이용해 예측 결과를 생성하기 위해 사용 | 모델의 성능을 평가하기 위해 사용 |
결과 | 예측값(출력)만 생성 | 예측값과 **정답(라벨)**을 비교하여 정확도, F1-score 등을 계산 |
사용 시점 | 모델 배포 후, 실시간 또는 배치 처리 시 사용 | 모델 학습 후, 검증/테스트 데이터셋을 이용한 평가 단계에서 사용 |
데이터 | 일반적으로 레이블이 없는 새로운 데이터 | 레이블이 있는 테스트 데이터셋 |
성능 지표 | 추론 속도, latency, throughput | 정확도, 손실(loss), 정밀도, 재현율 등 다양한 평가 지표 |
이 셋의 차이를 정확하게 이해하고 있으면 앞으로 좋을 것 같아요ㅎㅎ
이제 본론으로 들어와서 dropout은 언제 키고 꺼야 할까요?
답은 학습과정에서는 키고 테스트와 추론과정에서는 꺼야 합니다. 학습 시 오버피팅을 방지하기 위해 사용하는 것이기 때문에 학습 시에 드롭아웃을 이용합니다. 이후 테스트 또는 추론을 할 때는 모든 노드를 이용해야 하기 때문에 노드를 전부 활용해야죠!!
간단한 예시 코드를 같이 살펴보고 마무리하겠습니다.
import torch
import torch.nn as nn
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.fc1 = nn.Linear(10, 50)
self.dropout = nn.Dropout(p=0.5)
self.fc2 = nn.Linear(50, 1)
def forward(self, x):
x = self.fc1(x)
x = self.dropout(x) # 학습 시에만 Dropout 적용
x = self.fc2(x)
return x
model = SimpleModel()
# 학습 모드 (Dropout 활성화)
model.train()
output_train = model(torch.randn(5, 10))
# 평가/추론 모드 (Dropout 비활성화)
model.eval()
output_eval = model(torch.randn(5, 10))
여기서 보시면 pytorch를 이용하면 자동적으로 위에서 설명했던 내용이 적용되는 건데요. model.train()을 하면 알아서 dropout이 활성화되고 model.eval()을 하면 알아서 dropout이 비활성 되는 것을 알 수 있습니다.
이번 포스팅을 통해 dropout에 대해 이해할 수 있는 시간이 되었으면 좋겠습니다.
'Machine learning & Deep learning' 카테고리의 다른 글
[Deep learning] Transformer 자세히 공부한 것.. (0) | 2025.02.18 |
---|---|
[Deep learning] Transformer에 대한 기본 아이디어 (0) | 2025.02.17 |
[Deep learning] Attention Mechanism에 대하여 (0) | 2025.02.16 |
[Deep learning] LSTM과 GRU를 Vector combination 관점에서 살펴보기 (0) | 2025.02.16 |
[Machine learning] Ridge Regression (0) | 2025.02.15 |