Finite Difference Method with np.gradient

numpy
Author

신호연

Published

January 7, 2023

Gradient와 수치미분

\({\bf x} =\begin{bmatrix}x_1&x_2&\dots&x_m\end{bmatrix}^T\)일 때, \(x\)에 대한 다변수함수 \(f({\bf x})\)의 gradient는 다음과 같다.

\[\begin{aligned} &\text{gradient of }f({\bf{x}}) = \frac{\partial f}{\partial {\bf x}} = \nabla f(\bf{x}) = \begin{pmatrix} \frac{\partial f}{\partial x_1} \\ \frac{\partial f}{\partial x_2} \\ \vdots \\ \frac{\partial }{\partial x_m} \end{pmatrix} \end{aligned}\]

함수가 가지는 모든 변수에 대해서 편미분 한 뒤 모아놓은 벡터라고 생각하면 된다. 함수의 수식을 알고 미분이 가능하면 우리는 해석적으로 미분해서(미분공식써서) 그레디언트를 구하고 각각의 어떤 point에서의 편미분계수들도 구할 수 있다. 그러나 우리가 주어진 데이터는 함수f의 함숫값들이 주어진다. 예를 들면 다음과 같다.

import numpy as np
f = np.array([1,2,4,7,11,17],dtype = float)
print("f(x)")
print(f)
f(x)
[ 1.  2.  4.  7. 11. 17.]

위와 같은 함숫값들만 주어질때에는 원래의 함수를 알기는 불가능하다. 따라서 도함수를 통한 정확한 미분계수를 구하기가 불가능하므로 주어진 데이터로 \(\bf x\)에서의 미분계수의 값을 근사적으로 구할 수 있는데 이를 수치미분이라 한다.

Taylor Series

