[딥러닝]/[밑바닥부터 시작하는 딥러닝]

밑바닥부터 시작하는 딥러닝 1 - 4 경사 하강법

딥러닝 도전기 2021. 6. 27. 16:11
이 전 포스팅에서 미분을 이용하여 매개변수의 최적값을 찾기 위해 손실 함수를 설정한다고 했습니다.
여기에서는 미분에 대한 이야기를 해보려 합니다.

수치미분, 해석적 미분, 편미분에 대하여 다루어 보고 경사하강법에 대해 소개하겠습니다.

 

  • 수치 미분

다음 식은 미분을 나타낸 식 입니다.

$\frac{df(x)}{dx} = \lim_{h→0}\frac{f(x+h)-f(x)}{h}$

여기에서 수치미분은 $h$를 아주 작은 값, 예컨데 $h = 10^{-4}$등의 값으로 설정한 후 직접 $\frac{f(x+h)-f(x)}{h}$ 계산을 진행하는 것을 의미합니다.

(이론적으로는 $h$값이 작으면 작을수록 좋지만, 컴퓨터의 계산 문제 때문에 일반적으로 $h=10^{-4}$를 이용하면 좋은 결과를 얻을 수 있다고 알려져 있습니다.)

 

구현 (전방 차분)

def numerical_diff(f, x):
    h = 10e-4
    return (f(x+h)-f(x))/h

 

구현 (중심 차분)

def numerical_diff(f, x):
    h = 10e-4
    return (f(x+h)-f(x-h))/2h
  • 해석적 미분

해석적 미분은 우리가 이미 알고있는 일반적인 미분 방식을 말합니다.

ex) $\frac{d}{dx}x^3 = 3x^2$

 

  • 편미분

편미분은 변수가 두 개 이상일 때 어느 한 변수에 대해서만 미분을 하는 것을 의미합니다.

$f(x, y) = 2x+y^2$일 때, x에 대한 편미분 $\frac{\partial{f(x,y)}}{\partial{x}} = 2$,

y에 대한 편미분  $\frac{\partial{f(x,y)}}{\partial{y}} = 2y$  입니다.

미분 할 변수 외의 나머지 모든 변수는 상수(고정된 점)으로 취급하는 것 입니다.

 

gradient (기울기)

다변수 함수의 기울기는 다음과 같이 표현됩니다.

$\nabla f(x, y, z) = <\frac{\partial{f(x,y,z)}}{\partial{x}}, \frac{\partial{f(x,y,z)}}{\partial{y}} , \frac{\partial{f(x,y,z)}}{\partial{z}}>$

위처럼 모든 변수의 편미분을 벡터로 정리한 것을 기울기(gradient) 라고 하고 $\nabla f(x,y,z)$는 델f 혹은 나블라f 라고 읽습니다.

 

  • 경사하강법

손실함수의 최솟값을 찾기 위하여 경사하강법을 사용합니다.

현 위치에서 기울어진 방향으로 일정 거리만큼 이동합니다. 다음 또 이동한 곳에서 기울기를 구하고, 그 방향으로 이동하기를 반복합니다. 이렇게 해서 함수의 값을 점차 줄이는 방법이 경사하강법 입니다.

 

경사법을 수식으로 나타내보면

$x_0 = x_0 -\eta\frac{\partial{f}}{\partial{x_0}}$

$x_1 = x_1 -\eta\frac{\partial{f}}{\partial{x_1}}$

여기서 $\eta$ 는 학습률이라고 합니다. 학습률은 한 번의 학습으로 얼마만큼 학습해야 할지, 즉 매개변수 값을 얼마나 갱신하느냐를 정하는 것입니다.

 

구현

import numpy as np

def numerical_gradient(f,x):
    h = 1e-4
    grad = np.zeros_like(x)
    
    for idx in range(x.size):
        tmp_val = x[idx]

        x[idx] = tmp_val + h
        fxh1 = f(x)

        x[idx] = tmp_val - h
        fxh2 = f(x)

        grad[idx] = (fxh1 - fxh2)/(2*h)
        x[idx] = tmp_val
    return grad


def gradient_decent(f, init_x, lr = 0.01, step_num = 100):
    x = init_x
    for i in range(step_num):
        grad = numerical_gradient(f,x)
        x -= lr*grad
    return x

def function_2(x):
    return x[0]**2+x[1]**2

init_x = np.array([-3.0, 4.0])
gradient_decent(function_2, init_x = init_x, lr = 0.1, step_num = 100)

 

 

 

반응형