Home [수학/미적분] 수치미분, 심볼릭연산을 이용한 미분과 적분, 수치적분
포스트
취소

[수학/미적분] 수치미분, 심볼릭연산을 이용한 미분과 적분, 수치적분

데이터분석에서 미분의 쓸모

데이터분석의 중요한 목표 중 하나는 예측모형 최적화다.

곧, 예측모형 성능을 최대화(오차를 최소화) 하는 것이 매우 중요하다.

$\Rightarrow$ 예측모형의 성능함수 또는 손실함수가 있을 것이다.

성능함수 또는 손실함수 출력은 최대화 또는 최소화 되어야 한다.

최적화를 통해 목적함수 출력을 최대화 또는 최소화 시키는 최적해를 찾을 것이다.

이 최적 입력을 찾기 위해선 입력값을 변화시키면서 출력이 어떻게 변하는지 확인해야 한다.

바로 이 과정, 입력값이 변화할 때 출력값이 어떻게 변하는지 알려주는 게 ‘미분’이다.

결국 예측모형 최적화를 위해서는 성능함수(or 손실함수) 미분이 필수적이다.

$\Rightarrow$ 미분 : 입력값이 변할 때 출력값이 어떻게 변하는지 알려주는 ‘신호’, ‘도구’


기울기 (민감도)

$\lim_{\Delta{x} \to 0} \frac{f(x+\Delta{x})-f(x)}{\Delta{x}}$

정의 :

임의의 특정 입력값 $x_{0}$ 에서, 입력값이 매우 미세하게 증가할 때. 출력값이 어떻게 변할지 알려주는 신호.


만약 $x_{0}$ 에서 기울기가 양수이면

입력값을 $x_{0}$ 에서 살짝 증가시켰을 때 출력값이 증가한다는 뜻이다.

출력을 최대화 하는 게 목표라면, $x_{0}$ 에서 기울깃값을 확인하고 $x_{0}$ 에서 좀 더 증가시킨 입력값을 다시 넣어볼 것이다.


이 기울깃값은 함수에서 $x_{0}$ 점에 접하는 접선의 기울기와 같다.

이 접선 기울기는

$\frac{\Delta{y}}{\Delta{x}}$

x 증가량에 대한 y 증가량의 비율과도 같다.

Screen Shot 2021-08-28 at 20 13 48


수치미분

정의 :

dx 값을 직접 받아

특정 점에서의 대략적 기울깃값 계산.

수치미분을 위한 파이썬 코드 :

  • scipy.misc.derivative(함수 이름, 기울깃값 구할 지점, dx=)
1
2
3
4
# 수치미분
from scipy.misc import derivative

derivative(f, x0, dx=1/100000)

주의점 :

  1. ‘대략적’ 기울깃값이다. 정확한 값은 아니라는 걸 기억하자.
  2. dx 값은 작으면 작을 수록 좋지만, 너무 작아지면 오차가 커진다. 유의해서 넣자.

미분

정의 :

도함수 찾는 작업.

  • 어떤 함수를 미분해서 찾은 또 다른 함수를 ‘도함수’라고 한다.
  • 각 $x$ 점에서의 도함숫값이 $x$ 점에서의 기울깃값이다.

미분가능

함수가 전 구간 연속일 때, 함수는 전 구간 ‘미분가능’하다.

불연속 지점에서 함수는 ‘미분 불가능’하다.

미분불가능 예)

$x=0$ 지점에서 불연속인 렐루함수 예.

1
2
3
4
5
6
7
8
9
10
def ReLU(x) : 
    return np.where(x>0, x, 0)

xx = np.linspace(-5,5,100)
plt.plot(xx, ReLU(xx))
plt.plot(0,0, 'o', ms=10)
plt.title('ReLU 함수 : $x=0$ 에서 미분불가능(불연속)')
plt.xlabel('$x$')
plt.ylabel('$ReLU$')
plt.show()

