[AIB 18기] Section 3 - Sprint 1 - Note 3 - 더 나은 신경망 학습을 위한 방법들 - 학습률(Learning rate), 가중치 초기화(Weight Initialization) & Regularization

ysk1230·2023년 4월 20일
0

개요

기본적인 신경망 구축을 지난번에 진행했다면, 신경망 학습이 더 잘되도록 하는 방법도 생각해야 한다.

더 좋은 결과를 위해 2가지 방법에 대해 알아볼 것이다.

  1. 학습률(Learning rate)
  2. 가중치 초기화


개념

1. 학습률 감소 / 계획법(Learning rate Decay / Scheduling)

학습률(Learning rate, lr)이란 매 가중치에 대해 구해진 기울기 값을 얼마나 경사 하강법에 적용할 지를 결정하는 하이퍼파라미터입니다.

학습률은 얼마나 이동할지를 조정하는 하이퍼파라미터
경사 하강법이 산길을 내려가는 과정이라면 학습률은 보폭을 결정하게 된다.
그런데 이 보폭이 잘못 설정되면?

  • 학습률이 너무 낮다 = 최적점에 이르기까지 오래 걸려 주어진 Iteration내에서 최적점 도달에 실패

  • 학습률이 너무 높다 = 발산하는 형태로 경사하강 과정이 발생. 최적값 찾기에 실패

위 문제를 해결하기 위해 학습률 감소/ 계획법 을 사용합니다.

1). 학습률 감소 (Learning rate Decay)

학습률 감소는 Adagrad, RMSprop, Adam과 같은 주요 옵티마이저에 이미 구현되어 있기 때문에 쉽게 적용할 수 있습니다.

optimizer 내 lr(learning rate) 인자를 통해 학습률을 설정할 수 있습니다. beta_1 인자는 학습률 감소율을 설정하며 Adam 내 수식의 변수를 그대로 사용합니다.

model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.001, beta_1 = 0.89)
             , loss='sparse_categorical_crossentropy'
             , metrics=['accuracy'])

2). 학습률 계획법 (Learning rate Scheduling)


2. 가중치 초기화(Weight Initialization)

가중치 초기화(Weight Initialization)란, 신경망 모델의 가중치 매개변수를 초기값으로 설정하는 과정을 말합니다.

딥러닝 모델에서 가중치는 학습 과정에서 업데이트되면서 최적화되는 매우 중요한 파라미터입니다. 따라서 초기값을 어떻게 설정하느냐에 따라 모델의 성능이 크게 달라질 수 있습니다.

가중치 초기화를 제대로 수행하지 않으면, 모델의 학습이 제대로 이루어지지 않을 수 있습니다. 예를 들어, 모든 가중치를 0으로 초기화하는 경우, 모든 뉴런들이 같은 출력을 내게 되므로 모델이 학습하는 것이 불가능해집니다. 또한, 모든 가중치를 동일한 값으로 초기화하는 경우에도 비슷한 문제가 발생할 수 있습니다.

따라서 가중치 초기화를 적절하게 수행하여 모델의 학습이 원활하게 이루어지도록 해야 합니다. 이를 위해서는 가중치 초기화 방법에 대한 연구가 진행되고 있으며, 대표적인 초기화 방법으로는 Xavier 초기화와 He 초기화가 있습니다. 이러한 초기화 방법들은 각 층의 노드 수와 활성화 함수의 종류 등을 고려하여 적절한 초기값을 설정하는 것이 특징입니다.

1). Xavier 초기화

Xavier 초기화(Xavier initialization)는 가중치 초기화 방법 중 하나로, 2010년에 제안된 초기화 방법입니다.

Xavier 초기화는 신경망 모델의 가중치를 초기화할 때, 이전 층의 노드 수와 다음 층의 노드 수에 따라 적절한 표준편차를 가지는 분포로 초기화하는 방법입니다.
이전 층의 노드 수를 n_in, 다음 층의 노드 수를 n_out이라고 할 때, Xavier 초기화는 가우시안 분포(Gaussian distribution)를 사용하여 가중치를 초기화합니다. 이 때 표준편차는 다음과 같이 계산됩니다.

stddev = 2nin+nout\sqrt{2 \over n_{in} + n_{out}}
각 뉴런의 입력에 대한 가중치를 평균이 0,
분산이 2/(입력 개수+출력 개수)인 정규 분포(Normal distribution)로 초기화

예를 들어, 100개의 입력을 받고 50개의 출력을 내는 인공 신경망의 가중치를 초기화한다고 가정해봅시다. 이 경우, Xavier 초기화는 평균이 0, 분산이 2/(100+50) = 0.02인 정규 분포로 가중치를 초기화합니다.

