본문 바로가기
프로그래밍 놀이터/머신러닝, AI, 딥러닝

[머신러닝] #6 학습 관련 기술들

by 돼지왕왕돼지 2018. 7. 8.

[머신러닝] #6 학습 관련 기술들


"Deep Learning from Scratch” 책을 보고 제가 필요한 내용만 정리한 내용입니다.

자세한 내용은 책을 구매해서 보세요~

Adagrad, Adam, adaptive learning rate, anisotropy function, batch norm, batch normalization, bayes' theorem, bayesian optimization, dropout, EMA, ensemble learning, exponential moving average, gradient vanishing, grid search, he 초기값, l2 법칙, learning rate decay, log scale, Momentum, optimization, overfitting, rmsprop, scale shift, SGD, sgd의 단점, tanh, validation data, weight decay, xavier 초기값, 가중치 감소, 가중치 제곱 법칙, 가중치의 초기값, 검증 데이터, 경사 하강법, 그리드 서치, 기울기 솟ㄹ, 뉴런 수, 대칭 함수, 드롭 아웃, 드롭아웃, 로그 스케일 지정, 매개변수 갱신, 매개변수 갱신 시 학습률, 매개변수 최적값, 매개변수의 기울기, 모멘텀, 모멘텀 계수, 무작위 샘플링, 방향에 따라 기울기가 달라지는 함수, 배치 정규화, 배치 정규화 계층, 배치 정규화 알고리즘, 배치 정규화 장점, 배치 크기, 범용 성능, 범용성, 베이즈 정리, 베이즈 최적화, 비등방성 함수, 사비에르 초기값, 손실함수 최소화 매개변수, 쌍곡선 함수, 앙상블 학습, 에폭, 오버피팅, 오버피팅 억제, 원점 대칭 함수, 은닉층 활성화값 분포, 자비에르 초기값, 적절한 하이퍼파라미터 값 찾기, 정확도, 지수이동평균, 초기값 0, 초기값 의존도, 최적화, 출력 평균 추론, 카이밍 히, 편향 보정, 하이퍼파라미터, 하이퍼파라미터 성능 평가, 하이퍼파라미터 최적화, 하이퍼파라미터 최적화 구현, 학습 관련 기술들, 학습률, 학습률 감소, 확대와 이동, 확률적 경사 하강법


6.1. 매개변수 갱신


-

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

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

안타깝게도 신경망 최적화를 굉장히 어렵다. 매개변수 공간은 매우 넓고 복잡해서 최적의 솔루션은 쉽게 못 찾기 때문이다.


우리는 지금까지 최적의 매개변수를 찾는 단서로 매개변수의 기울기(미분)을 시용했다.

매개변수의 기울기를 구해, 기울어진 방향으로 매개변수 값을 갱신하는 일을 몇 번 반복해서 점점 최적의 값에 다가갔다.

이것이 확률적 경사 하강법(SGD) 이란 단순한 방법이다.




6.1.1. 모험가 이야기


-

최적 매개변수를 탐색하는 것은 모험가가 눈을 가리고 어둠 속에서 가장 낮은 골짜기를 찾아 가는 것과 같다.




6.1.2. 확률적 경사 하강법(SGD)


-