Screen Shot 2021-08-28 at 20 24 02

렐루함수는 $x=0$ 지점에서 불연속이다.

따라서 이 함수는 $x=0$ 에서 ‘미분불가능’이다.

핵심 미분공식

1. 로그를 미분하면 $x^{-1}$ 나온다.

$\frac{d}{dx}(logx) = \frac{1}{x}$

2. 밑이 $e$ 인 지수는 미분해도 안 바뀐다.

$\frac{d}{dx}(e^{x}) = e^{x}$

3. 어떤 함수 형태가 두 함수의 곱 이면 다음과 같이 미분한다.

$\frac{d}{dx} (f\cdot g) = f^{‘}g+fg^{‘}$

이를 미분 곱셈법칙이라 한다.

4. 어떤 함수 입력이 또 다른 함수 출력인 경우, 다음과 같이 미분한다.

$\frac{d}{dx} h(g(x)) = \frac{d}{dg}h \cdot \frac{d}{dx}g$

이를 미분 연쇄법칙이라 한다.

로그함수에 미분 연쇄법칙 적용할 경우, 다음과 같은 결과가 나온다.

$\frac{d}{dx}(\log{f(x)}) = \frac{f’(x)}{f(x)}$

2차 도함수

정의 :

2차 도함수는 1차 도함수를 다시 한번 미분해서 구한 함수다.

  • 1차 도함수의 기울기다.
  • 함수 $f(x)$ 의 볼록도

볼록도 (convexity) :

함수 $f(x)$ 각 점에서의 2차 도함숫값을 ‘볼록도’ 라고도 한다.

이 볼록도는 점 $x_{0}$ 까지 구간에서 함수가 ‘볼록한 정도’를 나타낸다.

아래쪽에서 바라봤을 때

2차 도함숫값이 양수인 구간에서 원래 함수 $f(x)$ 는 ‘볼록’하다.

2차 도함숫값이 음수인 구간에서 원래 함수 $f(x)$ 는 ‘오목’하다.

Screen Shot 2021-08-28 at 20 42 31

편미분

미분은 한번에 한 개 변수에 대해서만 할 수 있다.

정의 :

변수가 둘 이상인 다변수함수. 에서 1개 변수에 대해서만 미분하는 것.

다른 나머지 변수는 상수 취급한다.

$\partial$ 라운드 기호를 쓴다.

편미분 의미 :

다변수함수에 두 변수 $x, y$가 있다고 하자.

$x$ 에 대한 편미분은 $y$ 변수는 고정시켜둔 채. $x$ 입력변수만 변화시킬 때. 함수 출력이 어떻게 변화하는가 알려주는 신호다.

$y$ 에 대한 편미분은 그 반대다.

다변수함수의 연쇄법칙

다변수함수 입력이 다른 여러 함수들 출력인 경우, 똑같이 연쇄법칙 작용한다.

예를 들어

어떤 다변수함수 $g$ 가 있다고 하자.

$g$의 입력은 $x$ 를 입력으로 갖는 단변수함수 $f_{1}, f_{2}, f_{3}…f_{n}$ 이다.

$z = g(f_{1}, f_{2}, f_{3}…f_{n})$

또는

$z = g(y_{1},y_{2}, y_{3}, … y_{n})$

  • 이때 함수 $g$는 사실상 변수 $x$ 를 입력으로 갖는 단변수함수와도 같다.

$g$ 를 $x$로 미분하면

$\frac{dg}{dx} = \frac{\partial g}{\partial y_{1}}\cdot \frac{dy_{1}}{dx} + \frac{\partial g}{\partial y_{2}}\cdot \frac{dy_{2}}{dx}+ …\frac{\partial g}{\partial y_{n}}\cdot \frac{dy_{n}}{dx}$

이다.


만약 $g$ 의 입력이 $x_{1}, x_{2}, …x_{n}$ 을 입력으로 받는 다변수함수 $f_{1}, f_{2}, f_{3}…f_{n}$ 이라면 어떨까?