이렇게 계산된 표준편차를 가지는 가우시안 분포에서 무작위로 값을 선택하여 가중치를 초기화합니다.

Xavier 초기화의 핵심 아이디어는, 각 층의 입력과 출력의 분포를 동일하게 유지하면서 초기화를 수행하는 것입니다. 이렇게 함으로써, 입력값이 커지면 가중치도 커지고, 작아지면 가중치도 작아져서, 학습 과정에서 발생할 수 있는 그레디언트 소실 또는 그레디언트 폭주 문제를 방지할 수 있습니다.

Xavier 초기화는 활성화 함수로 tanh 함수를 사용할 때 가장 잘 동작합니다. 이는 tanh 함수의 출력 범위가 [-1, 1]이기 때문에, Xavier 초기화로 초기화된 가중치가 해당 범위 내에서 분포하면서 모델이 잘 학습되기 때문입니다. 그러나 ReLU와 같은 다른 활성화 함수를 사용할 때는 He 초기화(He initialization)가 더 좋은 결과를 낼 수 있습니다.

2) He 초기화

He 초기화(He initialization)는 딥 뉴럴 네트워크에서 가중치(weight)를 초기화하는 방법 중 하나입니다. 이 방법은 논문의 저자 중 한 명인 Kaiming He의 이름을 따서 He 초기화라고 불립니다.

He 초기화는 기존의 가중치 초기화 방법보다 더욱 효과적으로 네트워크의 학습 성능을 향상시킬 수 있습니다. 기존의 가중치 초기화 방법은 모든 가중치 값을 동일하게 설정하는 것이었는데, 이는 네트워크가 층을 거듭할수록 기울기 소실 문제를 야기할 수 있습니다. 그러나 He 초기화는 이러한 문제를 해결하기 위해, 다음과 같이 각 뉴런의 입력 개수에 따라 가중치를 초기화합니다.

  • 정규분포(Normal distribution)로부터 랜덤하게 추출한 값에 표준편차를 2n\frac{2}{\sqrt{n}}으로 나누어 줍니다. (n은 이전 층의 뉴런의 개수)

  • 혹은 균등분포(Uniform distribution)에서 랜덤하게 추출한 값에 6n\frac{6}{\sqrt{n}}으로 나누어 줍니다.

이 방법은 네트워크가 깊어지더라도 기울기 소실 문제를 방지하면서, 초기 가중치 값을 적절히 설정해줍니다. 따라서 He 초기화는 딥 뉴럴 네트워크에서 기본적으로 많이 사용되는 초기화 방법 중 하나입니다.

요약

Activation function에 따른 초기값 추천

1. SigmoidXavier 초기화를 사용하는 것이 유리.

2. ReLUHe 초기화 사용하는 것이 유리


3. 머신러닝으로서의 딥러닝

그림에서 볼 수 있는 것처럼 딥러닝, 즉 인공 신경망도 역시 머신러닝 모델이라고 할 수 있습니다.

그렇기 때문에 머신러닝 모델에서 발생할 수 있는 문제가 동일하게 발생하고, 문제를 해결할 수 있는 방법 역시 동일하게 적용할 수 있습니다.

머신러닝에서는 모델이 복잡해지면 과적합(Overfitting) 문제가 발생하는 경향이 있습니다.
과적합 방지를 위해 적용하는 방법에 대해서 알아보겠습니다.

* 과적합 방지를 위한 방법

1. Weight Decay (가중치 감소)

첫 번째로 알아볼 방법은 가중치 감소(Weight Decay) 입니다.

과적합은 가중치의 값이 클 때 주로 발생하는데요.

가중치 감소에서는 가중치가 너무 커지지 않도록 가중치 값이 너무 커지지 않도록 조건을 추가합니다.
이 과정에서 손실 함수(Cost function)에 가중치와 관련된 항을 추가됩니다.
조건을 어떻게 적용할지에 따라 L1 Regularization(LASSO), L2 Regularization(Ridge) 으로 나뉩니다.

각 방법에 따른 손실 함수 식은 다음과 같습니다.

L1(θw)=12i(outputitargeti)2+λθw1L2(θw)=12i(outputitargeti)2+λθw2\begin{aligned} L_1(\theta_w) &= \frac{1}{2} \sum_i (output_i - target_i)^2 + \color{blue}{\lambda} \cdot \color{red}{\Vert \theta_w \Vert_1}\\ L_2(\theta_w) &= \frac{1}{2} \sum_i (output_i - target_i)^2 + \color{blue}{\lambda} \cdot \color{red}{\Vert \theta_w \Vert_2} \end{aligned}

2. Dropout(드롭아웃)