Adagrad, Adam, adaptive learning rate, anisotropy function, batch norm, batch normalization, bayes' theorem, bayesian optimization, dropout, EMA, ensemble learning, exponential moving average, gradient vanishing, grid search, he 초기값, l2 법칙, learning rate decay, log scale, Momentum, optimization, overfitting, rmsprop, scale shift, SGD, sgd의 단점, tanh, validation data, weight decay, xavier 초기값, 가중치 감소, 가중치 제곱 법칙, 가중치의 초기값, 검증 데이터, 경사 하강법, 그리드 서치, 기울기 솟ㄹ, 뉴런 수, 대칭 함수, 드롭 아웃, 드롭아웃, 로그 스케일 지정, 매개변수 갱신, 매개변수 갱신 시 학습률, 매개변수 최적값, 매개변수의 기울기, 모멘텀, 모멘텀 계수, 무작위 샘플링, 방향에 따라 기울기가 달라지는 함수, 배치 정규화, 배치 정규화 계층, 배치 정규화 알고리즘, 배치 정규화 장점, 배치 크기, 범용 성능, 범용성, 베이즈 정리, 베이즈 최적화, 비등방성 함수, 사비에르 초기값, 손실함수 최소화 매개변수, 쌍곡선 함수, 앙상블 학습, 에폭, 오버피팅, 오버피팅 억제, 원점 대칭 함수, 은닉층 활성화값 분포, 자비에르 초기값, 적절한 하이퍼파라미터 값 찾기, 정확도, 지수이동평균, 초기값 0, 초기값 의존도, 최적화, 출력 평균 추론, 카이밍 히, 편향 보정, 하이퍼파라미터, 하이퍼파라미터 성능 평가, 하이퍼파라미터 최적화, 하이퍼파라미터 최적화 구현, 학습 관련 기술들, 학습률, 학습률 감소, 확대와 이동, 확률적 경사 하강법

W 는 갱신할 가중치 매개변수이고, G 는 Gradient, 알파는 학습률.

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


화살표는 우변의 값이 W 를 갱신한다는 의미이다.



-

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]



-

대부분의 딥러닝 프레임워크는 다양한 최적화 기법을 구현해 제공하며, 원하는 기법으로 쉽게 바꿀 수 있는 구조로 되어 있다.




6.1.3. SGD 의 단점


-

SGD 는 단순하고 구현도 쉽지만, 문제에 따라서 비효율적일 때가 있다.

SGD 의 단점은 비등방성(anisotropy)함수(방향에 따라 성질, 즉 기울기가 달라지는 함수)에서는 탐색 경로가 비효율적이라는 것이다.

SGD 의 이러한 단점을 개선해주는 모멘텀, AdaGrad, Adam 이라는 방법들이 있다.




6.1.4. 모멘텀


-

모멘텀(momentum)은 운동량을 뜻하는 단어이며, 이를 식으로 나타내면, 기울기 방향으로 힘을 받아 물체가 가속된다는 물리 법칙을 나타낸다.

v <- av - η dL/dW

W <- W + v


여기서 a 는 momentum 으로 0.9 등의 값으로 설정한다. (av 값은 물체가 아무런 힘을 받지 않을때 서서히 하강시키는 역할을 한다.), η 는 학습률이다.


class Momentum:

    def __init__(self, lr=0.01, momentum=0.9):

        self.lr = lr

        self.momentum = momentum

        self.v = None # velocity


    def update(self, params, grads):

        if self.v is None:

            self.v = { }

            for key, val in params.items():

                self.v[key] = np.zeros_lie(val)


        for key in params.keys():

            self.v[key] = self.momentum * self.v[key] - self.lr * grads[key]

            params[key] += self.v[key]



-

SGD 에서 기울기의 변화에 따라 지그재그로 춤추던 학습 그래프가, Momentum 에서는 공이 그릇 바닥을 구르듯 훨씬 적은 wave 를 만들면서 최저값을 찾아간다.




6.1.5. AdaGrad


-

신경망 학습에서 학습률 값이 너무 작으면 학습 시간이 너무 길어지고, 반대로 너무 크면 발산하여 학습이 제대로 이뤄지지 않는다.

이 학습률을 정하는 효과적 기술로 학습률 감소(learning rate decay)가 있다.

이는 학습을 진행하면서 학습률을 점차 줄여가는 방법이다.

처음에는 크게 학습하다가 조금씩 작게 학습한다는 얘기로, 실제 신경망 학습에 자주 쓰인다.



-

학습률을 서서히 낮추는 가장 간단한 방법은 매개변수 “전체”의 학습률 값을 일괄적으로 낮추는 것이다.

이를 발전시킨 것이 AdaGrad 이다. AdaGrad 는 ‘각각의’ 매개변수에 ‘맞춤형’ 값을 만들어 준다.


AdaGrad 는 개별 매개변수에 adaptive 학습률을 조정하면서 학습을 진행한다.

