Python - 以数值或分析方式区分三次样条

计算科学 Python
2021-12-02 04:34:15

我正在尝试在 numpy 数组中获取数据,对它们进行插值并检索此函数以在不同阶段进行区分/集成。

这是我到达这里的方式,包括数据:

import numpy as np

x = np.array([  50.,   55.,   60.,   65.,   70.,   75.,   80.,   85.,   90.,
         95.,  100.,  105.,  110.,  115.,  120.,  125.,  130.,  135.,
        140.,  145.,  150.,  155.,  160.,  165.,  170.,  173.,  174.,
        175.,  176.,  177.,  178.,  179.,  180.,  181.,  182.,  183.,
        184.,  185.,  186.,  187.,  188.,  189.,  190.,  191.,  192.,
        193.,  194.,  195.,  196.,  197.,  198.,  199.,  200.,  201.,
        202.,  203.,  204.,  205.,  206.,  207.,  208.,  209.,  210.,
        211.,  212.,  213.,  214.,  215.,  216.,  217.,  218.,  219.,
        220.,  221.,  222.,  223.,  224.,  225.,  226.,  227.,  228.,
        229.,  230.,  231.,  232.,  233.,  234.,  235.,  236.,  237.,
        238.,  239.,  240.,  245.,  250.,  255.,  260.,  265.,  270.,
        275.,  280.,  285.,  290.,  295.,  300.,  305.,  310.,  315.,
        320.,  325.])

y = np.array([  1.00000000e-02,   1.00000000e-02,   1.00000000e-02,
         1.00000000e-02,   1.00000000e-02,   1.00000000e-02,
         1.00000000e-02,   1.50000000e-02,   2.00000000e-02,
         2.50000000e-02,   3.50000000e-02,   4.00000000e-02,
         5.00000000e-02,   6.00000000e-02,   8.00000000e-02,
         1.05000000e-01,   1.30000000e-01,   1.70000000e-01,
         2.20000000e-01,   2.75000000e-01,   3.50000000e-01,
         4.50000000e-01,   5.75000000e-01,   7.30000000e-01,
         9.40000000e-01,   1.08500000e+00,   1.14000000e+00,
         1.19500000e+00,   1.25500000e+00,   1.32000000e+00,
         1.38500000e+00,   1.45000000e+00,   1.52500000e+00,
         1.60000000e+00,   1.68000000e+00,   1.76500000e+00,
         1.84500000e+00,   1.94000000e+00,   2.03500000e+00,
         2.13500000e+00,   2.24000000e+00,   2.35000000e+00,
         2.47500000e+00,   2.59000000e+00,   2.72500000e+00,
         2.85000000e+00,   2.99000000e+00,   3.15000000e+00,
         3.29500000e+00,   3.46500000e+00,   3.63000000e+00,
         3.81500000e+00,   4.00500000e+00,   4.20500000e+00,
         4.41500000e+00,   4.62500000e+00,   4.86500000e+00,
         5.10500000e+00,   5.36000000e+00,   5.62000000e+00,
         5.89500000e+00,   6.18000000e+00,   6.49000000e+00,
         6.80500000e+00,   7.14000000e+00,   7.49500000e+00,
         7.87000000e+00,   8.26000000e+00,   8.68500000e+00,
         9.12500000e+00,   9.58500000e+00,   1.00800000e+01,
         1.06000000e+01,   1.11500000e+01,   1.17300000e+01,
         1.23400000e+01,   1.29850000e+01,   1.36650000e+01,
         1.43700000e+01,   1.51150000e+01,   1.58900000e+01,
         1.67000000e+01,   1.75450000e+01,   1.84200000e+01,
         1.93150000e+01,   2.02200000e+01,   2.11600000e+01,
         2.20800000e+01,   2.30300000e+01,   2.39950000e+01,
         2.49600000e+01,   2.59400000e+01,   2.69150000e+01,
         3.18400000e+01,   3.68050000e+01,   4.17550000e+01,
         4.67450000e+01,   5.17150000e+01,   5.66950000e+01,
         6.16750000e+01,   6.66600000e+01,   7.16350000e+01,
         7.66150000e+01,   8.15900000e+01,   8.65700000e+01,
         9.15500000e+01,   9.65300000e+01,   1.01520000e+02,
         1.06490000e+02,   1.11470000e+02])

在一些帮助下,我做到了这一点。

import matplotlib.pyplot as plt
from scipy.interpolate import UnivariateSpline

y_spl = UnivariateSpline(x,y,s=0,k=4)
x_range = np.linspace(x[0],x[-1],1000)

plt.plot(x,y,'ro',label = 'data')
plt.plot(x_range,y_spl(x_range))

在此处输入图像描述

这似乎是一个相当不错的选择。我想取这个多项式并象征性地检索它的结果,因为我的数值导数看起来不自然,即使对于这个样条也是如此。

y_spl_2d = y_spl.derivative(n=2)
plt.plot(x_range,y_spl_2d(x_range))

在此处输入图像描述

我认为即使在视觉上,这个二阶导数也不能削减它。在数学意义上,初始函数看起来非常“平滑”。

从这里我有什么选择?我可以象征性地检索初始函数并以这种方式执行导数(分析?)。我可以实施哪些其他数值程序来平滑我的二阶导数?在我看来,我的二阶导数在任何时候都不应该是负数(并且在我正在物理建模的建模意义上,它永远不应该是负数)。

我可以从拟合中检索多项式,还是可以进行数值修改以平滑我的二阶导数?

编辑:目标是检索概率密度函数。我还想将这个最终导数限制为严格正数并积分为 1,但我认为我现在的问题比这更大。这些都是次要问题。

这是一阶导数,看起来很漂亮CDF,所以我越来越确定我的问题是数值问题。我是否也应该对这个结果进行插值并加以区分?我确信这些问题很常见——我的下一步是什么。

y_spl_2d = y_spl.derivative(n=1)
plt.plot(x_range,y_spl_2d(x_range), 'ro')

在此处输入图像描述

1个回答

scipy 样条插值例程可以创建一个平滑样条曲线,它不会精确地插值给定点,而是在平滑度与插值噪声点的紧密程度之间进行权衡。您可以调高平滑以获得更稳定的结果。