Gradient Descent Method
0. 개념 이해
parameter x1, x2, x3 ...로 이루어진 함수 f(x1, x2, x3...)의 최대 혹은 최소값이 되는 x1, x2, x3...set을 구할때 쓰는 알고리즘입니다.
간단한 예로 아래와 같은 함수가 있다고 가정합시다. 여기서 우리는 P를 최소로 만들고 싶은데요
w1, w2가 각각 0일때 최소가 되는걸 개념적으로도 왼쪽 optimization plane에서도 확인하실 수 있으실 겁니다.
그렇다면 어떻게 해야 우리는 최소인 P로 가는 w1과 w2를 얻을 수 있을까요?
여기서 사용되는것이 바로 gradient descent method입니다.
P를 구성하는 w1과 w2의 각각 편미분한 기울기방향으로 현재 값에서 점점 빼가는 원리인데요
제일 간단한 y=x^2을 생각해 봤을때 최소인 y를 만드는 x값인 0으로 x를 옮기려면 양수일때 빼줘야하고 음수일때 더해주어야하죠?
이걸 생각해보면 y' = 2x에서 우리가 기울기인 2x를 빼준다고 할때 양수이면 양수를 빼줘서 숫자가 작아지고 음수이면 음수를 빼주니깐 숫자가 커져서 0에 도달하는걸 알 수 있습니다.
하지만 기울기를 바로 빼줄 경우에 우리는 최소점을 기준으로 진동하거나 혹은 발산해 버리는 경우가 생길 수 있는데 이를 막기 위해서 learning rate라는 alpha값을 도입합니다. 기울기의 방향은 유지하되 천천히 최소점에 도달하도록 하는 것이지요
아래 그림을 통해 더 자세히 살펴보실 수 있습니다. initial point w1,w2 = (10,-8)에서 시작을 하였는데요
점점 w1,w2가 원점을 향해서 또 그에 따라 P값은 0에 다다르는것을 확인하실 수 있습니다.
clc clear close all num = [1:1:500]; x0 = 10; y0 = -7; alpha = 0.01; x_cur = x0; y_cur = y0; z_cur = 0; z_cur_arr = []; x_cur_arr = []; y_cur_arr = []; for i = 1 : 500 x_cur = x_cur - alpha*2*x_cur; y_cur = y_cur - alpha*2*y_cur; z_cur = x_cur.^2 + y_cur.^2; z_cur_arr = [z_cur_arr, z_cur]; x_cur_arr = [x_cur_arr, x_cur]; y_cur_arr = [y_cur_arr, y_cur]; end figure(2); hold on; plot(num,z_cur_arr); title('P value') figure(3); hold on; plot(num, x_cur_arr); plot(num, y_cur_arr); title('weight values') legend('w1', 'w2'); |
1. 선형 시스템에 적용
Neural Network에 적용하기에 앞서서 선형 시스템에 적용해서 실제 gradient descent method를 이용해서 weight를 구할 수 있는지 확인해 봅시다.
우리가 복잡한 Neural Network구조를 사용하는 이유는 비선형성을 가진 모델을 모의하기 위해서 인데요
사실 선형 시스템을 그대로 모의하기위해서는 hidden layer나 activation function등이 필요가 없어지지요
아래 왼쪽사진과 같은 시스템을 우리의 w1, w2를 통해서 모의해봅시다.x1, x2는 input이고 z_ref는 우리가 원하는 출력이고, z_est는 현재 Network의 출력입니다
여기서 w1, w2가 2,3이 되는 것이 목표인데 그렇게 하기 위해서는 minimize되어야하는 P함수를 (z_ref - z_est)^2으로 삼아야합니다.
이거 P함수가 w1과 w2의 함수가 아닌것 같은데 어떻게 해야하나 싶으시죠?
아닌것 같이 보여도 z_est가 w1과 w2의 함수이기 때문에 P함수는 결국 w1, w2의 함수입니다.
따라서 여기서도 gradient descent method를 적용할 수 있습니다.
matlab code |
clc clear close all num = [1:1:2000]; alpha = 0.0001; j = 1;k = 1; x1 = 2; x2 = 2; w1_real = 2; w2_real = 3; z_ref = w1_real*x1 + w2_real*x2; w1_init = -10; w2_init = 4; w1 = w1_init; w2 = w2_init; z_cur = 0; z_cur_arr = []; z_ref_arr = []; w1_real_arr = []; w2_real_arr = []; w1_arr = []; w2_arr = []; for i = 1 : 2000
z_cur = w1*x1+w2*x2; z_cur_arr = [z_cur_arr, z_cur]; z_ref_arr = [z_ref_arr, z_ref]; w1_arr = [w1_arr, w1]; w2_arr = [w2_arr, w2]; w1_real_arr = [w1_real_arr, w1_real]; w2_real_arr = [w2_real_arr, w2_real]; P = (z_ref - z_cur)^2; dp_div_dw1 = 2*(z_ref - z_cur) * (-1) *x1; dp_div_dw2 = 2*(z_ref - z_cur) * (-1) *x2; w1 = w1 - alpha*dp_div_dw1; w2 = w2 - alpha*dp_div_dw2; end figure(1); hold on; plot(num, z_cur_arr); plot(num, z_ref_arr); legend('z est', 'z ref'); hold off; figure(2); hold on; plot(num, w1_real_arr,'--', 'LineWidth',2,'Color',[0.6 0 0]); plot(num, w2_real_arr,'--', 'LineWidth',2,'Color',[0 0.6 0]); plot(num, w1_arr, 'LineWidth',1,'Color',[0.6 0 0]); plot(num, w2_arr, 'LineWidth',1,'Color',[0 0.6 0]); legend('w1 real', 'w2 real','w1 est', 'w2 est'); hold off; |
분명 optimization function이 minimize되도록 z_ref값에 z_est가 도달하는것은 맞는데 어째 w1, w2는 참값인 2와 3에서 멀어지고 있죠?
왜 이런 현상이 발생했을까요?
정답은 optimization function이 minimize되는것이 목적이지 w1, w2는 아무렇게나 되어도 상관없는게 어디서의 함정이었습니다.
사실 입력함수 2,2에 대해서 상수를 각각 곱해서 10이 나오게 하는 조합은 많잖아요? 그중에 가장 가까웠던 하나가 걸린 것이지요
그렇다면 우리가 원하는 w1과 w2가 진짜 2,3이 되도록 하려면 어떻게 해야할까요?
정답은 입력 숫자를 계속 바꿔주면서 모든 입력에 대해서 똑같이 되도록 설정을 해 주어야하지요 여기서 x1, x2를 잘 바꿔주어야지 이것도 한쪽으로 bias를 줘서 바꿔주면 안됩니다.
따라서 여기서는 rand 함수를 사용하였습니다.
이번에는 w1, w2도 우리가 원하는 값(2,3)과 매우 유사하게 바뀌고 그에 따라서 z_est가 z_ref와 어떤 input에 대해서도 똑같이 따라가는게 확인되었죠?
|
clc clear close all %w1*x1 + w2*x2 = z에서 a*x1+ b*x2 = z_ref; %P = (z_ref - z)^2; %dP/dw1 = 2*(z_ref - z)*(-1)*x1; %dP/dw2 = 2*(z_ref - z)*(-1)*x2; num = [1:1:20000]; alpha = 0.0001; j = 1;k = 1; x1 = 2; x2 = 2; w1_real = 2; w2_real = 3; z_ref = w1_real*x1 + w2_real*x2; w1_init = -10; w2_init = 4; w1 = w1_init; w2 = w2_init; z_cur = 0; z_cur_arr = []; z_ref_arr = []; w1_real_arr = []; w2_real_arr = []; w1_arr = []; w2_arr = []; for i = 1 : 20000 if j >100
j = 0; k = k + 1; x1 = x1 + 10*(rand-0.5); x2 = x2 + 10*(rand-0.5); z_ref = w1_real*x1 + w2_real*x2;
end j = j + 1;
z_cur = w1*x1+w2*x2; z_cur_arr = [z_cur_arr, z_cur]; z_ref_arr = [z_ref_arr, z_ref]; w1_arr = [w1_arr, w1]; w2_arr = [w2_arr, w2]; w1_real_arr = [w1_real_arr, w1_real]; w2_real_arr = [w2_real_arr, w2_real]; P = (z_ref - z_cur)^2; dp_div_dw1 = 2*(z_ref - z_cur) * (-1) *x1; dp_div_dw2 = 2*(z_ref - z_cur) * (-1) *x2; w1 = w1 - alpha*dp_div_dw1; w2 = w2 - alpha*dp_div_dw2; end figure(1); hold on; plot(num, z_cur_arr); plot(num, z_ref_arr); legend('z est', 'z ref'); hold off; figure(2); hold on; plot(num, w1_real_arr,'--', 'LineWidth',2,'Color',[0.6 0 0]); plot(num, w2_real_arr,'--', 'LineWidth',2,'Color',[0 0.6 0]); plot(num, w1_arr, 'LineWidth',1,'Color',[0.6 0 0]); plot(num, w2_arr, 'LineWidth',1,'Color',[0 0.6 0]); legend('w1 real', 'w2 real','w1 est', 'w2 est'); hold off; |
이처럼 gradient descent method는 미분가능한 optimization function가 minimize혹은 maximize하게 만드는 weight들을 찾아주는데 효과적인 툴입니다.
하지만 기울기를 이용하기 때문에 local minimum에 빠질수도 있고 또 어떤 input을 넣어주느냐에 따라서 수렴여부가 매우 중요합니다.
'Robotics > Machine Learning' 카테고리의 다른 글
인공신경망 학습 방법 (0) | 2018.04.23 |
---|---|
인공신경망 파라미터 추정 알고리즘 (0) | 2018.04.19 |
인공신경망 원리 (1) | 2018.04.04 |
인공신경망 구조 (0) | 2018.04.04 |