$z = g(f_{1}, f_{2}, f_{3}…f_{n})$

또는

$z = g(y_{1},y_{2}, y_{3}, … y_{n})$

  • $g$는 사실상 입력이 $x_{1}, x_{2}, …x_{n}$ 인 다변수함수다.

만약 $x_{1}$ 입력변수 변화에 따라 $g$ 의 출력 $z$ 가 어떻게 변하는지 알고 싶으면. 다음처럼 미분하면 된다.

$\frac{\partial g}{\partial x_{1}} = \frac{\partial g}{\partial y_{1}}\cdot \frac{\partial y_{1}}{\partial x_{1}} + \frac{\partial g}{\partial y_{2}}\cdot \frac{\partial y_{2}}{\partial x_{1}}…+\frac{\partial g}{\partial y_{n}}\cdot \frac{\partial y_{n}}{\partial x_{1}}$


2차 편미분

정의 :

$x$ 나 $y$ 로 한번 편미분 마친 상태에서. 다시 $x$ 나 $y$ 로 편미분을 한번 더 하는 작업이다.

슈와르츠 정리 : 편미분 순서는 상관 없다!

$x$로 편미분 하고 $y$로 편미분 하건.

$y$로 편미분 하고 $x$로 편미분 하건.

결과는 같다.

$x$로 먼저 하든, $y$로 먼저 하든.

편미분 순서는 상관없다.


테일러 전개

정의 :

특정 점 $x_{0}$ 에서의 기울기 만 가지고. 함수 $f(x)$의 근사함수를 찾는 작업.

단변수함수 테일러 전개 식 :

$f(x) \approx \frac{df(x_{0})}{dx}(x-x_{0})+f(x_{0})$

다변수함수 테일러 전개 식 :

$f(x,y) \approx \frac{\partial f(x_{0}, y_{0})}{\partial x}(x-x_{0}) + \frac{\partial f(x_{0},y_{0})}{\partial y}(y-y_{0})+f(x_{0}, y_{0})$


심파이 sympy

심볼릭연산 하게 해 주는 파이썬 패키지다.

심볼릭연산이란 내가 연필로 미분. 적분 하는 작업을 컴퓨터에서 그대로 구현해놓은 거라 생각하면 된다.

심볼릭 변수

파이썬에서 지금까지 사용해온 변수는 언제나 특정 숫자, 문자 등 데이터가 담겨 있었다.

하지만 심볼릭 변수는 아무것도 담겨 있지 않다. ‘변수’를 ‘의미 그대로’ 표현해 놓은 것이 심볼릭 변수다.

심파이로 심볼릭 연산 하기 위해서는 심볼릭 변수가 필요하다.

곧, 심볼릭 변수를 지정해주는 작업이 필요하다.

sympy.symbols(‘문자열’)

1
x, y = sympy.symbols('x y')

위 코드를 사용해서 심볼릭연산에 쓸 심볼릭 변수를 지정해줄 수 있다.

.symbols() 괄호 안에 들어가는 문자열에 특정한 문자를 집어넣어서 그 문자를 심볼릭 변수로 만든다.

문자열 안에는 심볼릭변수로 지정해주고 싶은 여러 문자 동시에 넣어도 된다. 이때 각 문자 간 구분은 띄어쓰기나 , 로 한다.

1
x, mu, y = sympy.symbols('x mu y')

위 코드처럼 입력해주면 x, mu, y가 심볼릭 변수로 지정된 것이다.

심볼릭함수

심볼릭 변수를 지정했으면, 이 변수 이용해서 미분. 적분 등 연산하려고 하는 함수 만들어주면 된다.

편의상 ‘심볼릭함수’라고 이름붙였다.

1
2
3
x = sympy.symbols('x')

f = x*sympy.exp(x)

f가 심볼릭변수로 만들어준 심볼릭함수다.

