注解

此笔记本可在此处下载: 03_Numerical_Derivation.ipynb

数值数据的推导

代码作者:Emile Roux emile.roux@univ-smb.fr

RISE 幻灯片

范围

  • 有限数 \(N\) 数据点数量 \((x,y)\) 是可用的,它描述了一个函数 \(f(x)\) :计算导数 \(\dfrac{{df}}{{dx}}\)

https://en.wikipedia.org/wiki/Numerical_differentiation

#setup
%load_ext autoreload
%matplotlib nbagg
%autoreload 2
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl

创建合成数据

对于本笔记本,我们使用来自已知函数的数据混合。这样我们就可以检查结果的准确性。

  • 第一个函数

# The function
def f(x):
    return (x**2-3*x+2*np.sin(5*x))

# The derivative
def df(x):
    return 2*x - 3 + 10 * np.cos(5*x)
  • 第二功能

# The function
def f(x):
    return (x**2)

# The derivative
def df(x):
    return 2*x

绘制函数及其嘲笑:

N = 400
xmin, xmax = 0., 4
x = np.linspace(xmin, xmax, N)
fig = plt.figure()
plt.plot(x,f(x),'b',label = "$f(x)$")
plt.legend()
plt.grid()
<IPython.core.display.Javascript object>
fig = plt.figure()
plt.plot(x,df(x),'b',label = "$\dfrac{df}{dx}$")
plt.legend()
plt.grid()
<IPython.core.display.Javascript object>

现在我们假设这个函数只有40个点是已知的:

N = 40
xmin, xmax = 0., 4
xi = np.linspace(xmin, xmax, N)
fi = f(xi)
fig = plt.figure()
plt.plot(xi,fi,'o',label = "the discretize data $(x_i,f_i)$")
plt.legend()
plt.grid()
<IPython.core.display.Javascript object>

一点有限差分公式

\(\dfrac{df}{dx} = \dfrac{f(x_{i+1})-f(x_i)}{x_{i+1}-x_i}\)

numpy diff()函数是计算此公式的快速方法:

df_1p = np.diff(fi)/np.diff(xi)

但是becarefull生成的数组的大小等于 \(n-1\) .

fig = plt.figure()
plt.plot(x,df(x),'b',label = "Analytical derivative")
plt.plot(xi[:-1],df_1p,'ro',label = "Finite difference derivative (1 point)")
plt.legend()
plt.grid()
<IPython.core.display.Javascript object>

两点有限差分公式

\(\dfrac{df}{dx} = \dfrac{f(x_{i+1})-f(x_{i-1})}{x_{i+1}-x_{i-1}}\)

numpy数组的切片方法是一种很好的操作方法

# Slicing exemple
a=np.linspace(0,6,7)
print(a[2:])
print(a[:-2])
[ 2.  3.  4.  5.  6.]
[ 0.  1.  2.  3.  4.]

使用numpy数组的切片方法,可以快速计算2点公式:

df_2p = (fi[2:] - fi[:-2])/(xi[2:] - xi[:-2])
fig = plt.figure()
plt.plot(x,df(x),'b',label = "Analytical derivative")
plt.plot(xi[:-1],df_1p,'ro',label = "Finite difference derivative (1 point)")
plt.plot(xi[1:-1],df_2p,'gs',label = "Finite difference derivative (2 points)")
plt.legend()
plt.grid()
<IPython.core.display.Javascript object>

我们来看看导数计算的误差

fig = plt.figure()
plt.plot(xi[:-1],(df_1p-df(xi[:-1])),'ro',label = "Finite difference derivative (1 point)")
plt.plot(xi[1:-1],(df_2p-df(xi[1:-1])),'gs',label = "Finite difference derivative (2 points)")
plt.legend()
plt.grid()
<IPython.core.display.Javascript object>

如果数据有噪声,附加什么?

fi_noise = f(xi) + 0.2*np.random.randn(fi.size)
fig = plt.figure()
plt.plot(x,f(x),':r',label = "$f(x)$")
plt.plot(xi,fi_noise,'o',label = "noisy data")
plt.legend()
plt.grid()
<IPython.core.display.Javascript object>

两点法更准确。让我们用它来推导噪声数据:

df_2p_n = (fi_noise[2:] - fi_noise[:-2])/(xi[2:] - xi[:-2])
fig = plt.figure()
plt.plot(x,df(x),':r',label = "Analytical derivative")
plt.plot(xi[1:-1],df_2p_n,'-g',label = "Finite difference derivative of noisy data")
plt.legend()
plt.grid()
<IPython.core.display.Javascript object>

此结果不值得进一步使用。应使用其他方法评估噪声数据的导数。