본문 바로가기
DATA Science/DeepLearing from scratch

딥러닝 학습 관련 기술들

by Rainbound-IT 2021. 5. 17.
반응형
가중치 매개변수의 최적값을 탐색하는 최적화방법
가중치 매개변수 초깃값
하이퍼파라미터 설정방법
가중치 감소, 드롭아웃등 정규화 방법
배치정규화
위와 같은걸 할 예정이다.

 

매개변수의 갱신

신경망 학습의 목적: 손실 함수의 값을 가능한 한 낮추는 매개변수를 찾는것

이것은 매개변수의 최적 값을 찾는 문제이며, 이러한 문제를 푸는것을 최적화 라고 한다.

 

여태까지 최적화를 확률적 경사 하강법(SGD)매개변수의 기울기를 구해서 기울어진 방향으로 매개변수값을 갱신했다.

이것과 다른방법을 알아보자

 

 

 

 

확률적 경사 하강법 SGD

SGD 수식

W는 갱신할 가중치 매개변수이고 dL/dW는 W에 대한 손실함수의 기울기이다.

η은 학습률인데 실제로는 0.01이나 0.001과 같은 값을 미리 정해서 사용한다.

←는 우변의 값으로 좌변의 값을 갱신한다는 뜻이다.

1
2
3
4
5
6
7
class SGD:
    def __init__(self, lr=0.01):
        self.lr = lr
        
    def update(self, params, grads):
        for key in params.keys():
            params[key] -= self.lr * grads[key]
cs

SGD를 구현 한것이다.

params와 grads는 가중치 매개변수와 기울기를 저장하고 있는 딕셔너리 변수이다.

 

 

 

SGD의 단점

위 식의 최솟값을 구하는 것을 생각해보자.

그걸 그림으로 그리면

3차원으로 표현하고(왼) 등고선으로 표현한것(오)
위 식을 기울기를 그린것

이걸 보면 기울기는 y축 방향은 크고, x축 방향은 작다는 것을 알 수 있다.

y축 방향은 가파른데 x축 방향은 완만한 것이다.

근데 최솟값이 되는 장소는 x,y =(0,0)이지만 그림에서보면 y=0이지만 x는 한장소만 가리키지 않는다.

여기다가 SGD를 적용해보면

SGD 최적화 경로

보면 지그재그로 가서 굉장히 비효융ㄹ적인것을 알수있다.

이것을 SGD의 단점인 비등방성(anisotrpy) 함수(방향에 따라 성질, 즉 여기에서는 기울기가 달라지는 함수)라고 한다.

이 단점을 대처하는 모멘텀, AdaGrad, Adam을 알아볼것이다.

 

 

모멘텀

마찬가지로 W는 갱신할 가중치 매개변수, dL/dW는 W에 대한 손실함수의 기울기, η는 학습률이다.

여기서 v라는 새로운변수가 나오는데 이것은 물리에서 말하는 속도이다.

이 av는 물체가 아무런 힘을 받지 않을 때 서서히 하강시키는 역할을 한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Momentum:
 
    """모멘텀 SGD"""
 
    def __init__(self, lr=0.01, momentum=0.9):
        self.lr = lr
        self.momentum = momentum
        self.v = None
        
    def update(self, params, grads):
        if self.v is None:
            self.v = {}
            for key, val in params.items():                                
                self.v[key] = np.zeros_like(val)
                
        for key in params.keys():
            self.v[key] = self.momentum*self.v[key] - self.lr*grads[key] 
            params[key] += self.v[key]
cs

이것을 구현하면 이처럼 된다.

momentum에 의한 최적화 갱신경로

단순히 변수하나 추가하니까 이렇게 되버린다.

그 이유는 모멘텀은 변하지 않는 방향으로 일정하게 가속하는데 

x축이 작지만 변하지 않아서 일정한 방향으로 움직이게 되는것이다.(y축은 일정하지 않다.)

 

 

AdaGrad

일반적으로 학습률을 정하는 기술은 합습률 감소가 있는데 학습을 진행하면서 학습률을 줄여가는 방법이다.

가장 효과적인 합습률을 낮추는 방법은 매개변수 전체의 학습률 값을 일괄적으로 낮추는 것이다.