심볼릭연산 할 때는 함수들도 모두 심파이 전용함수 써야 한다. 위 코드에서 sympy.exp() 가 그 예다.


심볼릭연산 이용한 미분

1
sympy.diff(심볼릭함수이름, 미분할 변수)

심볼릭연산으로 함수 미분 할 때는 sympy.diff()를 쓰면 된다.

diff() 괄호 안에는 미분할 심볼릭함수 이름을 넣으면 된다.

심볼릭변수가 함수 f 안에 하나밖에 없을 때는(단변수함수인 경우) 미분할 변수 굳이 안 지정해줘도 된다.

1
2
3
4
5
# 단변수함수 미분

f = 2*x**4+5*x**3+6*x**2+7*x+8 # 심볼릭함수 

sympy.diff(f)

Screen Shot 2021-08-28 at 21 37 13

하지만 다변수함수를 sympy.diff()로 미분하거나. 단변수함수지만 심볼릭함수 안에 심볼릭 변수가 여러 개 있는 경우는 어떤 변수로 미분 할 건지 정해줘야 한다.

  • 다변수함수 심볼릭연산으로 편미분 하는 경우 ```python

    다변수함수

    f = x2+4xy+4*y2

편미분

sympy.diff(f, x)

1
2
3
4
5
6
7
8
9
10
<img width="114" alt="Screen Shot 2021-08-28 at 21 38 47" src="https://user-images.githubusercontent.com/83487073/131218137-9b50173d-a5e5-4f8a-b82b-3787ef166293.png">

- 단변수함수인데 심볼릭변수가 여러개라서 미분할 변수 지정 하는 경우

```python
# 심볼릭변수가 여러 개 일 때는 무조건 편미분하듯 어떤 변수로 미분할건지 지정해야 한다. 
x, mu, sigma = sympy.symbols('x, mu, sigma')
f = sympy.exp((x-mu)**2/sigma**2)

sympy.diff(f, x)

Screen Shot 2021-08-28 at 21 40 21

2차 도함수

심볼릭 연산으로 2차 도함수 구하려면, 다음처럼 하면 된다.

1
2
# 2차 도함수 
sympy.diff(f, x, x) # x로 두번 미분

Screen Shot 2021-08-28 at 21 42 45

simplify()

수식 정리 함수다.

1
sympy.simplify(sympy.diff(f, x, x))

sympy.simplify() 형태로 쓴다.

괄호 안에 식 깔끔하게 정리 할 수식 넣으면 된다.


적분

부정적분은 ‘반-미분’,

정적분은 ‘구간 a,b 에서 함숫값과 수평선이 이루는 면적 구하는 작업’이다.

부정적분

정의 :

미분의 반대연산 (반-미분).

미분이 도함수 구하는 과정이었다면, 부정적분은 구한 도함수를 도로 원래 함수로 되돌리는 과정이다.

도함수를 $f(x)$ 라고 하면,

도함수를 부정적분해서 찾은 원래 함수를 $F(x)$ 로 표기한다.

$F(x) = \int{f(x)dx}+c$

$c$ 는 상수항을 의미한다. 생략해도 상관없다.


편미분의 부정적분

$x(y)$로 편미분 했으면 $x(y)$로 부정적분 해야 한다

부정적분은 미분의 반대연산이다.

만약 함수 $F(x, y)$ 를 $x$로 편미분 해서 $f(x,y)$ 가 나왔다면.

$f(x,y)$ 를 $x$ 에 대해 부정적분 하면 $F(x,y)$ 가 나올 것이다.

$F(x,y) = \int{f(x,y)}dx + c(y)$

이때는 뒤에 $c(y)$ 가 붙는다.

$c(y)$ 는 y에 대한 식일수도 있고, 단순 상수일 수도 있다.

위 과정을 $y$ 에 대해 생각한다면,

$F(x,y) = \int{f(x,y)}dx + c(x)$

일 것이다.