AdaGrad 의 갱신 방법은 수식으로 아래와 같다.

h <- h + dL/dW O dL/dW

W <- W - η * 1/h^0.5 * dL/dW


h 는 기존 기울기값을 제곱하여 계속 더해준다. ( O 은 행렬의 원소별 곱셈을 의미 )

매개변수를 갱신할 때 1 / h^0.5 을 곱해 학습률을 조정한다.

매개변수의 원소 중에서 많이 움직인(크게 갱신된) 원소는 학습률이 낮아진다는 뜻인데, 다시 말해 학습률 감소가 매개변수의 원소마다 다르게 적용됨을 뜻한다.



-

AdaGrad 는 과거의 기울기를 제곱하여 계속 더해간다. 그래서 학습을 진행할수록 갱신 강도가 약해진다.

실제로 무한히 계속 학습한다면 어느 순간 갱신량이 0이 되어 전혀 갱신되지 않게 된다.

이 문제를 개선한 기법이 RMSProp 이라는 방법이다.

RMSProp 은 과거의 모든 기울기를 균일하게 더해가는 것이 아니라, 먼 과거의 기울기는 서서히 잊고 새로운 기울기 정보를 크게 반영한다.

이를 지수이동평균(Exponential Moving Average, EMA)이라 하여, 과거 기울기의 반영 규모를 기하급수적으로 감소한다.



-

class 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) // divide by 0 막기




6.1.6. Adam


-

Momentum은 공이 그릇 바닥을 구르는 듯한 움직임을 보였다.

AdaGrad 는 매개변수의 원소마다 적응적으로 갱신 정도를 조정했다.

이 두 기법을 융합한 것이 Adam 이다.


Adam 은 2015년에 제안된 새로운 방법이다.

이론은 다소 복잡하지만 직관적으로는 모멘텀과 AdaGrad 를 융합한 듯한 방법이다.

또, 하이퍼파라미터의 “편향 보정” 이 진행된다는 점도 Adam 의 특징이다.

( 자세한 것은 논문을 봐야 한다... )



-

Adam 의 갱신 과정도 그릇 바닥을 구르듯 움직이지만, 기본 모멘텀에 비해 공의 좌우 흔들림이 적다.

이는 학습의 갱신 강도를 적응적으로 조정해서 얻는 혜택이다.



-

Adam 은 하이퍼파라미터를 3개 설정한다.

하나는 지금까지의 학습률, 나머지 두 개는 일차 모멘텀용 계수 베타1, 이차 모멘텀용 계수 베타2이다.

논문의 베타1은 0.9, 베타2는 0.999이며, 이 값이면 많은 경우에 좋은 결과를 얻을 수 있다고 한다.




6.1.7. 어느 갱신 방법을 이용할 것인가?


-

풀어야 할 문제가 무엇이냐에 따라 달라진다.

또, 학습률 등의 하이퍼파라마티를 어떻게 설정하느냐에 따라서도 결과가 바뀐다.


결론적으로 모든 문제에서 항상 뛰어난 기법이라는 것은 없다.

각자의 장단이 있어 잘 푸는 문제와 서툰 문제가 있다.



-

지금도 많은 연구에서 SGD 를 사용하고 있다.

모멘텀과 AdaGrad 도 시도해볼 만한 가치가 충분하다.

요즘에는 많은 사람들이 Adam 에 만족해하며 쓰는 듯 하다.




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


-

하이퍼파라미터인 학습률과 신경망의 구조(층 깊이) 등에 따라 결과가 다르지만,

일반적으로 SGD 보다는 다른 세 기법(Adam, AdaGrad, Momentum)이 빠르게 학습하고, 최종 정확도도 높게 나타나는 편이다.






6.2. 가중치의 초깃값


6.2.1. 초깃값을 0으로 하면?


-

오버피팅을 억제해 범용 성능을 높이는 테크닉으로 가중치 감소(weight decay) 가 있다.

가중치 감소는 간단히 말하자면 가중치 매개변수의 값이 작아지도록 학습하는 방법이다.

