两个版本的衍生计算之间的准确度差异是多少?

时间:2016-12-03 03:18:47

标签: python algorithm floating-accuracy

以下是旨在计算给定函数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代码。

  1. 第一版(解决方案)

    fx = f(x) # evalute f(x)
    x[ix] += h 
    fxh = f(x) # evalute f(x+h)
    x[ix] -= h
    numgrad = (fxh - fx) / h
    
  2. 第二版(我的版本)

      <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">&times;</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>
    
  3. 它表明第一版提供了更好的准确性,任何人都可以解释为什么会这样,这两个计算之间有什么区别?

    更新 我没有意识到这是一个数学问题,我认为这是一个与浮动精度影响有关的问题。正如 MSeifert 所建议的那样,我确实认为浮点噪声很重要,当暴露于噪声时,小幅度结果更容易受到影响。

2 个答案:

答案 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)

这比单边近似更接近真实值(两个数量级)。