다차 도함수와 다중적분

  • 다차 도함수 : 원래 함수를 편미분 여러 번 해서 얻어낸 도함수
  • 다중적분 : 부정적분을 여러번 하는 것.

위 경우는 편미분을 한번 한 경우였다.

편미분 한번 했으면 부정적분 한번 하면 될 것이다.

그러면 편미분을 여러번 한 경우는 어떻게 해야 원래 함수를 찾을 수 있을까?

다차 도함수

다변수함수의 다차도함수는 편미분을 여러번 한 대표적 예다.

2차 도함수라면 편미분을 두번 했을 것이고,

3차 도함수면 편미분을 세번 했을 것이다.

2번 편미분 한 다차도함수에서 원래 다변수함수를 찾아보자.

$F(x,y) = \int_{x}\int_{y} f_{2}(x,y) dy dx$

위 식처럼 부정적분을 여러번. ‘다중적분’ 해서 원래 다변수함수 찾을 수 있다.

위 경우는 $F(x,y)$ 를 $x$ 로 편미분하고 $y$로 편미분 해서 얻은 $f_{2}(x,y)$ 를 다시 원래 함수 $F$ 로 되돌리는 경우다.

순서를 역으로 $y$로 부정적분하고, $x$로 다시 부정적분 하면 원래 함수가 나올 것이다.

한편, 편미분 여러번 할 때 슈와르츠정리에 의해 미분 순서가 상관 없었듯이, 여기서도 부정적분 순서는 상관 없다.

$\int\int{f_{2}(x,y)}dxdy$

$\int\int{f_{2}(x,y)}dydx$


심볼릭연산을 이용한 부정적분

역시 sympy 를 이용한다.

1
sympy.integrate(함수 이름, 적분할 변수 이름)

심파이 사용한 부정적분 예 )

1
2
3
4
x, y = sympy.symbols('x y')
f = x*y*sympy.exp(x**2+y**2)

sympy.integrate(f, x)

Screen Shot 2021-08-28 at 22 11 10


정적분

정의 :

구간 a, b 에 대해서 함수 $f(x)$와 수평선이 이루는 면적 계산하는 작업또는 그 값.

$\int^{a}_{b}{f(x)}dx$


정적분을 계산하는 방법

미적분학의 기본정리, 수치적분.


1. 미적분학의 기본정리

$\int^{b}_{a}{f(x)}dx = F(b)-F(a)$

  • 심볼릭연산으로 계산할 수 있다.
  • 도함수 부정적분 이용하는 방법이다.

예)

1
2
3
4
5
6
7
# 미적분학의 기본정리 이용해서 정적분값 계산
x = sympy.symbols('x')

f = x**3-3*x**2+x+6 # 도함수

F = sympy.integrate(f, x)
F # 반-미분해서 찾은 원래 함수 F

Screen Shot 2021-08-28 at 22 18 57

1
(F.subs(x,2) - F.subs(x, 0)).evalf()

subs(값을 넣을 심볼릭변수 이름, 값)

  • 심볼릭변수에 실제로 어떤 값을 넣어 연산하고 싶을 때 쓰느 메서드다.

.evalf()

  • 심볼릭연산 결과의 실젯값을 계산해준다.

예를 들어 결과값이 $\sqrt{8}$ 이면, 2.82… 이런 식으로 나타내준다.

괄호 안에 소수 몇 째 자리 까지 나타낼 건지도 정해줄 수 있다. 예) 10


2. 수치적분 : 구간의 근사면적 구하기

정적분의 정의에 좀 더 걸맞게,

구간 a,b 를 작은 사각형들로 실제로 잘게 쪼갠 뒤.

이것들 면적 더해서 구간의 근사면적을 구한다.

  • 심볼릭 연산 아니다.

scipy.integrate.quad(파이썬함수 이름, 구간 시작점, 구간 끝점)

1
sp.integrate.quad(f, a, b)

예)

1
2
3
4
5
# 수치적분으로 정적분
def f(x) : 
    return 3*x**2-6*x+1

