미분은 변수의 움직임에 따른 함수값의 변화를 측정하기 위한 도구로 최적화에서 제일 많이 사용하는 기법
※ 미분의 변화율은 극한(limit)으로 정의
그림으로 보면, 미분은 함수 의 주어진 점에서의 접선의 기울기를 구하는 것
python으로 미분
import sympy as sym #함수를 sumbol, 즉 기호로 인식
#sympy.diff 로 미분을 컴퓨터로 계산 가능
from sympy.abc import x
sym.diff(sym.poly(x**2 + x*2 + 3), x)
>> Poly(2*x + 2, x, domain = 'ZZ')
미분값이 주어졌을 때 어느 방향으로 움직어야 함수값이 증가 혹은 감소하는지를 알 수 있음
함수값을 증가시킬 경우 =>
함수값을 감소시킬 경우 =>
목적함수의 최대화를 위해 미분값을 더하면 경사상승법(gradient ascent)
![]()
목적함수의 최소화를 위해 미분값을 더하면 경사하강법(gradient descent)
![]()
※ 극값(최대,최소)에 도달하면, 즉 미분값이 0이 되면 업데이트가 종료
import numpy as np
import sympy as sym
from sympy.abc import x
def func(val):
func = sym.poly(x**2 + x*2 + 3)
return fun.subs(x,val), fun
def func_gradient(fun,val):
_, function = fun(val)
diff = sym.diff(function, x)
return diff.subs(x,val) diff
def gradient_descent(fun, init_point, lr_rate = 0.01, epsilon = 0.00001):
cnt = 0
val = init_point
diff, _ = func_gradient(fun, val)
while np.abs(diff) > epsilon:
val = val - lr_rate*diff
diff, _ = func_gradient(fun, val)
cnt +=1
print("함수: {fun(val)[1]}, 연산횟수: {cnt}, chlthwja: ({val}, {fun(val)[0]})"
gradient_descent(fun = func, init_point=np.random.uniform(-2,2))
2차원 Input일 경우
※ 는 i번째 값만 1이고 나머지는 0인 단위 벡터
※는 변수로 값을 미분하라는 표시
에 대해 편미분 =>
2차원 Input일 경우
※ : nabla
import numpy as np
import sympy as sym
from sympy.abc import x
def func(val):
x_, y_ = val
func = sym.poly(x**2 + 2*y**3)
return fun.subs(x,[x_, y_]), fun
def eval_(fun,val):
val_x, val_y = val
func_eval = fun.subs(x, val_x).subs(y,val_y)
return func_eval
def func_gradient(fun,val):
x_, y_ = val
_, function = fun(val) #func 함수
diff_x = sym.diff(function, x)
diff_y = sym.diff(function, y)
grad_vec = np.array([eval_(diff_x, [x_,y_]), eval_(diff_y, [x_,y_])])
return grad_vec, [diff_x, diff_y]
def gradient_descent(fun, init_point, lr_rate = 0.01, epsilon = 0.00001):
cnt = 0
val = init_point
diff, _ = func_gradient(fun, val)
while np.linalg.norm(diff) > epsilon:
val = val - lr_rate*diff
diff, _ = func_gradient(fun, val)
cnt +=1
print("함수: {fun(val)[1]}, 연산횟수: {cnt}, chlthwja: ({val}, {fun(val)[0]})"
pt = [np.random.uniform(-2,2), np.random.uniform(-2,2)]
gradient_descent(fun = func, init_point=pt)