수치미분을 구하기 위해서는 먼저 테일러 급수가 나온다. 함수 \(f\)가 a를 포함하는 구간에서 무한번 미분 가능할 때, \(x = a\)에서 \(f(x)\)의 테일러 급수 전개(근사)는 다음과 같다.
\[f(x) = \sum_{n=0}^{\infty}\frac{f^{n}(a)}{n!}(x-a)^n = f(a) + \frac{f^{'}(a)}{1!}(x-a) + \frac{f^{''}(a)}{2!}(x-a)^2 + \dots \] 테일러급수는 어떤 함수를 다항함수의 합으로 표현하며 한점a에서의 미분계수의 합으로 표현한다는 것에 의미가 있다. 다만 주의할 점은 \(a\)의 위치와 다항식의 차수이다. \(a\)\(x\)근처에 가까울 수록 원래의 함수를 잘 근사하며 다항식의 차수 \(n\)이 클수록 오차가 작아진다.

수치미분

위에서 언급했듯이 수치미분은 주어진 데이터를 가지고 어떤 지점에서의 미분계수의 \(\bf x\)에서의 미분계수의 값을 근사적으로구하는 것이다. 각각의 방법으로 \(x_j\)에서의 미분계수(기울기)의 근삿값을 구해보면 다음과 아래의 그림과 같다. 가장오른쪽에 중앙차분법(central divided difference approximation)에 의한 기울기가 실제기울기와 가장 비슷해보인다.

Finite Difference Method

그림출처 - Finite Difference Method: https://pythonnumericalmethods.berkeley.edu/notebooks/chapter20.02-Finite-Difference-Approximating-Derivatives.html

유한차분법의 각각의 방법으로 도함수의 근사값을 유도하면 다음과 같다. (유도 : Section 5)

전향차분근사 \[\begin{align} &f'(x_i) \overset{\sim}{=} \frac{f(x_{i+1})-f(x_i)}{h}\\ &O(h) = - \frac{hf^{''}(x_i)}{2!} - \frac{h^2f^{'''}(x_i)}{3!} - \dots\\ &\text{where, } h = x_{i+1} - x_i \nonumber \end{align}\]

여기서 \(O(h)\)는 무한한항을 유한한항으로 근사시킬때 나타나는 절단오차라고 하며 h가 포함된 항이 가장 크게 기여하므로 \(O(h)\)로 표기한다. 절단오차에서 h의 차수는 크면 클수록 좋다. \(p<q\)라 가정하고 같은 구간안에서 더 많은 데이터를 얻었다고 하면 \(h\)가 작아지면 작아질수록 \(h^p\)가 최고차항인 절단오차 \(O(h^p)\) 보다는 \(h^q\)가 최고차항인 \(O(h^q)\)가 더 빨리 작아지기 때문이다.

(1)번식을 도함수\(f'(x_i)\)의 (1차)전향차분근사라고 한다.\(x_i\)의 도함수(미분계수)를 구하기 위해 \(x_{i+1}\)을 사용했기에 전향 + 절단오차의 차수가 1인 \(O(h)\)이기 떄문에 그렇다.

후향차분근사 \[\begin{align} &f'(x_i) \overset{\sim}{=} \frac{f(x_{i})-f(x_{i-1})}{h}\\ &O(h) = \frac{h}{2!}f^{''}(x_i) - \frac{h^2}{3!}f{'''}(x_i)+\dots \\ &\text{where, } h = x_{i} - x_{i-1}, \nonumber \end{align}\]

(1)번식을 도함수\(f'(x_i)\)의 (1차)후향차분근사라고 한다.\(x_i\)의 도함수(미분계수)를 구하기 위해 \(x_{i-1}\)을 사용했기에 후향 + 절단오차의 차수가 1인 \(O(h)\)이기 때문이다. 또한 후향차분근사의 절단오차는 전향차분근사와 마찬가지로 \(O(h)\)로 서로 동일하다.

중앙차분근사
\[\begin{align} &f'(x_i) \overset{\sim}{=} \frac{f(x_{i+1})-f(x_{i-1})}{2h}\\ &O(h) = - \frac{h^2}{3!}f{'''}(x_i)+\dots \\ &\text{where, } h = x_{i} - x_{i-1} = x_{i+1} - x_i\nonumber \end{align}\]

(1)번식을 도함수\(f'(x_i)\)의 (2차)중앙차분근사라고 한다.\(x_i\)의 도함수(미분계수)를 구하기 위해 \(x_{i-1},x_{i+1}\)을 사용했기에 중앙이라는 단어가 붙었고 절단오차의 차수가 2인 \(O(h^2)\)이기 때문이다. 또한 (2차)중앙차분근사의 절단오차는 \(O(h^2)\)으로 최고차항이 \(h\)인 전향,후향차분근사와는 다르다. 이는 같은 데이터를 가졌다고 하더라도 중앙차분근사법으로 구한 도함수의 근삿값이 해석적으로 구한값과 가장 비슷하며 또한 같은구간에서 데이터를 더 많이 취득할수록 더 빠르게 정확한값가 가까워짐을 의미한다.

np.gradient?

넘파이의 그레디언트 함수는 배열의 끝값을 제외한 내부의 포인트에서는 2차중앙차분근사(second order accurate central differences)를 미분계수를 계산하고 가장끝값에 있는 포인트들에대해서는 1차 혹은 2차 one-side 차분(전향,후향차분)근사를 통해서 수치미분을 해주는 함수다.

1차원 배열의 경우

Ex) \(dx\) = 1

넘파이 1차원 배열이 다음과 같이 주어져 있다고 하자.

from IPython.display import display, Markdown
f = np.array([1,2,4,7,11,16],dtype=float)
print(f)
[ 1.  2.  4.  7. 11. 16.]

np.gradient함수는 1차원 배열의 내부에 있는 각각의 값들은 \(x\)값이 거리가 \(dx\)=1씩 변화할때마다의 함숫값\(f(x)\)들로 이해한다. 즉,다음과 같다.

for i in range(len(f)):
    display(Markdown(rf'$x_{i+1}$에서의 함숫값 $f(x_{i+1})$ = {f[i]}'))

\(x_1\)에서의 함숫값 \(f(x_1)\) = 1.0

\(x_2\)에서의 함숫값 \(f(x_2)\) = 2.0

\(x_3\)에서의 함숫값 \(f(x_3)\) = 4.0

\(x_4\)에서의 함숫값 \(f(x_4)\) = 7.0

\(x_5\)에서의 함숫값 \(f(x_5)\) = 11.0

\(x_6\)에서의 함숫값 \(f(x_6)\) = 16.0

위에서 넘파이의 그래디언트는 끝값을 제외한 내부의 요소에는 중앙차분근사 양끝값에 대해서는 후향차분 또는 전향차분을 사용한다고 언급했었다. 계산한,\(x_2,x_5\)에서 미분계수의 2차중앙차분근사는 다음과 같다.
\[\begin{aligned} &f^{'}(x_2) \overset{\sim}{=} \frac{f(x_3)-f(x_1)}{2h} = \frac{4-1}{2} = 1.5 \\ &f^{'}(x_5) \overset{\sim}{=} \frac{f(x_6)-f(x_4)}{2h} = \frac{16-7}{2} = 4.5 \\ &\text{where, } h = x_3-x_2 = x_2-x_1 = 1 \end{aligned}\] 1차원 배열의 가장 처음에 오는 값에 전향차분근사를 사용하고 가장 마지막에 오는 값에서는 후향차분근사를 사용한다. \[\begin{aligned} &f^{'}(x_1) = \frac{f(x_2) - f(x_1)}{h} = \frac{2-1}{1} = 1 \\ &f^{'}(x_6) = \frac{f(x_6) - f(x_5)}{h} = \frac{16-11}{1} = 5 \end{aligned}\]

계산한 값과 실제로 일치하는지 확인.

num_diff = np.gradient(f)
print("np.gradient의 출력값")
print(num_diff)
for i in range(len(num_diff)):
    display(Markdown(rf'$x_{i+1}$에서의 도함수의 근삿값 $\frac{{dy}}{{dx}}|_{{x = x_{i+1}}}$ ~= {num_diff[i]}'))
np.gradient의 출력값
[1.  1.5 2.5 3.5 4.5 5. ]

\(x_1\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_1}\) ~= 1.0

\(x_2\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_2}\) ~= 1.5

\(x_3\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_3}\) ~= 2.5

\(x_4\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_4}\) ~= 3.5

\(x_5\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_5}\) ~= 4.5

\(x_6\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_6}\) ~= 5.0

Ex) \(dx \not = 1\) (default가 아닐 경우)

거리\(dx=2\)일때 계산한,\(x_2,x_5\)에서 미분계수의 2차중앙차분근사는 다음과 같다.
\[\begin{aligned} &f^{'}(x_2) \overset{\sim}{=} \frac{f(x_3)-f(x_1)}{2h} = \frac{4-1}{4} = 0.75 \\ &f^{'}(x_5) \overset{\sim}{=} \frac{f(x_6)-f(x_4)}{2h} = \frac{16-7}{4} = 2.25 \\ &\text{where, } h = x_3-x_1 = x_6-x_4 = 2 \end{aligned}\] 거리가 \(dx=2\)일때 배열의 양 끝값에서 전향,후향차분근사를 통한 미분계수의 값은 다음과 같다. \[\begin{aligned} &f^{'}(x_1) = \frac{f(x_2) - f(x_1)}{h} = \frac{2-1}{2} = 0.5 \\ &f^{'}(x_6) = \frac{f(x_6) - f(x_5)}{h} = \frac{16-11}{2} = 2.5 \end{aligned}\]

x값 사이의 거리\(dx\)를 바꾸고 싶다면? => 두번째 인수에 스칼라 대입하면 된다.

dx = 2
num_diff = np.gradient(f,dx)
print("np.gradient의 출력값")
print(num_diff)
for i in range(len(num_diff)):
    display(Markdown(rf'$x_{i+1}$에서의 도함수의 근삿값 $\frac{{dy}}{{dx}}|_{{x = x_{i+1}}}$ ~= {num_diff[i]}'))
np.gradient의 출력값
[0.5  0.75 1.25 1.75 2.25 2.5 ]

\(x_1\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_1}\) ~= 0.5

\(x_2\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_2}\) ~= 0.75

