본문 바로가기
머신러닝 딥러닝

0826 편미분(partial derivative), 연쇄법칙(Chain Rule)

by 대금부는개발자 2021. 8. 26.
SMALL

편미분(partial derivative) → 입력 변수(독립변수)가 2개 이상인 다변수함수(f(x, y)=x²+2xy+y)에서 미분을 하려면 미분하려는 변수를 제외한 나머지 변수를 상수로 취급하고 해당 변수를 미분하는 방법.

 

f(x, y)를 변수 x에 대해서 편미분을 하는 경우 ∂(라운드 d)라는 표현을 써요

∂f(x,y) / ∂x

 

f(x, y) = 2x + 3xy + y³

 

x 에 대해서 편미분 ∂f(x,y) / ∂x :  2 + 3y + 0                y는 상수기때문에 미분하면 0

y 에 대해서 편미분∂f(x,y) / ∂y  : 3x + 3y²                    x는 상수기때문에 미분하면 0  

 

 

 

연쇄 법칙(Chain Rule) : 일반적으로 합성함수(여러 함수로 구성된 함수)를 미분할 때 연쇄 법칙(Chain Rule)을 이용해요.

 

합성함수를 미분하려면 합성함수를 구성하고 있는 각각의 함수를 미분하고, 그 결과를 다 곱해서 결과를 도출

 

f(x) = e^3x²3x² → tfunction  e^t ,  function  t= 3x² 

 

↓ darivative

 

∂x/∂f = ∂t/∂f  * ∂x/∂t  =  e^t * 6x = 6x * e^3x²

 

 

 

f(x)=e^-x                  -x=t

function e^t , function t = -x

↓ darivative

 

e^t * -1 → -e^t = -e^-x

 

 

 

다변수 함수의 수치미분 코드를 구현해 보아요!!

 

f(x,y) = 2x+3xy+y³

 

다변수함수(입력 변수 2개)이기 때문에 수치기 미분을 2번 해야 해요.

 

f'(1.0,2.0) 

 

1. x=1.0 에서의 미분계수(미분값)를 구해요. y=2.0을 상수로 대입해서 편미분2 +3y = 8

 

2. y =2.0  에서의 미분계수(미분값)를 구해요.  x = 1.0을 상수로 대입해서 편미분

3 + 6y = 15

 

 

f'(1.0,2.0) = (8.0, 15.0)

 

이제 프로그램으로 만들어 보아요!

 

 

import numpy as np
# 수치미분 최종함수
# 다변수 함수에 대한 수치미분
# 수치미분을 수헹할 다변수 함수
# f(x,y) = 2x + 3xy + y^3
#f'(1.0, 2,0)  => (8.0, 15.0)

# 1. 수치미분을 수행할 함수

def numerical_derivative(f, x):
    #f : 미분을 하려고 하는 함수 
    #x : 모든 독립변수의 값을 포함하고 있는 ndarray(차원에 무관하게 처리할 수 있어야 해요)
    delta_x = 1e-4
    derivative_x = np.zeros_like(x)  # [0.0   0.0]
    #iter를 이용해 반복해줘야 차원에 상관없이 반복할 수 있어요
    it = np.nditer(x, flags=['multi_index'])
    
    while not it.finished:
        
        idx = it.multi_index
        

       # tmp를 준비하는 이유는 편미분 할 때 값이 변경되지 않아야 하기 때문에 준비해요.
        tmp = x[idx] # x : [1.0 2.0] , tmp - 1.0 ,2번반복때 tmp  - 2.0
        
        # 중앙차분으로 수치미분하는 식 : (f(x+deltax) - f(x-deltax) / 2 * delta_x)
        x[idx] = tmp + delta_x   # x : [1.0001  2.0]
        fx_plus_deltax = f(x)
        
        x[idx] = tmp - delta_x   # x : [0.9999  2.0]
        fx_minus_deltax = f(x)
        
        derivative_x[idx] = (fx_plus_deltax - fx_minus_deltax) / (2 * delta_x)
        

        # 현재 데이터(x)가 편미분으로 변했어요! tmp로 원상복귀
        x[idx] = tmp     # x : [ 1.0 2.0] 으로 원상복귀
        it.iternext()
        
    return derivative_x
        
             
        
# 2. 미분할 함수
#   모든 독립변수가 포함된 인자를 받아서 내부에서 분할해서 처리해야 해요!
def my_func(input_value):  #함수니까 인자를 2개 받아야 하지만 input_value로 하나로 받아요 #(1.0,2.0)라고 가정
    
    x = input_value[0]
    y = input_value[1]
    
    return 2*x + 3*x*y + np.power(y,3)

# 3. 다변수 함수에 대한 수치미분을 실행
# f'(1.0, 2.0)
result = numerical_derivative(my_func,np.array([1.0, 2.0]))
print(result) 

#[ 8.         15.00000001]

 

 

문제2. 다변수 함수에 대한 수치미분

# 수치미분을 수행할 다변수 함수
# f(a,b,c,d) = 2ab + 3a^2bc + 5cd + 2bd^2

# f'(1.0, 2.0, 3.0, 4.0) ??   => (.. , .. , .. , ..)

# 1. 수치미분을 수행할 함수
def numerical_derivative(f, x):
    # f : 미분을 하려고 하는 함수
    # x : 모든 독립변수의 값을 포함하고 있는 ndarray(차원에 무관하게 처리할 수 있어야 해요!)
    
    delta_x = 1e-4
    derivative_x = np.zeros_like(x)  # [0.0   0.0]
    
    it = np.nditer(x, flags=['multi_index'])
    
    while not it.finished:
        
        idx = it.multi_index
        
        tmp = x[idx]    # x : [1.0 2.0]  , tmp = 1.0
        
        # 중앙차분으로 수치미분하는 식 : (f(x + delta_x) - f(x-delta_x)) / 2 * delta_x
        
        x[idx] = tmp + delta_x   # x : [1.0001  2.0]
        fx_plus_deltax = f(x)
        
        x[idx] = tmp - delta_x   # x : [0.9999  2.0]
        fx_minus_deltax = f(x)
        
        derivative_x[idx] = (fx_plus_deltax - fx_minus_deltax) / (2 * delta_x)
        
        x[idx] = tmp     # x : [1.0   2.0]
        
        it.iternext()

    return derivative_x

# 2. 미분할 함수
#    모든 독립변수가 포함된 인자를 받아서 내부에서 분할해서 처리해야 해요!
#    f(a,b,c,d) = 2ab + 6a^bc + 5cd + 2bd^2

 a,b,c,d로 2차원 array를 mapping 시켜 쓸 거예요.(1차원으로 해도 돼요)
def my_func1(input_value):    
    
    a = input_value[0,0]
    b = input_value[0,1]
    c = input_value[1,0]
    d = input_value[1,1]
    
    return 2*a*b + 6*np.power(a,2)*b*c + 5*c*d + 2*b*np.power(d,2)

# 3. 다변수 함수에 대한 수치미분을 실행
# f'(1.0, 2.0)
result = numerical_derivative(my_func1,np.array([[1.0, 2.0], 
                                                 [3.0, 4.0]]))
print(result)  

#[[76. 52.]
# [32. 47.]]

LIST

'머신러닝 딥러닝' 카테고리의 다른 글

0827Machine Learning에서Linear Regression  (0) 2021.08.27
0826 회귀(regression )  (0) 2021.08.26
0825 수치미분  (0) 2021.08.25
0825 Machine Learning Process  (0) 2021.08.25
0825 지도학습(Supervised Learning)  (0) 2021.08.25

댓글