sp.integrate.quad(f, 0,1)[0] # 수치적분으로 구한 정적분값 

out : -1, 1.3085…

수치적분 첫번째 결과값은 정적분 값이다.

두번째 결과값은 오차 상한값이다.


다변수 정적분

다변수함수의 ‘부피’를 계산하는 작업

정적분의 의미를 잘 생각해야 한다.

2차원 평면상의 1차원 함수 기준으로, 정적분은 구간에 대한 함수와 수평선 사이 ‘면적’ 이었다.

다변수함수가 입력변수 2개인 2차원 함수라고 하자.

2차원 함수면 3차원 공간상의 입체로 표현된다.

임의의 구간에 대한 2차원 함수의 함숫값들과 수평선 사이 면적은 ‘부피’다.

따라서 다변수 정적분은 다변수함수의 ‘부피’를 계산하는 작업이다.

$\int_{a}^{b}\int_{c}^{d}{f(x,y)}dydx$

$\Leftarrow$ 구간 (x : a~b), (y : c~d) 에서 다변수함수 $f(x,y)$ 의 부피


수치이중적분

2차원 다변수함수에 대해 다변수 정적분 하는 것.

수치적분과 마찬가지로 구간을 잘게 쪼개서 대략적인 부피를 구한다.

scipy.integrate.dblquad(2차원 다변수함수 이름, x구간 시점, x구간 종점, y구간 시점, y구간 종점)

1
sp.integrate.dblquad(f, 1, np.inf, lambda x : 0, lambda x : np.inf)
  • f는 2차원 다변수함수다.
  • x의 구간 시점과 종점 차례로 입력한다.
  • y구간 시점과 종점에는 각 시점. 종점 값들을 입력변수가 x인 함수 꼴로 넣어야 한다.

수치 이중적분 예)

1
2
3
def f(x,y) : 
    return np.exp(-x*y)/y**2
sp.integrate.dblquad(f, 1, np.inf, lambda x : 0, lambda x : np.inf)

out : 0.49999, 1.06…

왼쪽은 수치이중적분 값, 오른쪽은 오차상한값이 나온다.


다차원 함수의 단일 정적분

다차원 함수는 정적분 할 때. 그 입력변수 갯수만큼 정적분 해야 한다.

예를 들어 2차원 함수는 정적분하려면 반드시 x에 대해 한 번, y에 대해 한 번.

정적분을 총 두번 해야 한다.

그런데

만약 입력변수가 x,y 두 개인 2차원 함수인데 정적분을 x에 대해 한번만 하려면

2차원 함수를 1차원 함수로 바꿔줘야 한다.

즉, x,y 입력변수 갖는 2차원 함수에서 y 입력변수를 상수취급해야 한다.

y 입력변수가 상수가 되면 함수에 입력변수가 x 하나만 남으므로, 함수가 사실상 1차원 함수가 된다.

그러면 이 1차원 함수를 x에 대해 한 번 정적분할 수 있다.

예)

$f(x, y) = 6x^{2}+12xy+8y$

라고 해보자.

이 함수는 입력변수가 2개인 2차원 다변수함수다.

이 함수의 정적분을 구하려면 $x$ 구간으로 한 번, $y$ 구간으로 한 번 총 두번 정적분 해야 한다.

그런데 만약 $x$로 한 번만 정적분 하려면 어떻게 해야 할까.

변수 $y$ 를 상수취급해서 함수를 1차원 함수로 바꿔야 한다.

$f(x;y) = 6x^{2}+(12y)x+(8y)$

위와 같이 $y$ 를 상수취급 하면 함수가 입력변수 $x$ 하나인 1차원 함수가 된다.

이 1차원 함수를 $x$ 구간 에 대해 정적분 할 수 있다.

[파이썬/넘파이] 데이터분석/머신러닝에 유용한 넘파이 명령어 정리

[수학/미적분] 행렬미분, 행렬미분법칙