Math/Numerical Analysis

[수치해석] 수치최적화 알고리즘2 (Adagrad, RMSProp, Adam)

frances._.sb 2022. 2. 11. 11:45
728x90

이 전에는 탐색 방향 기반 알고리즘에 대해 언급하였다.

탐색 방향 기반 알고리즘은 앞서 공부했다시피 학습률이 고정되어있으며, 스칼라 학습률에 의한 한계가 있다.

이러한 학습률 고정에 의한 한계를 극복하기 위해

 

1) 큰 학습률로 시작

2) 최적화 알고리즘을 통해 새로운 파라미터 추정치를 계산하고 이 추정치를 이용하여 손실함숫값을 계산

3) 새로운 추정치에 대한 손실함숫값이 기존의 손실함숫값보다 작다면 파라미터 추정치를 업데이트

4) 새로운 추정치에 대한 손실함숫값이 기존의 손실함숫값다 크면 업데이트를 하지 않고,

   학습률의 크기를 절반으로 줄인 후 기존 파라미터 값을 이용하여 다시 계산을 수행

 

스칼라 학습률에 의한 한계를 극복하기 위해

 

  단순히 미리 정한 상수 학습률을 곱하는 경우

  ≫ 탐색 방향에서 각 방향마다 크기의 불균형이 있을 때는 한쪽 방향에 치우침

  ≫ 추정된 최종 파라미터의 한쪽 방향은 변화량이 큰 반면 다른 방향은 변량이 적음

 

   → 각 방향별로 학습률을 차등해서 설정

 

을 가진 적응형 알고리즘이 생겨났다.

 

"즉, 변화량이 큰 파라미터는 이미 많이 변화했으니, 변화량이 적은 파라미터를 많이 변화시켜보자."

 

 

1. Adagrad

㉮ 초깃값을 설정하고 장기 누적 그래디언트 크기를 0으로 초기화

㉯ 전체 데이터를 임의로 섞는다.

㉰ 전체 데이터에서 개수가 m개인 부분집합 (배치, batch) 들을 만듭니다.

㉱ 각 부분집합마다 다음을 반복합니다.

- 부분집합으로 그래디언트를 현재위치에서 계산

- 장기 누적 그래디언트 크기를 계산하여 학습률 벡터를 정합니다.

- 탐색 방향을 설정합니다.

- 파라미터 추정치를 업데이트합니다.

㉲ 만들어진 부분집합을 모두 사용한 후 다시 ㉱를 Epoch번 반복합니다.

#adagrad
batch_size = 5
MaxEpochs = 2

epslion = 1.0
delta = 1E-7
r = np.zeros_like(w0)

paths = []
batch_loss = []

w0 = np.array([2.0,4.0]) #1)초깃값
print('Iter\tw_k\t\tgrad\t\tdw\t\tloss')
format_dict = {'float_kind' : lambda x: "%.2f" %x}
print('{:01d}-{:02d}\t{}'.format(1,0,
                                np.array2string(w0,
                                               formatter = format_dict)))
#2) 데이터 셔플링 : 생략

#알고리즘
for epoch in range(MaxEpochs): #5)MaxEpochs번 반복
    k = 0
    #3) 미니 배치 생성
    for x_batch,y_batch in generate_batches(batch_size,
                                            shuffled_x_train,
                                            shuffled_y_train):
        paths.append(w0)
        batch_loss.append(loss(w0,x_batch,y_batch))
        #4)-1 미니 배치에서 그래디언트 계산
        grad = loss_grad(w0,x_batch,y_batch)
        search_direction = -grad #4-2 탐색방향 설정
        #4)-3 학습률 설정
        r = r + grad * grad
        lr = epsilon / (delta + np.sqrt(r))
        dw = lr * search_direction #4)-4 파라미터 업데이트
        w0 = w0 +dw
        print('{:01d}-{:02d}\t{}\t{]\t{}\t{:5.4f}'.format(epoch+1,k+1,
                      np.array2string(w0,formatter=format_dict),
                      np.array2string(grad,formatter=format_dict),
                      np.array2string(dw,formatter=format_dict),
                      loss(w0,x_train,y_train)))
        k += 1

 

 

2. RMSProp (Root Mean Square Propagation)

㉮ 초깃값을 설정하고 장기 누적 그래디언트 크기를 0으로 초기화

㉯ 전체 데이터를 임의로 섞는다.

㉰ 전체 데이터에서 개수가 m개인 부분집합 (배치, batch) 들을 만듭니다.

㉱ 각 부분집합마다 다음을 반복합니다.

- 부분집합으로 그래디언트를 현재위치에서 계산

- 단기 누적 그래디언트 크기를 계산하여 학습률 벡터를 정합니다.

- 탐색 방향을 설정합니다.

- 파라미터 추정치를 업데이트합니다.

㉲ 만들어진 부분집합을 모두 사용한 후 다시 ㉱를 Epoch번 반복합니다.

#RMSProp
batch_size = 5
axEpochs = 2

epsilon = 0.25
delta = 1E-10
rho = 0.9
r - np.zeros_like(w0)

paths = []
batch_loss = []

w0 = np.array([2.0,4.0]) #1)초깃값
print('Iter\tw_k\t\tgrad\t\tdw\t\tloss')
format_dict = {'float_kind': lambda x: "%.2f" % x}
print('{:01d}-{:02d}\t{}'.format(1,0,
                                np.array2string(w0,
                                                formatter=format_dict)))

#2) 데이터 셔플링 : 생략
for epoch in range(MaxEpochs): #5)MaxEpochs번 반복
    k = 0
    #3) 미니 배치 생성
    for x_batch, y_batch in generate_batches(batch_size,
                                            shuffled_x_train,
                                            shuffled_y_train):
        paths.append(w0)
        batch_loss.append(loss(w0,x_batch,y_batch))
        #4)-1 미니 배치에서 그래디언트 계산
        grad = loss_grad(w0,x_batch,y_batch)
        search_direction = -grad #4)-2 탐색 방향 설정
        r = rho * r + (1. -rho) * grad * grad
        lr = epsilon / np.sqrt(delta + r)
        dw = lr * search_direction #4)-4 파라미터 업데이트
        w0 = w0+ dw
        print('{:01d}-{:02d}\t{}\t{}\t{}\t{:5.4f}'.format(epoch+1,k+1,
                                                         np.array2string(w0,formatter=format_dict),
                                                         np.array2string(grad,formatter=format_dict),
                                                         np.array2string(dw,formatter=format_dict),
                                                         loss(w0,x_train,y_train)))
        k+=1

 

 

3. Adam

㉮ 초깃값을 설정하고 단기 누적 그래디언트 크기를 0, 단기 누적 그래디언트 합을 0으로 초기화

㉯ 전체 데이터를 임의로 섞는다.

㉰ 전체 데이터에서 개수가 m개인 부분집합 (배치, batch) 들을 만듭니다.

㉱ 각 부분집합마다 다음을 반복합니다.

- 부분집합으로 그래디언트를 현재위치에서 계산

- 탐색 방향을 단기 누적 그래디언트 합으로 설정합니다.

- 단기 누적 그래디언트 크기를 계산하여 학습률 벡터를 정합니다.

- 파라미터 추정치를 업데이트합니다.

㉲ 만들어진 부분집합을 모두 사용한 후 다시 ㉱를 Epoch번 반복합니다.

728x90
반응형