Dropout은 Iteration마다 레이어 노드 중 일부를 사용하지 않으면서 학습을 진행하는 방법입니다.

3. Early Stopping(조기 종료)

학습 데이터에 대한 손실은 계속 줄어들지만
검증 데이터셋에 대한 손실은 증가한다면 학습을 종료한다는 설정입니다.


예제문제

Fashion MNIST 신경망 예제에 기법 적용하기

  1. 예제 불러오기 및 라이브러리 설치
from tensorflow.keras.datasets import fashion_mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Dropout
from tensorflow.keras import regularizers
import os
import numpy as np
import tensorflow as tf
import keras 
np.random.seed(42)
tf.random.set_seed(42)
  1. 데이터 셋 불러오기
(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
print(X_train.shape, X_test.shape)
  1. 데이터 정규화
X_train = X_train / 255.
X_test = X_test / 255.
np.unique(y_trian) #레이블 개수와 형태를 확인
  1. 신경망 모델 구축 및 Compile
model = Sequential([
	Flatten(input_shape=(28,28)),
	Dense(64,
	  kernel_regularizer = regularzers.12(0.01),
      activity_regularizer = regularizers.11(0.01)),
	Dropout(0.5),
	Dense(10, activation = 'softmax')
])
model.compile(optimizer = tf.keras.optimizers.Adam(learning_rate = 0.001
,beta_1 = 0.89
,loss = 'sparse_categorical_crossentropy'
,metrics = ['accuracy']
model.summary

결과값

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten (Flatten)           (None, 784)               0                    
 dense (Dense)               (None, 64)                50240         
 dropout (Dropout)           (None, 64)                0          
 dense_1 (Dense)             (None, 10)                650                 
=================================================================
Total params: 50,890
Trainable params: 50,890
Non-trainable params: 0
_________________________________________________________________
  1. 신경망 모델 학습
    Early Stopping(조기 종료)를 적용할 수 있도록 파라미터 저장 경로와 조기 종료 옵션을 설정

#파라미터 저장 경로를 설정하는 코드입니다.

checkpoint_filepath = "FMbest.hdf5"

#.hdf5는 데이터를 저장하는 확장자입니다. 'FMbest.hdf5' 파일로 최고 성능의 모델을 저장하며 .h5와 동일한 확장자입니다.
#moitor : 개선을 확인할 지표
#min_delta : 개선이 있다고 판단되는 최소 변경값. min_delta보다 변경 사항이 작다면 개선이 없다고 판단(default=0)
#patience : 개선이 없을 경우 개선되기까지 기다리는 epochs의 수

early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=10, verbose=1)

#ModelCheckpoint를 통해 모델을 저장합니다.
#filepath : 파일이 저장될 경로. 앞서 설정한 것처럼 'FMbest.hdf5'에 저장됩니다.
#save_best_only : 최고 성능을 보이는 경우만 저장합니다. False일 경우 filepath에 모든 학습 과정이 저장됩니다.
#save_weights_only : 모델의 가중치만 저장합니다. False일 경우 레이어까지 모두 저장합니다.
#mode : 검증 지표가 val_acc일 경우 정확도이기 때문에 높을 수록 좋기 때문에 'max'로 설정, val_loss일 경우 낮을 수록 좋기 때문에 'min'으로 설정, 'auto'의 경우 자동으로 탐지하여 진행함.
#save_freq : 매 에폭마다 저장을 시도합니다. integer로 설정할 경우 설정한 수만큼의 iteration마다 모델을 저장합니다.

save_best = tf.keras.callbacks.ModelCheckpoint(
    filepath=checkpoint_filepath, monitor='val_loss', verbose=1, save_best_only=True,
    save_weights_only=True, mode='auto', save_freq='epoch', options=None)
model.fit(X_train, y_train, batch_size=32, epochs=30, verbose=1, 
          validation_data=(X_test,y_test), # 검증 데이터
          callbacks=[early_stop, save_best]) # 앞서 선언한 Early Stopping과 Model Checkpoint를 callbacks를 통해 설정합니다.
  1. 조기 종료 직전 모델을 사용하여 평가를 진행
model.predict(X_test[0:1])
  1. 콜백(Callback)에 의해 Best 모델의 파라미터가 제대로 저장되었는지 확인하고 해당 모델로 평가를 진행합니다.

!ls # 현제 경로를 확인
FMbest.hdf5 sample_data

model.load_weights(checkpoint_filepath) # 'FMbest.hdf5'에 저장한 가중치를 불러옵니다.

불러온 모델을 사용하여 평가를 수행합니다.

model.predict(X_test[0:1]) # 테스트 실행
test_loss, test_acc = model.evaluate(X_test,  y_test, verbose=1) # 테스트 지표 확인

0개의 댓글