\(x_3\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_3}\) ~= 1.25

\(x_4\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_4}\) ~= 1.75

\(x_5\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_5}\) ~= 2.25

\(x_6\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_6}\) ~= 2.5

Ex) x값의 좌표를 직접 정해주는 경우

이전에는 각각의 인덱스간의 거리는 모두 동일하게 기본값 1이거나 다른값을 사용했다. 그러지 않고 \(x_1,x_2,\dots,x_6\)의 좌표를 직접 지정해주는 것도 가능하다. 함수의 2번재 인수에 좌표를 직접 넣어주면 된다.

먼저 x값의 좌표를 다음과 같다고 해보자.

x = np.array([0., 1., 1.5, 3.5, 4., 6.], dtype=float)
f = np.array([1,2,4,7,11,16],dtype=float)
print("각각의 좌표와 함숫값")
for i in range(len(x)):
    display(Markdown(rf'$x_{i+1}$ = {x[i]}, $f(x_{i+1})$ = {f[i]}'))
각각의 좌표와 함숫값

\(x_1\) = 0.0, \(f(x_1)\) = 1.0

\(x_2\) = 1.0, \(f(x_2)\) = 2.0

\(x_3\) = 1.5, \(f(x_3)\) = 4.0

\(x_4\) = 3.5, \(f(x_4)\) = 7.0

\(x_5\) = 4.0, \(f(x_5)\) = 11.0

\(x_6\) = 6.0, \(f(x_6)\) = 16.0

각각의 좌표에서 도함수의 근삿값을 구하면 아래와 같다.(수식 계산은 잘 모르겠네요 … 추후에 더 공부하겠습니다!)

num_diff = np.gradient(f,x)
print("np.gradient의 출력값")
print(num_diff)
for i in range(len(num_diff)):
    display(Markdown(rf'$x_{i+1}$에서의 도함수의 근삿값 $\frac{{dy}}{{dx}}|_{{x = x_{i+1}}}$ ~= {num_diff[i]}'))
np.gradient의 출력값
[1.  3.  3.5 6.7 6.9 2.5]

\(x_1\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_1}\) ~= 1.0

\(x_2\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_2}\) ~= 2.9999999999999996

\(x_3\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_3}\) ~= 3.5

\(x_4\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_4}\) ~= 6.700000000000001

\(x_5\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_5}\) ~= 6.899999999999999

\(x_6\)에서의 도함수의 근삿값 \(\frac{dy}{dx}|_{x = x_6}\) ~= 2.5

2차원 배열의 경우

2차원 배열의 경우 axis=0(세로축)과 axis=1(가로축) 두 축방향으로 계산한 도함수의 근삿값을 반환한다.axis=0일 경우 각각의 열마다 따로따로 독립적으로 \(x_1,x_2...\)에 대한 함숫값\(f(x_1),f(x_2),\dots\)이 있다고 생각하면 되고 axis=1일 경우 각각의 행마다 따로따로 독립적으로 \(x_1,x_2...\)에 대한 함숫값\(f(x_1),f(x_2),\dots\)이 있다고 생각하면 된다.또한 1차원 배열과 유사하게 각각의 행,열의 끝값에는 전향or후향차분근사를 행,열의 내부에 있는 값은 중앙차분근사를 사용한다.

Ex) \(dx=1,dy=1\)

2차원 배열은 다음과 같다.

np.array([[1, 2, 6], [3, 4, 5]], dtype=float)
array([[1., 2., 6.],
       [3., 4., 5.]])
ax0_difcoef,ax1_difcoef= np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float))
print(f'axis = 0 방향으로 도함수의 근삿값 계산 \n{ax0_difcoef}')
print(f'axis = 1 방향으로 도함수의 근삿값 계산 \n{ax1_difcoef}')
axis = 0 방향으로 도함수의 근삿값 계산 
[[ 2.  2. -1.]
 [ 2.  2. -1.]]
axis = 1 방향으로 도함수의 근삿값 계산 
[[1.  2.5 4. ]
 [1.  1.  1. ]]

Ex) \(dx \not = 1,dy \not = 1\) (default가 아닌 경우)

