如何从一维插值中获得导数
how to get derivatives from 1D interpolation
有没有办法让scipy的interp1d(在线性模式下)到return每个插值点的导数?我当然可以编写自己的 1D 插值例程,但大概 scipy 在 C 内部,因此速度更快,速度已经是一个主要问题。
我最终将插值函数的修改输入到多维最小化例程中,因此能够通过解析导数会大大加快速度,而不是让最小化例程尝试自行计算它们。 interp1d 必须在内部计算它们 --- 我可以访问它们吗?
使用 UnivariateSpline
instead of interp1d
, and use the derivative
method to generate the first derivative. The example at the manual page here 是不言自明的。
可以组合scipy.interpolate.interp1d and scipy.misc.derivative,但有一点必须要注意:
当调用 derivative
方法并选择一些 dx
作为 间距 时,x0
处的导数将被计算为一阶差分在 x0-dx
和 x0+dx
之间:
derivative(f, x0, dx) = (f(x0+dx) - f(x0-dx)) / (2 * dx)
因此,您不能使用比 dx
更接近内插函数范围限制的 derivative
,因为 f
会引发 ValueError 告诉你你的插值函数没有在那里定义。
那么,除了 dx
这些范围限制之外,您还能做些什么?
如果f
定义在[xmin, xmax]
内(范围):
- 在范围限制下,您可以
x0
移动一点:
x0 = xmin + dx
或 x0 = xmax - dx
- 对于其他点,您可以优化
dx
(使其变小)。
插值范围外的均匀函数:
如果你的插值函数恰好在插值范围之外是均匀的:
f(x0 < xmin) = f(x0 > xmax) = f_out
您可以这样定义插值函数:
f = interp1d(x, y, bound_errors=False, fill_value=f_out)
线性插值情况:
对于线性情况,只计算一次点之间的差异可能更便宜:
import numpy as np
df = np.diff(y) / np.diff(x)
这样您就可以将它们作为数组的组成部分进行访问。
据我所知,内部 interp1d
使用 BSpline。
BSpline
有一个 derivative
给出 nu
th 导数。
所以对于插值 f = interp1d(x, y)
你可以使用
fd1 = f._spline.derivative(nu=1)
但是,在使用带有前导下划线的函数时要一如既往地小心。
如果您选择插值区域之外的值,我认为不会检查边界。似乎 BSpline
附加了一个尾部维度,所以你必须写
val = fd1(0).item()
val_arr = fd1(np.array([0, 1]))[..., 0]
有没有办法让scipy的interp1d(在线性模式下)到return每个插值点的导数?我当然可以编写自己的 1D 插值例程,但大概 scipy 在 C 内部,因此速度更快,速度已经是一个主要问题。
我最终将插值函数的修改输入到多维最小化例程中,因此能够通过解析导数会大大加快速度,而不是让最小化例程尝试自行计算它们。 interp1d 必须在内部计算它们 --- 我可以访问它们吗?
使用 UnivariateSpline
instead of interp1d
, and use the derivative
method to generate the first derivative. The example at the manual page here 是不言自明的。
可以组合scipy.interpolate.interp1d and scipy.misc.derivative,但有一点必须要注意:
当调用 derivative
方法并选择一些 dx
作为 间距 时,x0
处的导数将被计算为一阶差分在 x0-dx
和 x0+dx
之间:
derivative(f, x0, dx) = (f(x0+dx) - f(x0-dx)) / (2 * dx)
因此,您不能使用比 dx
更接近内插函数范围限制的 derivative
,因为 f
会引发 ValueError 告诉你你的插值函数没有在那里定义。
那么,除了 dx
这些范围限制之外,您还能做些什么?
如果f
定义在[xmin, xmax]
内(范围):
- 在范围限制下,您可以
x0
移动一点:x0 = xmin + dx
或x0 = xmax - dx
- 对于其他点,您可以优化
dx
(使其变小)。
插值范围外的均匀函数:
如果你的插值函数恰好在插值范围之外是均匀的:
f(x0 < xmin) = f(x0 > xmax) = f_out
您可以这样定义插值函数:
f = interp1d(x, y, bound_errors=False, fill_value=f_out)
线性插值情况:
对于线性情况,只计算一次点之间的差异可能更便宜:
import numpy as np
df = np.diff(y) / np.diff(x)
这样您就可以将它们作为数组的组成部分进行访问。
据我所知,内部 interp1d
使用 BSpline。
BSpline
有一个 derivative
给出 nu
th 导数。
所以对于插值 f = interp1d(x, y)
你可以使用
fd1 = f._spline.derivative(nu=1)
但是,在使用带有前导下划线的函数时要一如既往地小心。
如果您选择插值区域之外的值,我认为不会检查边界。似乎 BSpline
附加了一个尾部维度,所以你必须写
val = fd1(0).item()
val_arr = fd1(np.array([0, 1]))[..., 0]