Python 曲线拟合-单调递增导数

Python 曲线拟合-单调递增导数,python,numpy,scipy,curve-fitting,Python,Numpy,Scipy,Curve Fitting,我试图得到一些实验数据的物理意义上的拟合。我知道不仅y值会随着x单调增加,而且dy/dx也会单调增加。我尝试过许多拟合函数,包括多项式拟合和单变量样条曲线拟合,但这两种拟合函数都不允许我产生我想要的拟合 因此,我正在寻找一个曲线拟合函数(在scipy中?),它允许我定义最终曲线的已知约束。下面是我的数据示例,其中一条拟合线不显示单调递增的导数 import numpy as np import matplotlib.pyplot as plt data = np.array([[ 6.30

我试图得到一些实验数据的物理意义上的拟合。我知道不仅y值会随着x单调增加,而且dy/dx也会单调增加。我尝试过许多拟合函数,包括多项式拟合和单变量样条曲线拟合,但这两种拟合函数都不允许我产生我想要的拟合

因此,我正在寻找一个曲线拟合函数(在scipy中?),它允许我定义最终曲线的已知约束。下面是我的数据示例,其中一条拟合线不显示单调递增的导数

import numpy as np
import matplotlib.pyplot as plt

data =  np.array([[  6.30991828, -10.22329935],
                  [  6.30991828, -10.2127338 ],
                  [  6.47697236, -10.01359361],
                  [  6.47697236,  -9.89353722],
                  [  6.47697236,  -9.81708052],
                  [  6.55108034,  -9.42113403],
                  [  6.55108034,  -9.21932801],
                  [  6.58617165,  -8.40428977],
                  [  6.62007321,  -7.6500927 ]])

interp = np.linspace(min(data[:,0]), max(data[:,0]), 20)
f = np.polyfit(data[:,0], data[:,-1], 3)
data_interp = np.polyval(f, interp)
plt.plot(data[:,0], data[:,1], 'x', interp, data_interp, '-')

编辑:我相信你可以用slmengine在MATLAB中实现这一点。

你的数据很有趣:你有三个不连续点:6.30991828、6.47697236和6.55108034。那些是真的吗?这就是你想要捕捉的吗

没有一个连续函数能够正确地捕捉这些不连续性。你唯一的希望是分段拟合不连续的两边。您将有三种适合:

  • x<6.47697236
  • 6.47697236
  • x>6.55108034
  • 当然,函数在不连续处是多值的

    如果这些对你没有意义,我会说任何三次多项式都会给你一个连续的,递增的一阶导数

    import numpy as np
    import matplotlib.pyplot as plt
    
    data =  np.array([[  6.30991828, -10.22329935],
                      [  6.30991828, -10.2127338 ],
                      [  6.47697236, -10.01359361],
                      [  6.47697236,  -9.89353722],
                      [  6.47697236,  -9.81708052],
                      [  6.55108034,  -9.42113403],
                      [  6.55108034,  -9.21932801],
                      [  6.58617165,  -8.40428977],
                      [  6.62007321,  -7.6500927 ]])
    
    interp = np.linspace(min(data[:,0]), max(data[:,0]), 20)
    f = np.polyfit(data[:,0], data[:,-1], 3)
    data_interp = np.polyval(f, interp)
    plt.plot(data[:,0], data[:,1], 'x', interp, data_interp, '-')
    

    编辑:另一次尝试。我以前贴过半生不熟的答案。我的阅读也失败了。我希望这样更好

    from scipy.optimize import minimize
    import numpy as np
    import matplotlib.pyplot as plt
    
    data = np.array([[  6.30991828, -10.22329935],
                      [  6.30991828, -10.2127338 ],
                      [  6.47697236, -10.01359361],
                      [  6.47697236,  -9.89353722],
                      [  6.47697236,  -9.81708052],
                      [  6.55108034,  -9.42113403],
                      [  6.55108034,  -9.21932801],
                      [  6.58617165,  -8.40428977],
                      [  6.62007321,  -7.6500927 ]])
    
    x = data[:, 0]
    
    def polynomial(p, x):
        return p[0]+p[1]*x+p[2]*x**2+p[3]*x**3
    
    def constraint_2nd_der(p):
        return 2*p[2]+6*p[3]*x
    
    def constraint_1st_der(p):
        return p[1]+2*p[2]*x+3*p[3]*x**2
    
    def objective(p):
        return ((polynomial(p, x)-data[:, 1])**2).sum()
    
    
    cons = (dict(type='ineq', fun=constraint_1st_der), dict(type='ineq', fun=constraint_2nd_der))
    res = minimize(objective, x0=np.array([0., 0., 0., 0.]), method='SLSQP', constraints=cons)
    if res.success:
        pars = res.x
        x = np.linspace(data[:, 0].min(), data[:, 0].max(), 100)
        pol = polynomial(pars, x)
        plt.plot(data[:, 0], data[:, 1], 'x', x, pol, '-')
        plt.show()
    else:
        print 'Failed'
    

    不连续性不是真实的,只是在这些值下进行了多次测试。我最好是对重复进行平均,然后通过平均值拟合曲线?正如您所见,最小二乘拟合将使均方误差最小化,并根据原始数据计算系数。我会这么做的。您可以看到,R值很高,拟合的视觉效果对于这条三阶曲线很好。足够好吗?恐怕你得选择一系列函数,用解析法计算你的导数。这将为您提供一个约束,您可以将其输入到优化例程中。好的,我明白您现在所说的。也许增加一个拉格朗日乘数来加强这一点可以管理它。我不知道如何在一个典型的最小二乘法软件包中实现它。也许这会有帮助:这可能是个好主意。谢谢你提出了一个有趣的问题和讨论。祝你好运。这是有道理的,但它似乎不起作用!如果我用更精细的时间步长绘制曲线,你可以看到它仍然是同一个无约束三次多项式。约束(cons)是否已正确应用?这看起来像一个未完成的答案,cons从未使用过,据我所知,曲线拟合不接受约束。看看scipy.optimize.fmin_slsqp.Brilliant,它正是我想要的。方法也不错。它不会产生视觉上的完美贴合,但我可以用任何阶导数来约束,这很好。很高兴它有帮助,但对以前的版本很抱歉。但我建议你总是目视检查拟合度——解算器并不总是正确的。