包括边界点在内的所有样本点的非符号导数
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)
函数进行插值然后取其导数吗?
在与初始数据相同的点处计算导数存在不同的方法:
- 有限差分:在你的内点使用中心差分方案,在你的first/last点使用forward/backward方案
或
- 曲线拟合:通过您的点拟合一条曲线,计算此拟合函数的导数,并在与原始数据相同的点对它们进行采样。典型的拟合函数是多项式或样条函数。
请注意,曲线拟合方法可提供更好的结果,但需要更多调整选项并且速度较慢 (~100x)。
演示
作为例子,我将计算正弦函数的导数:
t = 0:0.1:1;
y = sin(t);
它的精确导数众所周知:
dy_dt_exact = cos(t);
导数可以近似计算为:
有限差分:
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
或
多项式拟合:
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;
,结果如下图:
假设我有一个向量 t = [0 0.1 0.9 1 1.4]
和一个向量 x = [1 3 5 2 3]
。如何计算 x
相对于与原始向量具有相同长度的时间的导数?
我不应该使用任何符号操作。命令 diff(x)./diff(t)
不会生成相同长度的向量。我应该先对 x(t)
函数进行插值然后取其导数吗?
在与初始数据相同的点处计算导数存在不同的方法:
- 有限差分:在你的内点使用中心差分方案,在你的first/last点使用forward/backward方案
或
- 曲线拟合:通过您的点拟合一条曲线,计算此拟合函数的导数,并在与原始数据相同的点对它们进行采样。典型的拟合函数是多项式或样条函数。
请注意,曲线拟合方法可提供更好的结果,但需要更多调整选项并且速度较慢 (~100x)。
演示
作为例子,我将计算正弦函数的导数:
t = 0:0.1:1;
y = sin(t);
它的精确导数众所周知:
dy_dt_exact = cos(t);
导数可以近似计算为:
有限差分:
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
或
多项式拟合:
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;
,结果如下图: