💡 'Deep Learning from Scratch'를 참고하여 작성
1. 가중치의 초깃값(Initial value)
신경망의 학습에서 특히나 중요한 것은 가중치의 초깃값입니다. 가중치의 초깃값을 무엇으로 설정하느냐에 따라 신경망 학습의 성패가 갈리는 경우가 많습니다.
1.1 초깃값을 0으로 설정
가중치의 초깃값을 모두 0으로 설정하면, 올바른 학습이 이루어지지 않습니다. 가중치가 모두 0일 경우, 순전파시 같은 값들이 다음으로 전달됩니다. 이는 오차역전파법(back-propagation)에서 모든 가중치의 값이 동일하게 갱신되도록 만듭니다. 이렇게 가중치가 고르게 되어버리는 상황을 막기 위해 초깃값은 무작위로 설정해야 합니다.
1.2 은닉층(Hidden layer)의 활성화값 분포
1.2절에서는 가중치의 초깃값에 따라 은닉층의 활성화값이 어떻게 변화하는지 살펴보겠습니다. 예시를 위하여 5개의 층으로 이루어져 있고, 각 층의 노드가 100개씩인 모델을 사용하겠습니다. 이 모델에 1000개의 데이터를 정규분포(normal distribution)로 무작위 하게 생성하여 입력 데이터로 사용합니다. 활성화 함수(activation function)로는 시그모이드(Sigmoid) 함수를 이용했습니다.
우선 가중치의 분포에 표준편차가 1인 정규분포를 이용한 결과를 살펴보겠습니다. 각 층의 활성화값 데이터는 히스토그램으로 출력합니다.
그림 1에서 각 층의 활성화값들이 0과 1에 치우쳐 분포하고 있다는 것을 확인할 수 있습니다. 활성화 함수로 시그모이드 함수를 사용했기 때문에, 데이터가 0과 1에 치우쳐 분포하게 되면 역전파의 기울기 값이 점점 작아지다가 사라지게 됩니다. 이것이 기울기 소실(vanishing gradient)로 알려진 문제입니다. 이번에는 표준편차를 0.01로 수정하여 실험하겠습니다.
그림 2는 활성화값들이 0.5 부근에 집중되어 있습니다. 이는 앞서 언급한 기울기 소실 문제로는 이어지지 않겠지만, 활성화값이 치우쳤다는 것은 표현력을 제한한다는 점에서 큰 문제입니다. 이는 다수의 노드가 거의 같은 값을 출력하고 있기 때문에 노드를 여러 개 사용한 의미가 없어진다는 것으로 이어집니다.
1.3 Xavier 초깃값(Xavier initialization)
활성화 함수로 ReLU를 제외한 시그모이드 함수와 Tanh 같은 비선형 함수를 사용할 때 적용하는 방법입니다. Xavier 초깃값은 각 층의 활성화값을 광범위하게 분포시키는 것을 목적으로 가중치의 적절한 분포를 찾고자 하였습니다. Xavier 초깃값은 앞 계층의 노드가 $ n $개라면 $ \frac{1}{\sqrt{n}} $인 분포를 사용하면 된다는 결론을 도출했습니다. 이를 수식으로 표현하면 아래와 같습니다.
$$ W_{i, j} \sim N \left(0, \frac{1}{\sqrt{n}} \right) $$
- $ N $ : 정규 분포
- $ n $ : 이전 계층의 노드 수
Xavier 초깃값을 사용하면, 앞 층에 노드가 많을수록 대상 노드의 초깃값으로 설정하는 가중치가 좁게 퍼집니다. 이를 적용한 결과는 다음과 같습니다.
그림 3을 보면 층이 깊어지면서 형태가 다소 일그러지지만, 앞에서 본 방식들보다는 확실히 넓게 분포하고 있음을 확인할 수 있습니다. 이는 각 층의 데이터가 적당히 퍼져 있어, 시그모이드 함수의 표현력도 제한받지 않고 학습이 효율적으로 이루어질 것으로 기대할 수 있습니다. 일그러진 형태를 개선하기 위해서는 활성화 함수를 Tanh로 바꾸면 됩니다. Tanh를 적용한 활성화값 분포는 아래와 같습니다.
1.4 He 초깃값(He initialization)
활성화 함수에 ReLU를 이용할 경우, ReLU에 특화된 초깃값을 이용하기를 권장합니다. 이 특화된 초깃값을 찾아내는 방법이 바로 He 초깃값입니다. He 초깃값은 앞 계층의 노드가 $ n $개일 때, 표준편차가 $ \sqrt{\frac{2}{n}} $인 정규분포를 이용합니다. 이를 수식으로 표현하면 아래와 같습니다.
$$ W_{i, j} \sim N \left(0, \sqrt{\frac{2}{n}} \right) $$
활성화 함수로 ReLU를 이용한 경우의 활성화값 분포를 살펴보겠습니다. 또한, Xavier 초깃값에 ReLU를 적용한 경우와도 비교하겠습니다. 시각화 결과는 아래와 같습니다. 아래의 히스토그램은 빈도수가 7000이 넘는 부분은 시각화에서 제외했습니다.
Xavier 초깃값 결과를 살펴보면, 층이 깊어질수록 0으로 치우친다는 것을 확인할 수 있습니다. 이는 층이 깊어질수록 활성화값들의 치우침이 커지고, 이에 따라 학습할 때 기울기 소실 문제로 이어지게 됩니다. 반면, He 초깃값은 모든 층에서 균일하게 분포하고 있다는 것을 확인할 수 있습니다. 이는 층이 깊어지더라도 분포가 균일하게 유지하기 때문에 역전파에서도 적절한 값이 나올 것으로 기대할 수 있습니다.
2. 배치 정규화(Batch normalization)
배치 정규화는 2015년에 제안된 방법입니다. 배치 정규화가 주목을 받았던 이유는 다음과 같았습니다.
- 학습 속도의 개선
- 초깃값에 크게 의존하지 않음
- 과적합을 억제함
배치 정규화는 각 층의 활성화값이 적절하게 분포되도록 조정하는 역할을 맡습니다. 따라서 아래의 그림 7과 같이 신경망 사이에 '배치 정규화 계층(batch normalization layer)'을 삽입하여 사용합니다.
배치 정규화는 학습시 미니배치를 단위로 데이터의 분포가 $ N(0,1) $이 되도록 정규화합니다. 수식은 다음과 같습니다.
$$ \begin{aligned} \mu_B &\leftarrow \frac{1}{m} \sum_{i=1}^m{x_i}\\ \sigma^2 &\leftarrow \frac{1}{m}\sum_{i=1}^m{(x_i-\mu_B)^2}\\ \hat{x_i} &\leftarrow \frac{x_i-\mu_B}{\sqrt{\sigma_B^2 + \epsilon}} \end{aligned} $$
미니배치 $ B = {x_1, x_2, ..., x_m} $이라는 $ m $개의 입력 데이터의 집합에 대하여 평균 $ \mu_B $와 분산 $ \sigma^2_B $을 구합니다. 그리고는 입력 데이터를 평균이 0, 분산이 1이 되게 정규화 합니다. 위 식에서 $ \epsilon $은 10e-7과 같은 작은 값으로, 0으로 나누는 일을 막는 역할을 합니다.
위 식은 단순히 미니배치 입력 데이터 $ B $를 평균 0, 분산 1인 데이터 $ \{\hat{x_1}, \hat{x_2}, ..., \hat{x_m} \} $로 변환합니다. 이 처리를 활성화 함수의 앞 혹은 뒤에 삽입함으로써 데이터 분포가 덜 치우치게 만듭니다. 또한, 배치 정규화 계층마다 정규화된 데이터에 대해 확대(scale)와 이동(shift) 변환을 수행합니다. 수식은 아래와 같습니다.
$$ y_i \leftarrow \gamma \hat{x_i}+\beta $$
위 식에서 $ \gamma $가 확대, $ \beta $가 이동을 담당합니다. 처음에 두 값은 각각 1과 0으로 시작하고 학습하면서 적합한 값으로 조정합니다.
3. 과적합(Overfitting)
기계학습에서 과적합은 많은 문제를 만듭니다. 과적합이란 신경망이 학습 데이터에만 지나치게 적응(fitting)하여 그 외의 데이터에는 제대로 대응하지 못하는 상태를 말합니다. 이는 범용성을 지향하는 기계학습의 특성과 대비됩니다. 과적합은 주로 다음의 두 가지 이유로 발생합니다.
- 매개변수가 많고 표현력이 높은 모델
- 학습 데이터가 적게 이용된 모델
아래의 그림 8처럼 학습 데이터와 테스트 데이터 사이의 정확도 크게 벌어지는 것은 학습 데이터에만 적응한 결과입니다. 아래의 그림을 통해 테스트 데이터에는 제대로 대응하지 못하고 있다는 것을 확인할 수 있습니다. 이는 과적합을 억제할 방법이 필요하다는 것을 의미합니다.
3.1 가중치 감소(Weight Decay)
과적합을 억제하기 위해 과거부터 많이 사용하는 방법은 가중치 감소입니다. 학습 과정에서 큰 가중치에 대하여 그에 상응하는 패널티를 부과함으로써 과적합을 억제하는 방법입니다. 패널티의 부과를 위해 가중치에 대한 norm을 손실 함수에 더합니다. 여기서 norm은 벡터의 크기나 길이를 측정하는 방법을 의미합니다. 3.1절에서는 norm의 대표적인 2가지 방법과 더불어 가중치 감소를 위한 일반화(regularization) 방법을 소개하겠습니다.
- L1 Norm (Manhattan distance)
norm은 절댓값을 이용한 거리에 해당합니다. 이를 공식으로 표현하면 다음과 같습니다.
$$ d_1(\mathsf{p}, \mathsf{q})= \rVert \mathsf{p}-\mathsf{q} \rVert_1=\sum_{i=1}^n{|p_i-q_i|} $$
- $ \mathsf{p} $ : 벡터 $ \mathsf{p} =(p_1, p_2, ..., p_n) $
- $ \mathsf{q} $ : 벡터 $ \mathsf{q} =(q_1, q_2, ..., q_n) $
L1 norm은 맨해튼 거리라고도 불립니다. 이는 벡터 사이를 맨해튼에서 택시를 타고 이동하는 것처럼 이동하기 때문입니다. 대각선으로 가로지르지 않고 아래의 그림 9에서 파란 선이나 초록색 선처럼 직선으로만 이동하는 것을 확인할 수 있습니다.
- L2 norm (Euclidean distance)
L2 norm은 유클리디언 거리(직선 거리)라고도 불리며, 두 점 사이의 거리를 구할 때 사용하는 공식을 활용합니다. 위의 그림 9에서는 초록색 선에 해당합니다. 유클리디언 거리의 공식은 아래와 같습니다.
$$ d_1(\mathsf{p}, \mathsf{q})= \rVert \mathsf{p}-\mathsf{q} \rVert_2 = \sqrt{\sum_{i=1}^n{(p_i-q_i)^2}} $$
위 두가지의 norm을 일반화(regularization)를 위해 적용합니다. 이는 앞서 말한 학습 과정에서 큰 가중치에 상응하는 페널티를 부과하는 방법입니다. 각각의 norm은 아래와 같이 일반화 방법으로 사용됩니다.
- L1 regularization (Lasso regularization)
$$ Lasso\ cost = J(\theta) + \lambda \sum_{i=1}^n{|w_i|} $$
- $ J(\theta) $ : 손실 함수
- $ \lambda $ : 일반화 계수
- $ w $ : 가중치
L1 regularization은 Lasso regularization이라고도 표현합니다. 기존의 손실 함수에 가중치의 크기가 포함되면서 가중치가 너무 크지 않은 방향으로 학습하도록 합니다. 이때 $ \lambda $의 경우, 학습률과 같은 하이퍼파라미터로 0에 가까울수록 일반화의 효과는 떨어집니다.
L1 norm의 특성으로 인해 L2 regularization보다 더 강건하다(robust)는 특징이 있습니다. 이는 L2 regularization이 제곱값을 사용하여 특이치(outlier)에 대한 페널티가 기하급수적으로 증가한 결과입니다. 반면 L1 regularization은 절대값을 취하기 때문에 선형으로 증가합니다.
견고성(robustness)
데이터 집합에서 특이치에 대한 저항성을 의미. 데이터의 극단값을 더 잘 무시할수록 강건한 모델.
- L2 regularization (Ridge regularization)
$$ Ridge\ cost = J(\theta) + \lambda \sum_{i=1}^n{w_i^2} $$
L2 regularization은 Ridge regularization으로 표현하며, 손실 함수에 가중치의 제곱을 더합니다.
L2 regularization은 연산 복잡도가 낮다는 장점이 있습니다. L2 norm의 특성상, 유클리디언 거리는 하나의 최적해를 갖습니다. 하지만 L1 regularization은 절대값을 사용하기 때문에 하나의 최적해가 아닌 여러 개의 최적해가 만들어질 수 있습니다. 이는 컴퓨팅 비용을 증가시키는 것과 더불어, L2 regularization이 정확한 하나의 최적해가 아닌 근사치에 의존하게 만듭니다.
3.2 드롭아웃(Dropout)
드롭아웃은 노드를 임의로 삭제하면서 학습하는 방법입니다. 학습 과정에서 은닉층의 노드를 출력 비율만큼 무작위로 골라 삭제합니다. 삭제된 노드는 아래의 그림 10과 같이 신호를 전달하지 않습니다. 학습 때는 데이터를 흘릴 때마다 삭제할 노드를 무작위로 선택하지만, 추론 과정에서는 모든 노드를 이용합니다. 단, 추론 때 각 노드의 출력에 학습 과정에서 삭제하지 않은 비율을 곱하여 출력합니다.
드롭아웃은 앙상블 학습(ensemble learning)과 밀접합니다. 드롭아웃이 학습 과정에서 노드를 무작위로 삭제하는 행위가 매번 다른 모델을 학습시키는 것으로 해석할 수 있기 때문입니다. 추론 과정에서는 노드의 출력에 삭제한 비율을 곱함으로써 앙상블 학습에서 여러 모델의 평균을 내는 것과 같은 효과를 얻습니다. 즉, 드롭아웃은 앙상블 학습과 유사한 효과를 하나의 네트워크로 구현했다고 생각할 수 있습니다. 하지만 실제 딥러닝 프레임워크들에서는 삭제하지 않은 노드의 비율을 곱하지 않는다는 것 역시 확인할 수 있었습니다.
앙상블 학습
독립적으로 학습한 여러 모델의 출력 결과를 평균 내어 추론하는 방식
드롭아웃을 구현한 결과는 아래와 같습니다. 여기서는 드롭아웃의 원칙대로 추론 과정에서 삭제하지 않는 노드의 비율을 곱하겠습니다.
class Dropout:
def __init__(self, ratio: float=0.5) -> np.array:
self.ratio = ratio
self.mask = None
def foward(self, x, train_flg=True):
if train_flg:
self.mask = np.random.rand(*x.shape) > self.ratio
return self.mask
else:
return x * (1.0 - self.ratio)
def backward(self, dout: np.array):
return dout * self.mask
참고 자료
[1] A. Bilogur, "L1 Norms versus L2 Norms," https://www.kaggle.com/residentmario/l1-norms-versus-l2-norms
[2] CS231N, "Neural Networks Part 2: Setting up the Data and the Loss," https://cs231n.github.io/neural-networks-2/
'기초 > 인공지능' 카테고리의 다른 글
옵티마이저(Optimizer) (2/2) (0) | 2021.09.02 |
---|---|
옵티마이저(Optimizer) (1/2) (1) | 2021.08.31 |
오차역전파(Back-Propagation) (0) | 2021.08.29 |
손실 함수(Loss function) (0) | 2021.08.28 |
활성화 함수(Activation function) (0) | 2021.08.26 |