提问人:GabrielChu 提问时间:12/3/2016 最后编辑:GabrielChu 更新时间:12/19/2016 访问量:215
两个版本的导数计算之间的精度差异是什么?
What's the accuracy difference between the two versions derivative calculation?
问:
以下是旨在计算给定函数导数的Python代码。f
版本 1(解决方案)
x[ix] += h # increment by h fxh = f(x) # evalute f(x + h) x[ix] -= 2 * h fxnh = f(x) x[ix] += h numgrad = (fxh - fxnh) / 2 / h
版本二(我的版本)
fx = f(x) # evalute f(x) x[ix] += h fxh = f(x) # evalute f(x+h) x[ix] -= h numgrad = (fxh - fx) / h
它表明版本一提供了更好的准确性,谁能解释一下为什么会这样,两种计算之间有什么区别?
更新我一开始没有意识到这是一个数学问题,我以为这是一个与浮动精度影响有关的问题。正如MSeifert所建议的,我确实同意浮点噪声很重要,当暴露于噪声时,小幅度的结果更容易受到影响。
答:
0赞
MSeifert
12/19/2016
#1
你的解决方案是“片面的”,你比较,一般的解决方案是“双面的”。f(x+h) - f(x)
f(x+h) - f(x-h)
知道什么就好了
它表明版本一提供了更好的准确性
方法。因为这太笼统了。
但我想我有一个例子,在这里可能很合适:
def double_sided_derivative(f, x, h):
x_l, x_h = x - h, x + h
return (f(x_h) - f(x_l)) / 2 / h
def one_sided_derivative(f, x, h):
x_h = x + h
return (f(x_h) - f(x)) / h
h = 1e-8
def f(x):
return 1e-6 * x
# difference to real derivate:
double_sided_derivative(f, 10, h) - 1e-6, one_sided_derivative(f, 10, h) - 1e-6
# (6.715496481486314e-14, 1.5185825954029317e-13)
请注意,双面结果更接近预期值。这甚至可能导致灾难性的取消。然后,您最终可能会得到一个主要由浮点噪声控制的结果。这种效果进一步增强,因为该值除以一个非常小的数字。
通过使用两边,您可以增加(取决于您的功能!)差异,从而增加可能发生取消的点。但在我看来,最大的优势是你把两侧的斜率都考虑在内(稍微平均一下)。例如:
h = 1e-6
def f(x):
return 4 + x + 5 * x**2
def fdx(x):
return 1 + 10 * x
x = 10
double_sided_derivative(f, x, h) - fdx(x), one_sided_derivative(f, x, h) - fdx(x)
# (-2.7626811061054468e-08, 4.974594048690051e-06)
这比单侧近似更接近真实值(两个数量级)。
评论
0赞
Phillip
12/19/2016
我想说最大的优点是第一个版本的错误在,而另一个版本的错误在.O(h²)
O(h)
0赞
MSeifert
12/19/2016
@Phillip我想说这取决于功能。我主要关注浮点方面(它标有浮点精度)。还是浮点运算的结果?O(h**2)
0赞
Phillip
12/19/2016
它是一个数学结果,适用于存在一阶导数和二阶导数的所有函数,它是数学对象上的一个,而不是它们在计算机中的表示。
0赞
MSeifert
12/19/2016
是的,我知道。我只是感到困惑,因为你的原始评论模棱两可。在这种情况下,错误可能意味着任何事情。感谢您的澄清。
3赞
Serge Ballesta
12/19/2016
#2
这不是一个 Python 问题,而是一个纯粹的算法问题。假设函数 f 具有很好的性质,您可以查看它的泰勒级数发展:
f(x+h) = f(x) + h f'(x) + h*h/2 f"(x) + h*h*h/6 f'''(x) + o(h3)
它来了,你的第一个表格给出了错误:
((f(x+h) - f(x)) / h) - f'(x) = h/2 f"(x) + o(h)
这是 h 大小级的误差
如果使用第二种形式,则会获得:
((f(x+h) - f(x-h)) / 2*h) - f'(x) = h*h/3 f'''(x) + o(h2)
h 中的项已下降,误差为 h2 的大小级
当然,只有当所需的衍生品存在时,它才有意义......
评论
x[ix]