【问题标题】:Non-linear curve-fitting program in pythonpython中的非线性曲线拟合程序
【发布时间】:2017-12-17 09:55:37
【问题描述】:

我想找到并绘制一个函数 f,它代表一条拟合在我已经知道的一些设定点 x 和 y 上的曲线。

经过一些研究,我开始尝试使用 scipy.optimize 和 curve_fit 但在参考指南中我发现该程序使用一个函数来拟合数据,并且它假设 ydata = f(xdata, *params) + eps。

所以我的问题是:我必须在我的代码中进行哪些更改才能使用 curve_fit 或任何其他库来使用我的设定点找到曲线的函数? (注意:我也想知道该功能,以便稍后为我的项目集成并绘制它)。我知道它将是一个衰减的指数函数,但不知道确切的参数。这是我在程序中尝试的:

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit

    def func(x, a, b, c):
        return a * np.exp(-b * x) + c

    xdata = np.array([0.2, 0.5, 0.8, 1])
    ydata = np.array([6, 1, 0.5, 0.2])
    plt.plot(xdata, ydata, 'b-', label='data')
    popt, pcov = curve_fit(func, xdata, ydata)
    plt.plot(xdata, func(xdata, *popt), 'r-', label='fit')

    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    plt.show()

我目前正在 Raspberry Pi 上开发这个项目,如果它有任何改变的话。并且想使用最小二乘法,因为它既好又精确,但欢迎任何其他行之有效的方法。 同样,这是基于 scipy 库的参考指南。另外,我得到以下图表,它甚至不是曲线:Graph and curve based on set points

【问题讨论】:

  • 一切都很好,除了你的绘图:x = np.arange(0, 1, 0.01),然后是plt.plot(x, func(x, *popt), 'r-', label='fit'),因为你想在更多的点上评估你的拟合函数,以看到一个平滑的结果。关于拟合参数,它们在popt数组中。
  • 您现有代码的实际问题是什么?编辑:@MauroLacy 证实了我的怀疑。

标签: python raspberry-pi curve-fitting non-linear-regression


【解决方案1】:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def func(x, a, b, c):
    return a * np.exp(-b * x) + c

#c is a constant so taking the derivative makes it go to zero
def deriv(x, a, b, c):
    return -a * b * np.exp(-b * x)

#Integrating gives you another c coefficient (offset) let's call it c1 and set it equal to zero by default
def integ(x, a, b, c, c1 = 0):
    return -a/b * np.exp(-b * x) + c*x + c1

#There are only 4 (x,y) points here
xdata = np.array([0.2, 0.5, 0.8, 1])
ydata = np.array([6, 1, 0.5, 0.2])

#curve_fit already uses "non-linear least squares to fit a function, f, to data"
popt, pcov = curve_fit(func, xdata, ydata)
a,b,c = popt #these are the optimal parameters for fitting your 4 data points

#Now get more x values to plot the curve along so it looks like a curve
step = 0.01
fit_xs = np.arange(min(xdata),max(xdata),step)

#Plot the results
plt.plot(xdata, ydata, 'bx', label='data')
plt.plot(fit_xs, func(fit_xs,a,b,c), 'r-', label='fit')
plt.plot(fit_xs, deriv(fit_xs,a,b,c), 'g-', label='deriv')
plt.plot(fit_xs, integ(fit_xs,a,b,c), 'm-', label='integ')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

【讨论】:

  • 您应该将数据显示为带有“bx”之类的点而不是曲线(不过这是一个相当笼统的评论,不要太费心)
  • 我喜欢这个建议,我认为它更清楚地表明曲线是拟合点
  • 嗯,这是有道理的,我需要一些步骤来更好地适应曲线。所以为了清楚起见,函数给了我曲线的方程?如果是这样,以后我可以通过集成、推导等长时间操作函数“func”吗?
  • curve_fit 的返回值将是曲线 A,B,C 在这种情况下 Aexp(-BX)+C 的系数。如果您想要集成和推导,我建议您在纸上执行此操作,然后创建一个新函数。在这种情况下,导数是 -AB*exp(-BX) 所以你可以把它变成另一个函数并绘制它。相同的集成理念
  • 如果没有“p0”初始参数传递给curve_fit(),scipy使用所有1.0的默认参数。这对于更复杂的方程可能不是最理想的,因此 scipy 的作者添加了差分进化遗传算法用于初始参数估计。该模块名为 scipy.optimize.differential_evolution,它使用拉丁超立方算法来确保对参数空间的彻底搜索。我已经用它来将双洛伦兹方程拟合到碳纳米管的拉曼光谱数据,在bitbucket.org/zunzuncode/RamanSpectroscopyFit 获得了出色的结果
猜你喜欢
  • 1970-01-01
  • 2021-07-23
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
  • 2017-09-15
  • 2019-03-15
  • 1970-01-01
  • 2019-05-04
相关资源
最近更新 更多