๋ฐ์ํ
Gradient Descent (๊ฒฝ์ฌ ํ๊ฐ๋ฒ)
๊ฒฝ์ฌ ํ๊ฐ๋ฒ(Gradient Descent)์ ์ต์ ํ ์๊ณ ๋ฆฌ์ฆ ์ค ํ๋๋ก, ์ฃผ์ด์ง ํจ์์ ์ต์๊ฐ์ ์ฐพ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
์ด ์๊ณ ๋ฆฌ์ฆ์ ๋จธ์ ๋ฌ๋๊ณผ ๋ฅ ๋ฌ๋ ๋ชจ๋ธ์ ํ์ต ๊ณผ์ ์์ ์ฃผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
๊ฒฝ์ฌํ๊ฐ๋ฒ์ ์์ด๋์ด (The Idea Behind Gradient Descent)
- ์ฐ๋ฆฌ๋ ์ข ์ข ํจ์ ๐๋ฅผ ์ต๋ํ(๋๋ ์ต์ํ)ํด์ผ ํ ํ์๊ฐ ์์ ๊ฒ์ ๋๋ค.
- ์ฆ, ์ฐ๋ฆฌ๋ ๊ฐ๋ฅํ ๊ฐ์ฅ ์์(๋๋ ๊ฐ์ฅ ํฐ) ๊ฐ์ ์์ฑํ๋ ์ ๋ ฅ v๋ฅผ ์ฐพ์์ผ ํฉ๋๋ค.
- ๊ทธ๋ฆฌ๊ณ ์ด๋, ํจ์ ๐๋ฅผ ์ต๋ํ(๋๋ ์ต์ํ)ํด์ผ ํฉ๋๋ค. ์ฆ, ๊ฐ๋ฅํ ๊ฐ์ฅ ์์(๋๋ ๊ฐ์ฅ ํฐ) ๊ฐ์ ๋ง๋๋ ์ ๋ ฅ ๐ฃ๋ฅผ ์ฐพ์์ผ ํฉ๋๋ค.
- ์ด๊ฒ์ ๋ง์ ๋ฌธ์ ์์ ๋ฐ์ํ๋ ์ผ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ๋น์ฉ ํจ์(cost function)๋ฅผ ์ต์ํํ์ฌ ๋ชจ๋ธ์ ์ฑ๋ฅ์ ์ต์ ํํ๊ฑฐ๋,
- ์ด์ต ํจ์(profit function)๋ฅผ ์ต๋ํํ์ฌ ๋น์ฆ๋์ค์ ์์ต์ ๊ทน๋ํํ๋ ๋ฑ์ ๊ฒฝ์ฐ์ ํด๋นํฉ๋๋ค.
- ๊ทธ๋๋์ธํธ ∇๐(ํธ๋ฏธ๋ถ์ ๋ฒกํฐ)๋ ํจ์๊ฐ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๊ฐ์ํ๊ฑฐ๋ ์ฆ๊ฐํ๋ ์ ๋ ฅ ๋ฐฉํฅ์ ์ ๊ณตํฉ๋๋ค.
- ๊ทธ๋๋์ธํธ(๊ธฐ์ธ๊ธฐ) ๋ฒกํฐ์ธ ∇๐๋ ํจ์๊ฐ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๊ฐ์ํ๊ฑฐ๋ ์ฆ๊ฐํ๋ ๋ฐฉํฅ์ ๋ํ๋ ๋๋ค. ๊ฐ ์์๋ ํด๋น ๋ณ์์ ๋ํ ํธ๋ฏธ๋ถ ๊ฐ์ ๋๋ค.
- ํจ์๊ฐ ํ์ฌ ์์น์์ ๊ฐ์ฅ ๊ธ๊ฒฉํ๊ฒ ์ฆ๊ฐํ๋ ๋ฐฉํฅ์ ๋ฐ๋ฅด๋ฉด, ๊ทธ๋๋์ธํธ ๋ฒกํฐ๋ ์์ ๊ฐ์ ๋๋ค.
- ๋ฐ๋๋ก ํจ์๊ฐ ๊ฐ์ฅ ๊ธ๊ฒฉํ๊ฒ ๊ฐ์ํ๋ ๋ฐฉํฅ์ ๋ฐ๋ฅด๋ฉด, ๊ทธ๋๋์ธํธ ๋ฒกํฐ๋ ์์ ๊ฐ์ ๋๋ค.
๊ฒฝ์ฌ ํ๊ฐ๋ฒ์์๋ ํ์ฌ ์์น์์ ๊ทธ๋๋์ธํธ์ ๋ฐ๋ ๋ฐฉํฅ์ผ๋ก ์ด๋ํ์ฌ ํจ์๋ฅผ ์ต์ํ ํฉ๋๋ค.
- ๐์ ๊ตฌ๋ฐฐ๋ ์ต์ ๋๋ ์ต๋ 0 : ∇๐(๐ฏ)=0
- ํจ์ ๐์ ๊ทน์์ ๋๋ ๊ทน๋์ ์์ ๊ทธ๋๋์ธํธ(๊ธฐ์ธ๊ธฐ)๊ฐ 0์์ ์๋ฏธํฉ๋๋ค.
- ์ฆ, ํจ์๊ฐ ๊ทน์์ ๋๋ ๊ทน๋์ ์ ๋๋ฌํ๋ฉด ๊ทธ๋๋์ธํธ ๋ฒกํฐ์ ๋ชจ๋ ์์๊ฐ 0์ด ๋ฉ๋๋ค.
- ์ด๋ ํจ์๊ฐ ๊ทน์์ (์ต์๊ฐ)์ด๋ ๊ทน๋์ (์ต๋๊ฐ)์ ๋๋ฌํ์ ๋, ํจ์์ ๊ธฐ์ธ๊ธฐ๊ฐ ๋ ์ด์ ์ฆ๊ฐํ์ง ์๊ฑฐ๋ ๊ฐ์ํ์ง ์์์ ๋ํ๋ ๋๋ค.
- ๋ฐ๋ผ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ ์๊ณ ๋ฆฌ์ฆ์์ ์ด๋ฌํ ์ ์ ์ต์ ํ๋ ์ ์ด๋ผ๊ณ ๊ฐ์ฃผ๋ฉ๋๋ค.
Minimize or Maximize (์ต์ํ ๋๋ ์ต๋ํ)
ํจ์๋ฅผ ์ต์ํํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์์์ ์์์ ์ ์ ํํฉ๋๋ค.
- ๊ทธ๋๋์ธํธ๋ฅผ ๊ณ์ฐํฉ๋๋ค.
- ๊ทธ๋๋์ธํธ์ ๋ฐ๋ ๋ฐฉํฅ์ผ๋ก ์์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฆ ๋๋ค.
- ์๋ก์ด ์์์ ์ผ๋ก ๋ฐ๋ณตํฉ๋๋ค.
- ๊ทธ๋๋์ธํธ๋ ํจ์๋ฅผ ๊ฐ์ฅ ๋ง์ด ๊ฐ์์ํค๋ ๋ฐฉํฅ์ ๋ํ๋ ๋๋ค.
- ๋น์ทํ๊ฒ, ํจ์๋ฅผ ์ต๋ํํ๊ธฐ ์ํด ๊ทธ๋๋์ธํธ ๋ฐฉํฅ์ผ๋ก ์์ ๋จ๊ณ๋ฅผ ์ทจํ ์ ์์ต๋๋ค.
Using mathematical notation (์ํ์ ํ๊ธฐ๋ฒ ์ฌ์ฉํ๊ธฐ)
- with monotonic sequence(์์ด์ด ๋จ์กฐ๊ฐ์)ํ๋ ์ฑ์ง์ ์๋ฏธํฉ๋๋ค.
X๐ง+1 = X๐ง − ๐พ๐ง ∇ ๐(๐ฑ๐ง)
- x(n)์ ๐๋ฒ์งธ ๋ฐ๋ณต์์์ ํ์ฌ ์์น, γn ์ ํ์ต๋ฅ (learning rate),
- ∇ ๐(๐ฑ(๐ง))์ ํ์ฌ ์์น์์์ ํจ์ ๐ ์ ๊ทธ๋๋์ธํธ(๊ธฐ์ธ๊ธฐ)์ ๋๋ค.
- ์ด๋ฅผ ์ด์ฉํ์ฌ ๋ค์ ์์น์ธ ๐ฅ(๐+1)์ ๊ณ์ฐํฉ๋๋ค.
์ ์ ์์์ง๋ Sequence → Minimun์ ๋๋ฌ.. (์ธ์ ๊ฐ..?)
f(x0) ≥ f(x1)≥… ์ ๊ฐ์ด ํ์ฌ ์์น์์์ ํจ์ ๊ฐ์ด ๊ฐ ๋ฐ๋ณต์์ ์ ์ฐจ ๊ฐ์ํฉ๋๋ค.
์ฆ ์ด๋ ๊ฒฝ์ฌํ๊ฐ๋ฒ์ด ํจ์์ ์ต์๊ฐ์ ์ ์ง์ ์ผ๋ก ์๋ ดํจ์ ๋ณด์ฅํฉ๋๋ค.
- ๋ํ ์ฐ๋ฆฌ๋ ์ผ๋ฐ์ ์ผ๋ก ๊ฒฝ์ฌ ํ๊ฐ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ๋ค์์ ์ฐพ์ต๋๋ค
- ์์ค, ๋น์ฉ ๋๋ ์ค๋ฅ๋ฅผ ์ต์ํํ๋ ๊ฐ์ค์น(ํ๊ท, ์ ๊ฒฝ๋ง) ๋๋
- ํ๋ฅ ์ ์ต๋ํํ๋ Parameter(MLE: ์ต๋ ์ฐ๋ ์ถ์ )
- ๋ง์ฝ ์ ๋ ฅ์ด 2์ฐจ์์ธ ๊ฒฝ์ฐ (When input is two dimemsional)
- Gradient Descent(๊ฒฝ์ฌ ํ๊ฐ๋ฒ)์ "Zig-Zagging" ํน์ฑ
from collections import Counter
from linear_algebra import distance, vector_subtract, scalar_multiply
from functools import reduce
import math, random
- sum_of_squares ํจ์๋ฅผ ์ต์ํํ๋ ค๊ณ ํฉ๋๋ค.
def sum_of_squares(v):
"""v ๋ด ์์๋ค์ ์ ๊ณฑํฉ์ ๊ณ์ฐํฉ๋๋ค."""
return sum(v_i ** 2 for v_i in v)
- sum_of_squares๋ ํ์ด์ฌ ๋ฆฌ์คํธ๋ ๋ฐฐ์ด v ์์ ๊ฐ ์์๋ค์ ์ ๊ณฑ์ ๋ชจ๋ ๋ํ๋ ํจ์์ ๋๋ค.
- ์๋ฅผ ๋ค์ด, v๊ฐ [1, 2, 3]์ด๋ผ๋ฉด, ์ด ํจ์๋ (1^2 + 2^2 + 3^2 = 14)๋ฅผ ๋ฐํํ ๊ฒ.
def sum_of_squares_np(v):
"""v ๋ด ์์๋ค์ ์ ๊ณฑํฉ์ ๊ณ์ฐํฉ๋๋ค. - Numpy Version."""
return np.sum(v * v)
๊ทธ๋๋์ธํธ ์ถ์ (Estimating the Gradient)
f๊ฐ ํ ๋ณ์์ ํจ์๋ผ๋ฉด, ์ x์์์ ๋ํจ์๋ ์ฐ๋ฆฌ๊ฐ x๋ก ์์ฃผ ์์ ๋ณํ๋ฅผ ๋ง๋ค ๋ f(x)๊ฐ ์ด๋ป๊ฒ ๋ณํ๋์ง ์ธก์ ํฉ๋๋ค.
def difference_quotient(f, x, h):
# ํจ์ f์ x์์์ ์ฐจ๋ถ ๊ทผ์ฌ๊ฐ์ ๊ณ์ฐํฉ๋๋ค.
return (f(x + h) - f(x)) / h
- ์ฃผ์ด์ง ํจ์ f์ ๋ํด, ํน์ ์ x์์์ ๋ํจ์(๋ฏธ๋ถ๊ฐ)๋ฅผ ๊ทผ์ฌํ๋ ๋ฐฉ๋ฒ์ ๊ตฌํํฉ๋๋ค.
- ํจ์ f, ์ x, ๊ทธ๋ฆฌ๊ณ ์์ฃผ ์์ ๊ฐ h๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์, f์ x์์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ทผ์ฌํ
- ํจ์์ ์ ์์ ๋ฐ๋ผ, (f(x + h) - f(x)) / h ๊ณ์ฐ์ x์์ h๋งํผ ๋ณํํ์ ๋, ํจ์ f์ ์ถ๋ ฅ๊ฐ์ด ์ผ๋ง๋ ๋ณํ๋์ง๋ฅผ ์ธก์ ํฉ๋๋ค.
- ์ด๋ x์์ ํจ์ f์ ์ฆ์ ๋ณํ์จ์ด๋ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ทผ์ฌํ๋ ๊ฒ๊ณผ ๋์ผํฉ๋๋ค. h๊ฐ 0์ ๊ฐ๊น์์ง์๋ก, ์ด ๊ทผ์ฌ๊ฐ์ f์ x์์์ ์ค์ ๋ํจ์ ๊ฐ์ ๊ฐ๊น์์ง๋๋ค.
- ๋ํจ์๋ ํจ์์ ๋ณํ์จ์ ๋ํ๋ด๋ฉฐ, ํจ์ ๊ทธ๋ํ ์์ ํน์ ์ ์์์ ์ ์ ์ ๊ธฐ์ธ๊ธฐ์ ํด๋นํฉ๋๋ค.
def plot_estimated_derivative():
# ์ค์ ํจ์ ์ ์
def square(x):
"""x์ ์ ๊ณฑ์ ๋ฐํ"""
return x * x
# ์ค์ ๋ํจ์(๋ฏธ๋ถ๊ฐ) ์ ์
def derivative(x):
"""square ํจ์์ ๋ํจ์์ธ 2x๋ฅผ ๋ฐํ"""
return 2 * x
# ๊ทผ์ฌ ๋ํจ์ ๊ณ์ฐ์ ์ํ ๋๋ค ํจ์
derivative_estimate = lambda x: difference_quotient(square, x, h=10)
# ์ค์ ๋ํจ์์ ๊ทผ์ฌ ๋ํจ์๋ฅผ ๊ทธ๋ํ๋ก ๋น๊ต
import matplotlib.pyplot as plt
x = range(-10, 10)
# ์ค์ ๋ํจ์ ๊ทธ๋ํ (๋นจ๊ฐ์ x๋ก ํ์)
plt.plot(x, list(map(derivative, x)), 'rx', label='Actual')
# ๊ทผ์ฌ ๋ํจ์ ๊ทธ๋ํ (ํ๋์ +๋ก ํ์)
plt.plot(x, list(map(derivative_estimate, x)), 'b+', label='Estimate')
# ๋ฒ๋ก ์์น ์ค์ (9๋ ์๋จ ์ค์์ ์๋ฏธ)
plt.legend(loc=9)
plt.title('Actual vs Estimate')
plt.show()
- square ํจ์๋ ์ ๋ ฅ๊ฐ์ ์ ๊ณฑ์ ๋ฐํํ๋ฉฐ, ์ด ํจ์์ ์ค์ ๋ํจ์๋ 2x์ ๋๋ค.
- ๊ทผ์ฌ ๋ํจ์๋ difference_quotient ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ณ์ฐ๋๋ฉฐ, ์ฌ๊ธฐ์ h๋ ๊ทผ์ฌ ๊ณ์ฐ์ ์ฌ์ฉ๋๋ ๋งค์ฐ ์์ ๊ฐ์ ๋๋ค.
%matplotlib inline
plot_estimated_derivative()
- ์๋ ๋ฏธ๋ถ์ ๊ทธ๋ผ๋ฐ์ด์ ์ ์ฌ๋ฐ๋ฅด๊ฒ ๊ณ์ฐํฉ๋๋ค. (automatic differentiation computes the gradient correctly)
!pip install autograd
# autograd ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์๋ ๋ฏธ๋ถ์ ์ํํ๋ ์์ ์
๋๋ค.
import autograd.numpy as np
from autograd import grad
# f๋ผ๋ ํจ์๋ฅผ ์ ์ํฉ๋๋ค. ์ด ํจ์๋ ์
๋ ฅ x์ ๋ํด x^2์ ๊ฐ์ ๋ฐํํฉ๋๋ค.
def f(x):
return x * x
# f ํจ์์ ๋ํจ์(๋ฏธ๋ถ ํจ์)๋ฅผ ์๋์ผ๋ก ์์ฑํฉ๋๋ค.
df_dx = grad(f)
# ์์ฑ๋ ๋ํจ์๋ฅผ ์ด์ฉํ์ฌ x=5.0์ผ ๋์ ๋ํจ์ ๊ฐ(๋ฏธ๋ถ ๊ฐ)์ ๊ณ์ฐํ๊ณ ์ถ๋ ฅํฉ๋๋ค.
# f(x) = x^2์ ๋ํจ์๋ 2x์ด๋ฏ๋ก, x=5์ผ ๋ ๋ํจ์์ ๊ฐ์ 10์
๋๋ค.
print(df_dx(5.0))
# ์๊ทธ๋ชจ์ด๋ ํจ์๋ฅผ ์ ์ํฉ๋๋ค. ์๊ทธ๋ชจ์ด๋ ํจ์๋ ์ผ๋ฐ์ ์ผ๋ก
# ๋จธ์ ๋ฌ๋๊ณผ ๋ฅ๋ฌ๋์์ ํ์ฑํ ํจ์๋ก ๋ง์ด ์ฌ์ฉ๋ฉ๋๋ค.
def sigmoid(x):
return 1./(1. + np.exp(-x))
# ์๊ทธ๋ชจ์ด๋ ํจ์์ ๋ํจ์๋ฅผ ์๋์ผ๋ก ์์ฑํฉ๋๋ค.
dsigmoid_dx = grad(sigmoid)
# ์์ฑ๋ ๋ํจ์๋ฅผ ์ด์ฉํ์ฌ x=0์ผ ๋์ ๋ํจ์ ๊ฐ(๋ฏธ๋ถ ๊ฐ)์ ๊ณ์ฐํ๊ณ ์ถ๋ ฅํฉ๋๋ค.
# ์๊ทธ๋ชจ์ด๋ ํจ์์ ๋ฏธ๋ถ ๊ฐ์ sigmoid(x) * (1 - sigmoid(x))์ด๊ณ ,
# x=0์ผ ๋, ์ด ๊ฐ์ 0.25์
๋๋ค.
print(dsigmoid_dx(0.))
# ์๊ทธ๋ชจ์ด๋ ํจ์์ x=0์ผ ๋์ ํจ์ ๊ฐ ์์ฒด๋ฅผ ๊ณ์ฐํ๊ณ ์ถ๋ ฅํฉ๋๋ค.
# ์๊ทธ๋ชจ์ด๋ ํจ์๋ x=0์์ 0.5์ ๊ฐ์ ๊ฐ์ง๋๋ค.
print(sigmoid(0))
10.0
0.25
0.5
import autograd.numpy as np
from autograd import grad
# ํจ์ ์ ์: h(x, y) = x^2 + y
def h(x, y):
return x**2 + y
# x์ ๋ํ h์ ํธ๋ฏธ๋ถ ํจ์ ์์ฑ
dh_dx = grad(h, argnum=0)
# y์ ๋ํ h์ ํธ๋ฏธ๋ถ ํจ์ ์์ฑ
dh_dy = grad(h, argnum=1)
# x=2, y=2์์์ ํธ๋ฏธ๋ถ ๊ฐ ๊ณ์ฐ ๋ฐ ๋ฐฐ์ด๋ก ๋ฐํ
np.array([dh_dx(2., 2.), dh_dy(2., 2.)])
array([4., 1.])
- ์๋ ๋ฏธ๋ถ์ ์ฌ์ฉํ์ฌ x=0.5์์ f(x) = exp(2x) / (1 + sin(x^2))
ํจ์๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ผ๋ จ์ ๊ธฐ๋ณธ ์ฐ์ฐ์ผ๋ก ๋ถํดํ ์ ์์ต๋๋ค:
Step 1: Let z1 = 2x
Step 2: Let z2 = exp(z1)
Step 3: Let z3 = x^2
Step 4: Let z4 = sin(z3)
Step 5: Let z5 = 1 + z4
Step 6: Let z6 = z2 / z5
๋ค์ ๊ฐ ๋จ๊ณ์์ x์ ๋ํ ํจ์์ ๊ทธ ๋ํจ์์ ๊ฐ์ ์ถ์ ํฉ๋๋ค.
๋จผ์ ๊ทธ ์์ฒด์ ๋ํ ์ถ๋ ฅ์ ๋ํจ์๋ฅผ 1๋ก ์ค์ ํ ๋ค์ ์ฐ์๋ฒ์น์ ์ฌ์ฉํ์ฌ
x์ ๋ํ ๊ฐ ์ค๊ฐ๋ณ์์ ๋ํจ์๋ฅผ ๊ณ์ฐํฉ๋๋ค.
dz1/dx = 2
dz2/dx = dz1/dx * exp(z1)
dz3/dx = 2x
dz4/dx = cos(z3) * dz3/dx
dz5/dx = dz4/dx
dz6/dx = (dz2/dx * z5 - z2 * dz5/dx) / z5^2
Numerical gradient
- f๊ฐ ๋ง์ ๋ณ์์ ํจ์์ผ ๋, f๋ ์ฌ๋ฌ ๊ฐ์ ํธ๋ฏธ๋ถ์ ๊ฐ์ง๋ฉฐ, ๊ฐ๊ฐ์ ์ ๋ ฅ ๋ณ์ ์ค ํ๋์์ ์์ ๋ณํ๋ฅผ ๋ง๋ค ๋ f๊ฐ ์ด๋ป๊ฒ ๋ณํ๋์ง ๋ํ๋ ๋๋ค.
- ์ฐ๋ฆฌ๋ ๋ค๋ฅธ ๋ณ์๋ค์ ๊ณ ์ ํ ์ฑ๋ก i๋ฒ์งธ ๋ณ์๋ง์ ํจ์๋ก ์ทจ๊ธํ์ฌ i๋ฒ์งธ ํธ๋ฏธ๋ถ์ ๊ณ์ฐํฉ๋๋ค.
def partial_difference_quotient(f, v, i, h):
# ์ฃผ์ด์ง ํจ์ f์ i๋ฒ์งธ ๋ณ์์ ๋ํ ์ค์ ์ฐจ๋ถ๋ฒ์ ์ฌ์ฉํ์ฌ ํธ๋ฏธ๋ถ์ ๊ทผ์ฌํ๋ ํจ์
# v์์ i๋ฒ์งธ ๋ณ์์๋ง h๋ฅผ ๋ํฉ๋๋ค.
w = [v_j + (h if j == i else 0)
for j, v_j in enumerate(v)]
# w์ v์์์ ํจ์ ๊ฐ์ ์ฐจ์ด๋ฅผ h๋ก ๋๋์ด ํธ๋ฏธ๋ถ์ ๊ทผ์ฌํฉ๋๋ค.
return (f(w) - f(v)) / h
- ํจ์ f์ i๋ฒ์งธ ๋ณ์์ ๋ํ ํธ๋ฏธ๋ถ์ ๊ทผ์ฌํ๋ ์ค์ ์ฐจ๋ถ๋ฒ์ ์ฌ์ฉํฉ๋๋ค.
- ๐ฃ์์์ i๋ฒ์งธ ๋ณ์์๋ง ์์ ๋ณํ h๋ฅผ ์ถ๊ฐํ w๋ฅผ ๋ง๋ญ๋๋ค.
- w์ v์์์ ํจ์ ๊ฐ์ ์ฐจ์ด๋ฅผ h๋ก ๋๋์ด ํธ๋ฏธ๋ถ์ ๊ทผ์ฌํฉ๋๋ค.
def estimate_gradient(f, v, h=0.00001):
# ์ฃผ์ด์ง ํจ์ f์ ๊ทธ๋๋์ธํธ(๊ธฐ์ธ๊ธฐ)๋ฅผ ์ค์ ์ฐจ๋ถ๋ฒ์ ์ฌ์ฉํ์ฌ ๊ทผ์ฌํ๋ ํจ์
# ๊ฐ ๋ณ์์ ๋ํด partial_difference_quotient ํจ์(์ค์ ์ฐจ๋ถ๋ฒ)๋ฅผ ์ฌ์ฉํ์ฌ ๊ทธ๋๋์ธํธ๋ฅผ ๊ณ์ฐ.
return [partial_difference_quotient(f, v, i, h)
for i, _ in enumerate(v)]
estimate_gradient(sum_of_squares, [1,1,1])
2.00001000001393, 2.00001000001393, 2.00001000001393]
import numpy as np
def estimate_gradient_np(f, v, h=0.00001):
# f: ๋ฏธ๋ถํ๊ณ ์ ํ๋ ๋ค๋ณ์ ํจ์
# v: ํจ์ f์ ๋ํ ์
๋ ฅ ๋ฒกํฐ
# h: ๋ฏธ๋ถ ๊ณ์ฐ์ ์ํ ์์ฃผ ์์ ๊ฐ, ๊ธฐ๋ณธ๊ฐ์ 0.00001
# np.eye(v.shape[0])๋ v์ ์ฐจ์์ ๋ง๋ ๋จ์ํ๋ ฌ์ ์์ฑํฉ๋๋ค.
# v + h * np.eye(v.shape[0])๋ ๊ฐ ๋ณ์์ ๋ํด h๋งํผ ์ฆ๊ฐ์ํจ ์๋ก์ด ๋ฒกํฐ๋ค์ ์์ฑํฉ๋๋ค.
# np.apply_along_axis๋ ์์ฑ๋ ๊ฐ ๋ฒกํฐ์ ๋ํด ํจ์ f๋ฅผ ์ ์ฉํฉ๋๋ค.
gradients = np.apply_along_axis(f, 1, v + h * np.eye(v.shape[0])) - f(v)
# ๊ณ์ฐ๋ ์ฐจ์ด๋ฅผ h๋ก ๋๋์ด ๊ฐ ๋ณ์์ ๋ํ ํจ์ f์ ๊ทธ๋๋์ธํธ๋ฅผ ์ถ์ ํฉ๋๋ค.
return gradients / h
v + h * np.eye(v.shape[0]) → Numpy Broadcasting (v1+h …. vn)
estimate_gradient_np(lambda v: np.sum(v * v), np.array([1.,1.,1]))
# Result: array([2.00001, 2.00001, 2.00001])
- ๋จ์ํ๋ ฌ์ ์ฌ์ฉ: np.eye(v.shape[0])์ ํตํด ์์ฑ๋ ๋จ์ํ๋ ฌ์, ๊ฐ ๋ณ์์ ๋ ๋ฆฝ์ ์ผ๋ก h๋งํผ์ ๋ณํ๋ฅผ ์ฃผ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ ๊ฒ ํจ์ผ๋ก์จ, ๊ฐ ๋ณ์์ ๋ํ ํจ์์ ๋ณํ์จ(๋ฏธ๋ถ๊ณ์)์ ๋ ๋ฆฝ์ ์ผ๋ก ๊ณ์ฐํ ์ ์์ต๋๋ค.
- ํจ์ ์ ์ฉ๊ณผ ๊ทธ๋๋์ธํธ ๊ณ์ฐ: np.apply_along_axis ํจ์๋ ๋ณํ๋ ๋ฒกํฐ ๊ฐ๊ฐ์ ๋ํด ์๋ ํจ์ f๋ฅผ ์ ์ฉํ๊ณ , ์ด๋ฅผ ํตํด ์ป์ด์ง ํจ์ ๊ฐ์ ๋ณํ๋ฅผ h๋ก ๋๋์ผ๋ก์จ, ๊ฐ ๋ณ์๋ณ๋ก ํจ์์ ๊ทธ๋๋์ธํธ๋ฅผ ์ถ์ ํฉ๋๋ค.
- V * V = V์ Dot Product → (V1^2 + V2^2 + V3^2 / 2V1 * 2V2 * 2V3 ~ th)
Using the Gradient
- sum_of_squares ํจ์๋ ์ ๋ ฅ v๊ฐ 0์ ๋ฒกํฐ์ผ ๋ ๊ฐ์ฅ ์์ต๋๋ค.
- ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ์ฌ์ฉํ์ฌ ์ฌ์ค์ ํ์ธํ๊ณ ์ ํฉ๋๋ค.
- (๊ธฐ์ธ๊ธฐ ํ๊ฐ๋ฒ) ๊ทธ๋๋์ธํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ 3์ฐจ์ ๋ฒกํฐ ์ค ์ต์๊ฐ์ ์ฐพ์๋ด ์๋ค. ์ฐ๋ฆฌ๋ ์์์ ์์์ ์ ์ ํํ ๋ค์ ๊ทธ๋๋์ธํธ๊ฐ ๋งค์ฐ ์์ ์ง์ ์ ๋๋ฌํ ๋๊น์ง ๊ทธ๋๋์ธํธ์ ๋ฐ๋ ๋ฐฉํฅ์ผ๋ก ์์ฃผ ์์ ๋จ๊ณ๋ฅผ ๋ฐ์ ๊ฒ์ ๋๋ค
def step(v, direction, step_size):
"""move step_size in the direction from v"""
return [v_i + step_size * direction_i
for v_i, direction_i in zip(v, direction)]
- step ํจ์๋ ์ฃผ์ด์ง ๋ฐฉํฅ direction์ผ๋ก step_size๋งํผ ์ด๋ํ๋ ๊ธฐ๋ฅ
- v: ํ์ฌ ์์น๋ฅผ ๋ํ๋ด๋ ๋ฒกํฐ.
- direction: ์ด๋ํ๊ณ ์ ํ๋ ๋ฐฉํฅ์ ๋ํ๋ด๋ ๋ฒกํฐ. ์ด ๋ฐฉํฅ์ ๋ณดํต ๋ชฉํ ํจ์์ ๊ธฐ์ธ๊ธฐ์ ์ํด ๊ฒฐ์ ๋ฉ๋๋ค.
- step_size: ํ ๋ฒ์ ์ด๋ํ ๊ฑฐ๋ฆฌ. ์ฆ, ์ด๋์ ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
- ๋ฐํ๊ฐ: ์๋ก์ด ์์น๋ฅผ ๋ํ๋ด๋ ๋ฒกํฐ.
def sum_of_squares_gradient(v):
return [2 * v_i for v_i in v]
- ์ฃผ์ด์ง ๋ฒกํฐ v์ ๋ํด sum_of_squares ํจ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐ
- ๋งค๊ฐ๋ณ์:v: ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํ๊ณ ์ ํ๋ ์์น๋ฅผ ๋ํ๋ด๋ ๋ฒกํฐ.๋ฐํ๊ฐ:
- sum_of_squares ํจ์์ v์์์ ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ. ๊ฐ ์์๋ 2 * v_i๋ก, sum_of_squares ํจ์๋ ๊ฐ ๋ณ์์ ์ ๊ณฑ์ ํฉ์ผ๋ก ์ด๋ฃจ์ด์ ธ ์๊ธฐ ๋๋ฌธ์, ๊ทธ ๋ฏธ๋ถ๊ฐ์ 2 * v_i๊ฐ ๋ฉ๋๋ค.
- sum_of_squares_gradient(v) → 2V1, 2V2, 2VN…. - Gradient Function.
- ๋น๊ณ : step_size๋ learning_rate๋ผ๊ณ ๋ ํฉ๋๋ค.
def step(v, direction, step_size):
"""v์์ direction ๋ฐฉํฅ์ผ๋ก step_size๋งํผ ์ด๋"""
return [v_i + step_size * direction_i
for v_i, direction_i in zip(v, direction)]
def sum_of_squares_gradient(v):
"""v์ ์ ๊ณฑํฉ ํจ์์ ๊ธฐ์ธ๊ธฐ(gradient) ๊ณ์ฐ"""
return [2 * v_i for v_i in v]
step ํจ์
- ํ์ฌ ์์น v์์ ์ฃผ์ด์ง direction ๋ฐฉํฅ์ผ๋ก step_size๋งํผ ์ด๋ํ ์๋ก์ด ์์น๋ฅผ ๊ณ์ฐํฉ๋๋ค.
- v: ํ์ฌ ์์น๋ฅผ ๋ํ๋ด๋ ๋ฒกํฐ์ ๋๋ค.
- direction: ์ด๋ํ ๋ฐฉํฅ์ ๋ํ๋ด๋ ๋ฒกํฐ์ ๋๋ค. ๋ณดํต ์ต์ ํํ๋ ค๋ ํจ์์ ๊ธฐ์ธ๊ธฐ(gradient) ๋ฐ๋ ๋ฐฉํฅ์ด ๋ฉ๋๋ค.
- step_size: ํ ๋ฒ์ ์ด๋ํ ๊ฑฐ๋ฆฌ๋ฅผ ๋ํ๋ ๋๋ค. ์ด ๊ฐ์ด ๋๋ฌด ํฌ๋ฉด ์ต์ ์ ์ ๋์ด์๊ฒ ๋๊ณ , ๋๋ฌด ์์ผ๋ฉด ์ต์ ํ ๊ณผ์ ์ด ๋งค์ฐ ๋๋ ค์ง ์ ์์ต๋๋ค.๋ฐํ๊ฐ: ์๋ก์ด ์์น๋ฅผ ๋ํ๋ด๋ ๋ฒกํฐ์ ๋๋ค. ์ด๋ v์ ๊ฐ ์์์ direction์ ํด๋น ์์์ step_size๋ฅผ ๊ณฑํ ๊ฐ์ ๋ํด์ ๊ณ์ฐ๋ฉ๋๋ค.
sum_of_squares_gradient ํจ์
- ์ฃผ์ด์ง ๋ฒกํฐ v์ ๋ํด ์ ๊ณฑํฉ ํจ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํฉ๋๋ค. ์ ๊ณฑํฉ ํจ์๋ ๋ชจ๋ ์์์ ์ ๊ณฑ์ ๋ํ ๊ฒ์ด๋ฉฐ, ์ด ํจ์๋ ์ต์ ํ์์ ์์ฃผ ์ฌ์ฉ๋๋ ๊ฐ๋จํ ์์์ ๋๋ค.
- ํ๋ผ๋ฏธํฐ:v: ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํ ๋ฒกํฐ์ ๋๋ค.๋ฐํ๊ฐ: ์ ๊ณฑํฉ ํจ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๋ํ๋ด๋ ๋ฒกํฐ์ ๋๋ค. ์ ๊ณฑํฉ ํจ์์ ๊ฐ ๋ณ์์ ๋ํ ํธ๋ฏธ๋ถ์ 2 * v_i์ด๋ฏ๋ก, ๊ฒฐ๊ณผ ๋ฒกํฐ๋ ์ ๋ ฅ ๋ฒกํฐ v์ ๊ฐ ์์์ 2๋ฅผ ๊ณฑํ ๊ฐ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
- ์ด ๋ ํจ์๋ ๊ฒฝ์ฌํ๊ฐ๋ฒ(gradient descent) ์๊ณ ๋ฆฌ์ฆ์ ๊ธฐ๋ณธ ๊ตฌ์ฑ ์์์ ๋๋ค. ๊ฒฝ์ฌํ๊ฐ๋ฒ์ ํจ์์ ์ต์๊ฐ์ ์ฐพ๊ธฐ ์ํด ๊ธฐ์ธ๊ธฐ(๋๋ ๊ทธ๋๋์ธํธ) ์ ๋ณด๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ๋ณต์ ์ผ๋ก ํ์ฌ ์์น๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
- sum_of_squares_gradient ํจ์๋ ์ต์ ํํ๋ ค๋ ํจ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํ๊ณ , step ํจ์๋ ์ด ๊ธฐ์ธ๊ธฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ ์์น๋ก ์ด๋ํฉ๋๋ค.
print("using the gradient")
# try range(n) n = 1,2,3,4,5,...
v = [random.randint(-10,10) for i in range(2)] # ์์์ ์ด๊ธฐ ๋ฒกํฐ v ์์ฑ
tolerance = 0.0000001 # ์๋ ด ๊ธฐ์ค ๊ฐ (10**-5, 10์ -5์น ๊น์ง)
while True:
#print(v, sum_of_squares(v))
gradient = sum_of_squares_gradient(v) # v์์์ ๊ธฐ์ธ๊ธฐ ๊ณ์ฐ
next_v = step(v, gradient, -0.01) # ์์ ๊ธฐ์ธ๊ธฐ ๋ฐฉํฅ์ผ๋ก ํ ๊ฑธ์ ์ด๋
if distance(next_v, v) < tolerance: # ์ด์ v์ ํ์ฌ v์ ๊ฑฐ๋ฆฌ๊ฐ tolerance๋ณด๋ค ์์ผ๋ฉด ์ค๋จ
break
v = next_v # ์๋๋ฉด ๊ณ์
print("minimum v", v) # ์ต์ํ๋ v ์ถ๋ ฅ
print("minimum value", sum_of_squares(v)) # ์ต์ํ๋ ๊ฐ ์ถ๋ ฅ
- v: ์ต์ ํ๋ฅผ ์์ํ ์์์ ๋ฒกํฐ์ ๋๋ค. ์ฌ๊ธฐ์๋ 2์ฐจ์ ๋ฒกํฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- tolerance: ์๊ณ ๋ฆฌ์ฆ์ด ์๋ ดํ๋ค๊ณ ํ๋จํ๋ ๊ธฐ์ค์ ๋๋ค. v์ ์ฐ์๋ ๋ ๊ฐ์ ์ฐจ์ด๊ฐ ์ด ๊ฐ๋ณด๋ค ์์ผ๋ฉด ๋ฐ๋ณต์ ๋ฉ์ถฅ๋๋ค.
- while True ๋ฃจํ: ์๊ณ ๋ฆฌ์ฆ์ด ์๋ ด ์กฐ๊ฑด์ ๋ง์กฑํ ๋๊น์ง ๋ฐ๋ณตํฉ๋๋ค.
- gradient = sum_of_squares_gradient(v): ํ์ฌ ์์น v์์ ๋ชฉ์ ํจ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํฉ๋๋ค. → Gradient Step Size ๋งํผ ๊ฑธ์ด๋ค๋ฉด ๋ค์ Step Size
- next_v = step(v, gradient, -0.01): ๊ณ์ฐ๋ ๊ธฐ์ธ๊ธฐ์ ๋ฐ๋ ๋ฐฉํฅ(์ต์ํ ๋ฐฉํฅ)์ผ๋ก ์์ ๊ฑธ์(-0.01)์ ์ด๋ํ์ฌ ์๋ก์ด ์์น๋ฅผ ๊ณ์ฐํฉ๋๋ค.
- if distance(next_v, v) < tolerance: ์๋ก์ด ์์น์ ์ด์ ์์น ์ฌ์ด์ ๊ฑฐ๋ฆฌ๊ฐ tolerance๋ณด๋ค ์์ผ๋ฉด, ์ฆ ๋ณํ๊ฐ ์ถฉ๋ถํ ์์ ์๋ ดํ๋ค๊ณ ํ๋จํ๋ฉด ๋ฐ๋ณต์ ๋ฉ์ถฅ๋๋ค.
- ์ต์ข ์ ์ผ๋ก, ์๋ ดํ ์์น v์ ๊ทธ ๋์ ๋ชฉ์ ํจ์ ๊ฐ sum_of_squares(v)๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
using the gradient
minimum v [-4.157730989669425e-06, -2.7718206597796163e-06]
minimum value 2.4969716752438604e-11
Choosing the Right Step Size (or Learning rate)
์ฌ๋ฐ๋ฅธ ์คํ ํฌ๊ธฐ(๋๋ ํ์ต ์๋) ์ ํ
- gradient์ ์ญํํ์ฌ ์์ง์ผ ์ ์๋ ๊ทผ๊ฑฐ๋ ๋ถ๋ช
ํ์ง๋ง, ์ผ๋ง๋ ๋ฉ๋ฆฌ ์์ง์ผ ๊ฒ์ธ์ง๋ ๋ช
ํํ์ง ์์ต๋๋ค. ์ค์ ๋ก ์ฌ๋ฐ๋ฅธ ์คํ
ํฌ๊ธฐ๋ฅผ ์ ํํ๋ ๊ฒ์ ๊ณผํ์ด๋ผ๊ธฐ๋ณด๋ค๋ ์์ ์ ๊ฐ๊น์ต๋๋ค. ์ธ๊ธฐ ์๋ ์ต์
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๊ณ ์ ์คํ ํฌ๊ธฐ ์ฌ์ฉ (Using a fixed step size)
- ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋จ๊ณ ํฌ๊ธฐ๊ฐ ์ ์ฐจ ์ถ์๋จ (Gradually shrinking the step size over time)
- ๊ฐ ๋จ๊ณ์์ ๋ชฉ์ ํจ์์ ๊ฐ์ ์ต์ํํ๋ ๋จ๊ณ ํฌ๊ธฐ ์ ํ (At each step, choosing the step size that minimizes the value of the objective function)
- ๋ง์ง๋ง์ ์ต์ ์ธ ๊ฒ์ฒ๋ผ ๋ค๋ฆฌ์ง๋ง ์ค์ ๋ก๋ ๋น์ฉ์ด ๋ง์ด ๋๋ ๊ณ์ฐ์ ๋๋ค. ์ฐ๋ฆฌ๋ ๋ค์ํ ๋จ๊ณ ํฌ๊ธฐ๋ฅผ ์๋ํ๊ณ ๋ชฉ์ ํจ์์ ๊ฐ์ด ๊ฐ์ฅ ์์ ๋จ๊ณ๋ฅผ ์ ํํจ์ผ๋ก์จ ๊ทธ ๊ทผ์ฌ์น๋ฅผ ๊ตฌํ ์ ์์ต๋๋ค.
step_sizes = [100, 10, 1, 0.1, 0.01, 0.001, 0.0001, 0.00001]
- ํ์ต๋ฅ ์ด ๋๋ฌด ํฌ๋ฉด ํธ์ฐจ๊ฐ ๋ฐ์ํฉ๋๋ค.
- ํ์ต ์๋๊ฐ ๋๋ฌด ์์ผ๋ฉด ์๋ ด ์๋๊ฐ ๋๋ฌด ๋๋ฆฌ๊ฑฐ๋ ๋ก์ปฌ ์ต์๊ฐ์ผ๋ก ๋จ์ด์ง ์ ์์ต๋๋ค.
- ์ง์ญ์ ์ธ Global Local Minimum
Experiment with various learning rates (๋ค์ํ Learning Rate๋ก ์คํ)
# in class, changes lr = 10, 1.1, 1, 0.1, 0.01
# 10 : diverge
# 1.1: diverge
# 1: oscilliating
# 0.1: good pace
# 0.01 : two slow
import numpy as np
import matplotlib.pyplot as plt
def sum_of_squares_gradient_np(v):
"""์ ๊ณฑํฉ ํจ์์ ๊ทธ๋๋์ธํธ๋ฅผ ๊ณ์ฐํฉ๋๋ค."""
return 2 * v
def gradient_descent(gradient_f, init_x, lr=0.01, step_num=10000, tolerance=0.0000001):
"""๊ทธ๋๋์ธํธ ํ๊ฐ๋ฒ์ ์ฌ์ฉํด ์ต์๊ฐ์ ์ฐพ์ต๋๋ค."""
x = init_x
x_history = []
for i in range(step_num):
x_history.append(x.copy())
x_prev = x.copy()
x -= lr * gradient_f(x) # ๊ทธ๋๋์ธํธ ์คํ
if np.linalg.norm(x - x_prev) < tolerance: # ์๋ ด ์กฐ๊ฑด
break
return x, x_history
init_x = np.array([-1.0, 1.0])
lr = 1.1 # ํ์ต๋ฅ , # try with 10, 1.1, 1, 0.1, 0.01
step_num = 100
x, x_history = gradient_descent(sum_of_squares_gradient_np, init_x, lr=lr, step_num=step_num)
# ์๊ฐํ
plt.plot( [-5, 5], [0,0], '--b')
plt.plot( [0,0], [-5, 5], '--b')
x_history = np.array(x_history)
plt.plot(x_history[:,0], x_history[:,1], 'o')
plt.xlim(-3.5, 3.5)
plt.ylim(-4.5, 4.5)
plt.xlabel("X0")
plt.ylabel("X1")
plt.axis('equal')
plt.show()
- ์ด ์ฝ๋๋ ์ด๊ธฐ ์ (init_x)์์ ์์ํ์ฌ ์ ๊ณฑํฉ ํจ์์ ์ต์๊ฐ์ ์ฐพ๊ธฐ ์ํ ๊ฒฝ๋ก๋ฅผ ์๊ฐํํฉ๋๋ค.
- ๊ฒฝ์ฌ ํ๊ฐ๋ฒ ํจ์(gradient_descent)๋ ์ฃผ์ด์ง ๊ทธ๋๋์ธํธ ํจ์(gradient_f), ์ด๊ธฐ ์ (init_x), ํ์ต๋ฅ (lr), ์ต๋ ์คํ ์(step_num), ๊ทธ๋ฆฌ๊ณ ์๋ ด ๊ธฐ์ค(tolerance)์ ์ธ์๋ก ๋ฐ์ ์ต์๊ฐ์ ์ฐพ๋ ๊ณผ์ ์ ์ํํฉ๋๋ค.
- ํ์ต๋ฅ (lr)์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์์ ๋งค์ฐ ์ค์ํ ํ์ดํผํ๋ผ๋ฏธํฐ์ ๋๋ค. ๋๋ฌด ํฌ๋ฉด ๋ฐ์ฐํ ์ ์๊ณ , ๋๋ฌด ์์ผ๋ฉด ์๋ ด์ด ๋งค์ฐ ๋๋ ค์ง ์ ์์ต๋๋ค.
- ์ด ์์ ์์ lr ๊ฐ์ ๋ค์ํ๊ฒ ๋ณ๊ฒฝํด๋ณด๋ฉฐ ๊ทธ ์ํฅ์ ์๊ฐ์ ์ผ๋ก ๊ด์ฐฐํ ์ ์์ต๋๋ค.
- x -= lr * gradient_f(x) → x์ Gradient Function (Gradient์ ๋ฐ๋๋ฐฉํฅ์ผ๋ก ๊ฑท๋๋ค.)
- (Out of function domain) ํน์ ์คํ ํฌ๊ธฐ๋ก ์ธํด ํจ์์ ๋ํ ์ ๋ ฅ์ด ์๋ชป๋์์ต๋๋ค.
- ๋ฐ๋ผ์ ์๋ชป๋ ์ ๋ ฅ์ ๋ํด ๋ฌดํ๋๋ฅผ ๋ฐํํ๋ "์์ ์ ์ฉ" ํจ์๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
def safe(f):
"""f ํจ์๋ฅผ ์์ ํ๊ฒ ์คํํ๋ ์๋ก์ด ํจ์๋ฅผ ๋ฐํํ๋ค."""
def safe_f(*args, **kwargs):
try:
return f(*args, **kwargs) # f๋ฅผ ์คํํด๋ด -> ๋ชจ๋ ์ธ์, keyword & argument
except:
return float('inf') # ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ๋ฌดํ๋๋ฅผ ๋ฐํ
return safe_f
ํจ์ f ๋ฅผ ๋ฐ์, ํด๋น ํจ์๋ฅผ ์คํํ ๋ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ํ๋ก๊ทธ๋จ์ด ์ค๋จ๋์ง ์๊ณ ๋์ ๋ฌดํ๋(float('inf'))๋ฅผ ๋ฐํํ๋ ์๋ก์ด ํจ์ safe_f ๋ฅผ ๋ฐํํฉ๋๋ค.
Putting It All Together
- ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ์๋ ์ต์ํํ๋ ค๋ target_fn์ด ์๊ณ , gradient_fn๋ ์์ต๋๋ค.
- ์๋ฅผ ๋ค์ด target_fn์ ๋ชจ๋ธ์ ์ค๋ฅ๋ฅผ ๋งค๊ฐ๋ณ์์ ํจ์๋ก ๋ํ๋ผ ์ ์์ผ๋ฉฐ, ์ค๋ฅ๋ฅผ ๊ฐ๋ฅํ ์๊ฒ ๋ง๋๋ ๋งค๊ฐ๋ณ์๋ฅผ ์ฐพ๊ณ ์ ํ ์ ์์ต๋๋ค.
def minimize_batch(target_fn, gradient_fn, theta_0, tolerance=0.000001):
"""๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ์ฌ์ฉํ์ฌ ๋ชฉํ ํจ์๋ฅผ ์ต์ํํ๋ theta๋ฅผ ์ฐพ์ต๋๋ค."""
# tolerance -> f๊ฐ์ด ์ด๊ฒ๋ณด๋ค ๋ฎ์์ง๋ฉด ๋.
# ๊ฐ ๋จ๊ณ ํฌ๊ธฐ๋ฅผ ์ค์ ํฉ๋๋ค.
step_sizes = [100, 10, 1, 0.1, 0.01, 0.001, 0.0001, 0.00001]
# theta๋ฅผ ์ด๊ธฐ ๊ฐ์ผ๋ก ์ค์ ํฉ๋๋ค.
theta = theta_0
# target_fn์ ์์ ๋ฒ์ ์ ๋ง๋ญ๋๋ค.
target_fn = safe(target_fn)
# ์ต์ํํ ๊ฐ์ ์ค์ ํฉ๋๋ค.
value = target_fn(theta)
while True:
# ํ์ฌ theta์์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํฉ๋๋ค.
gradient = gradient_fn(theta)
# ๋ค์ ๋จ๊ณ ํ๋ณด๋ฅผ ์์ฑํฉ๋๋ค.
next_thetas = [step(theta, gradient, -step_size)
for step_size in step_sizes]
# ์ค์ฐจ ํจ์๋ฅผ ์ต์ํํ๋ ๊ฒ์ ์ ํํฉ๋๋ค.
next_theta = min(next_thetas, key=target_fn) # target function ์ต์๊ฐ ๊ตฌํจ
next_value = target_fn(next_theta) # value & next value์ ์ฐจ์ด
# ์๋ ดํ๋ ๊ฒฝ์ฐ ๋ฉ์ถฅ๋๋ค.
if abs(value - next_value) < tolerance:
return theta
else:
theta, value = next_theta, next_value
Example : Minimizing sum_of_squares
minimize_batch(sum_of_squares, sum_of_squares_gradient, [10,20,4,5])
[0.0006805647338418772,
0.0013611294676837543,
0.00027222589353675085,
0.0003402823669209386]
minimize_batch(sum_of_squares, sum_of_squares_gradient, [10,20,4,5,0,1])
[0.0006805647338418772,
0.0013611294676837543,
0.00027222589353675085,
0.0003402823669209386,
0.0,
6.805647338418771e-05]
Example : Centering a certain point
def myf(v):
# ์ฃผ์ด์ง ๋ฒกํฐ v์ ๊ฐ ์์์ 3, 2 ๊ฐ๊ฐ์ ๋บ ํ ์ ๊ณฑํ์ฌ ๋ฐํํฉ๋๋ค.
return (v[0]-3)**2 + (v[1]-2)**2
def myf_gradient(v):
# ์ฃผ์ด์ง ๋ฒกํฐ v์ ๊ฐ ์์์ 2๋ฅผ ๊ณฑํ๊ณ , ๊ฐ๊ฐ์ 6 ๋๋ 4๋ฅผ ๋บ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌ์คํธ๋ก ๋ฐํํฉ๋๋ค.
return [2.0*v[0]-6, 2.0*v[1]-4]
# minimize_batch ํจ์๋ฅผ ํธ์ถํ์ฌ myf ํจ์๋ฅผ ์ต์ํํฉ๋๋ค.
minimize_batch(myf, myf_gradient, [5000., 50.])
[3.0016059738814325, 2.000015426605225]
- myf_gradient ํจ์๋ฅผ ๊ทธ๋๋์ธํธ๋ก ์ฌ์ฉํ์ฌ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ์ํํฉ๋๋ค.
- ์ด๊ธฐ theta ๊ฐ์ [5000., 50.]์ผ๋ก ์ค์ ๋์ด ์์ต๋๋ค.
- ์ด ๊ฐ์ ์ฌ์ฉ์๊ฐ ๋ฌธ์ ์ ๋ฐ๋ผ ์ ์ ํ๊ฒ ์ค์ ํด์ผ ํฉ๋๋ค.
from functools import partial
def f1(x, c):
# ์ฃผ์ด์ง ๋ฒกํฐ x์ ์์ ๋ฒกํฐ c์ ์ฐจ์ด๋ฅผ ์ ๊ณฑํ์ฌ ํฉ์ฐํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
x = np.array(x)
c = np.array(c)
return np.sum((x - c)**2) # x, c ์ฌ์ด ๊ฑฐ๋ฆฌ
def f1_gradient(x, c):
# ์ฃผ์ด์ง ๋ฒกํฐ x์ ์์ ๋ฒกํฐ c์ ๊ฐ๊ฐ 2๋ฅผ ๊ณฑํ๊ณ , ๊ฐ๊ฐ์ ์์ ๋ฒกํฐ c๋ฅผ ๋บ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
x = np.array(x)
c = np.array(c)
return 2*x - 2*c
def numerical_gradient(v, f, h=0.00001):
# ์ค์ ์ฐจ๋ถ๋ฒ์ ์ฌ์ฉํ์ฌ ์ฃผ์ด์ง ๋ฒกํฐ v์์ ํจ์ f์ ๊ทธ๋๋์ธํธ๋ฅผ ๊ณ์ฐํฉ๋๋ค.
return (np.apply_along_axis(f, 1, v + h * np.eye(len(v))) - f(v)) / h
c = np.array([7,70,7,4])
# f1 ํจ์๋ฅผ ์์ c๋ฅผ ๊ณ ์ ์์ผ ๋ถ๋ถ ํจ์๋ก ์์ฑํฉ๋๋ค -> f function์ ์ธ์ ๋จผ์
f = partial(f1, c=c)
# f1_gradient ํจ์๋ฅผ ์์ c๋ฅผ ๊ณ ์ ์์ผ ๋ถ๋ถ ํจ์๋ก ์์ฑํฉ๋๋ค.
gradient_f = partial(f1_gradient, c=c)
# minimize_batch ํจ์๋ฅผ ํธ์ถํ์ฌ f๋ฅผ ์ต์ํํฉ๋๋ค.
# gradient_f๋ฅผ ๊ทธ๋๋์ธํธ๋ก ์ฌ์ฉํ์ฌ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ์ํํฉ๋๋ค.
# ์ด๊ธฐ theta ๊ฐ์ [0,0,0,0]์ผ๋ก ์ค์ ๋์ด ์์ต๋๋ค.
minimize_batch(f, gradient_f, [0,0,0,0])
[6.999843894783611, 69.99843894783609, 6.999843894783611, 3.9999107970192056]
- f1 ํจ์์ f1_gradient ํจ์์์๋ ์ฃผ์ด์ง ๋ฒกํฐ x์ ์์ ๋ฒกํฐ c์ ๋ํด ๊ฐ๊ฐ ํจ์ ๊ฐ์ ๊ณ์ฐํ๊ณ ๊ทธ๋๋์ธํธ๋ฅผ ๋ฐํํฉ๋๋ค.
- functools ๋ชจ๋์ partial ํจ์๋ฅผ ์ฌ์ฉํ์ฌ c๋ฅผ ๊ณ ์ ์ํจ ๋ถ๋ถ ํจ์๋ฅผ ์์ฑํฉ๋๋ค.
- ์ด๋ ๊ฒ ์์ฑ๋ ๋ถ๋ถ ํจ์๋ค์ minimize_batch ํจ์์ ์ธ์๋ก ์ ๋ฌํ์ฌ ์ต์ ํ๋ฅผ ์ํํฉ๋๋ค.
- ๋๋ก๋ ํจ์์ ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ์ต์ํํจ ์ผ๋ก์จ ํจ์๋ฅผ ์ต๋ํํ ์๋ ์์ต๋๋ค. (ํด๋น ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ฐ์ง)
def negate(f):
"""์ฃผ์ด์ง ํจ์ f์ ๋ํด -f(x)๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ๋ฐํํฉ๋๋ค."""
return lambda *args, **kwargs: -f(*args, **kwargs)
def negate_all(f):
"""๋ฆฌ์คํธ๋ฅผ ๋ฐํํ๋ ํจ์ f์ ๊ฐ ๊ฒฐ๊ณผ์ ๋ํด ์์๋ฅผ ์ทจํ ๋ฆฌ์คํธ๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ๋ฐํํฉ๋๋ค."""
return lambda *args, **kwargs: [-y for y in f(*args, **kwargs)] # -y: ๋ฐ๋ - functionํ
def maximize_batch(target_fn, gradient_fn, theta_0, tolerance=0.000001):
# minimize_batch ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ชฉํ ํจ์๋ฅผ ์ต๋ํํ๋ theta ๊ฐ์ ์ฐพ์ต๋๋ค.
# negate ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ชฉํ ํจ์๋ฅผ ์์๋ก ๋ณํํ๊ณ , gradient_fn์ ๊ฒฐ๊ณผ๋ฅผ ์์๋ก ๋ณํํ๋ negate_all ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
return minimize_batch(negate(target_fn),
negate_all(gradient_fn),
theta_0,
tolerance)
- minimize_batch ํจ์๋ฅผ ํธ์ถํ์ฌ ์ฃผ์ด์ง ๋ชฉํ ํจ์๋ฅผ ์ต๋ํํ๋ theta ๊ฐ์ ์ฐพ์ต๋๋ค.
- maximize_batch ํจ์๋ ์ฃผ์ด์ง ๋ชฉํ ํจ์์ ๊ทธ๋๋์ธํธ ํจ์๋ฅผ negate ํจ์์ negate_all ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์์๋ก ๋ณํํ ํ minimize_batch ํจ์์ ์ ๋ฌํฉ๋๋ค.
Maximizing batch Example
์ ๊ท pdf๋ฅผ ์ต๋ํํ๋ ๋ณ์๋ฅผ ์ฐพ์ต๋๋ค.
- normal pdf์ ๋ํจ์๋ ... (deriv ๊ฐ๋ฅ)
from functools import partial
def normal_pdf(npx, mu, sigma):
# ์ ๊ท ๋ถํฌ์ ํ๋ฅ ๋ฐ๋ ํจ์๋ฅผ ๊ณ์ฐํฉ๋๋ค.
x = npx[0]
return ((1/(np.sqrt(2*np.pi)*sigma)*np.exp(-(x-mu)**2/(2*sigma**2))))
def numerical_gradient(v, f, h=0.00001):
# ์ฃผ์ด์ง ํจ์ f์ ๊ทธ๋๋์ธํธ๋ฅผ ์ค์ ์ฐจ๋ถ๋ฒ์ ์ฌ์ฉํ์ฌ ๊ทผ์ฌํ๋ ํจ์์
๋๋ค.
return (np.apply_along_axis(f, 1, v + h * np.eye(len(v))) - f(v)) / h
# normal_pdf ํจ์์ ๋ํ ๋ถ๋ถ ํจ์๋ฅผ ์์ฑํฉ๋๋ค. mu=1, sigma=1๋ก ๊ณ ์ ๋ฉ๋๋ค.
f = partial(normal_pdf, mu=1, sigma=1)
# numerical_gradient ํจ์์ ๋ํ ๋ถ๋ถ ํจ์๋ฅผ ์์ฑํฉ๋๋ค.
gradient_f = partial(numerical_gradient, f=f)
# ์ด๊ธฐ๊ฐ์ ์ค์ ํฉ๋๋ค.
init_x = np.array([1.])
# maximize_batch ํจ์๋ฅผ ํธ์ถํ์ฌ normal_pdf ํจ์๋ฅผ ์ต๋ํํฉ๋๋ค.
# gradient_f๋ฅผ ๊ทธ๋๋์ธํธ๋ก ์ฌ์ฉํ์ฌ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ์ํํฉ๋๋ค.
maximize_batch(f, gradient_f, init_x)
array([1.])
- maximize_batch ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ฃผ์ด์ง ํจ์ normal_pdf๋ฅผ ์ต๋ํํ๋ ์์ ์ ๋๋ค.
- ์ฃผ์ด์ง ํจ์ normal_pdf๋ ์ ๊ท ๋ถํฌ์ ํ๋ฅ ๋ฐ๋ ํจ์๋ฅผ ๊ณ์ฐํฉ๋๋ค.
- ์ด ํจ์์ ๋ํ ๊ทธ๋๋์ธํธ๋ numerical_gradient ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ทผ์ฌํฉ๋๋ค.
- ์ด๊ธฐ๊ฐ์ init_x๋ก ์ค์ ๋์ด ์์ต๋๋ค. ์ต์ข ์ ์ผ๋ก maximize_batch ํจ์๋ฅผ ํธ์ถํ์ฌ ์ต๋ํ๋ ๊ฐ์ ์ฐพ์ต๋๋ค.
ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ (Stochastic Gradient Descent)
- ๋ฐฐ์น ๊ฒฝ์ฌ ํ๊ฐ
- ๋ฐฐ์น ์ ๊ทผ ๋ฐฉ์์์ ๊ฐ ๊ทธ๋ผ๋ฐ์ด์ ๋จ๊ณ๋ ์์ธก์ ์ํํ๊ณ ์ ์ฒด ๋ฐ์ดํฐ ์ธํธ์ ๋ํ ๊ทธ๋ผ๋ฐ์ด์ ์ ๊ณ์ฐํด์ผ ํ๋ฏ๋ก ๊ฐ ๋จ๊ณ์ ์ค๋ ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค.
- ์ผ๋ฐ์ ์ผ๋ก ์ค์ฐจ ํจ์๋ ๊ฐ์ฐ์ ์ด๋ฉฐ, ์ด๋ ์ ์ฒด ๋ฐ์ดํฐ ์ธํธ์ ๋ํ ์์ธก ์ค์ฐจ๊ฐ ๋จ์ํ ๊ฐ ๋ฐ์ดํฐ ํฌ์ธํธ์ ๋ํ ์์ธก ์ค์ฐจ์ ํฉ์ด๋ผ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
- ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ
- ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ํ ๋ฒ์ ํ ์ ์ ๋ํด์๋ง ๊ฒฝ์ฌ๋๋ฅผ ๊ณ์ฐํฉ๋๋ค(๊ทธ๋ฆฌ๊ณ ๋จ๊ณ๋ฅผ ๋ฐ์ต๋๋ค).
- ์ ์ง ์ง์ ์ ๋๋ฌํ ๋๊น์ง ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ํํฉ๋๋ค. ๋งค ์ฃผ๊ธฐ ๋์ ์ฐ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฌด์์ ์์๋ก ๋ฐ๋ณตํ๊ธฐ๋ฅผ ์ํ ๊ฒ์ ๋๋ค.
Batch vs SGD vs Mini-batch
์ ์ฒด Error = ๋ถ๋ถ ์๋ฌ์ ํฉ → 1๊ฐ ์ฉ๋ง ๋ณธ๋ค.
๋ฐฉ๋ฒ | ์ค๋ช | ์ฅ์ | ๋จ์ |
Batch | ์ ์ฒด ํ์ต ๋ฐ์ดํฐ์ ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํจ | ์ ํํจ | ๋ฐ์ดํฐ ํฌ๊ธฐ๊ฐ ๋งค์ฐ ํฌ๋ฉด 1) ๋๋ฆผ, 2) ๋ฉ๋ชจ๋ฆฌ์ ๋ง์ถ๊ธฐ ์ด๋ ค์ |
SGD | ํ๋์ ์ํ์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํ๊ณ ์ ๋ฐ์ดํธ | ๋น ๋ฆ | ๊ณผ๋ํ ์ค๋ฒ์ํ ๋ฐ ์๋ ด์ด ์ด๋ ค์ (ํ์ต๋ฅ ๊ฐ์๋ก ํด๊ฒฐ ๊ฐ๋ฅ) |
Mini-batch | n๊ฐ์ ์ํ์ ๋ฏธ๋๋ฐฐ์น์์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํ๊ณ ์ ๋ฐ์ดํธ | ๋ถ์ฐ ๊ฐ์, ์์ ์ ์ธ ์ ๋ฐ์ดํธ | ๋น ๋ฅธ ๊ณ์ฐ, (ํ๋์จ์ด/์ํํธ์จ์ด์ ๊ฐ์ ์ ํ์ฉ). ์ด๊ฒ์ ์ ๊ฒฝ๋ง์ ํ๋ จํ๋ ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค. |
NeuralNet Terminology: Epoch
ํ epoch๋ ์ ์ฒด ๋ฐ์ดํฐ ์ธํธ๊ฐ ํ๋ จ์ ์ํด ์๋น๋๋ ๊ฒฝ์ฐ์ ๋๋ค.
import random
def in_random_order(data):
# ์ฃผ์ด์ง ๋ฐ์ดํฐ๋ฅผ ๋ฌด์์ ์์๋ก ๋ฐํํ๋ ์ ๋๋ ์ดํฐ์
๋๋ค.
# Args: data: ๋ฌด์์๋ก ๋ฐํํ ๋ฐ์ดํฐ, Returns: ๋ฌด์์๋ก ์์ธ ๋ฐ์ดํฐ
indexes = [i for i, _ in enumerate(data)] # ๋ฐ์ดํฐ์ ์ธ๋ฑ์ค ๋ชฉ๋ก์ ์์ฑํฉ๋๋ค.
random.shuffle(indexes) # ์ธ๋ฑ์ค๋ฅผ ์์ต๋๋ค.
for i in indexes: # ํด๋น ์์๋๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐํํฉ๋๋ค.
yield data[i]
- in_random_order ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ์ ์ํฉ๋๋ค. ์ด ํจ์๋ ์ฃผ์ด์ง ๋ฐ์ดํฐ๋ฅผ ๋ฌด์์ ์์๋ก ๋ฐํํฉ๋๋ค.
- enumerate ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ์ ์ธ๋ฑ์ค ๋ชฉ๋ก์ ์์ฑํ๊ณ , random.shuffle ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ธ๋ฑ์ค๋ฅผ ์์ต๋๋ค.
- ๊ทธ๋ฐ ๋ค์ ์์ธ ์ธ๋ฑ์ค์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํฉ๋๋ค.
Understanding SGD Code
x๋ Training ๋ฐ์ดํฐ ์ธํธ์ ๋๋ค.
y๋ Lavel(๋๋ ํด๋์ค) ์งํฉ์ ๋๋ค.
def minimize_stochastic(target_fn, gradient_fn, x, y, theta_0, alpha_0=0.01):
data = list(zip(x, y))
theta = theta_0 # ์ด๊ธฐ ์ถ์ ๊ฐ
alpha = alpha_0 # ์ด๊ธฐ ์คํ
ํฌ๊ธฐ
min_theta, min_value = None, float("inf") # ํ์ฌ๊น์ง์ ์ต์๊ฐ
iterations_with_no_improvement = 0
# 100ํ ๋ฐ๋ณตํ์ฌ ๊ฐ์ ์์ผ๋ฉด ์ข
๋ฃ
while iterations_with_no_improvement < 100: # Total Error
value = sum(target_fn(x_i, y_i, theta) for x_i, y_i in data)
if value < min_value:
# ์๋ก์ด ์ต์๊ฐ์ ์ฐพ์์ผ๋ฉด ๊ธฐ์ตํ๊ณ ์ด๊ธฐ ์คํ
ํฌ๊ธฐ๋ก ๋์๊ฐ
min_theta, min_value = theta, value
iterations_with_no_improvement = 0
alpha = alpha_0
else:
# ๊ฐ์ ์ด ์๋ค๋ฉด ์คํ
ํฌ๊ธฐ๋ฅผ ์ค์ฌ๋ด
iterations_with_no_improvement += 1
alpha *= 0.9
# ๊ฐ ๋ฐ์ดํฐ ํฌ์ธํธ์ ๋ํด ๊ทธ๋๋์ธํธ ์คํ
์ ์ทจํจ
for x_i, y_i in in_random_order(data):
gradient_i = gradient_fn(x_i, y_i, theta)
theta = vector_subtract(theta, scalar_multiply(alpha, gradient_i))
return min_theta
- target_fn: ๋ชฉํ ํจ์
- gradient_fn: ๋ชฉํ ํจ์์ ๊ทธ๋๋์ธํธ(๊ธฐ์ธ๊ธฐ)
- x: ์ ๋ ฅ ๋ฐ์ดํฐ
- y: ์ถ๋ ฅ ๋ฐ์ดํฐ
- theta_0: ์ด๊ธฐ theta ๊ฐ
- alpha_0: ์ด๊ธฐ ํ์ต๋ฅ (๊ธฐ๋ณธ๊ฐ: 0.01)
- Returns: ์ต๋๊ฐ์ ๊ฐ์ง๋ theta ๊ฐ
def maximize_stochastic(target_fn, gradient_fn, x, y, theta_0, alpha_0=0.01):
"""
ํ๋ฅ ์ ๊ฒฝ์ฌ ์์น๋ฒ์ ์ฌ์ฉํ์ฌ ๋ชฉํ ํจ์๋ฅผ ์ต๋ํํ๋ ํจ์์
๋๋ค.
"""
return minimize_stochastic(negate(target_fn),
negate_all(gradient_fn),
x, y, theta_0, alpha_0)
- target_fn์ ๋ชฉํ ํจ์์ด๊ณ , gradient_fn์ ๋ชฉํ ํจ์์ ๊ทธ๋๋์ธํธ(๊ธฐ์ธ๊ธฐ) ํจ์์ ๋๋ค.
- x๋ ์ ๋ ฅ ๋ฐ์ดํฐ, y๋ ์ถ๋ ฅ ๋ฐ์ดํฐ, theta_0์ ์ด๊ธฐ ์ถ์ ๊ฐ์ ๋๋ค.
- alpha_0์ ์ด๊ธฐ ํ์ต๋ฅ ๋ก, ๊ธฐ๋ณธ๊ฐ์ 0.01์ ๋๋ค. ์ต์ ํ๋ theta ๊ฐ์ ๋ฐํํฉ๋๋ค.
๋ฐ์ํ
'๐ Data Mining' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Data Mining] Getting Data Part.1 (0) | 2024.07.24 |
---|---|
[Data Mining] Statistics (ํต๊ณํ) (0) | 2024.07.14 |
[Data Mining] Linear Algebra (์ ํ๋์) (0) | 2024.07.09 |
[Data Mining] Introduction to Numpy part.2 (0) | 2024.07.05 |
[Data Mining] Introduction to Numpy part.1 (0) | 2024.06.26 |