이것을 발전시킨 것이 Adagrad인데 각각의 매개변수에 맞춤형 값을 만들어준다.

 

새로운 변수가 나오는데 h는 기존기울기 값을 제곱하여 계속 더해주는 값이다.

⊙는 행렬의 원소별 곱셈을 의미한다.

매개변수 갱신시 1/√h 을 곱해 학습률을 조정한다. 

매개변수의 원소중에서 많이 움직인(크게 갱신된) 원소는 학습률이 낮아진다는 뜻인데,

다시말해 학습률 감소가 매개변수 원소마다 다르게 적용된다는 것이다.

Adagrad는 과거의 기울기를 곱해서 더해가는데 진행할수록 갱신 강도가 약해진다.
그래서 어느순간 0이 되는데 이를 개선하여 RMSProp가 있는데 이것은 과거의 모든기울기를 균일하게 더해가는 것이 아니라, 먼 과거의 기울기는 서서히 잊고 새로운 기울기 정보를 크게 반영하는것이다.
이를 지수이동평균(Exponetial Moving Average, EMA)이라 한다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class AdaGrad:
 
    """AdaGrad"""
 
    def __init__(self, lr=0.01):
        self.lr = lr
        self.h = None
        
    def update(self, params, grads):
        if self.h is None:
            self.h = {}
            for key, val in params.items():
                self.h[key] = np.zeros_like(val)
            
        for key in params.keys():
            self.h[key] += grads[key] * grads[key]
            params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)
cs

구현한건데 마지막에 1e-7은 self.h[key]에 0이 있더라도 0으로 나누는것을 방지하기 위함이다.

y축방향은 기울기가 커서 처음에 크게 움직이지만 움직임에 비례해 큰폭으로 줄어들고 있다. 

Adam

 이기법은 모멘텀과 Adagrad를 융합한 방법이다.

모멘텀보다 좌우흔들림이 적다.

위 네가지 방법중 가장좋은것은 상황에 따라 다르다.

MNIST 데이터 셋으로 본 갱신 방법 비교

보면 SGD가 가장 느리지만 학습률과 신경망 구조에 따라 다르다.

그래도 일반적으로 sGD 보다 다른 세기법이 빠르게 학습하고 정확도도 높게 나온다.

 

 

가중치의 초깃값

가중치 감소 기법을 할건데 만약 초깃값이 0이면 모두 같은 값이 전달되서 안된다. 

 

은닉층의 활성화값 분포

가중치를 표준편차가 1인 정규분포로 초기화 할때의 각층의 활성화 값 분포

1과 0에 치우쳐 분포가 되어 있다.

이런 경우 역전파의 기울기 값이 점점 작아지다가 사라진다. (기울기소실, gradient vanishing)

 

가중치를 표준편차가 0.01인 정규분포로 초기화 할때의 각층의 활성화 값 분포

이 경우 0,1로 치우치진 않았지만 0.5인 값이 하나에 치우쳐 있다.

이러면 다수의 뉴런이 거의 같은 값을 두어서 여러개 둔 의미가 없어져 표현력을 제한한다.

 

이것을 해결하기위해 Xavier 초깃값을 사용하는데 

앞계층의 노드가 n개라면 표준편차가 1/√n 인 분포를 사용하면 된다는 것이다.

 

Xavier 초깃값을 이용한 각층의 활성화값 분포

각 층에 흐르는 데이터가 잘퍼져있어서 시그모이드 함수의 표현력도 제한받지 않고 학습이 효율적으로 될것같다.

 

ReLU를 사용할 때의 가중치 초깃값

Xavier 초깃값은 활성화 함수가 선형인것을 전제로 나온 결과이다.(sigmoid, tanh함수)

ReLU쓸땐 해당 함수에 특화되어 있는 초깃값을 사용해야한다.

이것을 He 초깃값이라 하는데 

 앞계층의 노드가 n개일때, 표준편차가 √(2/n)인 정규분포를 사용한다.(Xavier에 2를곱한것)

표준편차가 0.01인경우는 치중되 있고 He를 사용하면 고르게 분포되어있다.

그래서 활성화 함수로 ReLU를 사용할땐 He, sigmoid나 tanh같은 S모양 곡선인경우는 Xavier를 사용한다.

 

 

배치정규화

각 층이 활성화를 적당히 퍼뜨리도록 강제하는 방법

 

