Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- gradient descent
- Python
- 청춘 화이팅
- set method
- 선형회귀
- Andrew ng
- 특별 메소드
- 오스트리아
- 나의23살
- Machine learning
- 미래에셋해외교환
- 딥러닝
- Linear Regression
- 교환학생
- anaconda 가상환경
- m1 anaconda 설치
- 최소공배수
- 2022년
- set add
- cost function
- 최대공약수
- 최소제곱법
- 이차전지
- 유럽
- fluent python
- 양극재
- special method
- 미래에셋 장학생
- Deeplearning
- 유럽 교환학생
Archives
- Today
- Total
Done is Better Than Perfect
[딥러닝] 5. 딥러닝 모델 학습의 문제점 pt.2 : 기울기 소실, 가중치 초기화 방법 본문
딥러닝 모델 학습의 문제점으로 아래의 4가지가 있다.
1. 학습 속도 문제와 최적화 알고리즘
2. 기울기 소실 문제
3. 초기값 설정 문제
4. 과적합 문제
이번 장에서는 2. 기울기 소실 문제, 3. 가중치 초기화 설정 문제와 이를 해결하기 위한 기법에 대해 자세히 알아보도록 하겠다.
2. 기울기 소실 문제와 방지 기법
기울기 소실 (Vanishing Gradient)
- 발생 원인 : 기울기가 0인 값을 전달하며 중간 전달값이 사라지는 문제
- 기울기가 소실되는 문제가 반복되며 학습이 잘 이루어지지 않음
- 깊은 층의 모델에서 역전파 시에 전달되는 손실 함수(loss function)의 gradient 값에 활성화 함수인 sigmoid 함수의 0에 가까운 기울기 값이 계속해서 곱해지면서 결국 가중치 업데이트가 잘 안되는 문제
- 해결 방법 :
- ReLU : 기존에 활성화 함수로 사용하던 sigmoid 함수 대신 ReLU 함수를 사용하여 해결
- Tanh : 내부 hidden layer에는 ReLU를 적용하고, output layer에서만 Tanh 적용
- ReLU가 sigmoid 보다 기울기 소실 문제에 강한 이유
- sigmoid 함수는 입력값이 매우 크거나 작다면 기울기도 0에 가까워짐
- ReLU 함수는 양수 입력 값에 대해 일정한 기울기를 갖고 있으므로 기울기 소실 문제를 방지할 수 있음
[ hidden layer의 activation function이 sigmoid인 모델 VS relu인 모델 비교]
import tensorflow as tf
import logging, os
logging.disable(logging.WARNING)
''' 1. hidden layer의 활성화 함수가 `relu`인 10층 이상의 모델 '''
def make_model_relu():
model_relu = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
return model_relu
''' 2. hidden layer의 활성화 함수가 `sigmoid`인 10층 이상의 모델 '''
def make_model_sig():
model_sig = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(32, activation='sigmoid'),
tf.keras.layers.Dense(32, activation='sigmoid'),
tf.keras.layers.Dense(32, activation='sigmoid'),
tf.keras.layers.Dense(32, activation='sigmoid'),
tf.keras.layers.Dense(32, activation='sigmoid'),
tf.keras.layers.Dense(32, activation='sigmoid'),
tf.keras.layers.Dense(32, activation='sigmoid'),
tf.keras.layers.Dense(32, activation='sigmoid'),
tf.keras.layers.Dense(32, activation='sigmoid'),
tf.keras.layers.Dense(32, activation='sigmoid'),
tf.keras.layers.Dense(10, activation='softmax')
])
return model_sig
''' 3. 두 모델을 불러온 후 학습시키고 테스트 데이터에 대해 평가 '''
def main():
# MNIST 데이터를 불러오고 전처리
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model_relu = make_model_relu() # hidden layer들의 활성화 함수로 relu를 쓰는 모델
model_sig = make_model_sig() # hidden layer들의 활성화 함수로 sigmoid를 쓰는 모델
# 모델 최적화
model_relu.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model_sig.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model_relu.summary()
model_sig.summary()
# 모델 학습
model_relu_history = model_relu.fit(x_train, y_train, epochs=5, verbose=0)
print('\n')
model_sig_history = model_sig.fit(x_train, y_train, epochs=5, verbose=0)
# 모델 평가
scores_relu = model_relu.evaluate(x_test, y_test)
scores_sig = model_sig.evaluate(x_test, y_test)
print('\naccuracy_relu: ', scores_relu[-1])
print('accuracy_sig: ', scores_sig[-1])
return model_relu_history, model_sig_history
if __name__ == "__main__":
main()
[ 코드 실행 결과 ]
- hidden layer의 활성화 함수로 ReLU를 선택한 모델의 정확도가 더 높음.
- 따라서, 기울기 소실 문제에서 ReLU 함수를 활성화 함수로 선택하는 것이 더욱 정확도가 높음
### output ###
accuracy_relu: 0.9632
accuracy_sig: 0.7123
3. 초기값 설정 문제와 방지 기법
가중치 초기화 (weight initialization)
- 활성화 함수의 입력 값이 너무 커지거나 작아지지 않게 만들어주는 것이 핵심 (기울기 소실 방지)
- 초기화 설정 문제 해결 방법 :
- 표준 정규분포를 이용한 초기화 (분산을 줄이기 위해 표준편차를 0.01로 하는 정규분포로 초기화)
- Xavier 초기화 방법 + sigmoid 함수 : 표준 정규 분포를 입력 개수의 제곱근으로 나누어 줌. sigmoid와 같은 S자 함수의 경우 출력 값들이 정규 분포 형태를 가져야 안정적으로 학습 가능
- Xavier 초기화 방법 + ReLU 함수 : ReLU 함수에는 Xavier 초기화가 부적합. 레이어를 거쳐갈수록 값이 0에 수렴
- He 초기화 방법 : 표준정규분포를 입력 개수 절반의 제곱근으로 나누어줌. 10층 레이어에서도 평균과 표준편차가 0으로 수렴하지 않음.
- 적절한 가중치 초기화 방법 :
- Sigmoid, tanh의 경우, Xavier 초기화 방법이 효율적.
- ReLU계의 활성화 함수 사용 시, He 초기화 방법이 효율적
- 최근 대부분의 모델에서는 He 초기화를 주로 선택
[ 1. 표준 정규 분포를 이용한 가중치 초기화 VS 표준편차를 0.01로 하는 정규분포로 가중치 초기화 ]
import numpy as np
from visual import *
np.random.seed(100)
def sigmoid(x):
result = 1 / (1 + np.exp(-x))
return result
def main():
# 100개의 노드를 가진 모델에 들어갈 1000개의 입력 데이터
x_1 = np.random.randn(1000,100)
x_2 = np.random.randn(1000,100)
node_num = 100
hidden_layer_size = 5
activations_1 = {}
activations_2 = {}
for i in range(hidden_layer_size):
if i != 0:
x_1 = activations_1[i-1]
x_2 = activations_2[i-1]
# 가중치 정의
w_1 = np.random.randn(100,100)*1 + 0 # 표준 정규 분포 - N(0,1)
w_2 = np.random.randn(100,100)*0.01 + 0 # 표준편차가 0.01인 정규분포 - N(0,0.01)
a_1 = np.dot(x_1, w_1)
a_2 = np.dot(x_2, w_2)
## sigmoid 통과
z_1 = sigmoid(a_1)
z_2 = sigmoid(a_2)
activations_1[i] = z_1
activations_2[i] = z_2
Visual(activations_1,activations_2)
return activations_1, activations_2
if __name__ == "__main__":
main()
[ 코드 실행 결과 - activation 결과의 분포도 ]
- 표준 정규 분포로 가중치를 초기화한 모델 -> activation 결과값이 0, 1 값으로 몰림
- 표준편차 0.01인 정규분포로 가중치를 초기화한 모델 -> activation 결과값이 0.5 주변으로 몰림
- activation 값이 양극단(0또는 1)으로 몰리는 현상은 좋지 않음
- 활성화 함수(예, sigmoid 함수)의 기울기가 0에 수렴 -> 학습이 잘 이루어 지지 않음
[ 2. Xavier 방법을 이용한 가중치 초기화 - 활성화 함수(sigmoid & relu)와 결합했을 때 비교]
- Xavier 초기화 방법은 앞 레이어의 노드가 n개일 때 표준 편차가 $ \frac{1}{ \sqrt{n}}$ 인 분포를 사용하는 것
- Xavier 초기화 방법을 사용하면 앞 레이어의 노드가 많을수록 다음 레이어의 노드의 초깃값으로 사용하는 가중치가 좁게 퍼짐.
import numpy as np
from visual import *
np.random.seed(100)
def sigmoid(x):
result = 1 / (1 + np.exp(-x))
return result
def relu(x):
result = np.maximum(0,x)
return result
def main():
# 100개의 노드를 가진 모델에 들어갈 1000개의 입력 데이터
x_sig = np.random.randn(1000,100)
x_relu = np.random.randn(1000,100)
node_num = 100
hidden_layer_size = 5
activations_sig = {}
activations_relu = {}
for i in range(hidden_layer_size):
if i != 0:
x_sig = activations_sig[i-1]
x_relu = activations_relu[i-1]
# Xavier 가중치 초기화 - 표준 편차가 1/root(n)인 정규분포
w_sig = np.random.randn(100,100)*(1/np.sqrt(node_num))+0
w_relu = np.random.randn(100,100)*(1/np.sqrt(node_num))+0
a_sig = np.dot(x_sig, w_sig)
a_relu = np.dot(x_relu, w_relu)
z_sig = sigmoid(a_sig) # sigmoid 활성화 함수 이용
z_relu = relu(a_relu) # relu 활성화 함수 이용
activations_sig[i] = z_sig
activations_relu[i] = z_relu
Visual(activations_sig, activations_relu)
return activations_sig, activations_relu
if __name__ == "__main__":
main()
[ 코드 실행 결과 - activation 결과의 분포도 ]
- (왼쪽 : sigmoid + Xavier 초기화) activation 결과 값이 어느 한쪽으로 몰리지 않고 고르게 분포됨을 확인할 수 있음
- (오른쪽 : ReLU + Xavier 초기화) activation 결과 값이 한쪽(0)으로 몰림 -> ReLU 함수에는 Xavier 초기화가 부적합
[ 3. He 방법을 이용한 가중치 초기화 ]
- He 초기화 방법 : 활성화 함수로 ReLU를 쓸 때 활성화 결괏값들이 한쪽으로 치우치는 문제를 해결하기 위해 나온 방법
- 앞 레이어의 노드가 n개일 때 표준 편차가 $ \frac{\sqrt{2}}{\sqrt{n}}$인 분포를 사용하는 것
- Xavier 초기화 방법은 표준 편차가 $ \frac{1}{\sqrt{n}}$.
- ReLU는 음의 영역에 대한 함숫값이 0이라서 더 넓게 분포시키기 위해 $ \sqrt{2} $배의 계수가 필요하다고 이해할 수 있음.
import numpy as np
from visual import *
np.random.seed(100)
def relu(x):
result = np.maximum(0,x)
return result
def main():
# 100개의 노드를 가진 모델에 들어갈 1000개의 입력 데이터 - 표준정규분포 따름
x_relu = np.random.randn(1000,100)
node_num = 100
hidden_layer_size = 5
activations_relu = {}
for i in range(hidden_layer_size):
if i != 0:
x_relu = activations_relu[i-1]
# He 가중치 초기화 - 표준 편차가 root(2)/root(n)인 정규분포
w_relu = np.random.randn(100,100)*np.sqrt(2/node_num)+0
a_relu = np.dot(x_relu,w_relu)
z_relu = relu(a_relu)
activations_relu[i] = z_relu
Visual(activations_relu)
return activations_relu
if __name__ == "__main__":
main()
[ 코드 실행 결과 - activation 결과의 분포도 ]
- 앞선 'ReLU + Xavier가중치 초기화 방법'보다 'ReLU + He 가중치 초기화 방법'이 activation 결과가 고르게 분포되어 있음
'공부 > 딥러닝' 카테고리의 다른 글
[딥러닝] 7. CNN (0) | 2024.06.27 |
---|---|
[딥러닝] 6. 딥러닝 모델 학습의 문제점 pt.3 : 과적합 (0) | 2024.06.22 |
[딥러닝] 4. 딥러닝 모델 학습의 문제점 pt.1 : 최적화 알고리즘 (0) | 2024.06.10 |
[딥러닝] 3. 딥러닝 모델 구현 (선형 회귀, 비선형 회귀 모델 구현) (0) | 2024.06.08 |
[딥러닝] 2. Backpropagation의 학습 (0) | 2024.06.07 |
Comments