미분 = 변화율의 극한(limit) !!
= 을 미분해보자.
h를 0으로 보내는 극한을 취해주면,
(x) =
구현 : sympy.diff
import sympy as sym
from sympy.abc import x
sys.diff(sym.poly(x**2 + 2*x + 3), x)
>>>> Poly(2*x _ 2, x, domain = 'zz')
미분은 함수 의 주어진 점 에서의 접선의 기울기를 구하는 것.
한 점에서 접선의 기울기를 알면 어느 방향으로 점을 움직여야 함수값이 증가하는지/감소하는지 알 수 있음.
경사하강법 : 알고리즘
var = init # 시작점
grad = gradient(var) # 미분값을 계산해주는 함수
while(abs(grad) > eps): # 미분값이 종료조건(eps)보다 작아지면 종료
var = var - lr * grad # 정해놓은 학습률로 미분 업데이트 속도를 조절
grad = gradient(var) # 업데이트
벡터 e의 i번째()에만 변화를 주는 단위벡터(벡터 e의 i번째 변화율만 계산할 수 있음.
ex)
x에 대한 편미분 -> y를 상수취급하고 미분을 함(x방향의 움직임만 보는 것)
위 식에 대한 편미분 구현 : sympy.diff
import sympy as sym
from sympy.abc import x, y
sys.diff(sym.poly(x**2 + 2*x*y + 3) + sym.cos(x + 2*y), x)
>>>> 2*x + 2*y - sin(x + 2*y)
각 변수별로 편미분을 계산한 그레디언트(gradient) 벡터를 이용하여 경사하강/경사상승법에 사용할 수 있음
미분 값(한 개) 대신 벡터 ( == nabla !!)를 사용하여 변수 을 동시에 업데이트 !!
경사하강법(그레디언트 벡터) : 알고리즘
var = init # 시작점
grad = gradient(var) # 미분값을 계산해주는 함수
while(norm(grad) > eps): # 미분값이 종료조건(eps)보다 작아지면 종료
var = var - lr * grad # 정해놓은 학습률로 미분 업데이트 속도를 조절
grad = gradient(var) # 업데이트
- = -> 😁
-> =
-> =
- 이처럼, Moore-Penrose 역행렬을 이용하면 y에 근접하는 을 찾을 수 있음(-노름을 최소화하는 계수 )
선형회귀의 목적식은 이고, 이를 최소화하는 를 찾아야 하므로 다음과 같은 그레디언트 벡터를 구해야 한다.
목적식을 로 미분 한 다음, 주어진 에서 미분값을 빼주면 최소점을 구할 수 있음
학습률 를 베타에 대한 편미분인 그레디언트 벡터를 곱한 값을 에서 빼주면 됨.
복잡해보이지만, 사실 를 계수 에 대해 미분한 결과인 만 곱해지는 것임.
for t in range(T): # 정해진 횟수가 종료조건
error = y - X @ beta # @ -> 행렬곱(numpy)
grad = - transpose(X) @ error # 그레디언트 벡터
beta = beta - lr * grad
항을 계산(grad)해서 를 업데이트.
** 경사하강법 알고리즘에선 학습률(lr)과 학습횟수가 중요한 하이퍼파라미터가 됨.
** 특히 선형회귀의 경우 목적식 은 회귀계수에 대해 볼록함수이기 때문에 알고리즘을 충분히 돌리면 수렴이 보장되지만, 비선형회귀 문제의 경우 목적식이 볼록하지 않을 수 있으므로 수렵이 항상 보장되지는 않음(특히 딥러닝의 경우🥲).
보충자료
- chain rule 설명
- 경사하강법 구현 및 보충설명