가중치 값을 작게 하여 오버피팅이 일어나지 않게 하는 것이다.



-

가중치를 작게 만들고 싶으면 초깃값도 최대한 작은 값에서 시작하는 것이 정공법이다.

그러나 0 부터 시작하는 것은 나쁜 아이디어이다.

실제로 가중치 초깃값을 0으로 하면 학습이 올바로 이뤄지지 않는다.

정확히는 가중치를 균일한 값으로 설정해서는 안 된다.

그 이유는 바로 오차역전파법에서 모든 가중치의 값이 똑같이 갱신되기 때문이다.

예를 들어 2층 신경망에서 첫 번째와 두 번째 층의 가중치가 0이면, 순전파 때는 입력층의 가중치가 0이기 때문에 두 번째 층의 뉴런에 모두 같은 값이 전달된다.

두 번째 층의 모든 뉴런에 같은 값이 입력된다는 것은 역전파 때 두 번째 층의 가중치가 모두 똑같이 갱신된다는 말이 된다.

그래서 가중치들은 같은 초깃값에서 시작하고 갱신을 거쳐도 여전히 같은 값을 유지하게 된다.

이는 가중치를 여러 개 갖는 의미를 사라지게 한다.

‘가중치가 고르게 되어버리는 상황’을 막으려면(정확히는 가중치의 대칭적인 구조를 무너뜨리려면) 초깃값을 무작위로 설정해야 한다.


지금까지 가중치의 초깃값은 0.01(표준편차) * np.random.randn(10, 100) 처럼 정규분포에서 생성되는 값을 사용했다.




6.2.2. 은닉층의 활성화값 분포


-

은닉층의 활성화값(활성화 함수의 출력 데이터)의 분포를 관찰하면 중요한 정보를 얻을 수 있다.

( 책에 있는 그래프를 참조하면 이해하기 좋다. )



-

시그모이드 함수는 출력이 작아지거나 커지면서 기울기가 0 에 다가간다. 

그래서 데이터가 큰 값 혹은 작은 값에 치우쳐 분포하게 되면 역전파의 기울기 값이 점점 작아지다가 사라진다.

이것이 기울기 소실(gradient vanishing)이라 알려진 문제이다.

층을 깊게 하는 딥러닝에서는 기울기 소실은 더 심각한 문제가 될 수 있다.


각 층에서 활성화값들이 같은 패턴을 보이는 것은 그것대로 문제이다.

뉴런을 여러 개 둔 의미가 없다는 의미이다.

그래서 활성화값들이 치우치면 “표현력을 제한”한다는 관점에서 문제가 된다.



-

각 층의 활성화값은 적당히 고루 분포되어야 한다.

층과 층 사이에 적당하게 다양한 데이터가 흐르게 해야 신경망 학습이 효율적으로 이뤄지기 때문이다.

반대로 치우친 데이터가 흐르면 기울기 소실이나 표현력 제한 문제에 빠져 학습이 잘 이줘지지 않는 경우가 생긴다.



-

사비에르 글로로트(Xavier Glorot) 와 요슈아 벤지오(Yoshua Bengio)의 논문에서 권장하는 가중치 초깃값인 일명 "Xavier 초기값” 를 쓰는 것도 권장된다.

현재 Xavier 초기값은 일반적인 딥러닝 프레임워크들이 표준적으로 이용하고 있다.

논문에서는 각 층의 활성화값들을 광범위하게 분포시킬 목적으로 가중치의 적절한 분포를 찾고자 했고, 앞 계층의 노드가 n개라면 표준편차가 1 / n^0.5 인 분포를 사용하면 된다는 결론을 이끌었다.


Xavier 초깃값을 사용하면 앞 층에 노드가 많을수록 대상 노드의 초기값으로 설정하는 가중치가 좁게 퍼진다.



-

Xavier 초기값을 사용했을 때 layer 를 통과하면서 그래프가 일그러지는 것은 sigmoid 함수 대신 tanh 함수(쌍곡선 함수)를 이용하면 개선된다.

실제로 tanh 함수를 이용하면 말끔한 종 모양으로 분포된다.