각각의 행,열마다 거리를 따로 설정해주고 싶은 경우? => 스칼라 2개 인수로 전달.

dx = 2;dy = 2
ax0_difcoef,ax1_difcoef= np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float),dx,dy)
print(f'axis = 0 방향으로 도함수의 근삿값 계산 \n{ax0_difcoef}')
print(f'axis = 1 방향으로 도함수의 근삿값 계산 \n{ax1_difcoef}')
axis = 0 방향으로 도함수의 근삿값 계산 
[[ 1.   1.  -0.5]
 [ 1.   1.  -0.5]]
axis = 1 방향으로 도함수의 근삿값 계산 
[[0.5  1.25 2.  ]
 [0.5  0.5  0.5 ]]

Appendix

전향차분근사 유도

\(x_1,x_2,\dots,x_{i-1},x_i,x_{i+1},\dots,x_n\)과 각각에 대응하는 함숫값 \(f(x_1),f(x_2),\dots,f(x_{i-1}),f(x_i),f(x_{i+1}),\dots,f(x_n)\) 주어진 데이터라고 가정하자. 목적은 x_i에서의 미분계수를 구하는 것이다. \(a = x_i\)에서 함수\(f(x)\)의 테일러 급수 근사는 다음과 같다.
\[f(x) = \sum_{n=0}^{\infty}\frac{f^{n}(x_i)}{n!}(x-x_i)^n = f(x_i) + \frac{f^{'}(x_i)}{1!}(x-x_i) + \frac{f^{''}(x_i)}{2!}(x-x_i)^2 + \dots \]

\(x=x_{i+1}\)에서의 함숫값은 다음과 같다.
\[f(x_{i+1}) = \sum_{n=0}^{\infty}\frac{f^{n}(x_i)}{n!}(x_{i+1}-x_i)^n = f(x_i) + \frac{f^{'}(x_i)}{1!}(x_{i+1}-x_i) + \frac{f^{''}(x_i)}{2!}(x_{i+1}-x_i)^2 + \dots \]

\(f'(x_i)\)가 포함된항만 남겨두고 나머지는 이항하면 다음과 같다.
\[f^{'}(x_i)(x_{i+1}-x_i) = f(x_{i+1}) - f(x_i) - \frac{f^{''}(x_i)}{2!}(x_{i+1}-x_i)^2 + \dots\]

\(h = x_{i+1}-x_i\)로 두고 양변을 h로 나누면 다음과 같다.
\[f'(x_i) = \frac{f(x_{i+1})}{h} - \frac{f(x_i)}{h} - \frac{hf^{''}(x_i)}{2!} - \frac{h^2f^{'''}(x_i)}{3!}\]

여기서 우변의 두개의 항만 남겨두고 \(O(h) = - \frac{hf^{''}(x_i)}{2!} - \frac{h^2f^{'''}(x_i)}{3!} - \dots\)라 하면 다음과 같다.
\[\begin{align} &f'(x_i) \overset{\sim}{=} \frac{f(x_{i+1})-f(x_i)}{h}\\ &O(h) = - \frac{hf^{''}(x_i)}{2!} - \frac{h^2f^{'''}(x_i)}{3!} - \dots\\ &\text{where, } h = x_{i+1} - x_i \nonumber \end{align}\]

후향차분근사 유도

\(x_1,x_2,\dots,x_{i-1},x_i,x_{i+1},\dots,x_n\)과 각각에 대응하는 함숫값 \(f(x_1),f(x_2),\dots,f(x_{i-1}),f(x_i),f(x_{i+1}),\dots,f(x_n)\) 주어진 데이터라고 가정하자. 목적은 x_i에서의 미분계수를 구하는 것이다. \(a = x_i\)에서 함수\(f(x)\)의 테일러 급수 근사는 다음과 같다.
\[f(x) = \sum_{n=0}^{\infty}\frac{f^{n}(x_i)}{n!}(x-x_i)^n = f(x_i) + \frac{f^{'}(x_i)}{1!}(x-x_i) + \frac{f^{''}(x_i)}{2!}(x-x_i)^2 + \dots \]

\(f(x_i)\)는 다음과 같다.
\[f(x_{i-1}) = \sum_{n=0}^{\infty}\frac{f^n(x_i)}{n!}(x_{i-1}-x_i)^n = f(x_i) + \frac{f^{'}(x_i)}{1!}(x_{i-1}-x_i) + \frac{f^{''}(x_i)}{2!}(x_{i-1}-x_i)^2+\dots \]

1차미분이 포함된 항만 남기고 나머지는 이항하면 다음과 같다.
\[f^{'}(x_i)(x_{i-1}-x_i) = f(x_{i-1}) - f(x_i) - \frac{f^{''}(x_i)}{2!}(x_{i-1}-x_i)^2-\frac{f^{'''}(x_i)}{3!}(x_{i-1}-x_i)^3-\dots \]

\(h = x_{i} - x_{i-1}\)로 놓으면 다음과 같다.
\[f^{'}(x_i)(-h) = f(x_{i-1}) - f(x_i) - \frac{f^{''}(x_i)}{2!}h^2+\frac{f^{'''}(x_i)}{3!}h^3-\dots \]

양변을 \(-h\)로 나누면 다음과 같다.
\[\begin{aligned} f^{'}(x_i) &= \frac{f(x_{i-1})}{-h} + \frac{f(x_i)}{h} + \frac{f^{''}(x_i)}{2!}h-\frac{f^{'''}(x_i)}{3!}h^2+\dots \\ &=\frac{f(x_i)-f(x_{i-1}) }{h} + \frac{f^{''}(x_i)}{2!}h-\frac{f^{'''}(x_i)}{3!}h^2+\dots \end{aligned}\]

마찬가지로 우변의 두개 항만 남겨두고 \(O(h) = \frac{hf^{''}(x_i)}{2!} - \frac{h^2f^{'''}(x_i)}{3!} + \dots\)라 하면 다음과 같다. \[\begin{align} &f'(x_i) \overset{\sim}{=} \frac{f(x_{i})-f(x_{i-1})}{h}\\ &O(h) = \frac{h}{2!}f^{''}(x_i) - \frac{h^2}{3!}f{'''}(x_i)+\dots \\ &\text{where, } h = x_{i} - x_{i-1}, \nonumber \end{align}\]

중앙차분근사 유도

전향차분근사와 후향차분근사의 유도과정에서의 테일러 전개식은 다음과 같다.
\[f'(x_i) = \frac{f(x_{i+1})}{h} - \frac{f(x_i)}{h} - \frac{hf^{''}(x_i)}{2!} - \frac{h^2f^{'''}(x_i)}{3!} - ...\] \[f'(x_i) = \frac{f(x_{i})}{h} - \frac{f(x_{i-1})}{h} + \frac{hf^{''}(x_i)}{2!} - \frac{h^2f^{'''}(x_i)}{3!} + ...\]

두 식을 더해주면 다음과 같다. \[\begin{aligned} &2f^{'}(x_i) = \frac{f(x_{i+1})-f(x_{i-1})}{h} - \frac{2h^2f^{'''}(x_i)}{3!} \\ &\Leftrightarrow f^{'}(x_i) = \frac{f(x_{i+1})-f(x_{i-1})}{2h} - \frac{h^2f^{'''}(x_i)}{3!} - ... \end{aligned}\]

마찬가지로 우변의 두개 항만 남겨두고 절단오차\(O(h^2) = -\frac{h^2f^{'''}(x_i)}{3!} - \dots\)라 하면 다음과 같다. \[\begin{align} &f'(x_i) \overset{\sim}{=} \frac{f(x_{i+1})-f(x_{i-1})}{2h}\\ &O(h) = - \frac{h^2}{3!}f{'''}(x_i)+\dots \\ &\text{where, } h = x_{i} - x_{i-1}\,\,\text{or}\,\, h = x_{i+1} - x_i\nonumber \end{align}\]

참고자료

다크프로그래머 - 테일러급수의 이해와 활용
위키피디아 - 테일러급수
링크
링크2
링크3
링크4
링크5