최적화(Optimization)

 신경망 학습에서의 목표는 최적의 매개변수를 찾아 손실함수의 값을 낮추는 것이다. 그런데 이때 무작정 찾는 것은 불가능하다. 이때 우리들은 사용할 수 있는 몇가지 방법이 있는데 그 중 몇가지를 소개하고 효율적인 방법에 대해 찾아보겠다.

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

이전 포스트에서 다뤄봤던 경사하강법에 대해 기억하는가? 경사 하강법은 각각의 순간 기울기를 계산해 아주 조금씩 일정한 거리만큼 움직이는 방법으로 최솟값을 찾는 방식이었다. 

식은 기존의 방식과 동일하다.  


여기서 달라진 화살표는 W를 좌변으로 값을 갱신한다는 소리이다. 

그럼 이제 구현해보도록 하겠다. 

class SDG():
def __init__(self,lr=0.01):
self.lr = lr

def SDG(self,para,grads):
for key in para:
para[key] = para[key] -
self.lr * grads[key] 

이런식으로 구현하면 매우 간단하게 최솟값을 구할 수 있다.

2.Momentum(모멘텀)

SDG의 단점은 기울기가 어느 이상으로 줄어들면 학습률이 어떻든 매우 비효율적이 되는 경우가 존재한다. 이를 막기 위해 나온 방법중 하나는 모멘텀이다. 모멘텀의 수식은 다음과 같다. 

무언가 크게 바뀌지 않았다 그저 v라는 갱신되는 변수 하나만 추가되었다. 이 변수는 모멘텀이라는 말 그대로 속도를 의미한다. 기울기가 심한 곳에서는 더욱 빠르게 움직이는 의미로 sdg에 비해서 더욱 효율적으로 이동하는게 가능하다.

class Mon():
def __init__(self,lr=0.01,mone=0.09):
self.lr = lr
self.mone = mone
self.v =None

def Mon(self,para,grads):
if self.v is None:
self.v = {}
for key, val in para.items():
self.v[key] = np.zeros_like(val)

for key in para.keys():
self.v[key] =self.mone*self.v[key] - grads[key]*self.lr
para[key] = para[key] + self.v[key]

소스코드는 다음과 같다. 뭔가 많이 추가 된 것 같지만 실제로는 크게 어렵지 않다. 초깃값 세팅에 모멘텀 인스턴스 변수가 추가되었고 v라는 속도 변수가 추가되었다. 밑에 코드는 위의 식을 그대로 구현 한 것과 v가 초기화 된 상태라면 들어오는 para(변수값)에 맞춰서 딕셔너리 형태로 생성한다는 뜻이다. 

3. AdaGrad

학습률은 신경망에서 학습을 하는데 중요한 요소라고 이야기했다. 그럼 이 학습률을 조정할 수는 없을까? 라는 생각으로 나온 방법이 바로 AdaGrad이다. 수식은 다음과 같다.  

여기서 새로나오는 변수 h는 말 그대로 학습률을 조정하기 위한 것인데 루트h분의 1을 곱해주면서 많이 움직인 즉 크게 갱신된 변수는 학습률을 적은 방향으로 조정한다. 이를 통해 더욱 효율적인 학습을 진행 할 수 있다.

4. Adam 
Adam은 모멘텀과 AdaGrad를 모두 합친 알고리즘으로 효율적으로 움직인다. 복잡하므로 설명은 생략하도록 하겠다. 

이번 포스팅에서는 매개변수의 최솟값을 찾는 방법들을 알아봤다. 각각의 방법에는 장단점있지만 보통 SDG에 비해 나머지 3개의 방법이 더 빠르다고 알려져 있다. 그리고 각각 3개의 방법은 데이터셋에 따라 가장 적절한 방법이 있으므로 잘 선택하면 좋다.


댓글

이 블로그의 인기 게시물

MongoDB와 VScode 이용한 드라이빙app 개발 일지 (2022.4.10)

다양한 계층 구현을 통한 오차역전파법 구현하기(2)