tanh 함수도 sigmoid 함수와 같은 S 자 모양 곡선 함수이다.

다만 tanh 함수가 원점(0,0)에서 대칭인 S곡선인 반면, sigmoid 함수는 (x, y) = (0, 0.5) 에서 대칭인 S 곡선이다.

활성화 함수용으로는 원점에서 대칭인 함수가 바람직하다고 알려져 있다.




6.2.3. ReLU 를 사용할 때의 가중치 초기값


-

Xavier 초기값은 활성화 함수가 선형인 것을 전제로 이끈 결과이다.

sigmoid 함수와 tanh 함수는 좌우 대칭이라 중앙 부근이 선형인 함수로 볼 수 있다.

그래서 Xavier 초기값이 적당하다.



-

반면, ReLU 를 이용할 때 ReLU 에 특화된 초기값을 이용하라고 권장한다.

이 특화된 초기값을 찾아낸 카이밍 히(Kaiming He)의 이름을 따 "He 초기값"이라 한다.

He 초기값은 앞 계층의 노드가 n 개일 때, 표준편차가 (2/n)^0.5 인 정규분포를 사용한다.

ReLU 는 음의 영역이 0이라서 더 넓게 분포시키기 위해 2배의 계수가 필요하다고 (직감적으로) 해석할 수 있다.



-

활성화값들이 작은 값이라는 것은 신경망에 작은 데이터가 흐른다는 것이다.

이는 역전파 때 가중치의 기울기 역시 작아진다는 뜻이다. ( 기울기 소실이 발생하기도 )

이는 실제로는 학습이 거의 이뤄지지 않음을 이야기한다.



-

활성화 함수로 ReLU 를 사용할 때는 He 초기값을,

sigmoid 나 tanh 등의 S 자 모양 곡선일 때는 Xavier 초기값을 사용하는 것이 좋다.




6.2.4. MNIST 데이터셋으로 본 가중치 초기값 비교


-

가중치 초기값은 신경망 학습에 아주 중요한 포인트이다.

가중치 초기값에 따라 신경망 학습의 성패가 갈리는 경우가 많다.





6.3. 배치 정규화


-

가중치의 초기값을 적절히 설정하면 각 층의 활성화값 분포가 적당히 퍼지면서 학습이 원활하게 수행된다.

각 층이 활성화를 적당히 퍼뜨리도록 ‘강제’ 할 수도 있는데,

이를 배치 정규화(Batch Normalization)이라 한다.




6.3.1. 배치 정규화 알고리즘


-

배치 정규화는 2015년에 제안된 방법이다.

배치 정규화는 아직 세상에 나온지 얼마 안 된 기법임에도 많은 연구자와 기술자가 즐겨 사용하고 있다.

실제로 기계학습 콘테스트의 결과를 보면 이 배치 정규화를 사용하여 뛰어난 결과를 달성한 예가 많다.


배치 정규화가 주목받는 이유는 다음과 같다.


1. 학습을 빨리 진행할 수 있다. (학습 속도 개선)

2. 초기값에 크게 의존하지 않는다. (골치 아픈 초기값 선택 장애여 안녕!)

3. 오버피팅을 억제한다 (드롭아웃 등의 필요성 감소)



-

배치 정규화의 기본 아이디어는 각 층에서의 활성화값이 적당히 분포되도록 조정하는 것이다.

데이터 분포를 정규화하는 ‘배치 정규화 계층(Batch Norm)’ 을 신경망에 삽입할 수 있다.

( Affine 과 Activation Function 사이에 넣는다. )


이는 학습 시 미니배치 단위로 정규화한다.

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

