Search
Duplicate

경사하강법

태그
기초수학

경사하강법

mai_03.pdf
4180.0KB

미분 (differentiation)

미분은 변수의 움직임에 따른 함수값의 변화를 측정하기 위한 도구로 최적화에서 제일 많이 사용하는 기법
최근엔 미분을 손으로 직접 계산하는 대신 컴퓨터가 계산해줄 수 있다
→ sybpy.diff 라이브러리 이용
import sympy as sym from sympy.abc import x sym.diff(sym.poly(s**2 + 2*x + 3), x)
Python
복사

미분을 어디에 쓸까?

미분은 함수 f 의 주어진 점 (x,f(x))(x, f(x)) 에서의 접선의 기울기를 구한다
한 점에서 접선의 기울기를 알면 어느 방향으로 점을 움직여야 함수값이 증가하는지 / 감소하는지 알 수 있다
증가시키고 싶다면, 미분값을 더하고,
감소시키고 싶다면, 미분값을 뺀다
미분값을 더하면 경사상승법 (gradient ascent) 이라하며, 함수의 극대값의 위치를 구할 때 사용한다
미분값을 빼면 경사하강법 (gradient descent) 이라하며, 함수의 극소값의 위치를 구할 때 사용한다
경사상승 / 경사하강 방법은 극값에 도달하면 움직임을 멈춘다

경사하강법 : 알고리즘

gradient : 미분을 계산하는 함수
init : 시작점
lr : 학습률
eps : 알고리즘 종료 조건
var = init grad = gradient(var) while(abs(grad) > eps): var = var - lr * grad grad = gradient(var) # 계속 미분값 업데이트
Python
복사
def func(val): fun = sym.poly(x**2 + 2*x + 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 = 1e-2, epsilon = 1e-5): cnt = 0 val = init_point diff, _ = func_gradient(fun, init_point) while np.abs(diff) > epsilon: val = val - lr_rate*diff diff, _ = func_gradient(fun, val) cnt += 1 print("함수: {}, 연산횟수: {}, 최소점: ({}, {})".format(fun(val)[1], cnt, val, fun(val)[0])) gradient_descent(fun*func, init_point*np.random.uniform(-2, 2))
Python
복사

변수가 벡터라면?

벡터가 입력인 다변수 함수의 경우 편미분 (parial differentiation) 을 사용한다
import sympy as sym from sympy.abc import x, y sym.diff(sym.poly(x**2 + 2*x*y + 3) + sym.cos(x + 2*y), x) # x 방향으로만 미분, y는 가만히
Python
복사
각 변수 별로 편미분을 계산한 그레디언트 (gradient) 벡터를 이용하여 경사하강 / 경사상승법에 사용할 수 있다
→ 일반적이 2차원에서 벡터에 적용되는 경사하강법과 똑같이 나타낼 수 있다
→ 그레디언트 벡터를 사용하여 주어진 함수의 극대점 또는 극소점으로 향하는 방향을 알 수가 있다

경사하강법 : 알고리즘

gradient : 그레디언트 벡터를 계산하는 함수
init : 시작점
lr : 학습률
eps : 알고리즘 종료 조건
var = init grad = gradient(var) while(norm(grad) > eps): # 경사하강법 알고리즘은 그대로 적용된다 # 그러나 벡터는 절대값 대신 노름(norm)을 계산해서 # 종료조건을 설정한다 var = var - lr * grad grad = gradient(var)
Python
복사