while (1): study();

Ch6. 학습 관련 기술들 본문

독서

Ch6. 학습 관련 기술들

전국민실업화 2021. 7. 21. 18:37
728x90

* 책 내용 요약이 아니니 유의하시기 바랍니다.

 

 개인적으로 딥러닝의 학습 방법에 대해서는 꽤 잘 알고 있다고 생각했었는데, 사실 겉핥기 수준으로만 알고 있었다는 것을 알게 된 장입니다. 한편으로는 절망스러우면서도, 조금 더 기초를 단단히 해야 할 이유를 찾은 것 같아서 한편으로는 매우 기쁩니다.

 

1. 매개변수 갱신

1) SGD

 이전 장에서 이미 오차역전파를 이용하여 기울기를 구할 수 있도록 코드를 구현해 놓았습니다. 이를 이용해서 훈련 시 단순히 가중치에서 그래디언트의 일정 비율을 빼는 방법으로 손실을 최소화해볼 수 있겠죠. 이것은 가장 기본적인 경사하강법(Gradient Descent)이며, 배치 기준으로 랜덤하게 하강시키는 방식을 확률적 경사하강법(SGD; Stochastic Gradient Descent)라고 합니다. 수식으로는 다음과 같이 표현할 수 있습니다.

$$W ← W - \eta{dL \over dW}$$

 다만 SGD는 비등방성(anisotropy) 함수에 취약한 모습을 보입니다. 비등방성 함수는 방향에 따라 성질이 달라지는 함수를 말합니다. 따라서 각 축을 기준으로 보았을 때 기울기 차이가 크게 난다면, 예를 들어 협곡의 형태로 함수가 분포한다면 SGD는 흔히 말하는 진동(Oscillation) 현상을 겪게 됩니다.

 

2) Momentum

 이것을 해결하기 위해 Momentum이 제안되었습니다. 관성이라는 본래 의미답게, 이전에 이동했던 방향으로 조금 더 이동시키는 것을 말합니다. 아래 수식을 보면, 이전에 이동했던 방향의 일정 방향을 재귀적으로 더해줍니다. 결과적으로 진동현상을 조금 더 방지할 수 있게 됩니다.

$$v ← {\alpha}v - \eta{dL \over dW}$$

$$W ← W + v$$   

 

3) AdaGrad

 한편 최적해에 조금 더 용이하게 접근하기 위해서 훈련이 진행될수록 학습률을 감소시키는 방법도 있습니다. 그 중 하나가 AdaGrad이며, 말 그대로 적응형 기울기(Adaptive Gradient)를 사용합니다. 기울기의 element-wise 곱을 수행하여 L2노름을 구하고 누적시킵니다. 이것을 scaling factor로 사용하여 업데이트 가중치를 계산합니다. 

$$h ← h + {dL \over dW} ⊙ {dL \over dW}$$

$$W ← W - \eta{1 \over \sqrt{h}}{dL \over dW}$$

 누적된 h는 계속해서 증가할 것이고, 따라서 학습이 진행될 수록 기울기가 더 작게 스케일링되어 학습이 덜 진행될 것입니다. 한편 이 경우 어느 순간 h가 너무 커져 학습이 아예 진행되지 않는 현상이 발생하는데, 이를 개선한 것이 지수이동평균(EMA)를 이용한 RMSprop입니다.

 

4) Adam

 Momentum과 AdaGrad를 융합한 것이 Adam입니다..라고 책에서 설명하고 있습니다만 자세한 설명은 나와있지 않습니다. 조만간 원 논문을 직접 읽어볼 예정입니다.

 

2. 가중치 초깃값

가장 흥미로웠던 부분입니다. 지금까지 딥러닝 프레임워크만 사용했기 때문에 가중치 초기화에 대해서 생각해본 적이 없었는데, 실제로 학습에 유의미하게 영향을 미치는 듯 합니다.

 기본적으로 가중치는 랜덤하게 학습해야 합니다. 다만 편차에는 신경을 써주어야 합니다. 편차가 너무 작을 시 대부분의 활성화값은 한 쪽에 편향되어 반환될 것이며, 나중에 역전파 과정에서 반환하는 기울기 또한 비슷할 것이기 때문입니다. 이는 노드를 여러 개 두는 의미가 없게 만듭니다. 즉, 모델의 표현력이 제한됩니다.

 만약 편차가 너무 크면 시그모이드 활성화 함수의 경우, 대부분의 활성화값이 0 혹은 1이 됩니다. 시그모이드 함수가 꼬리가 긴 형태라는 것을 생각해보면 당연한 일입니다. 시그모이드의 역전파 계산식은 $dLy(1 - y)$이기 때문에 결과적으로 대부분의 기울기는 0에 수렴합니다. 이것이 바로 기울기 소실(Gradient Vanishing) 문제입니다. 기울기 소실 문제는 초기값에 크게 영향을 받습니다.

 이러한 문제들을 미연에 방지하게 위해서 Xavier 초깃값을 사용할 수 있습니다. 이는 이전 층의 노드 개수가 n개라고 할 때, 표준편차를 ${1 \over \sqrt{n}}$으로 두는 방식입니다. 상대적으로 Xavier 초기값이 S자형 활성화 함수에 대해서 잘 작동하고, ReLU와 같은 비선형 활성화 함수에는 He 초기값을 사용합니다. 이는 표준편차를 ${2 \over \sqrt{n}}$로 둡니다. ReLU는 0 이하의 값을 모두 0으로 반환해버리기 때문에, 조금 더 편차를 넓게 주어 표현력을 향상시킨 것이라고 볼 수 있겠습니다. 그럼 한번 실험을 진행해보겠습니다. CLI 환경에서 실험이 가능하도록 모듈화해놓았으니 필요할 경우 사용하시기 바랍니다.

