包括边界点在内的所有样本点的非符号导数

Non-symbolic derivative at all sample points including boundary points

假设我有一个向量 t = [0 0.1 0.9 1 1.4] 和一个向量 x = [1 3 5 2 3]。如何计算 x 相对于与原始向量具有相同长度的时间的导数?

我不应该使用任何符号操作。命令 diff(x)./diff(t) 不会生成相同长度的向量。我应该先对 x(t) 函数进行插值然后取其导数吗?

在与初始数据相同的点处计算导数存在不同的方法:

  1. 有限差分:在你的内点使用中心差分方案,在你的first/last点使用forward/backward方案

  1. 曲线拟合:通过您的点拟合一条曲线,计算此拟合函数的导数,并在与原始数据相同的点对它们进行采样。典型的拟合函数是多项式或样条函数。

请注意,曲线拟合方法可提供更好的结果,但需要更多调整选项并且速度较慢 (~100x)。

演示

作为例子,我将计算正弦函数的导数:

t = 0:0.1:1;
y = sin(t);

它的精确导数众所周知:

dy_dt_exact = cos(t);

导数可以近似计算为:

  1. 有限差分:

    dy_dt_approx = zeros(size(y));
    dy_dt_approx(1) = (y(2) - y(1))/(t(2) - t(1)); % forward difference
    dy_dt_approx(end) = (y(end) - y(end-1))/(t(end) - t(end-1)); % backward difference
    dy_dt_approx(2:end-1) = (y(3:end) - y(1:end-2))./(t(3:end) - t(1:end-2)); % central difference
    

  1. 多项式拟合:

    p = polyfit(t,y,5); % fit fifth order polynomial
    dp = polyder(p); % calculate derivative of polynomial
    

结果可视化如下:

figure('Name', 'Derivative')
hold on
plot(t, dy_dt_exact, 'DisplayName', 'eyact');
plot(t, dy_dt_approx, 'DisplayName', 'finite difference');
plot(t, polyval(dp, t), 'DisplayName', 'polynomial');
legend show

figure('Name', 'Error')
hold on
plot(t, abs(dy_dt_approx - dy_dt_exact)/max(dy_dt_exact), 'DisplayName', 'finite difference');
plot(t, abs(polyval(dp, t) - dy_dt_exact)/max(dy_dt_exact), 'DisplayName', 'polynomial');
legend show

第一张图显示了导数本身,第二张图绘制了两种方法产生的相对误差。

讨论

可以清楚地看到,曲线拟合方法比有限差分法给出了更好的结果,但速度慢了约 100 倍。曲线拟合方法存在阶数相对误差10^-5。请注意,当您的数据采样更密集或您使用更高阶方案时,有限差分方法会变得更好。曲线拟合方法的缺点是必须选择一个好的多项式阶数。一般来说,样条函数可能更适合。

速度提高 10 倍的采样数据集,即 t = 0:0.01:1;,结果如下图: