λ―ΈλΆ?
μ΄λ€ ν¨μμ μ μμ μ κ° μ μμ λ 립λ³μμ λ³νλκ³Ό ν¨μκ°μ λ³νλμ λΉμ¨. κ·Έ λΉμ¨μ κ·Ήν νΉμ κ·Ήνμ μ§ν©μΌλ‘ μΉμμ΄ κ΅¬μ±λλ μλ‘μ΄ ν¨μ.
λ―ΈλΆμ ν¬κ² λκ°μ§λ‘ λλ μ μλ€.
μ΄λ νμ΄μ¬μμλ μ€μ κ³μ°μ ν΅ν΄ λ―ΈλΆμ κ·Όμ¬μΉλ₯Ό μ»μ΄λ΄λ μμΉλ―ΈλΆμ μ¬μ©νλ€. λ°©λ²μ 3κ°μ§λ‘ μ ν₯μ°¨λΆ, νν₯μ°¨λΆ, μ€μμ°¨λΆμ΄ μλλ° μ°λ¦¬λ μ€μμ°¨λΆμ ν΅ν΄ λ―ΈλΆμ ꡬνν΄ λ³Ό κ²μ΄λ€.
μ€μ λ―ΈλΆκ³Ό κ°μ₯ κ°κΉμ΄ λ―ΈλΆλ²μΌλ‘, μ λ₯Ό ν΄μ€ κ°μ μ¬μ©νμ¬ μ€μ μ°¨λΆμ ꡬνλ€. μ΄λ μ κ°μ 10 보λ€λ ν° κ°μ μ΄μ©νλ©°, μΌλ°μ μΌλ‘ 10μ λμ κ°μ μ¬μ©νλ€.
μ€μμ°¨λΆμ ꡬνλ μμ λ€μκ³Ό κ°λ€.
μ΄μ μ΄λ₯Ό μ½λλ‘ κ΅¬νν΄λ³΄μ.
def numerical_derivative(f, x):
# μ€μμ°¨λΆμ μ΄μ©ν λ―ΈλΆκ°μ κ³μ°
delta_x = 0.0001
return (f(x + delta_x) - f(x - delta_x)) / (2 * delta_x)
# f(x) = x^2
def my_func(x):
return x**2
result = numerical_derivative(my_func, 3)
print(result)
ꡬνμ κ·Έλ κ² μ΄λ ΅μ§ μμλ°, μ€μμ°¨λΆ κ³΅μμ κ·Έλλ‘ μ½λλ‘ μμ±νλ©΄ λλ€. μ΄λ μ£Όμν΄μΌ ν μ μΌλ‘ delta_xκ°μΈλ°, μ΄ κ°μ Hyper Parameterλ‘, κ°μ μ§μ ν λ μ κ²½μ¨μΌ ν λΆλΆμ΄ μλ€.
delta_x
μ»΄ν¨ν°λ κ·Ήνμ μ§μ κ³μ°ν μ μκΈ° λλ¬Έμ μμΉ λ―ΈλΆμμλ delta_xλ₯Ό λ§€μ° μμ κ°μΌλ‘ μ€μ νμ¬ λ―ΈλΆμ κ·Όμ¬νλ€. κ·Έλ¬λ delta_xλ₯Ό λ무 μκ² μ€μ νλ©΄ λ°μ¬λ¦Ό μ€μ°¨κ° λ°μνμ¬ μ€νλ € λ―ΈλΆκ°μ΄ λΆμ νν΄μ§ μ μλ€.
κ·Έλ λ€λ©΄ delta_x κ°μ μ΄λ»κ² μ§μ νλ©΄ μ’μκΉ?
=> μ΄λλ ν¨μμ λ³νλμ λ°λΌ μ§μ ν μ μλ€.
delta_xκ° ν¬λ©΄ λ μ μ¬μ΄μ κΈ°μΈκΈ°κ° μ€μ μκ° λ³νμ¨κ³Ό ν¬κ² μ°¨μ΄κ° λ μ μμΌλ―λ‘, delta_xλ₯Ό μκ² μ€μ νμ¬ λ μ μ λ κ°κΉκ² λ§λ€μ΄μΌ νλ€.
ex)
# λ³νκ° μ¬ν ν¨μ μμ: f(x) = sin(1/x) def f(x): return np.sin(1/x) # μμ delta_x κ° (μ: 0.00001) μ¬μ© delta_x = 0.00001 # x = 0.1 μμμ λ―ΈλΆκ° κ³μ° x = 0.1 derivative = (f(x + delta_x) - f(x - delta_x)) / (2 * delta_x) print(f"x = {x} μμμ λ―ΈλΆκ°: {derivative}") # x = 0.1 μμμ λ―ΈλΆκ°: 83.90713432193664
delta_xκ° ν¬λλΌλ λ μ μ¬μ΄μ κΈ°μΈκΈ°κ° μ€μ μκ° λ³νμ¨κ³Ό ν¬κ² μ°¨μ΄κ° λμ§ μμΌλ―λ‘, delta_xλ₯Ό ν¬κ² μ€μ ν΄λ λΉκ΅μ μ νν λ―ΈλΆκ°μ μ»μ μ μλ€.
ex)
# λ³νκ° μλ§ν ν¨μ μμ: f(x) = x^2 def f(x): return x**2 # ν° delta_x κ° (μ: 0.01) μ¬μ© delta_x = 0.01 # x = 2 μμμ λ―ΈλΆκ° κ³μ° x = 2 derivative = (f(x + delta_x) - f(x - delta_x)) / (2 * delta_x) print(f"x = {x} μμμ λ―ΈλΆκ°: {derivative}") # x = 2 μμμ λ―ΈλΆκ°: 3.999999999999937
κ·Έλ¬λ©΄ delta_xλ₯Ό ν¨μμ λ°λΌ μλμΌλ‘ μ€μ ν μ μμκΉ?
=> autograd λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ μλμΌλ‘ λ―ΈλΆμ μ§νν μ μλ€.
import autograd.numpy as np
from autograd import grad
# μλ λ―ΈλΆμ μν ν¨μ μ μ
def f(x):
return np.sin(1/x)
# μλ λ―ΈλΆ ν¨μ μμ±
gradient = grad(f)
# x = 0.1 μμμ λ―ΈλΆκ° κ³μ°
x = 0.1
derivative = gradient(x)
print(f"x = {x} μμμ λ―ΈλΆκ°: {derivative}")
x = 0.1 μμμ λ―ΈλΆκ°: 83.90715290764523
νΈλ―ΈλΆ?
λ 립λ³μκ° λ κ° μ΄μμΈ λ€λ³μ ν¨μμμ λ―ΈλΆμ ν λ μ¬μ©νλ λ―ΈλΆλ²
μ΄μ κ°μ x, y λ λ³μλ‘ μ΄λ£¨μ΄μ§ ν¨μ fκ° μλ€κ³ νμ.
μ΄λ₯Ό xμ yμ λν΄ κ°κ° λ―ΈλΆνλ©΄,
μ΄μ κ°μ΄ λνλΌ μ μλλ°, μ΄λ₯Ό νΈλ―ΈλΆμ΄λΌκ³ νλ€.
μ΄μ μ΄λ₯Ό μ½λλ‘ κ΅¬νν΄λ³΄μ.
def iter(x):
it = np.nditer(x, flags=['multi_index'])
while not it.finished:
print(it.multi_index)
it.iternext()
iter(np.array([[1, 5, 6, 4], [7, 6, 1, 2]]))
# (0, 0)
# (0, 1)
# (0, 2)
# (0, 3)
# (1, 0)
# (1, 1)
# (1, 2)
# (1, 3)
λ¨Όμ νΈλ―ΈλΆμ μ½κ² ꡬννκΈ° μν΄ NumPyμ nditer ν¨μλ₯Ό μμ보μ. nditerλ₯Ό μ¬μ©ν κ²½μ°, λ€μν μ°¨μμ ndarrayλ₯Ό 볡μ‘ν forλ¬Έμ΄ νμμμ΄ μ½κ² μμλ₯Ό νμν μ μλ€.
def partial_derivative(f, x):
# f : λ―ΈλΆμ νλ €λ ν¨μ (λ€λ³μ ν¨μ)
# x : λͺ¨λ λ³μλ₯Ό ν¬ν¨νκ³ μλ ndarray(μ°¨μ 무κ΄) ex) [1.0, 2.0]
delta_x = 0.0001
derivative_x = np.zeros(x.shape) # [0.0, 0.0]
it = np.nditer(x, flags=['multi_index'])
while not it.finished: # 첫λ²μ§Έ λ³μμλν μμ
idx = it.multi_index # 1.0
tmp = x[idx] # 첫λ²μ§Έ indexμ λν κ°μ μμλ‘ μ μ₯ (1.0)
x[idx] = tmp + delta_x # [1.0001, 2.0]
fx_plus_delta = f(x) # f(x + delta_x)
x[idx] = tmp - delta_x # [0.9999, 2.0]
fx_minus_delta = f(x) # f(x - delta_x)
derivative_x[idx] = (fx_plus_delta - fx_minus_delta) / (2 * delta_x)
x[idx] = tmp # μ볡
# μ΄ν xμ λ€μ μμμ λν΄μ λκ°μ΄ λ°λ³΅
it.iternext()
return derivative_x
μ°μ μ€μμ°¨λΆ κ³΅μμ μ¬μ©νμ¬ κ΅¬νν μ½λμΈλ°, iterλ₯Ό μ¬μ©νμ¬ μ λ ₯λ°μ μμ (μ¬κΈ°μ λ 립λ³μμ κ°μ)μ μκ΄μμ΄ λμμ΄ κ°λ₯νλ€. κ°κ°μ μμλ§λ€ delta_xλ₯Ό λν κ°κ³Ό λΊ κ°μ ꡬνμ¬ μ€μμ°¨λΆμ μ¬μ©ν΄ λ―ΈλΆκ°μ ꡬν ν derivative_xμ μ μ₯νλ λ°©μμΌλ‘ λμνλ€.
ꡬνν μ½λλ₯Ό ν΅ν΄ κ²°κ³Όλ₯Ό 보μ.
# 1λ³μ ν¨μ
def my_func1(x): # x^2
return x**2
result1 = partial_derivative(my_func1, np.array([3.0]))
print(result1) # [6.]
# 2λ³μ ν¨μ
def my_func2(input_object): # 2x + 3xy + y^3
x = input_object[0]
y = input_object[1]
return 2*x + 3*x*y + np.power(y, 3)
result2 = partial_derivative(my_func2, np.array([1.0, 2.0]))
print(result2) # [ 8. 15.00000001]
# 3λ³μ ν¨μ
def my_func3(input_object): # 2xy + 3xy^2z + 7z^3
x = input_object[0]
y = input_object[1]
z = input_object[2]
return 2*x*z + 3*x*np.power(y, 2)*z + 7*np.power(z, 3)
result3 = partial_derivative(my_func3, np.array([[1.0], [2.0], [3.0]]))
print(result3)
# [[ 42. ]
# [ 36. ]
# [203.00000007]]
μ΄λ λ€λ³μ ν¨μλ₯Ό μμ±ν λ μ λ¬νλ μμλ₯Ό ndarrayλ‘ μ λ¬ν΄ μ£Όλ©΄λλ€.