Adagrad, Adam, adaptive learning rate, anisotropy function, batch norm, batch normalization, bayes' theorem, bayesian optimization, dropout, EMA, ensemble learning, exponential moving average, gradient vanishing, grid search, he 초기값, l2 법칙, learning rate decay, log scale, Momentum, optimization, overfitting, rmsprop, scale shift, SGD, sgd의 단점, tanh, validation data, weight decay, xavier 초기값, 가중치 감소, 가중치 제곱 법칙, 가중치의 초기값, 검증 데이터, 경사 하강법, 그리드 서치, 기울기 솟ㄹ, 뉴런 수, 대칭 함수, 드롭 아웃, 드롭아웃, 로그 스케일 지정, 매개변수 갱신, 매개변수 갱신 시 학습률, 매개변수 최적값, 매개변수의 기울기, 모멘텀, 모멘텀 계수, 무작위 샘플링, 방향에 따라 기울기가 달라지는 함수, 배치 정규화, 배치 정규화 계층, 배치 정규화 알고리즘, 배치 정규화 장점, 배치 크기, 범용 성능, 범용성, 베이즈 정리, 베이즈 최적화, 비등방성 함수, 사비에르 초기값, 손실함수 최소화 매개변수, 쌍곡선 함수, 앙상블 학습, 에폭, 오버피팅, 오버피팅 억제, 원점 대칭 함수, 은닉층 활성화값 분포, 자비에르 초기값, 적절한 하이퍼파라미터 값 찾기, 정확도, 지수이동평균, 초기값 0, 초기값 의존도, 최적화, 출력 평균 추론, 카이밍 히, 편향 보정, 하이퍼파라미터, 하이퍼파라미터 성능 평가, 하이퍼파라미터 최적화, 하이퍼파라미터 최적화 구현, 학습 관련 기술들, 학습률, 학습률 감소, 확대와 이동, 확률적 경사 하강법



-

배치 정규화 계층을 활성화 함수의 앞(혹은 뒤)에 삽입함으로써 데이터 분포가 덜 치우치게 할 수 있다.

또, 배치 정규화 계층마다 이 정규화된 데이터에 고유한 확대(scale)과 이동(shift)변환을 수행한다.




6.3.2. 배치 정규화의 효과


-

대부분의 경우 배치 정규화를 사용할 때의 학습 진도가 빠르다.

그리고 배치 정규화를 이용하지 않는 경우엔 초기값이 잘 분포되어 있지 않으면 학습이 전혀 진행되지 않기도 한다.






6.4. 바른 학습을 위해


-

기계학습에서는 오버피팅이 문제가 되는 일이 많다.

오버피팅이란 신경망이 훈련 데이터에만 지나치게 적응되어 그 외의 데이터에는 제대로 대응하지 못하는 상태를 말한다.

기계학습은 범용 성능을 지향한다.

훈련 데이터에는 포함되지 않는, 아직 보지 못한 데이터가 주어져도 바르게 식별해내는 모델이 바람직하다.



6.4.1. 오버피팅


-

오버피팅은 주로 다음의 두 경우에 일어난다.


1. 매개변수가 많고 표현력이 높은 모델 ( 층 수가 많다. )

2. 훈련 데이터가 적음




6.4.2. 가중치 감소


-

오버피팅 억제용으로 예로부터 많이 이용해온 방법 중 하나는 가중치 감소(weight decay)라는 것이 있다.

이는 학습 과정에서 큰 가중치에 대해서는 그에 상응하는 큰 페널티를 부과하여 오버피팅을 억제하는 방법이다.

원래 오버피팅은 가중치 매개변수의 값이 커서 발생하는 경우가 많기 때문이다.



-

신경망 학습의 목적은 손실 함수의 값을 줄이는 것.

예를 들어 가중치의 제곱 법칙(L2 법칙)을 손실 함수에 더한다. 그러면 가중치가 커지는 것을 억제할 수 있다.


L2 법칙은 각 원소의 제곱들을 더한 것에 해당한다.

가중치가 있다면 L2 법칙에서는 (w1^2 + w2^2 + ... )^0.5 로 계산할 수 있다.

L2 법칙 외에 L1 법칙과 L무한대 법칙도 있다.

L1 법칙은 절댓값의 합 |w1| + |w2| + … 에 해당한다.

L무한대 법칙은 Max 법칙이라고도 하며, 각 원소의 절대값 중 가장 큰 것에 해당한다.

정규화 항으로 L2 법칙, L1 법칙, L무한대 법칙 중 어떤것도 사용할 수 있다.

