繁体   English   中英

数值微分:错误的行为不符合预期

[英]Numerical differentiation: Error does not behave as expected

我想使用差商在数字上区分 function f(x, y)关于xy

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM