[英]Numerical differentiation: Error does not behave as expected
我想使用差商在数字上区分 function f(x, y)
关于x
和y
def dfdx_v2(x, y, h):
return 0.5 * (f(x+h, y) - f(x-h, y)) / h
def dfdy_v2(x, y, h):
return 0.5 * (f(x, y+h) - f(x, y-h)) / h
其中h
是区间的长度。 在我的假设中,上面的实现应该越小h
越准确。 但是,我注意到情况并非如此。 当我 plot 出现h = [1e-12, 1e-4]
的错误时,我得到下图:
我会预料到,如果我让h
go 为零,误差会越来越小。 但是,对于非常小的h
,误差会大大增加。 另一个有趣的观察是误差波动非常强烈的区域。 为什么会这样? 我本来预计,该错误是一个单调增加的 function 没有任何波动。 有什么想法为什么错误会以这种方式表现?
这是我用来生成上图的代码:
import numpy as np
import matplotlib.pyplot as plt
def f(x, y):
return x * x + y * x + x * y**2 + np.exp(x) + np.sin(x) * np.cos(x) + np.sin(y)
def dfdx_v1(x, y):
return 2 * x + y + y**2 + np.exp(x) + np.cos(x)**2 - np.sin(x)**2
def dfdy_v1(x, y):
return x + 2 * x * y + np.cos(y)
def dfdx_v2(x, y, h):
return 0.5 * (f(x+h, y) - f(x-h, y)) / h
def dfdy_v2(x, y, h):
return 0.5 * (f(x, y+h) - f(x, y-h)) / h
def main():
x = 2.1415
y = -1.1415
h_min = 1e-12
h_max = 1e-4
n_steps = 10000
h = np.linspace(h_min, h_max, n_steps)
error = list()
for i in range(n_steps):
error.append(np.sqrt((dfdx_v1(x, y) - dfdx_v2(x, y, h[i]))**2 + (dfdx_v1(x, y) - dfdx_v2(x, y, h[i]))**2))
plt.plot(h, error, linewidth=0.2, label="Error")
plt.yscale("log")
plt.legend()
plt.show()
if __name__ == "__main__":
main()
误差不是单调增加的事实是数值微分的一个已知问题。 请参阅此链接。
基本上,当步长h
变得太小时,诸如f(x+h, y) - f(xh, y)
之类的表达式由于存在数值错误而无法正确计算。 发生这种情况是因为计算机以有限精度算术工作,因此计算f(x+h, y)
和f(xh, y)
时误差很小。 减去两个非常接近的数字,即f(x+h, y)
和f(xh, y)
对于足够小的h
而言,通常会得到以错误为主的结果。 除以h
不会纠正现有的错误。
这与 Python(或大多数其他编程语言)中float
的精度有关。 当h
趋于零时, f(x, y+h)
和f(x, yh)
之间的差异也趋于零 - 但是,后者不会同样平滑。 根据参数的确切值,差异有时会(一点点)更大,有时会更小。
由于数字更大, dfdy_v2
中的错误将大于h
中的错误。 因此误差的指数会更大。 由于f
的量化和严格增加的误差,当h
接近零时,这都会导致波动。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.