求一维插值函数的最大值/最小值

2024-05-14 13:26:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一组数据,我正在用 kind = 'cubic'插值。在

我想找到这个三次插值函数的最大值。在

目前我所做的只是求插值数据数组中的最大值,但是我想知道插值函数作为一个对象,是否可以被区分以找到它的极值?在

代码:

import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

x_axis = np.array([ 2.14414414,  2.15270826,  2.16127238,  2.1698365 ,  2.17840062, 2.18696474,  2.19552886,  2.20409298,  2.2126571 ,  2.22122122])
y_axis = np.array([ 0.67958442,  0.89628424,  0.78904004,  3.93404167,  6.46422317, 6.40459954,  3.80216674,  0.69641825,  0.89675386,  0.64274198])

f = interp1d(x_axis, y_axis, kind = 'cubic')

x_new = np.linspace(x_axis[0], x_axis[-1],100)

fig = plt.subplots()
plt.plot(x_new, f(x_new))

Tags: 数据对象函数importnewasnpplt
1条回答
网友
1楼 · 发布于 2024-05-14 13:26:20

三次样条曲线的导数是二次样条曲线。SciPy只有一个内置的方法来寻找三次样条曲线的根。所以有两种方法:

  1. 采用四次样条插值,可以方便地求出其导数的根。在
  2. 使用三次样条曲线(通常更可取),并为其导数的根编写一个自定义函数。在

我在下面描述这两种解决方案。在

四次样条曲线

使用InterpolatedUnivariateSpline。它的.derivative方法返回一个三次样条曲线,可以对其应用.roots方法。在

from scipy.interpolate import InterpolatedUnivariateSpline
f = InterpolatedUnivariateSpline(x_axis, y_axis, k=4)
cr_pts = f.derivative().roots()
cr_pts = np.append(cr_pts, (x_axis[0], x_axis[-1]))  # also check the endpoints of the interval
cr_vals = f(cr_pts)
min_index = np.argmin(cr_vals)
max_index = np.argmax(cr_vals)
print("Maximum value {} at {}\nMinimum value {} at {}".format(cr_vals[max_index], cr_pts[max_index], cr_vals[min_index], cr_pts[min_index]))

输出:

Maximum value 6.779687224066201 at 2.1824928509277037
Minimum value 0.34588448400295346 at 2.2075868177297036

三次样条

我们需要一个二次样条曲线根的自定义函数。在这里(解释如下)。在

^{2}$

现在,除了使用自定义解算器外,完全按照上述步骤进行。在

from scipy.interpolate import InterpolatedUnivariateSpline
f = InterpolatedUnivariateSpline(x_axis, y_axis, k=4)
cr_pts = quadratic_spline_roots(f.derivative())
cr_pts = np.append(cr_pts, (x_axis[0], x_axis[-1]))  # also check the endpoints of the interval
cr_vals = f(cr_pts)
min_index = np.argmin(cr_vals)
max_index = np.argmax(cr_vals)
print("Maximum value {} at {}\nMinimum value {} at {}".format(cr_vals[max_index], cr_pts[max_index], cr_vals[min_index], cr_pts[min_index]))

输出:

Maximum value 6.782781181150518 at 2.1824928579767167
Minimum value 0.45017143148176136 at 2.2070746522580795

与第一种方法的输出稍有出入不是一个缺陷;第四次样条曲线和第三次样条曲线略有不同。在

关于quadratic_spline_roots

假设我们知道一个二次多项式在-1,0,1处的值是u,v,w。它在区间[-1,1]上的根是什么?用一些代数我们可以发现多项式是

((u+w-2*v) * x**2 + (w-u) * x + 2*v) / 2

现在可以使用二次公式,但最好使用np.roots,因为它也可以处理导系数为零的情况。然后将根过滤为-1到1之间的实数。最后,如果区间是[a,b]而不是[-1,1],则进行线性变换。在

附加值:三次样条的宽度在中端

假设我们想要找到样条曲线的值等于它的最大值和最小值的平均值(即它的中间值)。那么我们应该明确地使用三次样条插值,因为现在需要使用roots方法。不能只做(f - mid_range).roots(),因为SciPy不支持向样条曲线添加常量。相反,从y_axis - mid_range构建一个下移的样条线。在

mid_range = (cr_vals[max_index] + cr_vals[min_index])/2
f_shifted = InterpolatedUnivariateSpline(x_axis, y_axis - mid_range, k=3)
roots = f_shifted.roots()
print("Mid-range attained from {} to {}".format(roots.min(), roots.max()))

Mid-range attained from 2.169076230034363 to 2.195974299834667

相关问题 更多 >

    热门问题