각자 특징이 있다.



-

가중치 감소를 사용하면 training data 의 정확도는 줄어들지만, test data 와의 정확도 차도 줄어든다.




6.4.3. 드롭아웃


-

오버피팅을 억제하는 방식으로 손실 함수에 가중치의 L2 법칙을 더한 가중치 감소 방법이 있다.

이는 간단하게 구현할 수 있고, 어느 정도 지나친 학습을 억제할 수 있다.

그러나 신경망 모델이 복잡해지면 가중치 감소만으로는 대응하기 어려워진다.

이럴 때는 흔히 드롭아웃(Dropout)이란 기법을 이용한다.



-

드롭아웃은 뉴런을 임의로 삭제하면서 학습하는 방법이다.

훈련 때 은닉층의 뉴런을 무작위로 골라 삭제한다.

삭제된 뉴런은 신호를 전달하지 않게 된다.

훈련때는 데이터를 흘릴 때마다 삭제할 뉴런을 무작위로 선택하고, 시험 때는 모든 뉴런에 신호를 전달한다.

단, 시험 때는 각 뉴런의 출력에 훈련 때 삭제한 비율을 곱하여 출력한다.



-

class Droupout:

    def __init__(self, dropout_ratio=0.5):

        self.dropout_ratio = dropout_ratio

        self.mask = None


    def forward(self, x, train_flg=True):

        if train_flg:

            self.mask = np.random.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



-

드롭아웃을 사용하면 training data 의 정확도는 줄어들지만, test data 와의 정확도 차도 줄어든다.



-

기계학습에서는 앙상블 학습(ensemble learning)을 애용한다.

앙상블 학습은 개별적으로 학습시킨 여러 모델의 출력을 평균 내어 추론하는 방식이다.

신경망의 맥락에서 얘기하면 가령 같은 (혹은 비슷한) 구조의 네트워크 5개를 준비하여 따로따로 학습시키고, 시험 때는 그 5개 출력을 평균 내어 답하는 것이다.

앙상블 학습을 수행하면 신경망의 정확도가 몇% 정도 개선된다는 것이 실험적으로 알려져 있다.


앙상블 학습은 드롭아웃과 밀접하다.

드롭아웃이 학습 때 뉴런을 무작위로 삭제하는 행위를 매번 다른 모델을 학습시키는 것으로 해석할 수 있기 때문이다.

그리고 추론 때는 뉴런의 출력에 삭제한 비율(이를테면 0.5 등)을 곱함으로써 앙상블 학습에서 여러 모델의 평균을 내는 것과 같은 효과를 얻는 것이다.

즉, 드롭아웃은 앙상블 학습과 같은 효과를 (대략) 하나의 네트워크로 구현했다고 생각할 수 있다.





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


-

하이퍼파라미터는 각 층의 뉴런 수, 배치 크기, 매개변수 갱신 시의 학습률과 가중치 감소 등이다.

이러한 값을 적절히 설정하지 않으면 모델의 성능이 크게 떨어진다.

하이퍼파라미터의 값은 매우 중요하지만, 그 값을 결정하기까지는 일반적으로 많은 시행착오를 겪는다.




6.5.1. 검증 데이터


-

하이퍼파라미터의 성능을 평가할 때는 시험 데이터를 사용해서는 안 된다.

중요하지만 놓치기 쉬운 포인트이다.


그 이유는.. 시험 데이터를 사용하여 하이퍼파라미터를 조정하면 하이퍼파라마티 값이 시험 데이터에 오버피팅되기 때문이다.

하이퍼파라미터 값의 “좋음”을 시험 데이터로 확인하게 되므로 하이퍼파라미터의 값이 시험 데이터에만 적합하도록 조정된다는 것이다.

그러면 범용성이 떨어진다.



-

하이퍼파라미터를 조정할 때는 하이퍼파라미터 전용 확인 데이터가 필요하다.

이 조정용 데이터를 일반적으로 검증 데이터(validation data)라고 부른다.



-