Github: https://github.com/jeongchanyoung-1234/My_Deep_Framework

 

GitHub - jeongchanyoung-1234/My_Deep_Framework: Constructing my own deep-learning framework with Python!

Constructing my own deep-learning framework with Python! - GitHub - jeongchanyoung-1234/My_Deep_Framework: Constructing my own deep-learning framework with Python!

github.com

 

 공평한 실험을 위해서 파라미터는 다음과 같이 초기화하였습니다.


에포크: 500

배치 사이즈: 128

홀드아웃 비율: 0.8

학습률: 0.1

옵티마이저: SGD

배치정규화, 드랍아웃, 가중치 규제 사용 X


우선 가중치를 모두 0으로 초기화해보겠습니다. 가독성을 위해서 verbose를 최소로 주었으니 양해바랍니다.

역시 가중치가 잘 업데이트되지 않은 듯 합니다. 0은 조금 심했고, 책에서 제시한대로 표준편차가 0.1인 정규분포로 초기화해보겠습니다.

운 좋게 잘 맞아 떨어졌는지 나쁘지 않은 성과를 보입니다. 다만, 좀 더 이론에 근거한 초깃값을 사용했을 때 높은 성능을 보여야 합당합니다. 따라서 이번에는 ReLU에 대해서는 Xavier 가중치를, Softmax에 대해서는 He 가중치를 주어 실험해보겠습니다.

 어떻게 된 건지 성능이 더 떨어져버렸습니다. 코드 단에서 무엇이 잘못된 걸까요? 네, 맞습니다.

if config.weight_init == 'xavier':
    alphas = [np.sqrt(2. / input_size) for _ in range(config.n_layers - 1)] + [np.sqrt(1. / input_size)]
else:
    w = float(config.weight_init)
    alphas = [w for _ in range(config.n_layers - 1)] + [w]

alpha는 표준정규분포에서 추출한 가중치 초기값에 곱해지는 Scaling factor입니다. I를 입력의 크기, H를 은닉상태의 크기라고 해봅시다. 정상적이라면 첫 번째 레이어의 초기값의 alpha는 $\sqrt{{2 \over I}}$가 되어야하고, 중간 레이어들은 $\sqrt{{2 \over H}}$, 마지막 레이어는 활성화 함수가 소프트맥스이기 때문에 $\sqrt{{1 \over I}}$가 되어야 합니다. 그러나 모든 가중치가 입력의 크기를 이용하여 초기화되어 있습니다. 코드를 수정해 보겠습니다.

 큰 차이가 나는 것은 아니지만, 분명 성능이 향상되었습니다. 또한 파라미터 서치를 할 필요없이 단순히 어떤 공식에 의해서 초기값이 도출된다는 것은 상당히 고무적인 일입니다.

 

3. 배치 정규화

 위의 가중치 초기화의 관건은 역전파 알고리즘에 의해 모델이 다양한 양상으로 학습할 수 있도록 활성화값을 골고루 분포시키는 것이었습니다. 그러나 이러한 과정이 번거로운 것은 확실합니다. 그렇다면 활성화 값을 아예 강제로 골고루 분포시켜보면 어떨까 싶은 아이디어에서 출발한 것이 바로 배치 정규화(Batch Normalization)라고 합니다. 즉, 배치 정규화는 데이터의 분포를 평균이 0, 분산이 1이 되도록 정규화합니다. 또한 배치 정규화 계층에서는 확대 계수 $\gamma$와 이동 계수 $\beta$를 학습시키고, 결과를 출력합니다.

$$x ← {x_{i} - \mu_{B} \over \sqrt{\sigma_{B}^{2} + \epsilon}}$$

$$y ← \gamma x + \beta$$

 배치 정규화는 다음과 같은 이점이 있습니다.


1. 학습 속도 개선

2. 초기값 의존성 저하

3. 과적합 억제


 각 배치마다 데이터의 분포가 바뀌는 것을 Internal Covariant Shift라고 합니다. 이것은 배치 단위로 학습하는 확률적 방식의 한계라고 볼 수 있습니다. 결국 모델 학습의 목표는 전체 데이터 분포를 모사하는 것이기 때문에, 일반화 성능을 향상시켜야 합니다. 지금의 정규화는 일종의 노이즈 제거 효과라고 볼 수 있기에, 과적합을 억제할 수 있습니다.

 그렇다면 학습속도가 개선되는지, 또한 초기값 의존성이 저하되는지도 한 번 확인해보겠습니다. 이전과 같은 설정을 사용하되, 가중치를 Xavier 초기값으로 초기화하고, 에포크는 1000회를 주며, 200에포크마다 점수를 출력하도록 하겠습니다.

 우선 배치 정규화를 사용하지 않았을 때의 결과입니다.

