티스토리 뷰
Dropout
정의 : 신경망의 학습 과정 중 Layer의 노드를 랜던함게 Drop함으로써 Generallization 효과를 가져오게 하는 테크닉. 과적합을 어느 정도 방지할 수 있음.적용 : Weight Matrix에 랜덤하게 일부 Column에 0을 집어넣어 연산. 적용시 얼마나 랜덤하게 Dropout할 것인지에 대한 확률값을 지정해야 하며 이는 Input Layer와 Hidden Layer에도 적용할 수 있음. 또한 Epoch마다 랜덤하게 Dropout함.
MNIST MLP모델 설계시 Dropout 적용하기
지난번 MNIST 데이터 셋을 활용한 MLP모델 설계 예제(여기 참고)를 아주 조금 수정하여 파이토치를 활용한 Dropout 실습을 진행해보겠다.
수정할 부분은 5. MLP 모델 설계하기 단계이다.
우선, 지난번에 구현했던 모델 설계 단계의 코드는 다음과 같다.

def __init__(self) 메서드를 이용해 MLP를 설계하는 데 필요한 요소를 정의했고, def forward(self, x) 메서드를 이용해 MLP에 데이터를 입력했을 때 Output으로 계산되는 과정을 정의했다.
이 부분에 Dropout을 적용해보자!
적용법은 간단하다. 1. Layer에 몇 퍼센트의 노드에 대해 가중값을 계산하지 않을 것인지 정의하고 2. 어느 부분에 Dropout을 적용할 것인지 명시해야 한다.

1. 50%의 노드에 대해 가중값을 계산하지 않기 위해 dropout_prob = 0.5로 정의하였다.
2. x = F.sigmoid(x)의 결괏값에 Dropout을 적용(비선형 함수의 Output에 적용하기 위해)하는 코드를 추가하였다.
✅ 여기서 training = self.traning 부분은 학습 상태일 때와 검증 상태일 때에 따라 다르게 적용하기 위해 존재하는 파라미터이다. Dropout은 학습 과정 속에서 랜덤으로 노드를 선택해 가중값이 업데이트되지 않도록 조정하지만, 평가 과정 속에서는 모든 노드를 이용해 Output을 계산하기 때문에 Dropout은 학습 상태일 때만 적용되야 한다. 이를 반영하기 위한 파라미터 값을 model.train()으로 명시할 때 self.training = True, model.eval(self.training = False)로 적용된다.
* 구글에 검색에서 다른 예시를 살펴보니까 def __init__(self) 메서드에 Dropout 과정을 정의하는 경우도 있는 것 같다. 두 경우가 무슨차인지는... 잘 모르겠네? 이건 더 찾아봐야 할 것 같다.
이론상 Dropout을 적용했을 때 일반화가 강해져 Test Accuray가 높아지는 결과가 기대되지만, 실제로는 그렇지 않다.
이는 학습 데이터셋과 검증 데이터셋의 피처 및 레이블의 분포 간 많은 차이가 있을 때 유효하게 작용하기 때문이다.
MNIST 데이터셋은 학습 데이터와 검증 데이터 간 많은 차이가 없기 때문에 오히려 성능이 하락할 수 있다. (나같은 경우는 위 코드를 수정하고 실행해봤더니 오히려 80%대로 성능이 떨어진 것을 확인할 수 있었다..)
Activation 함수
정의 : 어떤 신호를 입력받아 이를 적절히 처리해 출력해주는 함수. MLP에서 기본적으로 시그모이드 함수를 사용한다. 그러나 역전파 과정에서 시그모이드 함수를 사용하면 Gradient Vanishing 현상(Gradient 값이 0으로 수렴하는 현상)이 발생한다는 문제점이 있다.
ReLU 함수 : 시그모이드 함수와 같은 비선형 함수의 문제점을 어느정도 해결한 활성화 함수. f(x) = max(0,x)로 정의되고, 입력 값이 0 이상이면 그 값을 그대로 출력하고 0 이하이면 0으로 출력한다. 역전파 과정 중 곱해지는 활성화 미분값이 0 또는 1이 되기 때문에 아예 없애거나 완전히 살리는 것으로 해석할 수 있다. 따라서 Hidden Layer가 깊어져도 Gradient Vanishing이 일어나는 것을 완화시킬 수 있다.
MNIST MLP모델 설계시 Dropout + ReLU 적용하기
Dropout 실습을 한 위의 코드에서 ReLU 함수를 적용해보자. 수정할 부분은 마찬가지로 5. MLP 모델 설계하기 단계이다.수정방법은 아주 간단하다. 기존의 def forward(self, x) 메서드에서 사용한 비선형 함수 sigmoid(x)를 relu(x)로 변경해주면 된다.


Dropout과 함께 활성화함수로 ReLU() 함수를 적용하여 모델 학습 실행해본 결과, 성능이 매우 좋아졌음을 확인할 수 있었다. 무려 97.44%였다! 심지어 학습의 초기 시작부터 높은 성능을 보여주었다! 여기서, 제일 처음 실습(Dropout X, ReLU() 적용 X)했었을 때의 Test Accuracy가 90%에 불과했다는 점에서, Dropout + ReLU()의 적용은 무지막지한 힘을 가지고 있는 것임을 알 수 있다..
Batch Normalization
정의 : Internal Covariance shift(각 Layer마다 input 분포가 달라짐에 따라 학습 속도가 느려지는 현상 )을 방지하기 위한 기법. Layer의 Input을 정규화해 학습 속도를 빠르게 하겠다는 것. 학습 속도를 향상시켜주고 Gradient Vanishing 문제도 완화해준다.
이 부분은 아직 이해가 잘 안돼서 그냥 이런게 있구나 하고 넘어갈까 싶다.. 자세한 내용은 이 포스팅을 참고하도록 하자.
MNIST MLP모델 설계시 Dropout + ReLU + Batch Normalization적용하기
Batch Normalization은 차원에 따라 적용되는 함수명이 다르기 때문에 유의해서 사용해야 한다. MLP 내 각 Layer에서 데이터는 1차원 크기의 벡터 값을 계산하기 때문에 nn.BatchNorm1d()를 이용한다.
nn.BatchNorm() 함수를 활성화 함수 이전에 적용하는지, 이후에 적용하는지는 연구자의 선호도에 따라 다르다. 이 실습에서는 활성화 함수 이전에 적용하는 방식을 택했다.
수정할 부분은 5. MLP 모델 설계하기 단계이다.


ReLU() + Dropout + 배치 정규화를 적용하였을 때 무려 97.97%의 Test Accuracy가 나왔다. 배치정규화를 적용함으로써 모델의 성능이 향상되었음을 알 수 있다.
'딥러닝' 카테고리의 다른 글
[Deep Learning] AutoEncoder(AE) (0) | 2021.07.17 |
---|---|
[Deep Learning] Initialization, Optimizer (0) | 2021.07.16 |
[AI Background] 인공 신경망 & MNIST 실습 (0) | 2021.07.13 |
[AI Background] 과적합 (0) | 2021.07.11 |
[AI Background] 머신러닝의 정의와 종류 (0) | 2021.07.10 |