카테고리 없음

[밑바닥부터 시작하는 딥러닝]_optimizer(모멘텀, AdaGrad, RMSProp, Adam)

ROSEV 2021. 11. 28. 18:43

신경망 학습의 목적은 손실 함수의 값을 가능한 한 낮추는 매개변수를 찾는 것입니다. 이는 곧 매개변수의 최적값을 찾는 문제이며, 이러한 문제를 최적화(optimizer)라고 합니다. 하지만 신경망 최적화는 어려운 문제입니다.

 

매개변수 공간은 매우 넓고 복잡해서 최적의 솔루션은 쉽게 찾지 못하기 때문입니다. 그래서 순식간에 최솟값을 구하는 방법은 없습니다. 게다가 심층 신경망에서는 매개변수의 수가 엄청나게 많아져서 사태는 더 어려워집니다.

 

앞으로 다룰 것은 이러한 어려운 최적화 방법론에 대해서 다루고자 합니다.

 

최적화 방법론(optimizer) : 모멘텀

모멘텀은 '운동량'을 뜻하는 단어로 물리와 관계가 있는 개념입니다.

모멘텀 수식

W는 갱신할 가중치 매개변수, n은 학습률, n옆에 있는 것은 W에 대한 손실함수의 기울기입니다. v는 물리에서 말하는 속도에 해당합니다.

출처 : 수원대학교 한경훈교수님

 

class Momentum:
	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]

 

인스턴스 변수 v가 물체의 속도입니다. v는 초기화 때는 아무 값도 담지 않고, 대신 update()가 처음 호출될 때 매개변수와 같은 구조의 데이터를 딕셔너리 변수로 저장합니다. 나머지 부분은 위의 식을 코드로 옳긴 것입니다.

 

 

모멘텀의 갱신 경로는 공이 그릇 바닥을 구르듯 움직입니다. SGD와 비교하면 지그재그 정도가 덜한 것을 알 수 있씁니다. x축의 힘은 아주 작지만 방향은 변하지 않고 일정하게 가속하기 때문입니다.

 

거꾸로 y축의 힘은 크지만 위아래로 번갈아 받아서 상충하여 y축 방향의 속도는 안정적이지 않습니다. 전체적으로는 SGD에 비해 지그재그 움직임이 줄어든 모습을 알 수 있습니다.

 

최적화 방법론 : AdaGrad

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

 

이 학습률을 정하는 효과적 기술로 학습률 감소가 있습니다. 이는 학습을 진행하면서 학습률을 점차 줄여가는 방법입니다. 처음에는 크게 학습하다가 조금씩 작게 학습한다는 얘기로, 실제 신경망 학습에 자주 쓰입니다.

 

학습률을 서서히 낮추는 가장 간단한 방법은 매개변수 '전체'의 학습률 값을 일괄적으로 낮추는 것입니다. 이를 더욱 발전시킨 것이 AdaGrad입니다.

 

 

AdaGrad 수식

 

W는 갱신할 가중치 매개변수, h옆에있는 것은 W에 대한 손실 함수의 기울기, n은 학습률을 뜻합니다. 여기에서는 새로운 h라는 변수가 등장합니다. h는 기존 기울기 값을 제곱하여 계속 더해줍니다.

 

점동그라미기호는 행렬의 원소별 곱셈을 의미합니다. 매개변수를 갱신할 때 루트h에 대한 아래식처럼 학습률을 조정합니다.

 

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

 

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)

 

최적화 방법론 : RMSProp

RMSProp는 과거의 모든 기울기를 균일하게 더해가는 것이 아니라, 먼 과거의 기울기는 서서히 잊고 새로운 기울기 정보를 크게 반영합니다. 이를 자수이동평균이라 하여, 과거 기울기의 반영 규모를 기하급수적으로 감소시키는 방법입니다.

 

최적화 방법론 : Adam

모멘텀은 공이 그릇 바닥을 구르는 듯한 움직임을 보였습니다. AdaGrad는 매개변수의 원소마다 적응적으로 갱신 정도를 조정했습니다. 그럼 혹시 이 두 기법(Momentum, RMSProp)을 융합하면 어떻게 될까요? 이런 생각에서 출발한 기법이 바로 Adam입니다

 

Adam은 2015년도에 제안된 새로운 방법입니다. 그 이론은 다소 복잡하지만, 직관적으로는 모멘텀과 AdaGrad를 융합한 듯한 방법입니다. 이 두 방법의 이점을 조합했다면 매개변수 공간을 효율적으로 탐색해줄 것으로 기대해도 되겠습니다. 또, 하이퍼파라미터의 '편향 보정'이 진행된다는 점도 Adam의 특징입니다.

 

 

 

앞에서 많은 옵티마이저를 살펴보고 공부했습니다. 아래는 간단한 계보를 나타내었습니다. 

 

출처 : 수원대학교 한경훈교수님