배치 정규화 미사용

 다음은 배치 정규화를 사용했을 때의 결과입니다.

배치 정규화 사용

 앞서 배치 정규화를 사용하지 않았을 때, 200에포크의 검증 정확도는 약 0.83 정도였습니다. 그러나 배치 정규화를 사용했을 때는 200에포크밖에 훈련을 진행하지 않았음에도 불구하고 0.93으로 약 10%p나 더 높은 정확도를 보였습니다. 데이터 형태가 상대적으로 학습하기 용이해져 이런 결과가 발생한 듯 합니다. 또한 최종 결과도 (과적합은 있지만) 배치 정규화를 사용했을 때가 더 높은 것을 확인할 수 있습니다.

 이번에는 초기값을 바꾸며 실험해보겠습니다. 배치 정규화를 사용하되 초기값의 편차를 0, 0.1, 그리고 Xavier 초기값으로 설정해보겠습니다. 아래는 0으로 초기화 한 경우입니다.

초기값 0

 초기값을 0으로 두면 아예 역전파로 인한 학습이 불가능합니다. 따라서 학습이 거의 진행되지 않은 모습입니다. 이번에는 표준편차가 0.1인 정규분포로 초기화해보겠습니다.

초기값 표준편차가 0.1인 정규분포

 이전에 배치정규화를 사용하지 않았을 때에 비해서 월등하게 성능이 올라간 모습입니다! 약 12%p 정도 정확도가 향상되었습니다. 이번에는 Xavier 초기값을 사용해보겠습니다.

Xavier 초기값

검증 데이터에 대해서 거의 비슷한 성능을 보입니다. 

 이로써 배치 정규화를 사용하면 역전파가 가능하다는 가정 하에 초기값에 구애받지 않고 훈련시킬 수 있다는 것이 귀납적으로 증명되었습니다.

 

4. 가중치 감소

과적합(Overfitting)이 발생하는 조건은 다음과 같습니다.


1, 매개변수가 많고 표현력이 높은 모델

2. 훈련 데이터가 적음


 과적합을 방지하기 위해서 사용할 수 있는 방법론 중 하나는 가중치 감소입니다. L1 규제는 각 가중치의 절대값 합을 손실함수에 더합니다. L2 규제는 각 가중치의 제곱합을 더합니다. 여기서는 L2 규제를 사용하여 실험해보도록 하겠습니다. 기존에 배치정규화를 적용하고 Xavier 초기값을 사용했던 모델에서 과적합 양상이 보였으니, 여기서 L2 규제를 사용하여 과적합을 억제해보도록 하겠습니다. 기존 훈련 정확도는 0.9711, 검증 정확도는 0.9568이었습니다.

L2 lambda 1e-5

 l2 규제 가중치를 1e-5로 주었을 때, 훈련 정확도가 약 0.0038%p 상승한 반면, 검증 정확도는 0.0155%p로 약 5배 정도 더 많이 상승하였습니다. 따라서 l2 규제를 이용하면 훈련 성능과 추론 성능 간의 격차를 줄일 수 있다는 것이 확인되었습니다. 다만, 어떻게 진행을 해도 과적합이 완전히 해소되는 양상은 보지 못했습니다. 이는 L2 규제의 본질적인 성격일수도 혹은 데이터에 따라 다르게 적용되는 양상일 수도 있겠습니다.

 또한 이론적으로는 L2 규제 가중치는 어떤 양수든 될 수 있습니다만, 너무 크게 가중치를 주면 전체적으로 학습을 못하는 모습을 보였습니다. 

L2 lambda 1

 이것은 모델의 표현력이 지나치게 제한된 것이라는 관점에서 볼 수 있습니다. 혹은 듀얼러닝의 손실함수에서 LM을 이용한 regularization term이 너무 커지면 거기에 맞추어 학습되는 것처럼, 이 경우도 가중치의 크기에 점점 모델이 너무 몰두하게 된다고 볼 수 있습니다.

 

5. 드롭아웃

 검증 성능이 올랐지만 어쨌든 과적합이 남아 있으니, 드롭아웃을 이용하여 조금 더 일반화시켜 보겠습니다.

l2 lambda 6e-5 / dropout 2e-2

 훈련 성능은 조금 떨어지고, 나머지 검증 성능과 테스트 성능이 조금씩 올라간 것을 확인할 수 있습니다.

 과적합 상황을 만들기 위해서 층을 5개 쌓은 것이 근본적인 문제이기 때문에, 실험은 여기서 만족하고 종료하도록 하겠습니다.

728x90

'독서' 카테고리의 다른 글

Ch1. 신경망 복습  (0) 2021.07.24
Ch7. 합성곱 신경망  (0) 2021.07.22
Ch5. 오차역전파법  (0) 2021.07.19
Ch4. 신경망 학습  (0) 2021.07.18
Ch3. 신경망  (0) 2021.07.18
Comments