훈련 데이터는 매개변수(가중치와 편향)의 학습에 이용하고, 검증 데이터는 하이퍼파라미터의 성능을 평가하는 데 이용한다.

시험 데이터는 범용 성능을 확인하기 위해서 마지막에 (이상적으로는 한번만) 이용한다.


훈련데이터 : 매개변수 학습

검증 데이터 : 하이퍼파라미터 성능 평가

시험 데이터 : 신경망의 범용 성능 평가



-

훈련데이터에서 검증 데이터를 얻는 가장 간단한 방법은 훈련 데이터 중 20% 정도를 검증 데이터로 분리하는 것이다.




6.5.2. 하이퍼파라미터 최적화


-

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

범위를 조금씩 줄이려면 우선 대략적인 범위를 설정하고 그 범위에서 무작위로 하이퍼파라미터 값을 골라내(샘플링) 후, 그 값으로 정확도를 평가한다.

정확도를 잘 살피면서 이 작업을 여러 번 반복해서 최적값 범위를 좁혀가는 것이다.



-

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

이는 최종 정확도에 미치는 영향력이 하이퍼 파라미터마다 다르기 때문이다.



-

하이퍼파라미터의 범위는 대략적으로 지정하는 것이 효과적이다.

실제로도 0.001에서 1,000 와 같이 10의 거듭제곱 단위로 범위를 지정한다.

이를 로그 스케일(log scale)로 지정한다고 한다.



-

하이퍼파라미터를 최적화할 때는 딥러닝 학습에는 오랜 시간(예컨대 며칠이나 몇 주 이상)이 걸린다는 점을 기억해야 한다.

따라서 나쁠 듯한 값은 일찍 포기하는 게 좋다.

학습을 위한 에폭을 작게 하여, 1회 평가에 걸리는 시간을 단축하는 것이 효과적이다.



-

0단게 : 하이퍼파라미터 값의 범위를 설정

1단계 : 설정된 범위에서 하이퍼파라미터의 값을 무작위로 추출

2단계 : 1단계에서 샘플링한 하이퍼파라미터 값을 사용하여 학습하고, 검증 데이터로 정확도를 평가(단, 에폭을 작게 설정)

3단계 : 1단계와 2단계를 특정 횟수(100회 등) 반복하여, 그 정확도의 결과를 보고 하이퍼파라미터의 범위를 좁힌다.



-

여기서 설명한 하이퍼파라미터 최적화 방법은 실용적인 방법이다.

하지만 과학이라기보다는 다분히 수행자의 “지혜”와 “직관”에 의존한다는 느낌이다.

더 세련된 기법을 원한다면 베이즈 최적화(Bayesian optimization)을 쓸 수 있다.

베이즈 최적화는 베이즈정리(Bayes’ theorem)를 중심으로 한 수학 이론을 구사하여 더 엄밀하고 효율적으로 최적화를 수행한다.




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


-

weight_decay = 10 ** np.random.uniform(-8, -4) // 10^-8 ~ 10^-4

lr = 10 ** np.random.uniform(-6, -2) // 10^-6 ~ 10^-2



-

하이퍼파라미터 최적화를 한 후 돌려보면 학습이 잘 진행되는 범위가 좁혀진다.

이 범위에서 범위를 또 좁혀서 수행한다.

특정 단계에서 최종 하이퍼파라미터 값을 하나 선택해서 진행한다.





6.6. 정리


-

매개변수 갱신 방법에는 확률적 경사 하강법(SGD) 외에도 모멘텀, AdaGrad, Adam 등이 있다.

가중치 초기값을 정하는 방법은 올바른 학습을 하는 데 매우 중요하다.

가중치의 초기값으로는 Xavier 초기값과 He 초기값이 효과적이다.

배치 정규화를 이용하면 학습을 빠르게 진행할 수 있으며, 초기값에 영향을 덜 받게 된다.

오버피팅을 억제하는 정규화 기술로는 가중치 감소와 드롭아웃이 있다.

하이퍼파라미터 값 탐색은 최적 값이 존재할 법한 범위를 점차 좁히면서 하는 것이 효과적이다.




댓글0