zoukankan      html  css  js  c++  java
  • 数值计算day7-数值微分

    上一节课主要介绍了曲线拟合与插值,曲线拟合主要包括线性拟合(单特征线性回归和非线性拟合(非线性方程特征变换、高阶多项式拟合),插值包括多项式插值(拉格朗日形式、牛顿形式)、样条插值(线性插值、二次样条插值、三次样条插值),其中三次样条插值还有一个便于求解的拉格朗日形式。这里的曲线拟合与机器学习中的回归问题非常相似,具有很大的参考意义。本节课主要介绍几种求解微分的数值方法。

    1. 有限差分法

    给定一个函数(f(x))(f(x))(x=a)处的微分(f'(x))定义为:$$frac{df(x)}{dx}|{x=a}=f'(a)=lim{x ightarrow} frac{f(x)-f(a)}{x-a}$$ 图上的解释是(f(x))(x=a)处的斜率:
    image.png

    前向、后向以及中心差分法是最简单的有限差分法:

    • 前向差分:$$frac{df}{dx}|{x=x_i}=frac{f(x{i+1})-f(x_i)}{x_{i+1}-x_i}$$

    • 后向差分:$$frac{df}{dx}|{x=x_i}=frac{f(x{i})-f(x_{i-1})}{x_{i}-x_{i-1}}$$

    • 中心差分:$$frac{df}{dx}|{x=x_i}=frac{f(x{i+1})-f(x_{i-1})}{x_{i+1}-x_{i-1}}$$

    image.png

    例:(f(x)=x^3),计算(f(x))(x=3)处的微分
    (a) (x=2,x=3,x=4)
    真实值:(f'(x)=3x^2),(f'(3)=27)
    前向差分:(f'(3)=frac{f(4)-f(3)}{4-3}=64-27=37)
    后向差分:(f'(3)=frac{f(3)-f(2)}{3-2}=27-8=19)
    中心差分:(f'(3)=frac{f(4)-f(2)}{4-2}=frac{64-8}{2}=28)
    (b) (x=2.75,x=3,x=3.25)
    前向差分:(f'(3)=frac{f(3.25)-f(3)}{0.25}=29.3125)
    后向差分:(f'(3)=frac{f(3)-f(2.75)}{0.25}=24.8125)
    中心差分:(f'(3)=27.0625)

    可以看到中心差分最为准确,且两点间距变小时,差分计算会更为准确。
    MATLAB实现:

    function dx = derivative(x,y)
    % derivative calculates the derivative of a function that is given by a set
    % of points. The derivative at the first and last points are calculated by
    % using the forward and backward finite difference formula, respectively.
    % The derivative at all the other points is calculated by the central
    % finite difference formula.
    % Input variables:
    % x  A vector with the coordinates x of the data points.
    % y  A vector with the coordinates y of the data points.
    % Output variable:
    % dx  A vector with the value of the derivative at each point.
    
    n = length(x);
    dx(1)=(y(2)-y(1))/(x(2)-x(1));
    for i=2:n-1
        dx(i)=(y(i+1)-y(i-1))/(x(i+1)-x(i-1));
    end
    dx(n)=(y(n)-y(n-1))/(x(n)-x(n-1));
    

    2. 泰勒公式有限差分法

    2.1 一阶微分(两点法)
    • 前向展开:
      (f(x))在点(x_{i+1})处的值可以使用如下泰勒公式来逼近:$$f(x_{i+1})=f(x_i)+f'(x_i)h+frac{1}{2!}f''(x_i)h2+frac{1}{3!}f'''(xi_1)h3$$ 其中(h=x_{i+1}-x_i),(xi_1)(x_{i+1})(x_i)之间的数。求解该公式,有:$$f'(x_i)=frac{f(x_{i+1})-f(x_i)}{h}-frac{1}{2!}f''(x_i)h-frac{1}{3!}f'''(xi_1)h^2=frac{f(x_{i+1})-f(x_i)}{h}+O(h)$$ 等同于之前的前向差分,具有一阶准确度

    • 后向展开:
      (f(x))在点(x_{i-1})处的值可以使用如下泰勒公式来逼近:$$f(x_{i-1})=f(x_i)-f'(x_i)h+frac{1}{2!}f''(x_i)h2-frac{1}{3!}f'''(xi_2)h3$$ 其中(h=x_{i}-x_{i-1}),(xi_1)(x_{i-1})(x_i)之间的数。求解该公式,有:$$f'(x_i)=frac{f(x_{i})-f(x_{i-1})}{h}+frac{1}{2!}f''(x_i)h-frac{1}{3!}f'''(xi_2)h^2=frac{f(x_{i})-f(x_{i-1})}{h}+O(h)$$ 等同于之前的后向差分,具有一阶准确度

    • 中心展开(假设间距相同)
      结合上述两种展开,可以得到:$$f(x_{i+1})-f(x_{i-1})=2hf'(x_i)+frac{1}{3!}(f'''(xi_1)+f'''(xi_2))h^3$$ 因此有 $$f'(x_i)=frac{f(x_{i+1})-f(x_{i-1})}{2h}+O(h^2)$$ 等同于之前的中心差分,可以看到,具有二阶准确度

    2.2 一阶微分(三点法)

    分别写出(x_{i-2},x_{i-1},x_{i+1},x_{i+2})四点的泰勒展开:

    • (f(x_{i+1})=f(x_i)+f'(x_i)h+frac{1}{2!}f''(x_i)h^2+frac{1}{3!}f'''(xi_1)h^3)

    • (f(x_{i-1})=f(x_i)-f'(x_i)h+frac{1}{2!}f''(x_i)h^2-frac{1}{3!}f'''(xi_2)h^3)

    • (f(x_{i+2})=f(x_i)+f'(x_i)2h+frac{1}{2!}f''(x_i)(2h)^2+frac{1}{3!}f'''(xi_3)(2h)^3)

    • (f(x_{i-2})=f(x_i)-f'(x_i)2h+frac{1}{2!}f''(x_i)(2h)^2-frac{1}{3!}f'''(xi_4)(2h)^3)

    可以看到:$$f(x_{i+2})-4f(x_{i+1})=-3f(x_i)-2f'(x_i)h+frac{f'''(xi_3)}{3!}(2h)3-frac{4}{3!}f'''(xi_1)h3$$ 进一步得:$$f'(x_i)=frac{-3f(x_i)+4f(x_{i+1})-f(x_{i+2})}{2h}+O(h^2)$$ 这是一阶微分的三点前向公式,具有二阶准确度,类似地,可以得到如下具有二阶准确度的三点后向公式:$$f'(x_i)=frac{f(x_{i-2})-4f(x_{i-1})+3f(x_i)}{2h}+O(h^2)$$

    2.3 二阶微分(三点法)

    注意:

    • (f(x_{i+1})=f(x_i)+f'(x_i)h+frac{1}{2!}f''(x_i)h^2+frac{1}{3!}f'''(x_i)h^3+frac{1}{4!}f^{(4)}(xi_1)h^4)

    • (f(x_{i-1})=f(x_i)-f'(x_i)h+frac{1}{2!}f''(x_i)h^2-frac{1}{3!}f'''(x_i)h^3+frac{1}{4!}f^{(4)}(xi_2)h^4)

    • (f(x_{i+2})=f(x_i)+f'(x_i)2h+frac{1}{2!}f''(x_i)(2h)^2+frac{1}{3!}f'''(x_i)(2h)^3+frac{1}{4!}f^{(4)}(xi_3)(2h)^4)

    • (f(x_{i-2})=f(x_i)-f'(x_i)2h+frac{1}{2!}f''(x_i)(2h)^2-frac{1}{3!}f'''(x_i)(2h)^3+frac{1}{4!}f^{(4)}(xi_4)(2h)^4)

    前面两式相加,得 $$f(x_{i+1})+f(x_{i-1})=2f(x_i)+f''(x_i)h2+frac{1}{4!}f{(4)}(xi_1)h4+frac{1}{4!}f{(4)}(xi_2)h^4$$ 可得$$f''(x_i)=frac{f(x_{i+1})-2f(x_i)+f(x_{i-1})}{h2}+O(h2)$$ 此即为三点中心差分公式,具有二阶准确度。类似地,推导可得如下五点中心差分公式:$$ f''(x_i)=frac{-f(x_{i-2})+16f(x_{i-1})-30f(x_i)+16f(x_{i+1})-f(x_{i+2})}{12h2}+O(h4) $$ 具有四阶准确度。

    另一方面:$$f(x_{i+2})-2f(x_{i+1})=-f(x_i)+f''(x_i)h2+frac{6f'''(x_i)}{3!}h3+frac{1}{4!}f{(4)}(xi_3)(2h)4-frac{2}{4!}f{(4)}(xi_1)h4$$ 可得 $$f''(x_i)=frac{f(x_i)-2f(x_{i+1})+f(x_{i+2})}{h^2}+O(h)$$ 此即为三点前向差分公式,具有一阶准确度,类似可得如下具有一阶准确度三点后向差分公式: $$f''(x_i)=frac{f(x_{i-2})-2f(x_{i-1})+f(x_{i})}{h^2}+O(h)$$

    MATLAB实现:

    function [yd,ydd] = FirstScndDerivPt(x,y)
    n = length(x);
    h = x(2)-x(1);
    %  首个数据,一阶导数使用三点前向差分,二阶导数使用4点前向差分
    yd(1) = (-3*y(1)+4*y(2)-y(3))/(2*h);
    ydd(1) = (2*y(1)-5*y(2)+4*y(3)-y(4))/(h^2);
    
    % 中间数据,一阶导数使用两点中心差分,二阶导数使用三点中心差分
    for i=2:n-1
        yd(i)=(y(i+1)-y(i-1))/(2*h);
        ydd(i)=(y(i-1)-2*y(i)+y(i+1))/(h^2);
    end
    
    % 末尾数据,一阶导数使用三点后向差分,二阶导数使用4点后向差分
    yd(n) = (y(n-2)-4*y(n-1)+3*y(n))/(2*h);
    ydd(n) = (-y(n-3)+4*y(n-2)-5*y(n-1)+2*y(n))/(h^2);
    figure
    subplot(3,1,1)
    plot(x,y)
    subplot(3,1,2)
    plot(x,yd)
    subplot(3,1,3)
    plot(x,ydd)
    end
    

    3. 拉格朗日多项式求导公式

    对点((x_i,y_i),(x_{i+1},y_{i+1}),(x_{i+2},y_{i+2}))进行拉格朗日多项式插值,有 $$f(x)=frac{(x-x_{i+1})(x-x_{i+2})}{(x_i-x_{i+1})(x_i-x_{i+2})}y_i+frac{(x-x_{i})(x-x_{i+2})}{(x_{i+1}-x_{i})(x_{i+1}-x_{i+2})}y_{i+1}$$ $$+frac{(x-x_{i})(x-x_{i+1})}{(x_{i+2}-x_{i})(x_{i+2}-x_{i+1})}y_{i+2}$$
    此时 $$f'(x)=frac{2x-x_{i+1}-x_{i+2}}{(x_i-x_{i+1})(x_i-x_{i+2})}y_i+frac{2x-x_{i}-x_{i+2}}{(x_{i+1}-x_{i})(x_{i+1}-x_{i+2})}y_{i+1}$$ $$+frac{2x-x_{i}-x_{i+1}}{(x_{i+2}-x_{i})(x_{i+2}-x_{i+1})}y_{i+2}$$ 因此$$f'(x_i)=frac{2x_i-x_{i+1}-x_{i+2}}{(x_i-x_{i+1})(x_i-x_{i+2})}y_i+frac{x_{i}-x_{i+2}}{(x_{i+1}-x_{i})(x_{i+1}-x_{i+2})}y_{i+1}$$ $$+frac{x_{i}-x_{i+1}}{(x_{i+2}-x_{i})(x_{i+2}-x_{i+1})}y_{i+2}$$ 当(x_{i+1}-x_i=x_{i+2}-x_{i+1}=h)时,有 $$f'(x_i)=frac{-3y_i+4y_{i+1}-y_{i+2}}{2h}$$ 此式与三点前向差分公式一致。

    4. 数值偏微分

    image.png
    对二元函数(f(x,y)) ,其在点((a,b))处的偏微分定义为:$$frac{partial f}{partial x}|{(a,b)}=lim{x ightarrow a} frac{f(x,b)-f(a,b)}{x-a}$$ $$frac{partial f}{partial y}|{(a,b)}=lim{x ightarrow b} frac{f(a,y)-f(a,b)}{ y-b}$$ 对一阶偏微分(frac{partial f}{partial x})(frac{partial f}{partial y}),两点前向公式为:$$frac{partial f}{partial x}|{(x_i,y_i)}=frac{f(x{i+1},y_i)-f(x_i,y_i)}{x_{i+1}-x_i}$$ $$frac{partial f}{partial y}|{(x_i,y_i)}=frac{f(x{i},y_{i+1})-f(x_i,y_i)}{y_{i+1}-y_i}$$ 两点后向公式为:$$frac{partial f}{partial x}|{(x_i,y_i)}=frac{f(x{i},y_i)-f(x_{i-1},y_i)}{x_{i}-x_{i-1}}$$ $$frac{partial f}{partial y}|{(x_i,y_i)}=frac{f(x{i},y_{i})-f(x_i,y_{i-1})}{y_{i}-y_{i-1}}$$
    两点中心差分公式:$$frac{partial f}{partial x}|{(x_i,y_i)}=frac{f(x{i+1},y_i)-f(x_{i-1},y_i)}{2h_x}$$ $$frac{partial f}{partial y}|{(x_i,y_i)}=frac{f(x{i},y_{i+1})-f(x_i,y_{i-1})}{2h_y}$$ 对二阶偏微分(frac{partial^2 f}{partial x^2},frac{partial^2 f}{partial y^2}),三点中心差分公式为:$$frac{partial^2 f}{partial x2}|_{(x_i,y_i)}=frac{f(x_{i-1},y_i)-2f(x_i,y_i)+f(x_{i+1},y_i)}{h2_x}$$ $$frac{partial^2 f}{partial y2}|_{(x_i,y_i)}=frac{f(x_{i},y_{i-1})-2f(x_i,y_i)+f(x_{i},y_{i+1})}{h2_y}$$ 对二阶偏微分(frac{partial^2 f}{partial x partial y}=frac{partial}{partial x}(frac{partial f}{partial y})=frac{partial}{partial y}(frac{partial f}{partial x})),逐步计算即可:$$frac{partial^2 f}{partial x partial y}|{(x_i,y_i)}=frac{frac{f(x{i+1},y_{i+1})-f(x_{i-1},y_{i+1})}{2h_x}-frac{f(x_{i+1},y_{i-1})-f(x_{i-1},y_{i-1})}{2h_x}}{2h_y} ext{((frac{partial f}{partial x})取中心差分)}$$
    MATLAB实现:

    function [dfdx,dfdy] = ParDer(x,y,f)
    n = length(x);
    m = length(y);
    hx = x(2)-x(1);
    hy = y(2)-y(1);
    
    % 首位数据使用三点前向
    for j = 1:m
        dfdx(1,j) = (-3*f(1,j)+4*f(2,j)-f(3,j))/(2*hx);
    end 
    for i = 1:n
        dfdy(i,1) = (-3*f(i,1)+4*f(i,2)-f(i,3))/(2*hy);
    end
    
    % 两点中心差分
    for i = 2:n-1
        for j = 1:m
            dfdx(i,j) = (f(i+1,j)-f(i-1,j))/(2*hx);
        end
    end
    
    for j = 2:m-1
        for i = 1:n
            dfdy(i,j) = (f(i,j+1)-f(i,j-1))/(2*hy);
        end
    end
    
    % 末尾数据使用三点后向
    for j = 1:m
    dfdx(n,j) = (f(n-2,j)-4*f(n-1,j)+3*f(n,j))/(2*hx);
    end
    
    for i = 1:n
        dfdy(i,m) = (f(i,m-2)-4*f(i,m-1)+3*f(i,m))/(2*hy);
    end
    
    end
    

    5. Richardson外推加速算法

    Richardson外推加速算法能够把两个低精度的方法组合成一个高精度的计算方法,假设$$D=D(h)+k_2h2+k_4h4$$是一种数值微分计算方法,(D(h))是估计的微分,(k_2h^2)(k_4h^4)是估计误差,可以看到,具有二阶精度,如果把间距调整为(frac{h}{2}),则$$D=D(frac{h}{2})+k_2(frac{h}{2})2+k_4(frac{h}{2})4$$ 其精度仍是二阶的。但是有:$$4D-D=4D(frac{h}{2})-D(h)-frac{3}{4}k_4h^4$$ 因此,$$D=frac{1}{3}(4D(frac{h}{2})-D(h))+O(h^4)$$ 可以看到,具有四阶精度。

    举个例子,考虑一阶微分的两点中心差分法(二阶精度):$$f'(x_i)=frac{f(x_{i+1})-f(x_{i-1})}{2h}+frac{1}{3!}f'''(x_i)h2+O(h4)$$ $$=frac{f(x_{i}+h)-f(x_{i}-h)}{2h}+frac{1}{3!}f'''(x_i)h2+O(h4)$$ 缩短间距,有 $$f'(x_i)=frac{f(x_{i+1})-f(x_{i-1})}{h}+frac{1}{3!}f'''(x_i)(frac{h}{2})2+O(h4)$$ $$=frac{f(x_{i}+frac{h}{2})-f(x_{i}-frac{h}{2})}{h}+frac{1}{3!}f'''(x_i)(frac{h}{2})2+O(h4)$$ 按照Richardson外推加速算法,有 $$ 4f'(x_i)=4frac{f(x_{i}+frac{h}{2})-f(x_{i}-frac{h}{2})}{h}+frac{4}{3!}f'''(x_i)(frac{h}{2})2+4O(h4) $$ 进一步 $$ 3f'(x_i)=[4frac{f(x_{i}+frac{h}{2})-f(x_{i}-frac{h}{2})}{h}-frac{f(x_{i}+h)-f(x_{i}-h)}{2h}]+3O(h^4) $$ 因此 $$ f'(x_i)=frac{1}{3}[4frac{f(x_{i}+frac{h}{2})-f(x_{i}-frac{h}{2})}{h}-frac{f(x_{i}+h)-f(x_{i}-h)}{2h}]+O(h^4) $$ 可以看到,精度提高到了四阶。

    6. 总结

    本节课主要介绍了一些数值微分算法,对于一阶微分,最常用的有两点前向差分(精度为(O(h)))、两点后向差分(精度为(O(h)))以及两点中心差分算法(精度为(O(h^2))),其表达式均可以通过处理泰勒展开式来得到。通过处理泰勒展开式还可以得到一阶微分的三点前向差分和三点后向差分算法,精度与两点中心差分一致。对于二阶微分,同样可以利用泰勒展开,得到三点前向差分、三点后向差分以及三点中心差分算法。另一方面,还可以通过拉格朗日插值公式,得到相应的微分计算公式。这些公式又都可以很容易推广到多元函数的数值微分中去。最后,对于两个精度不高的微分算法,可以通过Richardson外推加速算法得到一个精度更高的算法,在实际问题中具有很广泛的应用。

  • 相关阅读:
    UVA 707
    我写了一起 Makefile(一)
    百度mp3接口
    MBProgressHUD -[__NSCFString sizeWithAttributes:]: unrecognized selector问题解决了
    BCM策略路由交换芯片
    HDU 4006 The kth great number AVL解
    PHP进口Excel至MySQL方法
    隐藏Console形式无效(继续1)
    优秀的前端project如何制定一个老师--html学习路径
    地址阵列
  • 原文地址:https://www.cnblogs.com/SweetZxl/p/11325961.html
Copyright © 2011-2022 走看看