以下是旨在计算给定函数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
的导数的Python代码。
第一版(解决方案)
fx = f(x) # evalute f(x)
x[ix] += h
fxh = f(x) # evalute f(x+h)
x[ix] -= h
numgrad = (fxh - fx) / h
第二版(我的版本)
<ul class="cropped-images">
<li class="la active"><a data-content="No 1" href="#lightbox" data-toggle="modal" data-slide-to="0"><img src="images/thumbs/1.jpg" alt="No 1"></a></li>
<li class="la"><a data-content="No 2" href="#lightbox" data-toggle="modal" data-slide-to="1"><img src="images/thumbs/2.jpg" alt="No 2"></a></li>
<li class="la"> etc... </ul>
<div id="lightbox" class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">TITLE</h4>
</div>
<div id="carousel-example-generic" class="carousel slide">
<!-- Wrapper for slides -->
<div class="carousel-inner">
<div class="item active">
<img src="images/large/1.jpg" alt="...">
<div class="carousel-caption">One Image</div>
</div>
<div class="item">
<img src="images/large/2.jpg" alt="...">
<div class="carousel-caption">Another Image</div>
</div>
... etc...
<!-- Controls -->
controls code
</div>
</div>
</div>
</div>
它表明第一版提供了更好的准确性,任何人都可以解释为什么会这样,这两个计算之间有什么区别?
更新 我没有意识到这是一个数学问题,我认为这是一个与浮动精度影响有关的问题。正如 MSeifert 所建议的那样,我确实认为浮点噪声很重要,当暴露于噪声时,小幅度结果更容易受到影响。
答案 0 :(得分:3)
这不是Python问题,而是纯粹的algorythmic问题。假设函数f具有不错的属性,您可以查看其Taylor series开发:
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中的项已经下降,错误的大小顺序为h 2
当然,只有存在所需的衍生物才有意义......
答案 1 :(得分:0)
您的解决方案是“片面的”,您比较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)
请注意,双面结果更接近预期值。这甚至可能导致catastrophic cancellation。然后,您最终可能会得到一个主要由浮点噪声控制的结果。这种效果进一步增强,因为该值除以非常小的数字。
通过使用两侧,您可以增加(取决于您的功能!)差异,从而增加取消的点。但在我看来,最大的优势在于你考虑了两侧的坡度(平均一点)。例如:
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)
这比单边近似更接近真实值(两个数量级)。