배치정규화 알고리즘

사용이유는 다음과 같다.

  • 학습 속도 개선
  • 초깃값에 의존 X
  • 오버피팅 억제

배치 정규화를 사용한 신경망의 예

중간에 미니배치를 단위로 두어 정규화 하는것을 볼수 있다.

구체적으로는 데이터 분포가 평균이 0, 분산이 1이 되도록 정규화 한다.

배치 정규화 수식

m개의 입력 데이터의 집합에 대해 평균 μB, 분산 σB^2을 구한다. 

그리고 이것을 평균이 0, 분산이 1이되게 정규화 한다.(수식의 세번째)

ε은 0으로 나누지 않기위해 놓는 값

또한 배치 정규화 계층마다 이 정규화된 데이터에 고유한 확대와 이동 변환을 수행한다.

γ은 확대, β는 이동을 뜻하는 변수이다.

배치 정규화 계산 그래프

 

배치 정규화의 효과

배치 정규화를 한것과 안한것의 차이를 알수 있다.

오버피팅을 억제하는 방법

오버피팅이 발생하는 경우는

  • 매개변수가 많고 표현력이 높은 모델
  • 훈련데이터가 적음

훈련데이터가 지나치게 정확한경우

 

가중치 감소

큰 가중치에 대해서는 그에 상응하는 큰 패널티를 부과하여 오버피팅을 억제하는 방법

 

가중치 제곱 노름(norm, L2노름)을 손실 함수에 더하는 것이다.

그러면 가중치가 커지는 것을 억제할수 있는데

가중치를 W라고 하면 L2노름에 따른 가중치 감소는 1/2λW^2 이되고, 이 1/2λW^2을 손실함수에 더한다.

여기서 λ는 정규화의 세기를 조절하는 하이퍼파라미터이다.

λ를 크게할수록 큰 가중치에 대한 패널티가 커진다.

 

가중치 감소는 모든 가중치 각각의 손실 함수에 1/2λW^2을 더한다. 

따라서 가중치의 기울기를 구하는 계산에서는 그 동안의 오차역전파법에 따른 결과에 정규화 항을 미분한 λW를 더한다.

위에 수행한 실험에서 λ = 0.1로 가중치 감소를 적용한다.

 

가중치 감소를 이용한 train, test 정확도

드롭 아웃

사용이유 : 신경망 모델이 복잡해지면 가중치 감소만으로는 대응하기 어려워지기 때문

방식 : 뉴런을 임의로 삭제하면서 학습하는 방법.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
 
class Dropout:
    def __init__(self, dropout_ratio = 0.5):
        self.dropout_ratio = dropout_ratio
        self.mask = None
 
    def forward(self, x, train_fig=True):
        if train_fig:
            self.mask - np.ranmdom.rand(*x, shape) > self.dropout_ratio
            return x* self.mask
 
        else:
            return x * (1.0 - self.dropout_ratio)
 
    def backward(self, dout):
        return dout * self.mask
cs

드롭아웃 구현

여기서 핵심은 훈련 시에는 순전파 때마다 self.mask에 삭제할 뉴런을 False로 표시한다는것이다.

self.mask는 x와 형상이 같은배열을 무작위로 생성하고, 그 값이 dropout_ratio보다 큰 원소만 True로 설정한다.

역전파때는 ReLU와 같다.

즉, 순전파때 신호를 통과시키는 뉴런은 역전파 때도 신호를 그대로 통과시키고,

순전파 때 통과시키지 않은 뉴런은 역전파 때도 신호를 차단한다.

 

왼쪽은 드롭아웃 없이, 오른쪽은 드롭아웃 적용

 

 보면 dropout을 적용하면 train과 test의 차이가 많이 줄었다는것을 볼수있다.

또한 정확도가 100%에 도달하지 않았다는 것을 알수 있다.

기계학습에선느 앙상블(ensemble learning)을 자주 사용한다. 
개별적인 학습시킨 여러 모델의 출력을 평균내어 출력하는 방식. (여러 모델을 사용)
ex.5개의 모델을 따로 학습시키고 5개의 출력을 평균내어 답하는것
이것은 드롭아웃과 비슷한데 무작위로 삭제하는 것이 매번 다른 모델을 학습시키는 것과 같다고 해석 

 

적절한 하이퍼파라미터 값 찾기

하이퍼파리미터에 대해 다시 살펴보면

각층의 뉴런수, 배치 크기, 매개변수 갱신시의 학습률과 가중치감소 등이다.( 모델링할 때 사용자가 직접 세팅해주는 값)

이 값을 적절하게 만드는 방법을 알아보자

 

검증 데이터(validation data)

하이퍼파라미터를 찾는데 시험데이터를 사용하면 오버피팅이 되어 범용성이 안좋게 되버린다.

그래서 하이퍼 파라미터 전용 확인 데이터가 필요한데 이것을 검증데이터라고 한다.

훈련데이터 : 매개변수 학습
검증데이터 : 하이퍼파라미터 성능 평가
시험데이터 : 신경망의 범용 성능 평가

예를 들어서 MNIST 데이터 셋에서 검증데이터를 얻는 가장 간단한 방법은

훈련데이터의 20% 정도를 검증 데이터로 먼저 분리하는것이다.

 

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
def shuffle_dataset(x, t):
    """데이터셋을 뒤섞는다.
    Parameters
    ----------
    x : 훈련 데이터
    t : 정답 레이블
    
    Returns
    -------
    x, t : 뒤섞은 훈련 데이터와 정답 레이블
    """
    permutation = np.random.permutation(x.shape[0])
    x = x[permutation,:] if x.ndim == 2 else x[permutation,:,:,:]
    t = t[permutation]
 
    return x, t
 
 
 
(x_train, t_train), (x_test, t_test) = load_mnist()
 
#훈련데이터를 뒤섞는다.
x_train, t_train = shuffle_dataset(x_train, t_train)
validation_rate = 0.20 #이것을 하이퍼 파라미터라고 할듯
validation_num = int(x_train.shape[0* validation_rate)
 
x_val = x_train[:validation_num]
t_val = t_train[:validation_num]
x_train = x_train[validation_num:]
t_train = t_train[validation_num:]
cs

 

이코드는 훈련데이터를 분리하기전에 입력 데이터와 정답 레이블을 뒤섞는다.

데이터 셋 안에 치우쳐져 있을지 모르기 때문이다.

 

 

하이퍼파라미터 최적화

하이퍼파라미터 최적화 할때 핵심은 최적값이 존재하는 범위를 조금씩 줄여간다는 것이다.

방법

대략적인 범위 선택 → 범위에서 무작위로 하이퍼파라미터 값 선택(샘플링) → 정확도 평가

신경망의 하이퍼파라미터 최적화에서는 그리드 서치 같은 규칙적인 탐색보다
무작위로 샘플링 하는 편이 좋은 결과를 낸다고 한다

 

  • 로그스케일 : 하이퍼파라미터의 범위를 대략적으로 지정하는것 ex.10^-3~10^3같은 10의 거듭제곱 단위

하이퍼파라미터를 최적화 하는 딥러닝 학습에는 오랜시간(며칠에서 몇주이상) 이 걸려서 쓸모없는값은 버리는게 좋다.

 

 

0단계 - 하이퍼파리머터 값의 범위를 설정한다.

 

1단계 - 

 

 

 

 

하이퍼파라미터 최적화 구현

 MNIST 데이터셋을 사용하여 하이퍼파라미터를 최적화 해보자

여기에서는 학습률과 가중치 감소의 세기를 조절하는 계수(가중치 감소 계수)를 탐색하는 문제를 풀어보자!

 

하이퍼파라미터의 검증은 그 값을 0.001 ~ 1000 사이 같은 로그 스케일 범위에서 무작위로 추출해 수행한다.

이 예시에서 가중치 감소 계수를 10^-8 ~ 10^-4, 학습률을 10^-6 ~ 10^-2범위 부터 시작한다.

실선은 검증데이터에 대한 정확도, 점선은 훈련 데이터에 대한 정확도

 

 

반응형

'DATA Science > DeepLearing from scratch' 카테고리의 다른 글

딥러닝  (0) 2021.05.23
CNN --- 합성곱 신경망  (0) 2021.05.20
오차역전파법  (0) 2021.05.14
신경망 학습 - 학습 알고리즘 구현  (0) 2021.05.13
신경망 학습  (2) 2021.05.12

댓글